samhain-4.1.4/0000777000175000017500000000000012724114745010154 500000000000000samhain-4.1.4/install-sh0000755000175000017500000001272012615253270012072 00000000000000#!/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=: 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 samhain-4.1.4/missing0000755000175000017500000001420212615253270011462 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright (C) 1996, 1997 Free Software Foundation, Inc. # Franc,ois 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. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi 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 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 lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing - GNU libit 0.0" ;; -*) 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` if test -z "$files"; then files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.ac` test -z "$files" || files="$files.in" else files=`echo "$files" | sed -e 's/:/ /g'` fi test -z "$files" && files="config.h.in" 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$/touch \1.in/' \ | sh ;; 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 ;; makeinfo) 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 ;; *) 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 samhain-4.1.4/rules.deb.in0000644000175000017500000000775012615253270012310 00000000000000#!/usr/bin/make -f # Samhain debian/rules # GNU copyright 20001 to 2003 by Javier Fernandez-Sanguino # based on # Sample debian/rules that uses debhelper. # GNU copyright 1997 to 1999 by Joey Hess. # Modified to use mydefargs by Rainer Wichmann. # # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # This is the debhelper compatability version to use. export DH_COMPAT=4 package=@install_name@ # CAVEAT: including the --enable-base= option is for packages to be # distributed INTERNALLY on your network, NOT for packages # to be distributed to THIRD PARTIES build: build-stamp build-stamp: dh_testdir @top_srcdir@/configure @mydefargs@ $(MAKE) echo '#!/bin/sh' > ./sstrip echo 'echo "*** SSTRIP DISABLED ***"' >> ./sstrip if ! test x$(PASSWORD) = x; then \ if test -f samhain_setpwd; then \ ./samhain_setpwd samhain new $(PASSWORD); \ rm samhain; \ mv samhain.new samhain; \ fi; \ fi touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp -[ -f Makefile ] && $(MAKE) distclean dh_clean install: build dh_testdir dh_testroot dh_clean -k dh_installdirs # Fix the permissions #chmod o-rX `pwd`/debian/tmp/var/log/samhain \ # `pwd`/debian/tmp/var/run/samhain \ # `pwd`/debian/tmp/var/lib/samhain \ # `pwd`/debian/tmp/etc/samhain # $(MAKE) install install-boot DESTDIR=`pwd`/debian/tmp $(MAKE) install install-boot DESTDIR=`pwd`/debian/@install_name@ # However, remove the rc.d links -rm -rf `pwd`/debian/tmp/etc/rc?.d # install -m 755 encode `pwd`/debian/tmp/usr/bin/samhain_encode # install -m 644 profiles/debianlinux_i386/samhainrc `pwd`/debian/tmp@myconffile@ # install -m 644 debian/samhain.logrotate `pwd`/debian/tmp/etc/logrotate.d/samhain # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install # dh_testversion dh_testdir dh_testroot dh_installdebconf dh_installdocs [ -f debian/@install_name@/usr/share/doc/@install_name@/MANUAL-2_4.html.tar ] && \ cd debian/@install_name@/usr/share/doc/@install_name@ && \ tar xf MANUAL-2_4.html.tar && mv MANUAL-2_4 manual.html && \ rm -f MANUAL-2_4.html.tar && \ mv MANUAL-2_4.pdf manual.pdf dh_installexamples @top_srcdir@/scripts/example_pager.pl \ @top_srcdir@/scripts/example_sms.pl \ @top_srcdir@/scripts/concat.pl \ @top_srcdir@/scripts/samhain.logrotator \ @top_srcdir@/scripts/samhainadmin.pl \ @top_srcdir@/scripts/check_samhain.pl \ @top_srcdir@/yulerc.template \ @top_srcdir@/samhainrc.linux dh_installmenu dh_installinit -- defaults 19 [ -f debian/@install_name@.postinst.debhelper ] && \ cd debian && \ cat @install_name@.postinst.debhelper | \ sed 's%/etc/init.d/@install_name@ start%:%' > postinst.tmp && \ mv postinst.tmp @install_name@.postinst.debhelper [ -f debian/@install_name@.postinst.debhelper ] && \ cd debian && \ cat @install_name@.postinst.debhelper | \ sed 's%invoke-rc.d @install_name@ start%:%' > postinst.tmp && \ mv postinst.tmp @install_name@.postinst.debhelper [ -f debian/@install_name@.prerm.debhelper ] && \ cd debian && \ cat @install_name@.prerm.debhelper | \ sed 's%/etc/init.d/@install_name@ stop%/etc/init.d/@install_name@ stop || echo service @install_name@ already stopped%' > prerm.tmp && \ mv prerm.tmp @install_name@.prerm.debhelper [ -f debian/@install_name@.prerm.debhelper ] && \ cd debian && \ cat @install_name@.prerm.debhelper | \ sed 's%invoke-rc.d @install_name@ stop%invoke-rc.d @install_name@ stop || echo service @install_name@ already stopped%' > prerm.tmp && \ mv prerm.tmp @install_name@.prerm.debhelper # dh_installmanpages dh_installchangelogs @top_srcdir@/docs/Changelog dh_link dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb define checkdir test -f debian/rules endef binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install samhain-4.1.4/LICENSE0000644000175000017500000004307612615253270011103 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. samhain-4.1.4/rules.deb-light.in0000644000175000017500000000615212615253270013410 00000000000000#!/usr/bin/make -f # Samhain debian/rules # GNU copyright 20001 to 2003 by Javier Fernandez-Sanguino # based on # Sample debian/rules that uses debhelper. # GNU copyright 1997 to 1999 by Joey Hess. # Modified to use mydefargs by Rainer Wichmann. # # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # This is the debhelper compatability version to use. export DH_COMPAT=4 package=@install_name@ # CAVEAT: including the --enable-base= option is for packages to be # distributed INTERNALLY on your network, NOT for packages # to be distributed to THIRD PARTIES build: build-stamp build-stamp: dh_testdir @top_srcdir@/configure @mydefargs@ $(MAKE) echo '#!/bin/sh' > ./sstrip echo 'echo "*** SSTRIP DISABLED ***"' >> ./sstrip if ! test x$(PASSWORD) = x; then \ if test -f samhain_setpwd; then \ ./samhain_setpwd samhain new $(PASSWORD); \ rm samhain; \ mv samhain.new samhain; \ fi; \ fi touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp -[ -f Makefile ] && $(MAKE) distclean dh_clean install: build dh_testdir dh_testroot dh_clean -k dh_installdirs $(MAKE) install-light install-boot DESTDIR=`pwd`/debian/@install_name@ # $(MAKE) install-light install-boot DESTDIR=`pwd`/debian/tmp # However, remove the rc.d links -rm -rf `pwd`/debian/tmp/etc/rc?.d # Remove samhain_stealth for light install -rm -f `pwd`/debian/tmp/@sbindir@/@install_name@_stealth # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install # dh_testversion dh_testdir dh_testroot dh_installdebconf # dh_installdocs dh_installmenu dh_installinit -- defaults 19 [ -f debian/@install_name@.postinst.debhelper ] && \ cd debian && \ cat @install_name@.postinst.debhelper | \ sed 's%/etc/init.d/@install_name@ start%:%' > postinst.tmp && \ mv postinst.tmp @install_name@.postinst.debhelper [ -f debian/@install_name@.postinst.debhelper ] && \ cd debian && \ cat @install_name@.postinst.debhelper | \ sed 's%invoke-rc.d @install_name@ start%:%' > postinst.tmp && \ mv postinst.tmp @install_name@.postinst.debhelper [ -f debian/@install_name@.prerm.debhelper ] && \ cd debian && \ cat @install_name@.prerm.debhelper | \ sed 's%/etc/init.d/@install_name@ stop%/etc/init.d/@install_name@ stop || echo service @install_name@ already stopped%' > prerm.tmp && \ mv prerm.tmp @install_name@.prerm.debhelper [ -f debian/@install_name@.prerm.debhelper ] && \ cd debian && \ cat @install_name@.prerm.debhelper | \ sed 's%invoke-rc.d @install_name@ stop%invoke-rc.d @install_name@ stop || echo service @install_name@ already stopped%' > prerm.tmp && \ mv prerm.tmp @install_name@.prerm.debhelper # dh_installmanpages # dh_installchangelogs @top_srcdir@/docs/Changelog dh_link dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb define checkdir test -f debian/rules endef binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install samhain-4.1.4/samhain.jpg0000644000175000017500000000552112615253270012211 00000000000000JFIFHHCreated with The GIMPC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222@h"@!1AQq"2a#3CSBRs%5rb ?舀ђpkt/U;{w͒y;ts r4Ou(wIdR?!*" """ """ """ """ """ """ &V_QC)PS2o{##AMa^d~(˃A$mNSLy>1NJ05~חKs|PZANtf1Z= U6$]i:rr7iQxː3_ pck* q+\;?H5!GԆ9?{ ƷCSXӹRCԶ*2F3t[4Mx;*/OnjBᛝҾ6)Y?e+*e&uD1xh/梦X_@?*O-n+TS+d>:<|%[MiNQ[HK =01p+9NŞG|v_)H+%⪁ѺH}`xb.@4M8zlOs]-Sn$-89KtFį # ̇F~n;ER㍹{GiLU|Q!pF]Ak\j)fqDᒠHg$.v_LI v$ӿ Z;!1n|qv{t.@k,Ệ:}^1TOPKLMAc]cgqt iCQ+cF>8~jȪFIL^i wo$CDNK=3& X AgRTTskь|=ۮtȉ7gv} p-G7u5ՂO,m<ƂGBW{acrdhkMÐ:í{=oVEw)XX-ҖHНc/TNS#L齞Gꅗď6S*d:I>S*\67E5GGꂛ!{'y#]~$~(N>Ffp@+?ZqtpXFEdpp ֲ:{\9)tً#'w?k'PtP'Ϋښr _E)&1)Wg{(敖58K驵:!`TǴ9q=`8skۍ la>*)},n|wj?[ݛ8.$~jKCN рjF. 'd?Wg'i~jveJxη\Ygi5ED.` ݁= Mr| npxmAS,N}K䱵6vTKhq.B 5fןdݐJ׹6HFLg_sP<бi,t]'Q2vY&5ihpiP=z)wWgqa-+c/F"k'%~Y>q#5 ~ ;#'_7;+Wp j[mZHe\['$z|Vl T*bxO$=g\Y8=W5F*''=W ݥ(<ٮ;Ƭ;tTq EԞWAKi0u\Y=rgd'}'U𨼐uCb-x;Y01_H ЮQeuwVNH-u~S4쭋A9"jI'Hl1DV{HA))HdQ%D33#XsqbKڤo<pTd t9DDD@DDD@DDD@DDD@DDD@^ 3$H^AKhWH-X'%[ ƃ"E埴ՔPeO0oKs Q˵3NʢNjwPH\@DDDAsamhain-4.1.4/config.guess0000755000175000017500000012355012615253270012412 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-03-23' # 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 3 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, see . # # 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. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. 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 1992-2014 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 ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # 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 trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; 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 ; set_cc_for_build= ;' # 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 case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # 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 tuples: *-*-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. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ 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 # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # 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 ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # 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. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; 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 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; 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 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; 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 ;; 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 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /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 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # 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 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build 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 $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; 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 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????: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 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; 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 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi 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 ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | 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 ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 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]) 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" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build 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 (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build 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 $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; 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 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; 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 ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; 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 i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; 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=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; 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-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; 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 ;; 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 ;; 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 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; 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 ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. 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 ;; 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|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; 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 i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; 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 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*: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; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' 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; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *: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 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; 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 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *: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 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac 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: samhain-4.1.4/configure.ac0000644000175000017500000022412512724016101012347 00000000000000dnl We want to override the standard _AC_INIT_PARSE_ARGS dnl AU_ALIAS([_AC_INIT_PARSE_ARGS], [SH_INIT_PARSE_ARGS]) AU_ALIAS([_AC_INIT_help], [SH_INIT_HELP]) AC_INIT(src/samhain.c) AC_ARG_VAR([LIBS], [libraries to link against, e.g. -lintl]) dnl dnl start dnl AM_INIT_AUTOMAKE(samhain, 4.1.4) AC_DEFINE([SAMHAIN], 1, [Application is samhain]) AC_CANONICAL_HOST dnl dnl checks for programs dnl AC_PROG_CC if test "$host" != "$build"; then AC_CHECK_PROGS(BUILD_CC, gcc cc) else BUILD_CC=$CC fi AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_AWK SH_PROG_LD AC_PATH_PROG(cmd_hostname,hostname) AC_SUBST(cmd_hostname) AC_SUBST(BUILD_CC) if test "x$GCC" = "xyes"; then SH_GCC_VERSION fi AC_HEADER_STDC AC_CHECK_HEADERS([sys/ipc.h sys/sem.h sys/msg.h sys/uio.h fcntl.h]) AC_MSG_CHECKING([for OS specific issues]) mydebugflag=no myneedg3=no uid_cast="signed long" selectconfig=linux mynetbsd=no sh_use_lcaps="undef" dnmalloc_ok=yes sh_use_pie=yes enable_asm_ok=yes case "$host_os" in *linux*) sh_use_lcaps="yes" AC_DEFINE(HOST_IS_LINUX) AC_DEFINE(HAVE_EXT2_IOCTLS) AC_MSG_RESULT([use ioctl to get e2fs flags]) case "$host_cpu" in i*86*) AC_DEFINE(HOST_IS_I86LINUX) ;; x86_64) AC_DEFINE([HOST_IS_64LINUX], 1, [Define if host OS is 64bit Linux]) ;; *) ;; esac ;; *osf*) AC_DEFINE([HOST_IS_OSF], 1, [Define if host OS is OSF]) if test "x$GCC" != "xyes"; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` CFLAGS="$CFLAGS -O2 -assume noaligned_objects" myneedg3=yes AC_MSG_RESULT([compiler needs assume noaligned_objects]) else AC_MSG_RESULT([none]) fi ;; *cygwin*) AC_DEFINE(HOST_IS_CYGWIN) AC_DEFINE([USE_REGISTRY_CHECK], 1, [Define for registry check]) dnmalloc_ok=no enable_asm_ok=no AC_MSG_RESULT([no trusted paths, no dnmalloc. no asm optimize]) ;; *darwin*|*apple*) AC_DEFINE(HOST_IS_DARWIN) dnmalloc_ok=no AC_MSG_RESULT([check resource forks, no dnmalloc]) ;; *freebsd8*|*freebsd9*) AC_DEFINE(HOST_IS_FREEBSD) selectconfig=freebsd case "$host_cpu" in amd64|x86_64) dnmalloc_ok=no AC_MSG_RESULT([no dnmalloc]) ;; *) AC_MSG_RESULT([none]) ;; esac ;; *freebsd7*) AC_DEFINE(HOST_IS_FREEBSD) selectconfig=freebsd case "$host_cpu" in amd64|x86_64) sh_use_pie=no dnmalloc_ok=no AC_MSG_RESULT([no dnmalloc and broken compiler toolchain]) ;; *) AC_MSG_RESULT([none]) ;; esac ;; *freebsd*) AC_DEFINE(HOST_IS_FREEBSD) selectconfig=freebsd AC_MSG_RESULT([none]) ;; *openbsd*) AC_DEFINE([HOST_IS_OPENBSD], 1, [Define if host OS is OPENBSD]) selectconfig=freebsd dnmalloc_ok=no AC_MSG_RESULT([dnmalloc does not work with pthreads]) ;; *netbsd*) mynetbsd=yes selectconfig=netbsd AC_MSG_RESULT([bug with libresolve]) ;; *solaris*) selectconfig=solaris AC_DEFINE(HOST_IS_SOLARIS) case "$host_cpu" in i*86) AC_DEFINE(HOST_IS_I86SOLARIS) AC_MSG_RESULT([vsnprintf prototype]) ;; *) AC_MSG_RESULT([none]) ;; esac if test "x$GCC" != "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g" 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\-xO2" 2> /dev/null`"; then CFLAGS="$CFLAGS -xO2" fi if test -z "`echo "$CFLAGS" | grep "\-Xa" 2> /dev/null`"; then CFLAGS="$CFLAGS -Xa" fi LIBS="-lc $LIBS" fi ;; *sun*) selectconfig=solaris AC_DEFINE(HOST_IS_SOLARIS) AC_MSG_RESULT([none]) ;; *aix*) AC_DEFINE(HOST_IS_AIX) selectconfig=aix5.2.0 uid_cast="unsigned long" if test "x$GCC" != "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g" 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\-O3" 2> /dev/null`"; then CFLAGS="$CFLAGS -O3" fi if test -z "`echo "$CFLAGS" | grep "\-qstrict" 2> /dev/null`"; then CFLAGS="$CFLAGS -qstrict" fi AC_MSG_RESULT([AIX size_t in the accept call and optimize O3 qstrict]) else AC_MSG_RESULT([AIX size_t in the accept call]) fi ;; *hpux*) AC_MSG_RESULT([HPUX need _XOPEN_SOURCE_EXTENDED for h_errno]) AC_DEFINE(HOST_IS_HPUX) if test "x$GCC" != "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g" 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\+O2" 2> /dev/null`"; then CFLAGS="$CFLAGS +O2" fi fi ;; *ultrix*) AC_MSG_RESULT([ULTRIX getcwd uses popen]) AC_DEFINE(HAVE_BROKEN_GETCWD) ;; *) AC_MSG_RESULT([none]) ;; esac AC_SUBST(selectconfig) AC_DEFINE_UNQUOTED(UID_CAST, ${uid_cast}) dnl ***************************************** dnl dnl checks for header files dnl dnl ***************************************** AC_HEADER_DIRENT AC_HEADER_MAJOR AC_HEADER_TIME dnl used in minilzo.c AC_HEADER_STAT AC_DECL_SYS_SIGLIST AC_CHECK_HEADERS(stddef.h libgen.h sched.h malloc.h sys/uio.h \ sys/mman.h sys/param.h sys/inotify.h \ sys/vfs.h mntent.h \ sys/select.h sys/socket.h netinet/in.h \ regex.h glob.h fnmatch.h \ linux/ext2_fs.h linux/fs.h ext2fs/ext2_fs.h asm/segment.h \ elf.h linux/elf.h auparse.h \ paths.h arpa/nameser.h arpa/nameser_compat.h \ rpc/rpcent.h rpc/rpc.h sys/statvfs.h, [], [], [#include ] ) AC_CHECK_HEADER(utmpx.h, sh_utmpx="yes", sh_utmpx="no") if test "x$sh_utmpx" = "xyes"; then AC_DEFINE(HAVE_UTMPX_H) AC_EGREP_HEADER(ut_host, utmpx.h, AC_DEFINE(HAVE_UTHOST) ) AC_EGREP_HEADER(ut_addr, utmpx.h, AC_DEFINE(HAVE_UTADDR) ) AC_EGREP_HEADER(ut_addr_v6, utmpx.h, AC_DEFINE(HAVE_UTADDR_V6) ) AC_EGREP_HEADER(ut_xtime,utmpx.h, AC_DEFINE(HAVE_UTXTIME) ) AC_EGREP_HEADER(ut_type, utmpx.h, AC_DEFINE(HAVE_UTTYPE) ) else AC_EGREP_HEADER(ut_addr, utmp.h, AC_DEFINE(HAVE_UTADDR) ) AC_EGREP_HEADER(ut_host, utmp.h, AC_DEFINE(HAVE_UTHOST) ) AC_EGREP_HEADER(ut_type, utmp.h, AC_DEFINE(HAVE_UTTYPE) ) fi dnl dnl figure out where acct.h lives dnl and whether fields are int/comp_t dnl dnl GNU Accounting Utilities dnl Copyright (C) 1993, 1996, 1997, 2003, 2005 Free Software Foundation, Inc. dnl The GNU Accounting Utilities are free software; you can redistribute dnl them and/or modify them under the terms of the GNU General Public dnl License as published by the Free Software Foundation; either version dnl 2, or (at your option) any later version. dnl AC_CHECK_HEADER(sys/acct.h, AC_DEFINE(HAVE_SYS_ACCT_H, , [Define if you have the header file.]) AC_HEADER_EGREP(ac_utime, sys/acct.h, AC_DEFINE(HAVE_ACUTIME, , [Define if has the AC_UTIME field.]) AC_HEADER_EGREP(comp_t.*ac_utime, sys/acct.h, AC_DEFINE(ACUTIME_COMPT, , [Define if 's AC_UTIME field is a COMP_T.])) ) AC_HEADER_EGREP(ac_stime, sys/acct.h, AC_DEFINE(HAVE_ACSTIME, , [Define if has the AC_STIME field.]) AC_HEADER_EGREP(comp_t.*ac_stime, sys/acct.h, AC_DEFINE(ACSTIME_COMPT, , [Define if 's AC_STIME field is a COMP_T.])) ) AC_HEADER_EGREP(ac_etime, sys/acct.h, AC_DEFINE(HAVE_ACETIME, , [Define if has the AC_ETIME field.]) AC_HEADER_EGREP(comp_t.*ac_etime, sys/acct.h, AC_DEFINE(ACETIME_COMPT, , [Define if 's AC_ETIME field is a COMP_T.])) ) AC_HEADER_EGREP(ac_io, sys/acct.h, AC_DEFINE(HAVE_ACIO, , [Define if has the AC_IO field.]) AC_HEADER_EGREP(comp_t.*ac_io, sys/acct.h, AC_DEFINE(ACIO_COMPT, , [Define if 's AC_IO field is a COMP_T.])) ) AC_HEADER_EGREP(ac_mem, sys/acct.h, AC_DEFINE(HAVE_ACMEM, , [Define if has the AC_MEM field.]) AC_HEADER_EGREP(comp_t.*ac_mem, sys/acct.h, AC_DEFINE(ACMEM_COMPT, , [Define if 's AC_MEM field is a COMP_T.])) ) AC_HEADER_EGREP(ac_minflt, sys/acct.h, AC_HEADER_EGREP(ac_majflt, sys/acct.h, AC_HEADER_EGREP(ac_swaps, sys/acct.h, AC_DEFINE(HAVE_PAGING, , [Define if has the AC_MINFLT, AC_MAJFLT and AC_SWAPS fields.]) AC_HEADER_EGREP(comp_t.*ac_minflt, sys/acct.h, AC_DEFINE(ACMINFLT_COMPT, , [Define if 's AC_MINFLT field is a COMP_T.])) AC_HEADER_EGREP(comp_t.*ac_mayflt, sys/acct.h, AC_DEFINE(ACMAJFLT_COMPT, , [Define if 's AC_MAJFLT field is a COMP_T.])) AC_HEADER_EGREP(comp_t.*ac_swaps, sys/acct.h, AC_DEFINE(ACSWAPS_COMPT, , [Define if 's AC_SWAPS field is a COMP_T.])) ) ) ) AC_HEADER_EGREP(comp_t, sys/acct.h, AC_DEFINE(HAVE_COMP_T, , [Define if uses the COMP_T type.])) AC_HEADER_EGREP([struct acct_v3], sys/acct.h, AC_DEFINE(HAVE_ACCT_V3, , [Define if has struct acct_v3.])) AC_HEADER_EGREP([struct acctv2], sys/acct.h, AC_DEFINE(HAVE_ACCTV2, , [Define if has struct acctv2.])) ) dnl need to check because AIX 4.2 does not have it dnl AC_CHECK_MEMBERS([struct statfs.f_flags],[],[],[ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif ]) AC_SYS_LARGEFILE dnl dnl check whether _POSIX_SOURCE is required dnl SAMHAIN_POSIX dnl ***************************************** dnl dnl Checks for library functions. dnl dnl ***************************************** AC_FUNC_STRFTIME AC_CHECK_FUNCS(memcmp memcpy memmove memset getpwent endpwent fpurge \ gettimeofday strlcat strlcpy strstr strchr strerror strsignal \ seteuid setreuid setresuid lstat getwd getcwd ptrace \ usleep setpriority getpeereid nanosleep \ strptime basename sched_yield hasmntopt \ inet_aton gethostbyname setutent setrlimit gethostname uname \ initgroups getpagesize \ ttyname fchmod writev mmap tzset \ getsid getpriority getpgid statvfs \ strerror_r getgrgid_r getpwnam_r getpwuid_r \ gmtime_r localtime_r rand_r readdir_r strtok_r \ mincore posix_fadvise inotify_init1 ) AC_CHECK_FUNC(statfs, AC_DEFINE(HAVE_STATFS) statfs="yes", statfs="no") SL_CHECK_VA_COPY AC_CHECK_FUNCS(vsnprintf, [SL_CHECK_VSNPRINTF]) AC_CHECK_MLOCK SH_STRFTIME_Z AC_MSG_CHECKING(how to get filesystem type) fstype=no # The order of these tests is important. AC_TRY_CPP([#include #include ], AC_DEFINE(FSTYPE_STATVFS) fstype=SVR4) if test $fstype = no; then AC_TRY_CPP([#include #include ], AC_DEFINE(FSTYPE_USG_STATFS) fstype=SVR3) fi if test $fstype = no; then AC_TRY_CPP([#include #include ], AC_DEFINE(FSTYPE_AIX_STATFS) fstype=AIX) fi if test $fstype = no; then AC_TRY_CPP([#include ], AC_DEFINE(FSTYPE_MNTENT) fstype=4.3BSD) fi if test $fstype = no; then AC_EGREP_HEADER(f_type;, sys/mount.h, AC_DEFINE(FSTYPE_STATFS) fstype=4.4BSD/OSF) fi if test $fstype = no; then AC_TRY_CPP([#include #include ], AC_DEFINE(FSTYPE_GETMNT) fstype=Ultrix) fi AC_MSG_RESULT($fstype) sh_libsocket= dnl Solaris needs -lsocket and -lnsl. Unisys system includes dnl gethostbyname in libsocket but needs libnsl for socket. AC_CHECK_LIB(nsl, gethostbyname) AC_CHECK_LIB(socket, socket, ac_need_libsocket=1, ac_try_nsl=1) if test x$ac_need_libsocket = x1; then LIBS="$LIBS -lsocket" sh_libsocket="-lsocket" fi if test x$ac_try_nsl = x1; then AC_CHECK_LIB(nsl, gethostbyname, ac_need_libnsl=1) if test x$ac_need_libnsl = x1 then LIBS="$LIBS -lnsl" fi fi AC_SUBST(sh_libsocket) AC_CHECK_LIB(socket, res_search, [ AC_CHECK_LIB(resolv, dn_skipname) AC_CHECK_LIB(resolv, __dn_skipname) if test x$ac_need_libsocket = x1; then : else LIBS="$LIBS -lsocket" fi ], [ AC_CHECK_LIB(resolv, res_search, [ LIBS="$LIBS -lresolv" ], [ AC_CHECK_LIB(resolv, dn_skipname) AC_CHECK_LIB(resolv, __dn_skipname) ]) ]) AC_CHECK_FUNCS( getnameinfo getaddrinfo ) sh_auparse=no if test "x$ac_cv_header_auparse_h" = "xyes" then AC_CHECK_LIB(auparse, auparse_find_field, [ LIBS="$LIBS -lauparse" sh_auparse=yes AC_DEFINE(HAVE_AUPARSE_LIB, 1, [Define if you have the auparse lib]) ]) fi dnl arguments for accept dnl check for Unix98 socklen_t (found on dnl xemacs-patches mailing list, written dnl by Martin Buchholz) dnl dnl On Darwin(MacOSX) socklen_t needs to be dnl an int (see accept man page), on all other dnl unix systems we need a size_t. AC_MSG_CHECKING(for socklen_t) AC_TRY_COMPILE([ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif socklen_t x; ], [],[ AC_MSG_RESULT(yes) AC_DEFINE_UNQUOTED([ACCEPT_TYPE_ARG3],[socklen_t], [type of arg3 of accept]) AC_DEFINE([HAVE_SOCKLEN_T], 1, [Define if you have socklen_t]) ],[ AC_TRY_COMPILE([ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif int accept (int, struct sockaddr *, size_t *); ],[],[ AC_MSG_RESULT(size_t) AC_DEFINE_UNQUOTED([ACCEPT_TYPE_ARG3],[size_t], [type of arg3 of accept]) ], [ AC_MSG_RESULT(int) AC_DEFINE_UNQUOTED([ACCEPT_TYPE_ARG3],[int], [type of arg3 of accept]) ] ) ]) dnl ***************************************** dnl checks for extended attribute or ACL dnl support dnl ***************************************** AC_ARG_ENABLE([selinux], [AS_HELP_STRING([--enable-selinux], [support checking selinux attributes])], [], [enable_selinux=check]) if test "x$enable_selinux" != xno; then sh_CHECK_XATTR fi AC_ARG_ENABLE([posix-acl], [AS_HELP_STRING([--enable-posix-acl], [support checking posix acls])], [], [enable_posix_acl=check]) if test "x$enable_posix_acl" != xno; then sh_CHECK_POSIX_ACL fi dnl ***************************************** dnl checks for typedefs dnl ***************************************** AC_C_LONG_DOUBLE SH_CHECK_TYPEDEF(long long, HAVE_LONG_LONG) SH_CHECK_TYPEDEF(uint16_t, HAVE_UINT16_T) SH_CHECK_TYPEDEF(uint32_t, HAVE_UINT32_T) SH_CHECK_TYPEDEF(uint64_t, HAVE_UINT64_T) if test "$sh_HAVE_LONG_LONG" = "yes"; then AC_CHECK_SIZEOF(unsigned long long, 4) sh_sizeof_unsigned_long_long=`echo "$ac_cv_sizeof_unsigned_long_long" | sed 's%[^0-9]%%g'` if test "$sh_sizeof_unsigned_long_long" = "8"; then AC_DEFINE(HAVE_LONG_LONG_64, 1, [Define if you have 64bit long long]) fi fi AC_CHECK_TYPE(ptrdiff_t, long) AC_TYPE_SIZE_T AC_CHECK_SIZEOF(char *, 4) AC_CHECK_SIZEOF(size_t, 4) AC_CHECK_SIZEOF(unsigned long, 4) AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned short, 2) sh_sizeof_unsigned_long=`echo "$ac_cv_sizeof_unsigned_long" | sed 's%[^0-9]%%g'` if test "$sh_sizeof_unsigned_long" = "4"; then AC_DEFINE(HAVE_LONG_32) fi if test "$sh_sizeof_unsigned_long" = "8"; then AC_DEFINE(HAVE_LONG_64) fi sh_sizeof_unsigned_int=`echo "$ac_cv_sizeof_unsigned_int" | sed 's%[^0-9]%%g'` if test "$sh_sizeof_unsigned_int" = "4"; then AC_DEFINE(HAVE_INT_32) fi sh_sizeof_unsigned_short=`echo "$ac_cv_sizeof_unsigned_short" | sed 's%[^0-9]%%g'` if test "$sh_sizeof_unsigned_short" = "4"; then AC_DEFINE(HAVE_SHORT_32) fi dnl dnl check for 64 bit programming environment dnl SAMHAIN_64 dnl ***************************************** dnl checks for structures dnl ***************************************** AC_STRUCT_TM dnl dnl from e2fsprogs dnl AC_MSG_CHECKING(whether struct stat has a st_flags field) AC_CACHE_VAL(e2fsprogs_cv_struct_st_flags, AC_TRY_COMPILE([#include ], [struct stat stat; stat.st_flags = 0;], [e2fsprogs_cv_struct_st_flags=yes], [e2fsprogs_cv_struct_st_flags=no])) AC_MSG_RESULT($e2fsprogs_cv_struct_st_flags) if test "$e2fsprogs_cv_struct_st_flags" = yes; then AC_MSG_CHECKING(whether st_flags field is useful) AC_CACHE_VAL(e2fsprogs_cv_struct_st_flags_immut, AC_TRY_COMPILE([#include ], [struct stat stat; stat.st_flags |= UF_IMMUTABLE;], [e2fsprogs_cv_struct_st_flags_immut=yes], [e2fsprogs_cv_struct_st_flags_immut=no])) AC_MSG_RESULT($e2fsprogs_cv_struct_st_flags_immut) if test "$e2fsprogs_cv_struct_st_flags_immut" = yes; then AC_DEFINE(HAVE_STAT_FLAGS) fi fi dnl dnl from dbus dnl AC_MSG_CHECKING(for struct cmsgcred) AC_TRY_COMPILE([ #include #include ],[ struct cmsgcred cred; cred.cmcred_pid = 0; ],sh_have_struct_cmsgcred=yes,sh_have_struct_cmsgcred=no) AC_MSG_RESULT($sh_have_struct_cmsgcred) if test x$sh_have_struct_cmsgcred = xyes; then AC_DEFINE(HAVE_STRUCT_CMSGCRED,1,[Have cmsgcred structure]) fi AC_MSG_CHECKING(for struct fcred) AC_TRY_COMPILE([ #include #include #include ],[ struct fcred sockcred; ],sh_have_struct_fcred=yes,sh_have_struct_fcred=no) AC_MSG_RESULT($sh_have_struct_fcred) if test x$sh_have_struct_fcred = xyes; then AC_DEFINE(HAVE_STRUCT_FCRED,1,[Have fcred structure]) fi AC_MSG_CHECKING(for struct sockcred) AC_TRY_COMPILE([ #include #include #include ],[ struct sockcred sockcred; ],sh_have_struct_sockcred=yes,sh_have_struct_sockcred=no) AC_MSG_RESULT($sh_have_struct_sockcred) if test x$sh_have_struct_sockcred = xyes; then AC_DEFINE(HAVE_STRUCT_SOCKCRED,1,[Have sockcred structure]) fi AC_MSG_CHECKING(for SO_PEERCRED) AC_TRY_COMPILE([ #include #include ],[ int test = SO_PEERCRED; ],sh_have_SO_PEERCRED=yes,sh_have_SO_PEERCRED=no) AC_MSG_RESULT($sh_have_SO_PEERCRED) if test x$sh_have_SO_PEERCRED = xyes; then AC_DEFINE(HAVE_SO_PEERCRED,1,[Have SO_PEERCRED define]) fi dnl ***************************************** dnl checks for compiler characteristics dnl ***************************************** AC_C_INLINE AC_C_CONST AC_C_BIGENDIAN AC_C_RESTRICT AM_SA_SIGACTION_WORKS AC_ARG_ENABLE(ssp, [ --disable-ssp disable the GCC stack protector], [], [enable_ssp=yes;] ) if test "x$GCC" = "xyes"; then if test x"${enable_ssp}" = xno; then : else GCC_STACK_PROTECT_LIB GCC_STACK_PROTECT_CC dnl GCC_STACK_CHECK_CC GCC_PIE_CC fi fi dnl ***************************************** dnl dnl checks for system services dnl dnl ***************************************** dnl dnl check for /proc filesystem dnl if test -d "/proc/$$" then AC_DEFINE([HAVE_PROCFS],[1],[Define if you have a proc fs]) fi dnl dnl check for GNU gmp dnl AC_CHECK_LIB(gmp, __gmpz_init, [sh_have_gmp=yes], [sh_have_gmp=no]) if test "x${sh_have_gmp}" = xno then AC_CHECK_LIB(gmp, mpz_init, [sh_have_gmp=yes], [sh_have_gmp=no]) fi if test "x${sh_have_gmp}" = xyes then # LIBS="-lgmp $LIBS" AC_DEFINE(HAVE_LIBGMP, 1, [Have GNU gmp library]) fi AC_CHECK_HEADERS(gmp.h) AC_MSG_CHECKING([for ps]) PS= for ff in /usr/ucb /bin /usr/bin; do if test -x "$ff/ps"; then PS="$ff/ps" AC_MSG_RESULT([$PS]) break fi done if test x$PS = x then AC_MSG_RESULT([no]) AC_MSG_ERROR([Cannot find ps in any of /usr/ucb /bin /usr/bin]) fi AC_DEFINE_UNQUOTED([PSPATH], _("$PS"), [Path to ps]) AC_MSG_CHECKING([how to use ps]) $PS ax >/dev/null 2>&1 if test $? -eq 0; then case "$host_os" in *openbsd*) one=`$PS akx | wc -l` ;; *) one=`$PS ax | wc -l` ;; esac else one=0 fi $PS -e >/dev/null 2>&1 if test $? -eq 0; then two=`$PS -e | wc -l` else two=0 fi if test $one -ge $two then case "$host_os" in *openbsd*) PSARG="akx" ;; *) PSARG="ax" ;; esac else PSARG="-e" fi AC_DEFINE_UNQUOTED([PSARG], _("$PSARG"), [Argument for ps]) AC_MSG_RESULT([$PS $PSARG]) dnl ***************************************** dnl dnl enable features dnl dnl ***************************************** AC_ARG_ENABLE(db-reload, [ --enable-db-reload enable database reload on SIGHUP [[no]]], [ if test "x${enable_db_reload}" = xyes; then AC_DEFINE(RELOAD_DATABASE) fi ] ) AC_ARG_ENABLE(xml-log, [ --enable-xml-log enable XML logfile format [[no]]], [ if test "x${enable_xml_log}" = xyes; then AC_DEFINE(SH_USE_XML) fi ] ) AC_ARG_ENABLE(mail, [ --disable-mail disable the internal SMTP mailer], [ if test "x${enable_mail}" = xno; then : else AC_DEFINE(SH_WITH_MAIL) fi ], [AC_DEFINE(SH_WITH_MAIL)] ) AC_ARG_ENABLE(suid, [ --enable-suid allow suid], [ if test "x${enable_suid}" = xyes; then AC_DEFINE(SH_ALLOW_SUID, [1], [Define if you want to allow suid execution for samhain]) fi ] ) AC_ARG_ENABLE(shellexpand, [ --disable-shellexpand disable shell expansion in config file], [ if test "x${enable_shellexpand}" = xno; then : else AC_DEFINE(SH_EVAL_SHELL, [1], [Define if you want shell expansion in configuration file]) fi ], [AC_DEFINE(SH_EVAL_SHELL, [1], [Define if you want shell expansion in configuration file])] ) AC_ARG_ENABLE(external-scripts, [ --disable-external-scripts disable interface to external scripts], [ if test "x${enableval}" = xno; then : else AC_DEFINE(WITH_EXTERNAL) fi ], [AC_DEFINE(WITH_EXTERNAL)] ) AC_ARG_ENABLE(message-queue, [ --enable-message-queue[[=MODE]] enable SysV message queue [[MODE=0700]]], [ if test "x${ac_cv_header_sys_msg_h}" = "xyes"; then if test "x${enable_message_queue}" = xyes; then AC_DEFINE(WITH_MESSAGE_QUEUE) AC_DEFINE_UNQUOTED(MESSAGE_QUEUE_MODE, 0700) elif test "x${enable_message_queue}" != xno; then echo "${enableval}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([With --enable-message-queue=MODE, MODE must be numeric]) echo "${enableval}" | \ grep ['0[0123456789][0123456789][0123456789]'] >/dev/null 2>&1 || AC_MSG_ERROR([With --enable-message-queue=MODE, MODE must be an octal (0nnn) number]) AC_DEFINE(WITH_MESSAGE_QUEUE) AC_DEFINE_UNQUOTED(MESSAGE_QUEUE_MODE, ${enable_message_queue}) fi else echo echo "**********************************************" echo AC_MSG_WARN([sys/msg.h missing, --enable-message-queue disabled]) echo echo "**********************************************" echo fi ] ) AC_ARG_WITH(cflags, [ --with-cflags additional flags to pass to compiler], [ if test "x$withval" != "xno" ; then CFLAGS="$CFLAGS $withval" fi ] ) AC_ARG_WITH(libs, [ --with-libs additional libraries to link with], [ if test "x$withval" != "xno" ; then LIBS="$LIBS $withval" fi ] ) # # this is from ssh # AC_MSG_CHECKING(whether to use libwrap) LIBWRAP_LIB="" LIBWRAP_INC="" AC_ARG_WITH(libwrap, [ --with-libwrap[=PATH] Compile in libwrap (TCP Wrappers) support], [ AC_MSG_RESULT($withval) case "$withval" in no) ;; ""|yes) LIBWRAP_LIB="-lwrap" ;; *) if test -d "$withval"; then LIBWRAP_LIB="-L$withval -lwrap" changequote(<<, >>)dnl sh_libwrap_inc=`echo ${withval} | sed 's%/[^/][^/]*$%%'` LIBWRAP_INC="-I${sh_libwrap_inc}/include" changequote([, ])dnl else LIBWRAP_LIB="-lwrap" changequote(<<, >>)dnl sh_libwrap_inc=`echo ${withval} | sed 's%/[^/][^/]*$%%'` LIBWRAP_INC="-I${sh_libwrap_inc}" changequote([, ])dnl fi ;; esac if test -n "$LIBWRAP_LIB"; then # OLDLIBS="$LIBS" LIBS="$LIBWRAP_LIB $LIBS" # OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS $LIBWRAP_INC" AC_CHECK_HEADER(tcpd.h, [], [ AC_MSG_ERROR([Could not find tcpd.h for libwrap. You need to install tcp_wrappers.]) ]) AC_TRY_LINK([ #include int allow_severity; int deny_severity; ], [ hosts_access((struct request_info *) 0); ], [ AC_DEFINE(SH_USE_LIBWRAP,1,[Build with tcp wrapper support]) ], [ AC_MSG_ERROR([Could not find the libwrap library.]) ]) fi ], AC_MSG_RESULT(no) ) dnl dnl NETWORK OPTIONS dnl AC_ARG_ENABLE(network, [ --enable-network=[[client|server]] compile client or server [[no]]], [ if test "x$enable_network" = xclient; then mytclient="-DSH_WITH_CLIENT" yulectl_prg= samhainadmin_prg= setpwd_prg="samhain_setpwd" sh_main_prg="samhain" if test "x${sh_have_gmp}" = xyes then LIBS="-lgmp $LIBS" fi dnl AC_CHECK_HEADER(sys/capability.h, dnl [AC_CHECK_LIB(cap, cap_get_proc,,sh_use_lcaps="no")], dnl [sh_use_lcaps="no"]) elif test "x$enable_network" = xserver; then mytclient="-DSH_WITH_SERVER" yulectl_prg="yulectl" samhainadmin_prg="scripts/samhainadmin.pl" setpwd_prg="samhain_setpwd" sh_main_prg="yule" if test "x${sh_have_gmp}" = xyes then LIBS="-lgmp $LIBS" fi sh_use_lcaps="undef" elif test "x$enable_network" = xno; then mytclient="-DSH_STANDALONE" yulectl_prg= samhainadmin_prg= setpwd_prg= sh_main_prg="samhain" dnl AC_CHECK_HEADER(sys/capability.h, dnl [AC_CHECK_LIB(cap, cap_get_proc,,sh_use_lcaps="no")], dnl [sh_use_lcaps="no"]) else AC_MSG_ERROR([With --enable-network=WHAT, WHAT must be client, server, or no]) fi ], [ mytclient="-DSH_STANDALONE" setpwd_prg= yulectl_prg= samhainadmin_prg= sh_main_prg="samhain" dnl AC_CHECK_HEADER(sys/capability.h, dnl [AC_CHECK_LIB(cap, cap_get_proc,,sh_use_lcaps="no")], dnl [sh_use_lcaps="no"]) ], ) AC_SUBST(setpwd_prg) AC_SUBST(yulectl_prg) AC_SUBST(samhainadmin_prg) AC_SUBST(sh_main_prg) AC_SUBST(mytclient) # needed for the rpm spec clmytclient=`echo ${mytclient} | sed s%\-%%` AC_SUBST(clmytclient) sh_no_gcc_static=no AC_ARG_ENABLE(static, [ --enable-static enable static linking [[no]]], [ if test x$enable_static = xyes; then if test x"$mynetbsd" = xyes then tmp_LIBS=`echo $LIBS | sed 's%\-lresolv%%' ` LIBS="${tmp_LIBS}" fi if test x"${sh_auparse}" = xyes then tmp_LIBS=`echo $LIBS | sed 's%\-lauparse%%' ` LIBS="${tmp_LIBS}" fi if test "x$GCC" = "xyes"; then case "$host_os" in *solaris*) AC_MSG_WARN([option --enable-static ignored on Solaris]) ;; *) AC_DEFINE(SH_COMPILE_STATIC, 1, [Define if compiling static]) sh_no_gcc_static=no LDFLAGS="$LDFLAGS -static" ;; esac else AC_DEFINE(SH_COMPILE_STATIC, 1, [Define if compiling static]) sh_no_gcc_static=yes case "$host_os" in *aix*) LDFLAGS="$LDFLAGS -bnso -bI:/lib/syscalls.exp" ;; *hpux*) LDFLAGS="$LDFLAGS -Wl,-a,archive" ;; *osf*) LDFLAGS="$LDFLAGS -non_shared" ;; *irix*) LDFLAGS="$LDFLAGS -non_shared" ;; *sco*) LDFLAGS="$LDFLAGS -dn" ;; *sun*) LDFLAGS="$LDFLAGS -Bstatic" ;; *solaris*) LDFLAGS="$LDFLAGS -Bstatic" ;; *) echo "***********************************************" echo "*" echo "* Don't know how to enable static linking" echo "* with your compiler. Please set the environment" echo "* variable LDFLAGS to:" echo "* ${LDFLAGS} + the static linking flag" echo "* and run configure again" echo "*" echo "***********************************************" ;; esac fi fi ] ) if test x"${mytclient}" = x-DSH_STANDALONE -o x"${mytclient}" = x-DSH_WITH_CLIENT; then dnl For threaded modules ACX_PTHREAD CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" LDFLAGS="$PTHREAD_CFLAGS $LDFLAGS" CC="$PTHREAD_CC" dnl For MODI_TXT CHECK_ZLIB() fi if test x$enable_static = xyes; then : else if test x$sh_use_pie = xyes; then LDFLAGS="$LDFLAGS $PIE_LDFLAGS" CFLAGS="$CFLAGS $PIE_CFLAGS" fi fi AC_CHECK_FUNC(pmap_getmaps, AC_DEFINE([HAVE_PMAP_GETMAPS], [], [Define if pmap_getmaps available]), [],[]) # # this is from the snort configure.in # AC_DEFUN(FAIL_MESSAGE,[ echo echo echo "**********************************************" echo " ERROR: unable to find" $1 echo " checked in the following places" for i in `echo $2`; do echo " $i" done echo "**********************************************" echo exit ]) AC_ARG_WITH(libprelude-prefix, [ --with-libprelude-prefix=PFX Prefix where libprelude is installed (optional)], libprelude_config_prefix="$withval", libprelude_config_prefix="") AC_MSG_CHECKING(whether to use prelude) AC_ARG_WITH(prelude, [ --with-prelude Prelude IDS support [[no]]], [ if test "x${withval}" = "xno"; then AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) if test x$libprelude_config_prefix != x ; then if test x${LIBPRELUDE_CONFIG+set} != xset ; then LIBPRELUDE_CONFIG=$libprelude_config_prefix/bin/libprelude-config fi fi AC_PATH_PROG(LIBPRELUDE_CONFIG, libprelude-config, no) if test x"$LIBPRELUDE_CONFIG" = "xno" ; then HAVE_PRELUDE_CONFIG=no else HAVE_PRELUDE_CONFIG=yes fi dnl AC_CHECK_PROG(HAVE_PRELUDE_CONFIG, libprelude-config, yes, no) if test "$HAVE_PRELUDE_CONFIG" = "yes"; then sh_libprelude_version=`$LIBPRELUDE_CONFIG --version` case "$sh_libprelude_version" in 0.8*) AC_MSG_ERROR([You have Libprelude 0.8, which is too old. Version 0.9.6 or higher is required.]) ;; *) AM_PATH_LIBPRELUDE([0.9.6], [ AC_DEFINE(HAVE_LIBPRELUDE,1,[Have libprelude]) CFLAGS="$CFLAGS $LIBPRELUDE_PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $LIBPRELUDE_LDFLAGS" LIBS="$LIBS $LIBPRELUDE_LIBS" ], [ AC_MSG_ERROR([Could not find libprelude (if you are using --enable-static, the static library libprelude.a might be missing).]) ]) ;; esac else AC_MSG_ERROR([Could not find libprelude-config.]) fi fi ], [ AC_MSG_RESULT(no) ] ) # # partly based on the snort configure.in # AC_ARG_WITH(database, [ --with-database=[[mysql|postgresql|oracle|odbc]] database support [[no]]], [ if test x"$enable_xml_log" != xyes; then AC_MSG_ERROR([With --with-database, --enable-xml-log is required as well.]) fi if test "x${withval}" = "xmysql"; then if test "x$zlib_found" = "x" then CHECK_ZLIB() fi AC_CHECK_PROG(HAVE_MYSQL_CONFIG, mysql_config, yes, no) if test "$HAVE_MYSQL_CONFIG" = "yes"; then sh_mysql_libs="`mysql_config --libs`" sh_mysql_libs="`eval echo ${sh_mysql_libs}`" LIBS="$LIBS ${sh_mysql_libs}" sh_mysql_cflags="`mysql_config --cflags`" sh_mysql_cflags="`eval echo ${sh_mysql_cflags}`" CPPFLAGS="$CPPFLAGS ${sh_mysql_cflags}" else AC_MSG_CHECKING([for MySQL in /usr /usr/local /usr/local/mysql MYSQL_HOME]) mysql_directory="/usr /usr/local /usr/local/mysql ${MYSQL_HOME}" for i in $mysql_directory; do if test -r $i/include/mysql/mysql.h; then MYSQL_DIR=$i MYSQL_INC_DIR=$i/include # we use AC_CHECK_HEADERS to check for mysql/mysql.h fi done if test -z "$MYSQL_DIR"; then for i in $mysql_directory; do if test -r $i/include/mysql.h; then MYSQL_DIR=$i MYSQL_INC_DIR=$i/include fi done fi if test -z "$MYSQL_DIR"; then tmp="" for i in $mysql_directory; do tmp="$tmp $i/include $i/include/mysql" done FAIL_MESSAGE("mysql headers (mysql.h)", $tmp) fi for i in lib lib/mysql; do str="$MYSQL_DIR/$i/libmysqlclient.*" for j in `echo $str`; do if test -r $j; then MYSQL_LIB_DIR="$MYSQL_DIR/$i" break 2 fi done done if test -z "$MYSQL_LIB_DIR"; then for ff in $mysql_directory; do for i in lib lib/mysql; do str="$ff/$i/libmysqlclient.*" for j in `echo $str`; do if test -r $j; then MYSQL_LIB_DIR="$ff/$i" break 3 fi done done done fi if test -z "$MYSQL_LIB_DIR"; then tmp="" for i in $mysql_directory; do tmp="$i/lib $i/lib/mysql" done FAIL_MESSAGE("mysql library libmysqlclient", $tmp) fi AC_MSG_RESULT(yes) LIBS="$LIBS -L${MYSQL_LIB_DIR} -lmysqlclient" # CFLAGS="$CFLAGS -I${MYSQL_INC_DIR}" CPPFLAGS="$CPPFLAGS -I${MYSQL_INC_DIR}" fi AC_DEFINE(WITH_MYSQL) AC_DEFINE(WITH_DATABASE) if test "x$zlib_found" = "xyes" then LIBS="$LIBS -lz -lm" else echo echo " Mysql library was not found or not useable." echo " Possible reasons include:" echo " - an old, incompatible version compiled from source" echo " - on Solaris, libmysql is compiled with the Solaris" echo " compiler, thus the mysql_config script provides" echo " compiler options unsuitable for gcc (move" echo " mysql_config out of your PATH)" echo " For other problems, check config.log for the error" echo " message from the compiler." echo echo " If your mysql libraries are installed in an" echo " unusual place, use --with-libs=-L/path/to/libdirectory" echo " where libdirectory is the directory holding libmysql." if test x"$enable_static" = xyes; then echo " Note that for compiling a static binary, you need" echo " the static libraries, rather than the shared ones." fi echo AC_MSG_ERROR([Could not find libmysql, or it is not useable.]) fi AC_CHECK_HEADERS(mysql/mysql.h) elif test "x${withval}" = "xpostgresql"; then AC_DEFINE(WITH_POSTGRES) AC_DEFINE(WITH_DATABASE) # PGCONF="no" MY_PATH="${PATH}:/usr/local/bin:/usr/local/pgsql/bin" OLD_IFS="$IFS" IFS=":" for ff in ${MY_PATH} do if test -f "$ff/pg_config" then PGCONF="$ff/pg_config" fi done IFS="${OLD_IFS}" # # if test "x${PGCONF}" = "xno" then AC_MSG_CHECKING(for PostgreSQL in /usr/local/pgsql /usr/pgsql /usr/local /usr PGSQL_HOME) pgsql_directory="/usr/local/pgsql /usr/pgsql /usr/local /usr ${PGSQL_HOME}" for i in $pgsql_directory; do if test -r $i/include/pgsql/libpq-fe.h; then PGSQL_INC_DIR=$i/include PGSQL_DIR=$i # use AC_CHECK_HEADERS to check for pgsql/libpq-fe.h fi done if test -z "$PGSQL_DIR"; then for i in $pgsql_directory; do if test -r $i/include/postgresql/libpq-fe.h; then PGSQL_INC_DIR=$i/include PGSQL_DIR=$i fi done fi if test -z "$PGSQL_DIR"; then for i in $pgsql_directory; do if test -r $i/include/libpq-fe.h; then PGSQL_INC_DIR=$i/include PGSQL_DIR=$i fi done fi if test -z "$PGSQL_DIR"; then tmp="" for i in $pgsql_directory; do tmp="$tmp $i/include $i/include/pgsql $i/include/postgresql" done FAIL_MESSAGE("PostgreSQL header file (libpq-fe.h)", $tmp) fi for i in lib lib/pgsql lib/postgresql; do str="$PGSQL_DIR/$i/libpq.*" for j in `echo $str`; do if test -r $j; then PGSQL_LIB_DIR="$PGSQL_DIR/$i" break 2 fi done done if test -z "$PGSQL_LIB_DIR"; then for ff in $pgsql_directory; do for i in lib lib/pgsql lib/postgresql; do str="$ff/$i/libpq.*" for j in `echo $str`; do if test -r $j; then PGSQL_LIB_DIR="$ff/$i" break 3 fi done done done fi if test -z "$PGSQL_LIB_DIR"; then tmp="" for i in $pgsql_directory; do tmp="$i/lib $i/lib/pgsql $i/lib/postgresql" done FAIL_MESSAGE("postgresql library libpq", $tmp) fi AC_MSG_RESULT(yes) LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lm" if test x"$enable_static" = xyes; then LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lcrypt -lm" else LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lm" fi # CFLAGS="$CFLAGS -I${PGSQL_INC_DIR}" CPPFLAGS="$CPPFLAGS -I${PGSQL_INC_DIR}" AC_CHECK_HEADERS(pgsql/libpq-fe.h) AC_CHECK_HEADERS(postgresql/libpq-fe.h) else pg_lib_dir=`${PGCONF} --libdir` if test x"$enable_static" = xyes; then LIBS="$LIBS -L${pg_lib_dir} -lpq -lcrypt -lm" else LIBS="$LIBS -L${pg_lib_dir} -lpq -lm" fi pg_inc_dir=`${PGCONF} --includedir` # CFLAGS="$CFLAGS -I${pg_inc_dir}" CPPFLAGS="$CPPFLAGS -I${pg_inc_dir}" fi elif test "x${withval}" = "xodbc"; then AC_MSG_CHECKING(for odbc in /usr /usr/local ODBC_HOME) odbc_directory="/usr /usr/local" for i in $odbc_directory; do if test -r $i/include/sql.h; then if test -r $i/include/sqlext.h; then if test -r $i/include/sqltypes.h; then ODBC_DIR=$i ODBC_INC_DIR=$i/include fi fi fi done if test -z "$ODBC_DIR"; then tmp="" for i in $odbc_directory; do tmp="$tmp $i/include" done FAIL_MESSAGE("odbc headers (sql.h sqlext.h sqltypes.h)", $tmp) fi str="$ODBC_DIR/lib/libodbc.*" for j in `echo $str`; do if test -r $j; then ODBC_LIB_DIR="$ODBC_DIR/lib" ODBC_LIB="odbc" fi done if test -z "$ODBC_LIB_DIR"; then FAIL_MESSAGE("odbc library (libodbc)", "$ODBC_DIR/lib") fi AC_MSG_RESULT(yes) CPPFLAGS="${CPPFLAGS} -I${ODBC_INC_DIR}" LIBS="${LIBS} -L${ODBC_LIB_DIR} -l$ODBC_LIB" AC_DEFINE(WITH_ODBC) AC_DEFINE(WITH_DATABASE) elif test "x${withval}" = "xoracle"; then AC_MSG_CHECKING(for oracle in ORACLE_HOME /usr/local /usr) oracle_directory="/usr /usr/local ${ORACLE_HOME}" for i in $oracle_directory; do ff=`find $i -name oci.h 2>/dev/null | tail -1` if test "x$ff" = "x"; then : else ORACLE_INC=`dirname $ff` fi fg=`find $i -name libclntsh.so 2>/dev/null | tail -1` if test "x$fg" = "x"; then : else ORACLE_LIB=`dirname $fg` fi done if test -z "$ORACLE_INC"; then tmp="" for i in $oracle_directory; do tmp="$tmp $i" done FAIL_MESSAGE("OCI header file (oci.h) please define ORACLE_INC directory where oci.h resides", $tmp) elif test -z "$ORACLE_LIB"; then tmp="" for i in $oracle_directory; do tmp="$tmp $i" done FAIL_MESSAGE("OCI library file (libclntsh.so) please define ORACLE_LIB directory where libclntsh.so resides", $tmp) else ORACLE_CPP_FLAGS="-I$ORACLE_INC" ORACLE_LIB_DIR="$ORACLE_LIB" AC_MSG_RESULT([$ORACLE_INC $ORACLE_LIB]) CPPFLAGS="${CPPFLAGS} ${ORACLE_CPP_FLAGS}" ORACLE_LIBS="-lclntsh" if test -r $ORACLE_LIB_DIR/libnnz11.so; then ORACLE_LIBS="${ORACLE_LIBS} -lnnz11" fi if test -r $ORACLE_LIB_DIR/libwtc9.so; then ORACLE_LIBS="${ORACLE_LIBS} -lwtc9" elif test -r $ORACLE_LIB_DIR/libwtc8.so; then ORACLE_LIBS="${ORACLE_LIBS} -lwtc8" fi LIBS="${LIBS} -L${ORACLE_LIB_DIR} ${ORACLE_LIBS}" if test "x$GCC" != "xyes"; then CFLAGS="${CFLAGS} -fno-strict-aliasing" fi fi AC_DEFINE(WITH_ORACLE) AC_DEFINE(WITH_DATABASE) else AC_MSG_ERROR([Option --with-database=database used with unsupported database ${withval}]) fi ] ) AC_ARG_WITH(console, [ --with-console=PATH set path to console device [[/dev/console]]], [ if test "x${withval}" != xno; then mycons="$withval" AC_DEFINE_UNQUOTED(DEFAULT_CONSOLE, _("${mycons}") ) fi ]) AC_ARG_WITH(altconsole, [ --with-altconsole=PATH set path to second console device [[none]]], [ if test "x${withval}" != xno; then myaltcons="$withval" else myaltcons="NULL" fi ], [myaltcons="NULL"]) AC_DEFINE_UNQUOTED(ALT_CONSOLE, _("${myaltcons}") ) AC_ARG_WITH(timeserver, [ --with-timeserver=HOST set host address for time server [[none]]], [ if test "x${withval}" != xno; then mytimeserv="$withval" AC_DEFINE(HAVE_NTIME) else mytimeserv="NULL" fi ], mytimeserv="NULL") AC_DEFINE_UNQUOTED(DEFAULT_TIMESERVER, _("${mytimeserv}") ) AC_ARG_WITH(alttimeserver, [ --with-alttimeserver=HOST set address for backup time server [[none]]], [ if test "x${withval}" != xno; then myalttimeserv="$withval" AC_DEFINE(HAVE_NTIME) else myalttimeserv="NULL" fi ], myalttimeserv="NULL") AC_DEFINE_UNQUOTED(ALT_TIMESERVER, _("${myalttimeserv}") ) AC_ARG_ENABLE(login-watch, [ --enable-login-watch watch for login/logout [[no]]], [ if test "x${enable_login_watch}" = xyes; then AC_DEFINE(SH_USE_UTMP) fi ] ) AC_ARG_ENABLE(mounts-check, [ --enable-mounts-check check mount options on filesystems [[no]]], [ if test "x${enable_mounts_check}" = xyes; then AC_DEFINE(SH_USE_MOUNTS) fi ] ) AC_ARG_ENABLE(logfile-monitor, [ --enable-logfile-monitor monitor logfiles [[no]]], [ if test "x${enable_logfile_monitor}" = xyes; then AC_CHECK_HEADER(pcre.h, [ AC_DEFINE(USE_LOGFILE_MONITOR, 1, [Define if you want the logfile monitor module.]) LIBS="-lpcre $LIBS" ], [ AC_CHECK_HEADER(pcre/pcre.h, [ AC_DEFINE(USE_LOGFILE_MONITOR, 1, [Define if you want the logfile monitor module.]) AC_DEFINE(HAVE_PCRE_PCRE_H, 1, [Define if you have pcre/pcre.h.]) LIBS="-lpcre $LIBS" ], AC_MSG_ERROR([The --enable-logfile-monitor option requires libpcre. For compiling the pcre development package is needed.]) ) ] ) AC_CHECK_LIB(pcre, pcre_dfa_exec, [ AC_DEFINE([HAVE_PCRE_DFA_EXEC], 1, [Define if you have pcre_dfa_exec]) ], [ AC_MSG_WARN([pcre_dfa_exec not available]) ]) fi ] ) AC_ARG_ENABLE(process-check, [ --enable-process-check check processes [[no]]], [ if test "x${enable_process_check}" = xyes; then AC_CHECK_LIB([rt], [sched_getparam], sh_lrt=yes, sh_lrt=no) if test x"$sh_lrt" = xyes; then LIBRT=-lrt else LIBRT= fi LIBS="$LIBS $LIBRT" AC_DEFINE(SH_USE_PROCESSCHECK, [1], [Define if you want to check processes]) fi ] ) AC_ARG_ENABLE(port-check, [ --enable-port-check check ports [[no]]], [ if test "x${enable_port_check}" = xyes; then AC_DEFINE(SH_USE_PORTCHECK, [1], [Define if you want to check ports]) fi ] ) AC_ARG_ENABLE(userfiles, [ --enable-userfiles check for users' config files [[no]]], [ if test "x${enableval}" = "xyes"; then AC_DEFINE(SH_USE_USERFILES) fi ] ) AC_ARG_ENABLE(debug, [ --enable-debug enable debug options [[no]]], [ if test "x${enable_debug}" = "xyes"; then if test "x${mydebugflag}" != "xyes"; then AC_DEFINE(MEM_DEBUG) fi AC_DEFINE(WITH_TPT) AC_DEFINE(SL_DEBUG) AC_DEFINE(DNMALLOC_CHECKS, 1, [Debug dnmalloc]) AC_DEFINE(PARANOIA, 0, [Paranoia level for dnmalloc]) AC_DEFINE(SL_FAIL_ON_ERROR) if test "x${myneedg3}" = "xyes"; then mydebugdef="-g3" else mydebugdef="-g" fi mydebugit="yes" elif test "x${enable_debug}" = "xgdb"; then AC_DEFINE(SH_ABORT_ON_ERROR, 1, [Use abort]) if test "x${myneedg3}" = "xyes"; then mydebugdef="-g3" else mydebugdef="-g" fi mydebugit="yes" fi ] ) AC_SUBST(mydebugdef) if test "x${enable_asm_ok}" = "xyes"; then sh_enable_asm=yes else sh_enable_asm=no fi AC_ARG_ENABLE(asm, [ --disable-asm disable asm inline code], [ if test "x${enable_asm}" = xno; then sh_enable_asm=no fi ] ) if test "x${samhain_64_asm}" = xyes; then if test "x${sh_enable_asm}" = xyes; then AC_DEFINE([TIGER_OPT_ASM],1,[Define to use tiger x86_64 optimized assembly]) fi fi AC_ARG_ENABLE(ipv6, [ --disable-ipv6 disable ipv6 support], [ if test "x${enable_ipv6}" = xno; then AC_DEFINE(USE_IPV4,1,[Define if you do not want IPv6]) fi ] ) if test "x${dnmalloc_ok}" = "xyes"; then sh_dnmalloc_enabled=yes else sh_dnmalloc_enabled=no fi AC_ARG_ENABLE(dnmalloc, [ --disable-dnmalloc disable dnmalloc], [ if test "x${enable_dnmalloc}" = xno; then sh_dnmalloc_enabled=no else sh_dnmalloc_enabled=yes fi ] ) dnl Handle the problem that static linking against libc.a on Linux dnl produces the error "multiple definitions of malloc" dnl if test "x$sh_dnmalloc_enabled" = "xyes"; then if test x$enable_static = xyes; then if test "x$sh_no_gcc_static" = "xyes"; then sh_dnmalloc_enabled=no else if test "x$with_gnu_ld" = "xyes"; then LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition" else sh_dnmalloc_enabled=no fi fi fi fi if test "x${sh_dnmalloc_enabled}" = xno; then AC_DEFINE(USE_SYSTEM_MALLOC,1,[Define if you want to use the system malloc]) fi AC_ARG_ENABLE(ptrace, [ --enable-ptrace use anti-debugger options [[no]]], [ if test "x${enable_ptrace}" = xyes; then if test "x$mydebugit" != "xyes"; then AC_DEFINE(SCREW_IT_UP) fi fi ] ) dnl if test "x$GCC" = "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g\ " 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi dnl -W is the older name for -Wextra if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then case "$host_os" in *solaris*) CFLAGS="$CFLAGS -Wall -W -Wno-missing-braces " ;; *) CFLAGS="$CFLAGS -Wall -W " ;; esac fi if test -z "`echo "$CFLAGS" | grep "\-fstrength\-reduce" 2> /dev/null`" then if test -z "`echo "$CFLAGS" | grep "\-fno\-strength\-reduce" 2> /dev/null`" then GCC_FLAG_CHECK([-fno-strength-reduce]) fi fi if test -z "`echo "$CFLAGS" | grep "\-fomit\-frame\-pointer" 2> /dev/null`" then if test -z "`echo "$CFLAGS" | grep "\-fno\-omit\-frame\-pointer" 2> /dev/null`" then GCC_FLAG_CHECK([-fno-omit-frame-pointer]) fi fi fi dnl Test whether gcc supports -Wno-empty-body dnl Suppresses warnings from glibc pthread_cleanup_pop dnl GCC_FLAG_CHECK([-Wno-empty-body]) dnl This one is for clang dnl GCC_FLAG_CHECK([-Wno-invalid-source-encoding]) AC_MSG_CHECKING([which random module to use]) AC_ARG_WITH(rnd, [ --with-rnd=[[egd|unix|dev|default]] random number generator [[default]]], [use_static_rnd=$withval], [use_static_rnd=default] ) if test "$use_static_rnd" = no; then use_static_rnd=default fi case "$use_static_rnd" in egd | dev | unix | default ) AC_MSG_RESULT($use_static_rnd) ;; * ) AC_MSG_RESULT([invalid argument]) AC_MSG_ERROR([Option --with-rnd=module used with unsupported module ${use_static_rnd}]) ;; esac AC_ARG_WITH(egd-socket, [ --with-egd-socket=NAME EGD socket name], egd_socket_name="$withval", egd_socket_name="" ) AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, _("$egd_socket_name") ) dnl dnl See whether the user wants to disable checking for /dev/random try_dev_random=yes case "$use_static_rnd" in dev | default ) try_dev_random=yes ;; egd) AC_DEFINE(HAVE_EGD_RANDOM) try_dev_random=no ;; unix) AC_DEFINE(HAVE_UNIX_RANDOM) try_dev_random=no ;; esac if test "x$try_dev_random" = "xyes"; then AC_MSG_CHECKING(whether /dev/random exists) if test -r "/dev/srandom" && test -c "/dev/srandom"; then AC_DEFINE(HAVE_URANDOM) AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, _("/dev/srandom") ) AC_MSG_RESULT(yes) if test -r "/dev/urandom" && test -c "/dev/urandom"; then AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, _("/dev/urandom") ) fi else if test -r "/dev/random" && test -c "/dev/random"; then AC_DEFINE(HAVE_URANDOM) AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, _("/dev/random") ) AC_MSG_RESULT(yes) if test -r "/dev/urandom" && test -c "/dev/urandom"; then AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, _("/dev/urandom") ) fi else AC_MSG_RESULT(no) AC_DEFINE(HAVE_UNIX_RANDOM) fi fi fi AC_ARG_ENABLE(udp, [ --enable-udp server can listen on port 514/udp [[no]]], [ if test "x${enable_udp}" = xyes; then AC_DEFINE(INET_SYSLOG) fi ] ) myencrypt=yes AC_ARG_ENABLE(encrypt, [ --disable-encrypt disable client/server encryption], [ if test "x${enable_encrypt}" = xno; then myencrypt=no fi ] ) if test "x${myencrypt}" = "xyes"; then AC_DEFINE(SH_ENCRYPT) AC_DEFINE(SH_ENCRYPT_2) fi sh_use_srp_proto=yes AC_ARG_ENABLE(srp, [ --disable-srp disable SRP for authentication], [ if test "x${enable_srp}" = xno; then sh_use_srp_proto=no fi ] ) if test "x${sh_use_srp_proto}" = xyes; then AC_DEFINE(USE_SRP_PROTOCOL) fi AC_ARG_WITH(port, [ --with-port=PORT set port to use for TCP/IP connection [[49777]]], [ echo "${withval}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([For --with-port=PORT, PORT must be numeric.]) myport=${withval} ], [myport="49777"]) AC_DEFINE_UNQUOTED(SH_DEFAULT_PORT, ${myport}) AC_SUBST(myport) AC_ARG_WITH(logserver, [ --with-logserver=HOST set host address for log server [[none]]], [ case "$withval" in *.* | localhost) mylogsrv="$withval" ;; *) mylogsrv="$withval" ;; esac ], [mylogsrv="NULL"]) AC_DEFINE_UNQUOTED(DEFAULT_LOGSERVER, _("${mylogsrv}") ) AC_SUBST(mylogsrv) AC_ARG_WITH(altlogserver, [ --with-altlogserver=HOST set address for backup log server [[none]]], [ case "$withval" in *.* | localhost) myaltlogsrv="$withval" ;; *) myaltlogsrv="$withval" ;; esac ], [myaltlogsrv="NULL"]) AC_DEFINE_UNQUOTED(ALT_LOGSERVER, _("${myaltlogsrv}")) dnl dnl STEALTH OPTIONS dnl nocl_code= xor_code=0 AC_ARG_ENABLE(nocl, [ --enable-nocl=PW no CL parsing unless first CL argument is PW], [ if test "x${enableval}" != "x"; then AC_DEFINE(SH_STEALTH_NOCL) fi if test "x${enableval}" = "xstop" || test "x${enableval}" = "xstart"; then AC_MSG_ERROR([For --enable-nocl=PW start/stop/reload/restart/status are reserved words.]) fi if test "x${enableval}" = "xreload" || test "x${enableval}" = "xrestart"; then AC_MSG_ERROR([For --enable-nocl=PW start/stop/reload/restart/status are reserved words.]) fi if test "x${enableval}" = "xstatus"; then AC_MSG_ERROR([For --enable-nocl=PW start/stop/reload/restart/status are reserved words.]) fi if test "x${enableval}" = "xno"; then AC_MSG_ERROR([With --enable-nocl=PW, the use of --enable-nocl=no is ambiguous.]) fi nocl_code="${enable_nocl}" ] ) AC_DEFINE_UNQUOTED(NOCL_CODE, _("${nocl_code}") ) AC_SUBST(nocl_code) AC_ARG_ENABLE(stealth, [ --enable-stealth=XOR_VAL enable stealth mode [[no]]], [AC_DEFINE(SH_STEALTH) if test "x${enableval}" != "xyes"; then echo "${enableval}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([For --enable-stealth=XOR_VAL, XOR_VAL must be numeric.]) if test "${enableval}" -lt 127 || test "${enableval}" -gt 255; then if test x"${enableval}" = x0 then : else AC_MSG_ERROR([For --enable-stealth=XOR_VAL, XOR_VAL must be in the range 127 to 255.]) fi fi xor_code="${enable_stealth}" else xor_code=0 fi stegin_prg="samhain_stealth" ], [ stegin_prg= ] ) AC_ARG_ENABLE(micro-stealth, [ --enable-micro-stealth=XOR_VAL enable micro stealth mode [[no]]], [ AC_DEFINE(SH_STEALTH) AC_DEFINE(SH_STEALTH_MICRO) if test "x${enableval}" != "xyes"; then echo "${enableval}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([For --enable-micro-stealth=XOR_VAL, XOR_VAL must be numeric.]) if test "${enableval}" -lt 127 || test "${enableval}" -gt 255; then if test x"${enableval}" = x0 then : else AC_MSG_ERROR([For --enable-micro-stealth=XOR_VAL, XOR_VAL must be in the range 127 to 255.]) fi fi xor_code="${enable_micro_stealth}" else xor_code=0 fi ] ) install_name="samhain" INSTALL_NAME="SAMHAIN" AC_ARG_ENABLE(install-name, [ --enable-install-name=NAME name under which to install [[samhain|yule]]], [ if test "x${enableval}" != "xyes"; then install_name="${enableval}" INSTALL_NAME=`echo "${enableval}" | tr [a-z] [A-Z]` else install_name="${sh_main_prg}" INSTALL_NAME=`echo "${sh_main_prg}" | tr [a-z] [A-Z]` fi ], [ install_name="${sh_main_prg}" INSTALL_NAME=`echo "${sh_main_prg}" | tr [a-z] [A-Z]` ] ) need_user_install=0 AC_ARG_ENABLE(identity, [ --enable-identity=USER user if dropping root [[daemon]]], [ if test x"$enableval" = xno; then myident="daemon" else myident="$enableval" fi echo "${myident}" | grep ['[^0123456789]'] >/dev/null 2>&1 || \ AC_MSG_ERROR([With --enable-identity=USER, please supply a username, not a UID.]) myident_uid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${myident}:" | awk -F: '{ print $3; }'` if test x"${myident_uid}" = x; then AC_MSG_WARN([Option --enable-identity used, user ${myident} will be added upon install.]) need_user_install=1 fi ], [ for myident in ${install_name} daemon nobody; do AC_MSG_CHECKING(for user ${myident}) myident_uid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${myident}:" | awk -F: '{ print $3; }'` if test x"${myident_uid}" != x; then AC_MSG_RESULT(yes) break; else AC_MSG_RESULT(no) fi done if test x"${myident_uid}" = x; then myident=${install_name} AC_MSG_WARN([--enable-identity: user ${myident} will be added upon install]) need_user_install=1 fi ]) AC_DEFINE_UNQUOTED(DEFAULT_IDENT, _("${myident}") ) AC_SUBST(myident) AC_SUBST(need_user_install) AC_SUBST(install_name) AC_SUBST(INSTALL_NAME) AC_SUBST(stegin_prg) AC_SUBST(xor_code) AC_DEFINE_UNQUOTED(XOR_CODE, ${xor_code}) AC_DEFINE_UNQUOTED(SH_SYSCALLTABLE, ${sh_syscalltable}) exepack_state0=`${srcdir}/c_random.sh 2>/dev/null` exepack_state1=`${srcdir}/c_random.sh 2>/dev/null` exepack_state2=`${srcdir}/c_random.sh 2>/dev/null` AC_DEFINE_UNQUOTED(EXEPACK_STATE_0, ${exepack_state0}) AC_DEFINE_UNQUOTED(EXEPACK_STATE_1, ${exepack_state1}) AC_DEFINE_UNQUOTED(EXEPACK_STATE_2, ${exepack_state2}) AC_ARG_ENABLE(suidcheck, [ --enable-suidcheck check for suid/sgid files [[no]]], [ if test "x${enableval}" = "xyes"; then AC_DEFINE(SH_USE_SUIDCHK) fi ] ) AC_ARG_ENABLE(base, [ --enable-base=B1,B2 base key (0...2147483647)], [ AC_MSG_CHECKING(base key setting) my_key_A=`echo ${enableval} | awk 'BEGIN{FS=","}{print $1}'` my_key_B=`echo ${enableval} | awk 'BEGIN{FS=","}{print $2}'` AC_MSG_RESULT(${my_key_A} ${my_key_B}) if test "x${my_key_A}" = x; then AC_MSG_ERROR([Option --enable-base=B1,B2 used with invalid first base key (zero length).]) fi if test "x${my_key_B}" = x; then AC_MSG_ERROR([Option --enable-base=B1,B2 used with invalid second base key (zero length).]) fi echo "${my_key_A}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([For --enable-base=B1,B2, B1 and B2 must be numeric in the range 0 to 2147483647.]) echo "${my_key_B}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([For --enable-base=B1,B2, B1 and B2 must be numeric in the range 0 to 2147483647.]) ], [ AC_MSG_CHECKING(base key setting .. collecting entropy) my_key_1=`${srcdir}/c_random.sh 2>/dev/null` my_key_2=`${srcdir}/c_random.sh 2>/dev/null` my_key_3=`${srcdir}/c_random.sh 2>/dev/null` my_key_4=`${srcdir}/c_random.sh 2>/dev/null` my_key_A=`expr $my_key_1 \* 32767` my_key_A=`echo ${my_key_A} | sed 's%^0*%%g' 2>/dev/null` my_key_A=`expr $my_key_A \+ $my_key_2` my_key_B=`expr $my_key_3 \* 32767` my_key_B=`echo ${my_key_B} | sed 's%^0*%%g' 2>/dev/null` my_key_B=`expr $my_key_B \+ $my_key_4` AC_MSG_RESULT(${my_key_A} ${my_key_B}) ] ) AC_SUBST(my_key_A) AC_SUBST(my_key_B) dnl low bytes my_key_1=`expr $my_key_A \% 65536` dnl high bytes my_key_2=`expr $my_key_A \/ 65536` dnl low bytes my_key_3=`expr $my_key_B \% 65536` dnl high bytes my_key_4=`expr $my_key_B \/ 65536` dnl echo ${my_key_1} ${my_key_2} ${my_key_3} ${my_key_4} dnl touch ./sh_MK.h dnl echo "#ifndef SH_MK_H" >> ./sh_MK.h dnl echo "#define SH_MK_H" >> ./sh_MK.h dnl ${srcdir}/c_bits.sh ${my_key_1} MKB >> ./sh_MK.h dnl ${srcdir}/c_bits.sh ${my_key_2} MKA >> ./sh_MK.h dnl ${srcdir}/c_bits.sh ${my_key_3} MKC >> ./sh_MK.h dnl ${srcdir}/c_bits.sh ${my_key_4} MKD >> ./sh_MK.h dnl echo "#endif" >> ./sh_MK.h AC_SUBST(my_key_1) AC_SUBST(my_key_2) AC_SUBST(my_key_3) AC_SUBST(my_key_4) AC_MSG_CHECKING(key position) pos_tf_1=`${srcdir}/c_random.sh 2>/dev/null` pos_tf_2=`expr $pos_tf_1 \% 8` pos_tf=`expr $pos_tf_2 + 1` AC_MSG_RESULT(${pos_tf}) AC_DEFINE_UNQUOTED(POS_TF, ${pos_tf} ) mykeybase=`echo ${my_key_A},${my_key_B}` AC_DEFINE_UNQUOTED(DEFKEY, ${mykeybase} ) AC_SUBST(mykeybase) dnl dnl GPG/PGP options dnl AC_ARG_WITH(gpg, [ --with-gpg=PATH use GnuPG to verify database/config [[no]]], [ if test "x${withval}" != "xno"; then if test "x${cross_compiling}" = xyes; then mygpg="${withval}" else if test -f "${withval}"; then mygpg="${withval}" mychk0=`${withval} --load-extension tiger --print-md TIGER192 ${withval} 2>/dev/null` if test "x$?" != "x0"; then mychktest=no for sampre in ./samhain ./yule /usr/local/sbin/samhain /usr/local/bin/samhain /usr/bin/samhain /usr/sbin/samhain /usr/local/sbin/yule /usr/local/bin/yule /usr/bin/yule /usr/sbin/yule; do if test x"${mychktest}" = xyes then : else if test -f ${sampre} then echo "use existing ${sampre} for gpg checksum" mychk0=`${sampre} -H ${withval} 2>/dev/null` if test "x$?" != "x0"; then if test "x${nocl_code}" != "x"; then mychk0=`echo -H ${withval} | ${sampre} ${nocl_code} 2>/dev/null` if test "x$?" != "x0"; then : else mychk="${mychk0}" mychktest=yes fi fi else mychk="${mychk0}" mychktest=yes fi fi fi done if test x${mychktest} = xno; then AC_MSG_WARN([--with-gpg: cannot determine TIGER192 checksum of ${withval}]) echo "-------------------------------------------------------------" echo " Your gpg binary does not support the TIGER192 checksum, " echo " and I cannot find an existing samhain binary to use instead." echo " You can:" echo " (a) run make to compile a samhain binary, then repeat" echo " ./configure and make" echo " (b) ignore the failure. The checksum of the gpg binary" echo " will not get compiled in, thus allowing an attacker" echo " to replace gpg with a trojan and subverting the gpg" echo " signature verification of configure and database files." echo echo " PLEASE IGNORE THIS MESSAGE IF YOU ALSO USE --with-checksum" echo "-------------------------------------------------------------" fi else mychk="${mychk0}" fi else AC_MSG_ERROR([--with-gpg: cannot find GnuPG PATH=${withval}]) fi fi AC_DEFINE(WITH_GPG) AC_DEFINE_UNQUOTED(DEFAULT_GPG_PATH, _("${mygpg}") ) AC_SUBST(mygpg) fi ] ) AC_ARG_WITH(keyid, [ --with-keyid=KEYID specify KeyID (0x...) for GPG/PGP functions [[none]]], [ if test "x${withval}" != "x"; then echo "${withval}" | awk '{if((length($0)==10)||(length($0)==18)){exit 2}else{exit 0}}' && AC_MSG_ERROR([--with-keyid:${withval} must be "0x" + 8|16 hex digits]) echo "${withval}" | grep ['[^0][^x][^0123456789ABCDEFabcdef]'] >/dev/null 2>&1 && AC_MSG_ERROR([--with-keyid:${withval} must be "0x" + 8|16 hex digits]) mykeyid="$withval" mykeytag="--default-key" else mykeyid="" mykeytag="" fi AC_SUBST(mykeyid) AC_SUBST(mykeytag) ] ) dnl AC_ARG_WITH(pgp, dnl [ --with-pgp=PATH Use PGP to verify database/config (no).], dnl [myppg="$withval" dnl AC_DEFINE(WITH_PGP) dnl AC_DEFINE_UNQUOTED(DEFAULT_PGP_PATH, _("${myppg}") ) dnl ]) AC_ARG_WITH(checksum, [ --with-checksum=CHKSUM compile in gpg/pgp checksum [[yes]]], [ if test "x${withval}" != "xno"; then if test "x${withval}" != "xyes"; then if test "x${mychk}" != "x"; then if test "x${mychk}" != "x${withval}"; then AC_MSG_WARN([--with-checksum: possible gpg CHKSUM problem]) AC_MSG_WARN([--with-checksum: CHKSUM=${withval}]) AC_MSG_WARN([--with-checksum: autodetected=${mychk}]) fi fi mychk="${withval}" else if test "x${mychk}" = "x"; then AC_MSG_ERROR([Option --with-checksum=CHKSUM: checksum CHKSUM of the gpg binary not specified.]) fi fi AC_DEFINE(HAVE_GPG_CHECKSUM) AC_DEFINE_UNQUOTED(GPG_HASH, _("${mychk}") ) echo "${mychk}" | sed 's,.*:,,g' | sed 's, ,,g' | sed 's,\(.\),\1:,g' | awk '{ split($0, arr, ":"); m = length($1)/2; print "#ifndef CHKSUM_H"; print "#define CHKSUM_H"; print "char gpgchk[50];"; for (i=1; i <= m; i++) printf "gpgchk[%d] = %c%s%c;\n", i-1, 39, arr[i], 39; printf "gpgchk[48] = %c%c0%c;\n", 39, 92, 39; print "#endif"; }' > sh_gpg_chksum.h fi ], [ if test "x${mygpg}" != "x"; then if test "x${mychk}" != "x"; then AC_DEFINE(HAVE_GPG_CHECKSUM) AC_DEFINE_UNQUOTED(GPG_HASH, _("${mychk}") ) echo "${mychk}" | sed 's,.*:,,g' | sed 's, ,,g' | sed 's,\(.\),\1:,g' | awk '{ split($0, arr, ":"); m = length($1)/2; print "#ifndef CHKSUM_H"; print "#define CHKSUM_H"; print "char gpgchk[50];"; for (i=1; i <= m; i++) printf "gpgchk[%d] = %c%s%c;\n", i-1, 39, arr[i], 39; printf "gpgchk[48] = %c%c0%c;\n", 39, 92, 39; print "#endif"; }' > sh_gpg_chksum.h fi fi ] ) AC_ARG_WITH(fp, [ --with-fp=FINGERPRINT compile in public key fingerprint [[no]]], [ if test "x${withval}" != "xno"; then if test "x${withval}" != "xyes"; then withval0=`echo ${withval} | sed 's% %%g'` echo "${withval0}" | \ grep ['[^0123456789abcdefABCDEF]'] >/dev/null 2>&1 && AC_MSG_ERROR([In option --with-fp=FINGERPRINT, there is an invalid character(s) in FINGERPRINT=${withval0}.]) sh_len=`echo ${withval0} | wc -c | sed 's% %%g'` sh_len0=`expr ${sh_len} \- 1` if test "x${sh_len0}" = "x40" || test "x${sh_len0}" = "x32" then myfp="${withval0}" AC_DEFINE(USE_FINGERPRINT) AC_DEFINE_UNQUOTED(SH_GPG_FP, _("${myfp}") ) echo "${myfp}" | sed 's,.*:,,g' | sed 's, ,,g' | sed 's,\(.\),\1:,g' | awk '{ split($0, arr, ":"); m = length($1)/2; print "#ifndef FINGERPRINT_H"; print "#define FINGERPRINT_H"; printf "char gpgfp[%d];\n", m+1; for (i=1; i <= m; i++) printf "gpgfp[%d] = %c%s%c;\n", i-1, 39, arr[i], 39; printf "gpgfp[%d] = %c%c0%c;\n", m, 39, 92, 39; print "#endif"; }' > sh_gpg_fp.h else AC_MSG_ERROR([In option --with-fp=FINGERPRINT, the length (${sh_len0}) of FINGERPRINT ${withval0} is incorrect.]) fi else AC_MSG_ERROR([For option --with-fp=FINGERPRINT, FINGERPRINT=yes is invalid, please specify a valid key fingerprint.]) fi fi ]) dnl dnl MAIL OPTIONS dnl AC_ARG_WITH(recipient, [ --with-recipient=ADDR set recipient(s) for e-mail [[none]]], [ withval0=`echo ${withval} | sed 's%,% %g'` for sh_item in ${withval0} do case ${sh_item} in *@localhost) ;; *@*.*) sh_tmp=`echo ${sh_item} | awk '{ if ($1 ~ [/^[a-zA-Z0-9][a-zA-Z0-9\-_\.]*@[a-zA-Z0-9\-\.]+\.([a-zA-Z]+|[0-9]+)$/]) {print 1; } else { print 0}}'` if test "x${sh_tmp}" != "x1" then AC_MSG_ERROR([Option --with-recipient=ADDR used with invalid mail address ${sh_item}.]) fi ;; *) AC_MSG_ERROR([Option --with-recipient=ADDR used with invalid mail address ${sh_item}.]) ;; esac done myrcp="$withval0" ], [myrcp="NULL"]) AC_DEFINE_UNQUOTED(DEFAULT_MAILADDRESS, _("${myrcp}") ) AC_ARG_WITH(sender, [ --with-sender=SENDER set sender for e-mail [[daemon]]], [ mysender="${withval}" ], [ mysender="daemon" ]) AC_DEFINE_UNQUOTED(DEFAULT_SENDER, _("${mysender}") ) dnl dnl PATHS dnl AC_ARG_WITH(trusted, [ --with-trusted=UID Set uid(s) of trusted users [[0]]], [ sh_tmp_test=no sh_tmp=`echo ${withval} | sed 's%,% %g'` for sh_tmp1 in ${sh_tmp} do echo "${sh_tmp1}" | grep ['[^0123456789]'] >/dev/null 2>&1 && AC_MSG_ERROR([Option --with-trusted=UID used with non-numeric UID in ${withval}.]) if test "x${sh_tmp1}" = "x0" then sh_tmp_test=yes fi done if test "x${sh_tmp_test}" = "xno" then withval="0,${withval}" fi mytrust="${withval}" ], [mytrust="0"] ) AC_DEFINE_UNQUOTED(SL_ALWAYS_TRUSTED, ${mytrust} ) AC_SUBST(mytrust) mytmpdir= AC_ARG_WITH(tmp-dir, [ --with-tmp-dir=PFX set directory for temporary files [[HOME]]], [ if test "x${cross_compiling}" = xyes; then mytmpdir="$withval" AC_DEFINE_UNQUOTED(SH_TMPDIR, _("${mytmpdir}") ) else if test -d "${withval}"; then mytmpdir="$withval" AC_DEFINE_UNQUOTED(SH_TMPDIR, _("${mytmpdir}") ) else mytmpdir="$withval" AC_DEFINE_UNQUOTED(SH_TMPDIR, _("${mytmpdir}") ) AC_MSG_WARN([--with-tmp-dir: tmp directory ${withval} does not exist]) fi fi ] ) AC_SUBST(mytmpdir) dnl dnl PATH DEFAULTS dnl if test "x${ac_prefix_set}" = xyes then if test "x${exec_prefix}" = xNONE then exec_prefix="${prefix}" fi if test "x${prefix}" = xOPT then tmp_sbindir="/opt/${install_name}/bin" tmp_sysconfdir="/etc/opt" tmp_mandir="/opt/${install_name}/man" tmp_localstatedir="/var/opt/${install_name}" elif test "x${prefix}" = xUSR then tmp_sbindir="/usr/sbin" tmp_sysconfdir="/etc" tmp_mandir="/usr/share/man" tmp_localstatedir="/var" else tmp_sbindir=`eval echo ${sbindir}` tmp_sysconfdir=`eval echo ${sysconfdir}` tmp_mandir=`eval echo ${mandir}` tmp_localstatedir=`eval echo ${localstatedir}` fi else prefix="" if test "x${ac_exec_prefix_set}" = xyes then tmp_sbindir=`eval echo ${sbindir}` else tmp_sbindir="/usr/local/sbin" fi tmp_sysconfdir="/etc" # share/man -> man (FHS) 11.10.2002 tmp_mandir="/usr/local/man" tmp_localstatedir="/var" fi if test "x${ac_sbindir_set}" = xyes then : else sbindir=`eval echo ${tmp_sbindir}` fi if test "x${ac_sysconfdir_set}" = xyes then : else sysconfdir=`eval echo ${tmp_sysconfdir}` fi if test "x${ac_mandir_set}" = xyes then : else mandir=`eval echo ${tmp_mandir}` fi if test "x${ac_localstatedir_set}" = xyes then : else localstatedir=`eval echo ${tmp_localstatedir}` fi AC_ARG_WITH(config-file, [ --with-config-file=FILE configuration file [[/etc/{install_name}rc]]], [ myconffile="${withval}" changequote(<<, >>)dnl tmp=`echo ${withval} | sed 's%^REQ_FROM_SERVER%%'` sysconfdir=`echo ${tmp} | sed 's%/[^/][^/]*$%%'` myrpmconffile="${tmp}" changequote([, ])dnl ], [ myconffile="${sysconfdir}/${install_name}rc" myrpmconffile="${myconffile}" ] ) AC_DEFINE_UNQUOTED(DEFAULT_CONFIGFILE, _("${myconffile}") ) AC_SUBST(myconffile) AC_SUBST(myrpmconffile) AC_ARG_WITH(log-file, [ --with-log-file=FILE path of log file [[/var/log/{install_name}_log]]], [ mylogfile="$withval" changequote(<<, >>)dnl mylogdir=`echo ${withval} | sed 's%/[^/][^/]*$%%'` changequote([, ])dnl ], [ if test "x${mytclient}" = "x-DSH_WITH_SERVER"; then mylogfile="${localstatedir}/log/${install_name}/${install_name}_log" mylogdir="${localstatedir}/log/${install_name}" else mylogfile="${localstatedir}/log/${install_name}_log" mylogdir="${localstatedir}/log" fi ] ) AC_DEFINE_UNQUOTED(DEFAULT_ERRFILE, _("${mylogfile}") ) AC_DEFINE_UNQUOTED(DEFAULT_LOGDIR, _("${mylogdir}") ) AC_SUBST(mylogfile) AC_SUBST(mylogdir) AC_ARG_WITH(pid-file, [ --with-pid-file=FILE set path of pid file [[/var/run/{install_name}.pid]]], [ mylockfile="$withval" changequote(<<, >>)dnl mylockdir=`echo ${withval} | sed 's%/[^/][^/]*$%%'` changequote([, ])dnl ], [ if test -h /var/run && test -d /run; then mylockfile="/run/${install_name}.pid" mylockdir="/run" else mylockfile="${localstatedir}/run/${install_name}.pid" mylockdir="${localstatedir}/run" fi ] ) AC_DEFINE_UNQUOTED(DEFAULT_ERRLOCK, _("${mylockfile}") ) AC_DEFINE_UNQUOTED(DEFAULT_PIDDIR, _("${mylockdir}") ) AC_SUBST(mylockfile) AC_SUBST(mylockdir) AC_ARG_WITH(state-dir, [ --with-state-dir=PFX set state data directory [[/var/lib/{install_name}]]], [ mydataroot="$withval" ], [ mydataroot="${localstatedir}/lib/${install_name}" ] ) AC_ARG_WITH(data-file, [ --with-data-file=FILE set path of data file], [ mydatafile="$withval" changequote(<<, >>)dnl tmp=`echo ${withval} | sed 's%^REQ_FROM_SERVER%%'` mydataroot=`echo ${tmp} | sed 's%/[^/][^/]*$%%'` myrpmdatafile="${tmp}" changequote([, ])dnl if test x"${tmp}" = x then echo "No local path in data file ${withval}" echo "This will not work for initializing the database." if test x"${withval}" = xREQ_FROM_SERVER then echo "It should be REQ_FROM_SERVER/some/local/path" fi AC_MSG_ERROR([Option --with-data-file=FILE used with invalid path ${withval}.]) fi ], [ mydatafile="${mydataroot}/${install_name}_file" myrpmdatafile="${mydatafile}" ]) AC_DEFINE_UNQUOTED(DEFAULT_DATA_FILE, _("${mydatafile}") ) AC_SUBST(mydatafile) AC_SUBST(myrpmdatafile) AC_DEFINE_UNQUOTED(DEFAULT_DATAROOT, _("${mydataroot}") ) AC_SUBST(mydataroot) AC_DEFINE_UNQUOTED(DEFAULT_QDIR, _("${mydataroot}/.quarantine") ) AC_SUBST(myqdir) AC_ARG_WITH(html-file, [ --with-html-file=FILE set path of html file,], [ myhtmlfile="$withval" ], [ myhtmlfile="${mylogdir}/${install_name}.html" ]) AC_DEFINE_UNQUOTED(DEFAULT_HTML_FILE, _("${myhtmlfile}") ) AC_SUBST(myhtmlfile) mydefargs=$ac_configure_args # if test -z "`echo "$mydefargs" | grep "\-\-enable\-static" 2> /dev/null`" # then # mydefargs="--enable-static $mydefargs" # fi if test -z "`echo "$mydefargs" | grep "\-\-enable\-base" 2> /dev/null`" then mydefargs="--enable-base=${mykeybase} $mydefargs" fi AC_SUBST(mydefargs) AC_DEFINE_UNQUOTED(SH_INSTALL_DIR, _("${sbindir}")) AC_DEFINE_UNQUOTED(SH_INSTALL_PATH, _("${sbindir}/${install_name}")) AC_DEFINE_UNQUOTED(SH_INSTALL_NAME, _("${install_name}")) AC_CONFIG_HEADER(config.h) AC_OUTPUT( [ Makefile samhain-install.sh init/samhain.startLSB init/samhain.startLinux init/samhain.startGentoo init/samhain.startFreeBSD init/samhain.startSolaris init/samhain.startHPUX init/samhain.startIRIX init/samhain.startMACOSX samhain.spec rules.deb rules.deb-light hp_ux.psf scripts/logrotate scripts/samhain.spec scripts/redhat_i386.client.spec scripts/samhain.ebuild scripts/samhain.ebuild-light scripts/samhainadmin.pl scripts/yuleadmin.pl scripts/check_samhain.pl deploy.sh ], [ echo timestamp > stamp-h chmod +x samhain-install.sh chmod +x scripts/samhainadmin.pl chmod +x scripts/yuleadmin.pl chmod +x scripts/check_samhain.pl ] ) chmod +x deploy.sh if test "x${cross_compiling}" = xyes then echo "--------------------------------------------------------------" echo echo "You are using a cross-compiler. The following system dependent" echo "values may have been set to default values that may be" echo "incorrect for your target system: " echo echo "ac_cv_c_bigendian bigendian byte order ${ac_cv_c_bigendian}" echo "ac_cv_c_long_double long double exists ${ac_cv_c_long_double}" echo "ac_cv_sizeof_char_p size of pointer to char ${ac_cv_sizeof_char_p}" echo "ac_cv_sizeof_char_p size of size_t ${ac_cv_sizeof_size_t}" echo "ac_cv_sizeof_unsigned_int size of unsigned int ${ac_cv_sizeof_unsigned_int}" echo "ac_cv_sizeof_unsigned_long size of unsigned long ${ac_cv_sizeof_unsigned_long}" echo "ac_cv_sizeof_unsigned_short size of unsigned short ${ac_cv_sizeof_unsigned_short}" echo echo "If these values are incorrect, change them in the file " echo "config.cache and run configure again." echo echo "--------------------------------------------------------------" fi if test x${silent} != xyes then # A=`eval echo ${sbindir}` ; A=`eval echo ${A}` # B=`eval echo ${myconffile}` ; B=`eval echo ${B}` # C=`eval echo ${mandir}` ; C=`eval echo ${C}` # D=`eval echo ${mylockfile}` ; D=`eval echo ${D}` # E=`eval echo ${mylogfile}` ; E=`eval echo ${E}` # F=`eval echo ${mydataroot}` ; F=`eval echo ${F}` echo echo " samhain has been configured as follows:" echo " System binaries: ${sbindir}" echo " Configuration file: ${myconffile}" echo " Manual pages: ${mandir}" echo " Data directory: ${mydataroot}" echo " Database file: ${mydatafile}" echo " PID file: ${mylockfile}" echo " Log file: ${mylogfile}" echo " Base key: ${mykeybase}" if test x"$mykeyid" != x then echo " target GPG/PGP key: ${mykeyid}" fi echo if test x"$mytclient" = x"-DSH_WITH_SERVER" then echo " Selected rc file: yulerc" else echo " Selected rc file: samhainrc.${selectconfig}" fi fi samhain-4.1.4/config.sub0000755000175000017500000010577512615253270012066 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-09-11' # 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 3 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, see . # # 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. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # 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. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # 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 1992-2014 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 ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # 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 ;; * ) 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* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) 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 | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -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 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -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/'` ;; -sco5v6*) # 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*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -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. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # 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. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # 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 ;; abacus) basic_machine=abacus-unknown ;; 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 ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; 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 ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; 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 | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; 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*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 ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; 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 ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; 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 ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) 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/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-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 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; 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=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; 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 ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-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 ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; 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 ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) 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 ;; *-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. -auroraux) os=-auroraux ;; -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* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -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 ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -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 ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -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 score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. 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 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-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 ;; -cnk*|-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 ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: samhain-4.1.4/test/0000755000175000017500000000000012705513446011127 500000000000000samhain-4.1.4/test/testit.sh0000755000175000017500000000161312615253277012726 00000000000000#!/bin/sh # if test x$UID != x -a x$UID != x0; then TRUST="--with-trusted=0,2,$UID" else TRUST="--with-trusted=0,2,1000" fi export TRUST # PW_DIR=`pwd`; export PW_DIR RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE # OPTIONS="\ --enable-db-reload \ --enable-suidcheck \ --enable-login-watch \ --enable-mounts-check \ --enable-logfile-monitor \ --enable-process-check \ --enable-port-check \ --enable-xml-log \ --enable-userfiles \ --disable-shellexpand \ --disable-ipv6 \ " ./configure --quiet $TRUST \ --prefix=$PW_DIR \ --localstatedir=$PW_DIR \ --with-config-file=$RCFILE \ --with-log-file=$LOGFILE \ --with-pid-file=$PW_DIR/.samhain_lock \ --with-data-file=$PW_DIR/.samhain_file $OPTIONS if [ $? -ne 0 ]; then echo "Configure failed" exit 1 fi make samhain if [ $? -ne 0 ]; then echo "Make failed" exit 1 fi samhain-4.1.4/test/testrun_2f.sh0000775000175000017500000002406312615253277013513 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE RCFILE="$PW_DIR/testrc_2"; export RCFILE SERVER_BUILDOPTS="--quiet $TRUST --enable-network=server --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER$PW_DIR/testrc_2 --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-logserver=${SH_LOCALHOST} --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --enable-debug=gdb"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="--quiet $TRUST --enable-network=client --enable-srp --prefix=$PW_DIR --with-tmp-dir=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER$RCFILE --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --enable-debug"; export CLIENT_BUILDOPTS do_test_2_f () { [ -z "$verbose" ] || { echo; echo "${S}Start Server${E}: ./yule -l info -p none &"; echo; } rm -f test_log_valgrind # SetSocketAllowUid=$(id -u) # if test -f /usr/xpg4/bin/id; then MY_ID=$(/usr/xpg4/bin/id -u) else MY_ID=$(id -u) fi # sed -i -e "s/SetSocketAllowUid=0/SetSocketAllowUid=${MY_ID}/g" $RCFILE # Start server # ${VALGRIND} ./yule -l info -p none >/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -t check --foreground --forever .. &"; echo; } ${VALGRIND} ./samhain.new -t check -D -p none -l none -e info --bind-address=127.0.0.1 --server-host=localhost >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "starting samhain.new"; else [ -z "$quiet" ] && log_msg_fail "starting samhain.new"; kill $PROC_Y return 1 fi five_sec_sleep PROC_S=$( ps aux | grep samhain.new | grep -v grep | awk '{ print $2; }' ) for ff in 1 2; do five_sec_sleep done egrep "File check completed" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; kill $PROC_S; kill $PROC_Y; return 1 fi NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (1)"; kill $PROC_S; kill $PROC_Y; return 1 fi # # >>> (1) Send SIGTTOU to force a second scan, # >>> and verify that it was done # kill -TTOU $PROC_S if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Kill -TTOU"; kill $PROC_S; kill $PROC_Y; return 1 fi for ff in 1 2; do five_sec_sleep done NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "sigttou"; NR=$( egrep "POLICY" $LOGFILE | wc -l ) if [ $NR -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (3)"; kill $PROC_S; kill $PROC_Y; return 1 fi # # >>> (2) Modify the file system # UUID=$(uuidgen) mkdir /tmp/testrun_samhain/$UUID if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "mkdir"; kill $PROC_S; kill $PROC_Y; return 1 fi kill -TTOU $PROC_S if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Kill -TTOU (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi for ff in 1 2; do five_sec_sleep done NR=$( egrep "POLICY" $LOGFILE | wc -l ) if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (4)"; kill $PROC_S; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "/tmp/testrun_samhain modified"; kill $PROC_S; five_sec_sleep rm -f ./.samhain_file rm -f ./file.${SH_LOCALHOST} rm -f "./file.${ALTHOST}" rm ./.samhain_log rm -f ./.samhain_lock # # >>> (3) Re-init the database # ./samhain.new -t init -p none if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "init (2) .."; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "init (2) .."; # # >>> (4) Re-start Samhain with delay # sed --in-place -e 's/SetUdpActive=no/StartupLoadDelay=10/g' ./rc.${SH_LOCALHOST} if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "sed (1) .."; kill $PROC_Y; return 1 fi sed --in-place -e 's/SetUdpActive=no/StartupLoadDelay=10/g' "./rc.${ALTHOST}" if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "sed (2) .."; kill $PROC_Y; return 1 fi ${VALGRIND} ./samhain.new -t check -D -p none -l none -e info --bind-address=127.0.0.1 --server-host=localhost >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "starting samhain.new (2)"; else [ -z "$quiet" ] && log_msg_fail "starting samhain.new (2)"; kill $PROC_Y return 1 fi five_sec_sleep PROC_S=$( ps aux | grep samhain.new | grep -v grep | awk '{ print $2; }' ) # # >>> (5) Copy database to server after Samhain startup # >>> verifies that StartupLoadDelay works # if test -f ./.samhain_file; then mv ./.samhain_file ./file.${SH_LOCALHOST} chmod 644 ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` cp ./file.${SH_LOCALHOST} "./file.${ALTHOST}" 2>/dev/null chmod 644 ./file.${ALTHOST} else [ -z "$verbose" ] || log_msg_fail "baseline file .."; kill $PROC_S; kill $PROC_Y; return 1 fi for ff in 1 2 3; do five_sec_sleep done NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (5)"; kill $PROC_S; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "file check after delay"; NR=$( egrep "POLICY" $LOGFILE | wc -l ) if [ $NR -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (6)"; kill $PROC_S; kill $PROC_Y; return 1 fi kill $PROC_S; kill $PROC_Y return 0 } testrun2f_internal () { [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo; } # # [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure ${CLIENT_BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # save binary and build server # cp samhain samhain.build || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure ${SERVER_BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi ##################################################################### # # rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} rm -f "./rc.${ALTHOST}" rm -f "./file.${ALTHOST}" cp ${SCRIPTDIR}/testrc_2.in testrc_2 sed --in-place -e 's,file = /tmp,file = /tmp/testrun_samhain,g' testrc_2 mkdir /tmp/testrun_samhain 2>/dev/null ./samhain.build -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi # Create a password SHPW=`./yule -G` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi # Set in client ./samhain_setpwd samhain.build new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd samhain.build new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd samhain.build new $SHPW"; return 1 fi mv samhain.build.new samhain.new || return 1 rm -f ./.samhain_log* rm -f ./.samhain_lock SHCLT=`./yule -P $SHPW` if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "yule -P $SHPW"; else [ -z "$quiet" ] && log_msg_fail "yule -P $SHPW"; return 1 fi SHCLT1=`echo "${SHCLT}" | sed s%HOSTNAME%${SH_LOCALHOST}%` AHOST=`find_hostname` SHCLT2=`echo "${SHCLT}" | sed s%HOSTNAME%${AHOST}%` echo $SHCLT1 >> testrc_2 echo $SHCLT2 >> testrc_2 cp ./testrc_2 ./rc.${SH_LOCALHOST} mv ./.samhain_file ./file.${SH_LOCALHOST} chmod 644 ./rc.${SH_LOCALHOST} chmod 644 ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` cp ./testrc_2 "./rc.${ALTHOST}" cp ./file.${SH_LOCALHOST} "./file.${ALTHOST}" 2>/dev/null chmod 644 ./rc.${ALTHOST} chmod 644 ./file.${ALTHOST} echo $SHPW > ./testpw } MAXTEST=1; export MAXTEST testrun2f () { log_start "RUN CLIENT/SERVER CASE ONE"; # if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi # SH_LOCALHOST=$1; export SH_LOCALHOST # testrun2f_internal do_test_2_f if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Case One Change Management Integration"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Case One Change Management Integration"; fi # log_end "RUN CLIENT/SERVER CASE ONE" } samhain-4.1.4/test/testhash.sh0000755000175000017500000001065312615253277013241 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE MAXTEST=2; export MAXTEST testhash () { log_start "HASH FUNCTION" C_LOGFILE="" ls /lib/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " else ls /usr/lib/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " else ls /usr/lib/*/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " else ls /usr/local/lib/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " fi fi fi fi if [ x"${C_LOGFILE}" = x ]; then log_msg_ok "Not testing --enable-logfile-monitor"; fi # # test standalone compilation # TEST="${S}standalone agent${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --enable-debug=gdb --quiet $TRUST --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file --enable-db-reload '--enable-login-watch' '--enable-mounts-check' ${C_LOGFILE} '--enable-port-check' '--enable-process-check' '--enable-message-queue' '--enable-suidcheck' '--disable-dnmalloc' # fail=0 # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>> test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; fail=1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; fail=1 fi # if [ $fail -eq 1 ]; then [ -z "$quiet" ] && log_fail 1 ${MAXTEST}; return 1 fi # echo "Test results of the TIGER hash algorithm" > testhash.tmp echo >> testhash.tmp echo "(use samhain -H string to test)" >> testhash.tmp echo >> testhash.tmp ./samhain -H "" >> testhash.tmp ./samhain -H "abc" >> testhash.tmp ./samhain -H "Tiger" >> testhash.tmp ./samhain -H "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" >> testhash.tmp ./samhain -H "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" >> testhash.tmp ./samhain -H "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" >> testhash.tmp ./samhain -H "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge." >> testhash.tmp ./samhain -H "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996." >> testhash.tmp ./samhain -H "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" >> testhash.tmp # RESU=`diff testhash.tmp ${SCRIPTDIR}/testtiger.txt 2>/dev/null` if test "x${RESU}" = "x"; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST}; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST}; return 1 fi # # # TEST="${S}files${E}" # case $SCRIPTDIR in /*) testpath="${SCRIPTDIR}/testtiger.txt";; *) testpath="`pwd`/${SCRIPTDIR}/testtiger.txt";; esac # RESU=`./samhain -H ${testpath}` # if test x"$RESU" = x"${testpath}: 8125E439 4E7E20F9 24FD8E37 BC4D90C7 FC67F40C 1681F05D"; then [ -z "$quiet" ] && log_ok 2 ${MAXTEST}; else [ -z "$quiet" ] && log_fail 2 ${MAXTEST}; return 1 fi # log_end "HASH FUNCTION" return 0 } samhain-4.1.4/test/testrun_1d.sh0000755000175000017500000001311012615253277013475 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # BUILDOPTS="--quiet $TRUST --enable-xml-log --enable-process-check --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" export BUILDOPTS MAXTEST=3; export MAXTEST PROCPOLICY_3=" [ReadOnly] file=${BASE} [ProcessCheck] ProcessCheckActive = yes ProcessCheckPsPath = ${PW_DIR}/${SCRIPTDIR}/testrun_1d.sh ProcessCheckPsArg = --fake ProcessCheckMaxPid = 67000 " chk_procdata_3 () { one_sec_sleep egrep 'CRIT.*POLICY \[Process\] Fake pid: 66666[[:space:]]' $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Fake pid"; return 1 fi egrep 'CRIT.*POLICY \[Process\] Fake pid: [012345789]+[[:space:]]' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "Fake pids incorrect"; return 1 fi } PROCPOLICY_2=" [ReadOnly] file=${BASE} [ProcessCheck] ProcessCheckActive = yes " chk_procdata_2 () { one_sec_sleep egrep 'CRIT.*POLICY \[Process\] Hidden pid' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "Hidden pids (ps)"; return 1 fi } PROCPOLICY_1=" [ReadOnly] file=${BASE} [ProcessCheck] ProcessCheckActive = yes ProcessCheckPsPath = ${PW_DIR}/${SCRIPTDIR}/testrun_1d.sh ProcessCheckPsArg = --hide " chk_procdata_1 () { one_sec_sleep egrep 'CRIT.*POLICY \[Process\] Hidden pid: [[:digit:]][[:space:]]' $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Hidden pids"; return 1 fi egrep 'CRIT.*POLICY \[Process\] Hidden pid: [[:digit:]][[:digit:]]+[[:space:]]' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "Hidden pids incorrect"; return 1 fi } prep_procpolicy () { test -f "${RCFILE}" || touch "${RCFILE}" eval echo '"$'"PROCPOLICY_$1"'"' >>"${RCFILE}" } testrun_internal_1d () { [ -z "$verbose" ] || echo Working directory: $PW_DIR [ -z "$verbose" ] || { echo MAKE is $MAKE; echo; } # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } if test -r "Makefile"; then $MAKE distclean >/dev/null fi tcount=1 ${TOP_SRCDIR}/configure ${BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Running test suite${E}"; echo; } POLICY=`eval echo '"$'"PROCPOLICY_$tcount"'"'` until [ -z "$POLICY" ] do prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_procpolicy ${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi for iseq in 0 1 2 3 4 5 6 7 8 9; do rm -f "$LOGFILE" if [ $errval -eq 0 ]; then run_check info check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval chk_procdata_${tcount} check_err $? ${tcount}; errval=$? fi done # if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi let "tcount = tcount + 1" >/dev/null POLICY=`eval echo '"$'"PROCPOLICY_$tcount"'"'` done return 0 } testrun1d () { log_start "RUN STANDALONE W/PROCESSCHECK" testrun_internal_1d log_end "RUN STANDALONE W/PROCESSCHECK" return 0 } proc_pspath () { PS=ps for ff in /usr/ucb /bin /usr/bin; do if test -x "$ff/ps"; then PS="$ff/ps" break fi done echo "$PS" } proc_psarg () { OS=`uname -s` case $OS in *Linux*|*linux*) PSARG="-eT";; *OpenBSD*) PSARG="akx";; *) PS=`proc_pspath` $PS ax >/dev/null 2>&1 if test $? -eq 0; then one=`$PS ax | wc -l` else one=0 fi $PS -e >/dev/null 2>&1 if test $? -eq 0; then two=`$PS -e | wc -l` else two=0 fi if test $one -ge $two then PSARG="ax" else PSARG="-e" fi ;; esac echo "$PSARG" } proc_hide() { PSPATH=`proc_pspath` PSARG=`proc_psarg` "${PSPATH}" "${PSARG}" | egrep -v '^[[:space:]]*[[:digit:]]{1}[[:space:]]+' } proc_fake() { FAKE_PID=2 PSPATH=`proc_pspath` PSARG=`proc_psarg` "${PSPATH}" "${PSARG}" if [ x"${PSARG}" = x-eT ]; then echo "66666 66666 pts/2 S 0:14 THIS_IS_FAKE" else echo "66666 pts/2 S 0:14 THIS_IS_FAKE" fi } if [ "x$1" = "x--hide" ]; then proc_hide; exit 0; fi if [ "x$1" = "x--fake" ]; then proc_fake; exit 0; fi samhain-4.1.4/test/test.sh0000755000175000017500000005347412615253277012405 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # ----------------------------------------------------------------------- # Be Bourne compatible # ----------------------------------------------------------------------- if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi # ----------------------------------------------------------------------- # Make sure we support functions (from the autoconf manual) # ----------------------------------------------------------------------- TSHELL="${TSHELL-/bin/sh}" if test x"$1" = "x--re-executed" then shift elif "$TSHELL" -c 'foo () { (exit 0); exit 0; }; foo' >/dev/null 2>&1 then : else for cmd in sh bash ash bsh ksh zsh sh5; do X="$PATH:/bin:/usr/bin:/usr/afsws/bin:/usr/ucb:/usr/xpg4/bin"; OLD_IFS=${IFS} IFS=':'; export IFS for dir in $X; do shell="$dir/$cmd" if (test -f "$shell" || test -f "$shell.exe") then if "$shell" -c 'foo () { (exit 0); exit 0; }; foo' >/dev/null 2>&1 then TSHELL="$shell"; export TSHELL IFS=${OLD_IFS}; export IFS exec "$shell" "$0" --re-executed ${1+"$@"} fi fi done IFS=${OLD_IFS}; export IFS done echo "-----------------------------------------------------------------" echo "ERROR: Unable to locate a shell interpreter with function support" >&2 echo "-----------------------------------------------------------------" { (exit 1); exit 1; } fi # ----------------------------------------------------------------------- # Make sure we support 'let' (from the autoconf manual) # ----------------------------------------------------------------------- TSHELL="${TSHELL-/bin/sh}" if test x"$1" = "x--re-run" then shift elif "$TSHELL" -c 'a=5; let "a = a + 5"' >/dev/null 2>&1 then : else for cmd in sh bash ash bsh ksh zsh sh5; do X="$PATH:/bin:/usr/bin:/usr/afsws/bin:/usr/ucb:/usr/xpg4/bin"; OLD_IFS=${IFS} IFS=':'; export IFS for dir in $X; do shell="$dir/$cmd" if (test -f "$shell" || test -f "$shell.exe") then if "$shell" -c 'foo () { (exit 0); exit 0; }; foo' >/dev/null 2>&1 then if "$shell" -c 'a=5; let "a = a + 5"' >/dev/null 2>&1 then TSHELL="$shell"; export TSHELL IFS=${OLD_IFS}; export IFS exec "$shell" "$0" --re-run ${1+"$@"} fi fi fi done IFS=${OLD_IFS}; export IFS done echo "-----------------------------------------------------------------" echo "ERROR: Unable to locate a shell interpreter with support for 'let'" >&2 echo "-----------------------------------------------------------------" { (exit 1); exit 1; } fi umask 0022 isok=`test -t 1 2>&1 | wc -c` if [ "$isok" -eq 0 ]; then test -t 1 isok=$? fi # The following two are the ANSI sequences for start and end embolden if [ x"$isok" = x0 ]; then case $TERM in vt*|ansi*|con*|xterm*|linux*|screen*|rxvt*) S='' R= G= B= E= ;; *) S= R= G= B= E= ;; esac fi usage() { echo "test.sh [options] [hostname]" echo " [-q|--quiet|-v|--verbose] [-s|--stoponerr] [-n|--no-cleanup]" echo " [--srcdir=top_srcdir] [--color=always|never|auto]" echo echo " ${S}test.sh 1${E} -- Compile with many different options" echo " ${S}test.sh 2${E} -- Hash function (testrc_1)" echo " ${S}test.sh 3${E} -- Standalone init/check" echo " ${S}test.sh 4${E} -- Microstealth init/check" echo " ${S}test.sh 5${E} -- External program call (testrc_1ext.in)" echo " ${S}test.sh 6${E} -- Controlling the daemon" echo " ${S}test.sh 7${E} -- GnuPG signed files / prelude log" echo " ${S}test.sh 8${E} -- Suidcheck" echo " ${S}test.sh 9${E} -- Process check" echo " ${S}test.sh 10${E} -- Port check" echo " ${S}test.sh 11${E} -- CL verify option" echo " ${S}test.sh 12${E} -- CL create DeltaDB" echo " ${S}test.sh 13${E} -- CL create/verify partial DB" echo " ${S}test.sh 20${E} -- Test c/s init/check (testrc_2.in)" echo " ${S}test.sh 21${E} -- Test full c/s init/check (testrc_2.in)" echo " ${S}test.sh 22${E} -- Test full c/s w/gpg (testrc_2.in)" echo " ${S}test.sh 23${E} -- Test full c/s w/mysql (testrc_2.in)" echo " ${S}test.sh 24${E} -- Test full c/s w/postgres (testrc_2.in)" echo " ${S}test.sh 25${E} -- Test server w/yulectl (testrc_2.in)" echo " ${S}test.sh 26${E} -- Test c/s case one (testrc_2.in)" echo " ${S}test.sh 27${E} -- Test c/s case two (testrc_2.in)" echo " ${S}test.sh all${E} -- All tests" } scripts () { echo echo "Scripts used by tests:" echo " (1) testcompile.sh (2) testhash.sh (3) testrun_1.sh (4) testrun_1a.sh" echo " (5) testext.sh (6) testtimesrv.sh (7) testrun_1b.sh (8) testrun_1c.sh" echo " (9) testrun_1d.sh (10) testrun_1e.sh (11) testrun_1f.sh (12) testrun_1g.sh" echo " (13) testrun_1h.sh" echo " (20) testrun_2.sh (21) testrun_2a.sh (22) testrun_2b.sh (23) testrun_2c.sh" echo " (24) testrun_2d.sh (25) testrun_2e.sh (26) testrun_2f.sh (27) testrun_2g.sh" } # # Option parsing # verbose= quiet= stoponerr= color=auto cleanup=on doall= usevalgrind= while [ $# -gt 0 ] do case "$1" in -h|--help) usage; exit 0;; --scripts) usage; scripts; exit 0;; -v|--verbose) verbose=on; quiet= ;; -q|--quiet) quiet=on; verbose= ;; -s|--stoponerr) stoponerr=on;; -n|--no-cleanup) cleanup= ;; --really-all) doall=on;; --valgrind) usevalgrind=on;; --srcdir=*) TOP_SRCDIR=`echo $1 | sed s,--srcdir=,,`; export TOP_SRCDIR;; --color=*) arg=`echo $1 | sed s,--color=,,` case $arg in auto) ;; never|none|no) S= R= G= B= E= ;; always|yes) S='' R= G= G= E= ;; *) echo "Invalid argument $1"; exit 1;; esac ;; -*) echo "Invalid argument $1"; exit 1;; *) break;; esac shift done export verbose export quiet export stoponerr export cleanup export doall export S; export R; export G; export B; export E; SCRIPTDIR=. # # 'make test' will copy the 'test' subdirectory and replace TEST_SRCDIR # TEST_SRCDIR="XXXSRCXXX"; if test "x${TOP_SRCDIR}" = x; then # not within source tree, and not called with 'make testN' if test -f "${TEST_SRCDIR}/src/samhain.c"; then TOP_SRCDIR="${TEST_SRCDIR}"; export TOP_SRCDIR if test -f test/testcompile.sh; then SCRIPTDIR=test fi # not within source tree, not called by 'make', and in 'test' subdir elif test -f "../${TEST_SRCDIR}/src/samhain.c"; then cd .. SCRIPTDIR=test TOP_SRCDIR="${TEST_SRCDIR}"; export TOP_SRCDIR # within source tree, and not called with 'make testN' else if test -f ../src/samhain.c; then cd .. SCRIPTDIR=test TOP_SRCDIR=. export TOP_SRCDIR elif test -f ./src/samhain.c; then SCRIPTDIR=test TOP_SRCDIR=. export TOP_SRCDIR else echo "Please use --srcdir=DIR, where DIR should be the" echo "top directory in the samhain source tree." exit 1 fi fi else # called by make, or with --srcdir=TOP_SRCDIR if test -f "${TOP_SRCDIR}/src/samhain.c"; then SCRIPTDIR="${TOP_SRCDIR}/test" elif test -f "../${TOP_SRCDIR}/src/samhain.c"; then cd ..; SCRIPTDIR="${TOP_SRCDIR}/test" else echo "Please use --srcdir=DIR, where DIR should be the" echo "top directory in the samhain source tree." exit 1 fi fi export SCRIPTDIR PW_DIR=`pwd`; export PW_DIR # # group/world writeable will cause problems # chmod go-w . # # # if test x$UID != x -a x$UID != x0; then TRUST="--with-trusted=0,2,$UID" else TRUST="--with-trusted=0,2,1000" fi export TRUST # # find a good 'make' # MAKE=`which gmake` if test "x$?" = x1 ; then MAKE="make -s -j 3" else MAKE=`which gmake | sed -e "s%\([a-z:]\) .*%\1%g"` if test "x$MAKE" = x; then MAKE="make -s" elif test "x$MAKE" = xno; then MAKE="make -s" else if test "x$MAKE" = "xwhich:"; then MAKE="make -s" else MAKE="gmake -s" gmake -v >/dev/null 2>&1 || MAKE="make -s" fi fi fi export MAKE failcount=0 okcount=0 skipcount=0 global_count=0 last_count=0 # args: #test, #total, status, optional msg log_msg () { if [ x"$COLUMNS" != x ]; then TERMWIDTH=$COLUMNS elif [ x"$COLS" != x ]; then TERMWIDTH=$COLS else TERMWIDTH=80 fi cols=66; # if [ $1 -eq 0 ]; then msg=" ${4}" else if [ ${1} -eq 1 ]; then global_count=${last_count} fi let "v = $1 + global_count" >/dev/null last_count=${v} dd=''; if [ $v -lt 10 ]; then dd=" "; fi dt=''; if [ $2 -lt 10 ]; then dt=" "; fi if [ -z "$4" ]; then msg=" test ${dd}${v}/${dt}${2}" else msg=" test ${dd}${v}/${dt}${2} ${4}" fi fi # if [ x"$3" = xfailure ]; then ccode=$R elif [ x"$3" = xsuccess ]; then ccode=$G else ccode=$B fi if [ -z "${R}" ]; then echo " [${3}] ${msg}" else # len=${#...} is not bourne shell # also, need to account for terminal control sequences len=`echo "$msg" | awk '/1;30m/ { print length()-10; }; !/1;30m/ { print length();}'` let "cols = cols - len" >/dev/null if [ $cols -ge 0 ]; then moveto='['$cols'C' echo "${msg}${moveto}${ccode}[${3}]${E}" else echo "${msg}${ccode}[${3}]${E}" fi fi } log_fail () { [ -z "$quiet" ] && log_msg "$1" "$2" failure "$3"; let "failcount = failcount + 1" >/dev/null; test -z "$stoponerr" || exit 1; } log_ok () { [ -z "$quiet" ] && log_msg "$1" "$2" success "$3"; let "okcount = okcount + 1" >/dev/null; } log_skip () { [ -z "$quiet" ] && log_msg "$1" "$2" skipped "$3"; let "skipcount = skipcount + 1" >/dev/null; } log_msg_fail () { log_msg 0 0 failure "$1"; } log_msg_ok () { log_msg 0 0 success "$1"; } log_msg_skip () { log_msg 0 0 skipped "$1"; } log_start () { if [ -z "$quiet" ]; then echo; echo "${S}__ START TEST ${1} __${E}"; echo; fi } log_end () { if [ -n "$verbose" ]; then echo; echo "${S}__ END TEST ${1} __${E}"; echo; fi } # This looks silly, but with solaris10/i386 on vmware, # 'sleep' occasionally does not sleep... one_sec_sleep () { onesdate=`date` onestest=0 while [ $onestest -eq 0 ]; do sleep 1 twosdate=`date` if [ "x$twosdate" = "x$onesdate" ]; then onestest=0 else onestest=1 fi done } five_sec_sleep () { for f in 1 2 3 4 5; do one_sec_sleep done } do_cleanup () { rm -f testrc_1.dyn rm -f testrc_2 rm -f testrc_22 rm -f testrc_1ext rm -f ./.samhain_file rm -f file.*.*-*-*-*-* rm -f ./.samhain_log* rm -f ./.samhain_lock* test -d testrun_testdata && chmod -f -R 0700 testrun_testdata test -d .quarantine && rm -rf .quarantine rm -rf testrun_testdata rm -f test_log_db rm -f test_log_prelude rm -f test_log_valgrind* rm -f test_log_yulectl rm -f yule.html rm -f yule.html2 rm -f test_dnmalloc rm -f tmp_list_file rm -f test_filter.txt } print_summary () { # let "gcount = okcount + skipcount + failcount" >/dev/null; gcount=$MAXTEST; let "failcount = gcount - okcount - skipcount" >/dev/null; [ -z "$quiet" ] && { echo echo "__ ${S}Tests: ${gcount} Ok: ${okcount} Skipped: ${skipcount} Failed: ${failcount}${E}" } if [ $failcount -eq 0 ]; then [ -z "$quiet" ] && { echo "__ ${G}All tests passed successfully.${E}"; echo; } elif [ $failcount -eq 1 ]; then [ -z "$quiet" ] && { echo "__ ${R}There was 1 failure.${E}"; echo; } else [ -z "$quiet" ] && { echo "__ ${R}There were $failcount failures.${E}"; echo; } fi [ -z "$cleanup" ] || do_cleanup; } find_path () { ( save_IFS=$IFS; IFS=: for dir in $PATH; do IFS=$as_save_IFS test -z "$dir" && dir=. if test -f "$dir/$1"; then echo "$dir/$1"; break; fi done IFS=${save_IFS}; ); } find_hostname () { uname -a | grep Linux >/dev/null if [ $? -eq 0 ]; then tmp=`hostname -f 2>/dev/null` if [ $? -ne 0 ]; then tmp=`hostname 2>/dev/null` fi else tmp=`hostname 2>/dev/null` fi if [ -z "$tmp" ]; then tmp="localhost" fi # # first one is hostname, others are aliases # tmp2=`cat /etc/hosts | egrep "^ *[0123456789].* $tmp" | awk '{ print $2 }'` if [ -z "$tmp2" ]; then echo "$tmp" else echo "$tmp2" fi } rm -f ./test_log # first one is hostname, others are aliases # hostname=`cat /etc/hosts | egrep "^ *127.0.0.1" | awk '{ print $2 }'` if [ x"$hostname" = xlocalhost ]; then hostname="127.0.0.1" fi # Seems that 'valgrind' causes random hangs :-( # if [ -z "$usevalgrind" ]; then VALGRIND= else VALGRIND=`find_path valgrind`; fi [ -z "$VALGRIND" ] || { VALGRIND="$VALGRIND --quiet --tool=memcheck --suppressions=.test.supp"; export VALGRIND; [ -z "$verbose" ] || log_msg_ok "using valgrind" cat > ".test.supp" </dev/null . ${SCRIPTDIR}/testhash.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1a.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testext.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testtimesrv.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1b.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1c.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1d.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1e.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1f.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1g.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_1h.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2a.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2b.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2c.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2d.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2e.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2f.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null . ${SCRIPTDIR}/testrun_2g.sh let "TEST_MAX = TEST_MAX + MAXTEST" >/dev/null # # ${SCRIPTDIR}/testtimesrv.sh # ${SCRIPTDIR}/testrun_1b.sh # ${SCRIPTDIR}/testrun_2.sh $2 # ${SCRIPTDIR}/testrun_2a.sh $2 # MAXTEST=${TEST_MAX}; export MAXTEST testcompile testhash # . ${SCRIPTDIR}/testrun_1.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1 # . ${SCRIPTDIR}/testrun_1a.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1a # testext0 # . ${SCRIPTDIR}/testtimesrv.sh MAXTEST=${TEST_MAX}; export MAXTEST testtime0 # . ${SCRIPTDIR}/testrun_1b.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1b # . ${SCRIPTDIR}/testrun_1.sh . ${SCRIPTDIR}/testrun_1c.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1c # . ${SCRIPTDIR}/testrun_1.sh . ${SCRIPTDIR}/testrun_1d.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1d # . ${SCRIPTDIR}/testrun_1.sh . ${SCRIPTDIR}/testrun_1e.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1e # . ${SCRIPTDIR}/testrun_1.sh . ${SCRIPTDIR}/testrun_1f.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1f # . ${SCRIPTDIR}/testrun_1.sh . ${SCRIPTDIR}/testrun_1g.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1g # . ${SCRIPTDIR}/testrun_1.sh . ${SCRIPTDIR}/testrun_1h.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun1h # . ${SCRIPTDIR}/testrun_2.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2 $hostname # . ${SCRIPTDIR}/testrun_2a.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2a $hostname # . ${SCRIPTDIR}/testrun_2b.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2b $hostname # . ${SCRIPTDIR}/testrun_2c.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2c $hostname # . ${SCRIPTDIR}/testrun_2d.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2d $hostname # . ${SCRIPTDIR}/testrun_2e.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2e $hostname # . ${SCRIPTDIR}/testrun_2f.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2f $hostname # . ${SCRIPTDIR}/testrun_2g.sh MAXTEST=${TEST_MAX}; export MAXTEST testrun2g $hostname # print_summary exit 0 fi usage; exit 1; # gpg -a --clearsign --not-dash-escaped testrc.gpg # gpg -a --clearsign --not-dash-escaped .samhain_file # tar czvf foo.tgz testrc.gpg.asc .samhain_file.asc # cat foo.tgz >>test/test.sh __ARCHIVE_FOLLOWS__ p{U=lF!s-diD&%r #Q֗نQ0҉bd+Kеk@75k塀l}!KaD:C=ՂؖRA 8Mw;َ(#R1ܜ[2?=^0@b~^R4cX3Ivd BʒUY)7]n bD11QBpIH&yQ6E/"tB& p,B,bL KRseUȶe6xDZ{Eٛ jENk0h!YP3ɾqG(ki;P)ʖl8:QmlJT16JjcR릓. %d8I:7 @s9!1ReC+OgM޾Q BiIb5ۖ-\M}.TT#g+c4l`g6jgxυe[ӆbzp9ƒjg6AHFinxV+G#Ү@e4Q, ;4Hi9ᢦ># ڱz +nh&SN0ZI8h8‹Zb<^~$J+Q(| ݎvzYw;tŽ|:}O㟗Ҵ^_Jto ,R"(|#r"z _ǖ/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep ./yulectl -c LIST >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (1)"; kill $PROC_Y return 1 fi NR=$( ./yulectl -c LIST | wc -l ) if [ $NR -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (2)"; kill $PROC_Y return 1 fi ./yulectl -c SCAN localhost.localdomain if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c SCAN"; kill $PROC_Y return 1 fi UUID=$(uuidgen) ./yulectl -c DELTA:$UUID localhost.localdomain if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c DELTA:$UUID"; kill $PROC_Y return 1 fi ./yulectl -c RELOAD localhost.localdomain if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c RELOAD"; kill $PROC_Y return 1 fi ./yulectl -c LIST >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (3)"; kill $PROC_Y return 1 fi NR=$( ./yulectl -c LIST | wc -l ) if [ $NR -ne 3 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (4)"; kill $PROC_Y return 1 fi { ./yulectl -c LIST | head -n 1 | grep SCAN; } >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (5)"; kill $PROC_Y return 1 fi { ./yulectl -c LIST | tail -n 1 | grep RELOAD; } >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (6)"; kill $PROC_Y return 1 fi { ./yulectl -c LIST | tail -n 2 | head -n 1| grep "DELTA:$UUID"; } >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (7)"; kill $PROC_Y return 1 fi ./yulectl -c CANCEL localhost.localdomain if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c CANCEL"; kill $PROC_Y return 1 fi ./yulectl -c LIST >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (8)"; kill $PROC_Y return 1 fi NR=$( ./yulectl -c LIST | wc -l ) if [ $NR -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "./yulectl -c LIST (9)"; kill $PROC_Y return 1 fi kill $PROC_Y return 0 } testrun2e_internal () { [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo; } # # [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure ${CLIENT_BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # save binary and build server # cp samhain samhain.build || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure ${SERVER_BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi ##################################################################### # # rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} rm -f "./rc.${ALTHOST}" rm -f "./file.${ALTHOST}" cp ${SCRIPTDIR}/testrc_2.in testrc_2 ./samhain.build -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi # Create a password SHPW=`./yule -G` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi # Set in client ./samhain_setpwd samhain.build new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd samhain.build new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd samhain.build new $SHPW"; return 1 fi mv samhain.build.new samhain.new || return 1 rm -f ./.samhain_log* rm -f ./.samhain_lock SHCLT=`./yule -P $SHPW` if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "yule -P $SHPW"; else [ -z "$quiet" ] && log_msg_fail "yule -P $SHPW"; return 1 fi SHCLT1=`echo "${SHCLT}" | sed s%HOSTNAME%${SH_LOCALHOST}%` AHOST=`find_hostname` SHCLT2=`echo "${SHCLT}" | sed s%HOSTNAME%${AHOST}%` echo $SHCLT1 >> testrc_2 echo $SHCLT2 >> testrc_2 cp ./testrc_2 ./rc.${SH_LOCALHOST} mv ./.samhain_file ./file.${SH_LOCALHOST} chmod 644 ./rc.${SH_LOCALHOST} chmod 644 ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` cp ./testrc_2 "./rc.${ALTHOST}" cp ./file.${SH_LOCALHOST} "./file.${ALTHOST}" 2>/dev/null chmod 644 ./rc.${ALTHOST} chmod 644 ./file.${ALTHOST} echo $SHPW > ./testpw } MAXTEST=1; export MAXTEST testrun2e () { log_start "RUN SERVER W/YULECTL"; # if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi # SH_LOCALHOST=$1; export SH_LOCALHOST # testrun2e_internal do_test_2_e if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Server w/yulectl"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Server w/yulectl"; fi ####### EXIT HERE FOR TESTING ###### # # log_end "RUN SERVER W/YULECTL" } samhain-4.1.4/test/testrun_1h.sh0000664000175000017500000001570012615253277013507 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE # --enable-login-watch --enable-xml-log # --enable-debug --enable-suidcheck --with-prelude BUILDOPTS="--quiet $TRUST --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file --enable-debug" export BUILDOPTS BASE="${PW_DIR}/testrun_testdata"; export BASE TDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; export TDIRS TFILES="x y z"; export TFILES TFILES_PART="c/miss c/add c/change c/leave"; export TFILES_PART ########################################################### # # ---- [Define tests here] ---- # # 1 for testing new tests testrun1_setup=0 MAXTEST=5; export MAXTEST PARTIAL_OUTFILE=".samhain_file_partial"; export PARTIAL_OUTFILE PARTIAL_FILTER="c/create c/miss c/change c/leave"; export PARTIAL_FILTER TEST_PART_POLICY_1=" [ReadOnly] dir=${BASE} " mod_testdata_partial_1 () { one_sec_sleep rm "${BASE}/a/a/c/x" # delete } EXPECT_1="nullok" TEST_PART_POLICY_2=" [ReadOnly] dir=${BASE} " mod_testdata_partial_2 () { one_sec_sleep echo "foobar" > "${BASE}/foo" # new } EXPECT_2="nullok" TEST_PART_POLICY_3=" [ReadOnly] dir=${BASE} " mod_testdata_partial_3 () { one_sec_sleep rm -f "${BASE}/c/miss" } EXPECT_3="" TEST_PART_POLICY_4=" [ReadOnly] dir=${BASE} " mod_testdata_partial_4 () { one_sec_sleep echo foo >"${BASE}/c/create" } EXPECT_4="" TEST_PART_POLICY_5=" [ReadOnly] dir=${BASE} " mod_testdata_partial_5 () { one_sec_sleep echo toodledoo >"${BASE}/c/change" } EXPECT_5="" # # $2 == "nullok" means no mods should be detected, # else it is an error to detect no mods # run_check_partial_verify () { if [ "x$1" = "x" ]; then logsev=debug else logsev=$1 fi if ! test -f ${PARTIAL_OUTFILE}; then [ -z "$quiet" ] && log_msg_fail "missing ${PARTIAL_OUTFILE} ..."; return 1 fi rm -f test_log_valgrind ${VALGRIND} ./samhain -p =err --verify-database ${PARTIAL_OUTFILE} 2>>test_log_valgrind if test x$? = x0; then if [ "x$2" != "xnullok" ]; then [ -z "$quiet" ] && log_msg_fail "check (1a)..."; return 1 fi else if [ "x$2" = "xnullok" ]; then [ -z "$quiet" ] && log_msg_fail "check (1b)..."; return 1 fi fi LL=`wc -l test_log_valgrind | awk '{ print $1; }'` if ! test x$LL = x0; then [ -z "$quiet" ] && log_msg_fail "check (2)..."; [ -z "$quiet" ] && cat test_log_valgrind return 1 fi [ -z "$verbose" ] || log_msg_ok "check..."; } run_update_partial_verify () { ${VALGRIND} ./samhain -t update -p none -l debug 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "update..."; else [ -z "$quiet" ] && log_msg_fail "update..."; return 1 fi } run_check_after_update_partial () { rm -rf $LOGFILE run_check_partial_verify debug nullok } create_partial () { echo "${BASE}/c" > test_filter.txt for ff in ${TFILES_PART}; do echo "${BASE}/${ff}" >> test_filter.txt done ./samhain -o "${PARTIAL_OUTFILE}" --binary --list-filter=test_filter.txt --list-database=./.samhain_file if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "create partial DB..."; else [ -z "$quiet" ] && log_msg_fail "create partial DB..."; return 1 fi if test -f "${PARTIAL_OUTFILE}"; then [ -z "$verbose" ] || log_msg_ok "partial DB exists..."; else [ -z "$quiet" ] && log_msg_fail "partial DB exists..."; return 1 fi rm -f test_filter.txt } prep_partial_testpolicy () { test -f "${RCFILE}" || touch "${RCFILE}" eval echo '"$'"TEST_PART_POLICY_$1"'"' >>"${RCFILE}" } prep_testdata_partial () { prep_testdata if test x$? = x0; then touch "${BASE}/c/miss" touch "${BASE}/c/change" touch "${BASE}/c/leave" else return 1 fi } testrun_internal_partial_verify () { [ -z "$verbose" ] || echo Working directory: $PW_DIR [ -z "$verbose" ] || { echo MAKE is $MAKE; echo; } # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } if test -r "Makefile"; then $MAKE distclean >/dev/null fi ${TOP_SRCDIR}/configure ${BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Running test suite${E}"; echo; } tcount=1 POLICY=`eval echo '"$'"TEST_PART_POLICY_$tcount"'"'` until [ -z "$POLICY" ] do prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata_partial check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_partial_testpolicy ${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then create_partial check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval mod_testdata_partial_${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then arg2=`eval echo '"$'"EXPECT_$tcount"'"'` run_check_partial_verify debug $arg2 check_err $? ${tcount}; errval=$? fi if [ $testrun1_setup -eq 0 ]; then if [ $errval -eq 0 ]; then run_update_partial_verify check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then create_partial check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check_after_update_partial check_err $? ${tcount}; errval=$? fi fi # if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi # let "tcount = tcount + 1" >/dev/null # POLICY=`eval echo '"$'"TEST_PART_POLICY_$tcount"'"'` done return 0 } testrun1h () { log_start "RUN CL Partial DB Verify" testrun_internal_partial_verify log_end "RUN CL Partial DB Verify" return 0 } samhain-4.1.4/test/test_ext.c.in0000644000175000017500000000106012615253277013457 00000000000000#include #include #include #include #include #include int main () { char line[256]; int flags; FILE * foo = fopen ("MYPWDIR", "a"); flags = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, flags|O_NONBLOCK); xagain: errno = 0; while (NULL != fgets(line, 255, stdin)) { fprintf (foo, "RECV: %s", line); fflush (foo); } if (ferror(stdin) && errno == EAGAIN) { clearerr(stdin); goto xagain; } fclose(foo); return 0; } samhain-4.1.4/test/testrun_1f.sh0000755000175000017500000001632712615253277013514 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE # --enable-login-watch --enable-xml-log # --enable-debug --enable-suidcheck --with-prelude BUILDOPTS="--quiet $TRUST --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file --enable-debug --with-gpg=/usr/bin/gpg --with-keyid=0x8A0B337A --with-fp=DCCBBB6625591ECE2B8F3AC94ED99E4E8A0B337A" export BUILDOPTS BASE="${PW_DIR}/testrun_testdata"; export BASE TDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; export TDIRS TFILES="x y z"; export TFILES ########################################################### # # ---- [Define tests here] ---- # # 1 for testing new tests testrun1_setup=0 MAXTEST=17; export MAXTEST TESTPOLICY_17=" [ReadOnly] dir=${BASE} " mod_testdata_17 () { one_sec_sleep rm "${BASE}/a/a/c/x" # delete } TESTPOLICY_16=" [ReadOnly] dir=${BASE} " mod_testdata_16 () { one_sec_sleep echo "foobar" > "${BASE}/foo" # new } prep_sign_file () { scripts/samhainadmin.pl -s ./test/gnupg/ -m R $1 >/dev/null scripts/samhainadmin.pl -s ./test/gnupg/ -k 8A0B337A -m E $1 >/dev/null } run_check_CLverify () { if [ "x$1" = "x" ]; then logsev=debug else logsev=$1 fi if test -f ./.samhain_file; then mv ./.samhain_file ./.samhain_file_clverify if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv ./.samhain_file ..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "test -f ./.samhain_file ..."; return 1 fi rm -f test_log_valgrind ${VALGRIND} ./samhain -p =err --verify-database ./.samhain_file_clverify 2>>test_log_valgrind if test x$? = x0; then if [ "x$2" != "xnullok" ]; then [ -z "$quiet" ] && log_msg_fail "check (1)..."; return 1 fi else if [ "x$2" = "xnullok" ]; then [ -z "$quiet" ] && log_msg_fail "check (1)..."; return 1 fi fi LL=`wc -l test_log_valgrind | awk '{ print $1; }'` if ! test x$LL = x0; then [ -z "$quiet" ] && log_msg_fail "check (2)..."; [ -z "$quiet" ] && cat test_log_valgrind return 1 fi [ -z "$verbose" ] || log_msg_ok "check..."; } run_update_CLverify () { if test -f ./.samhain_file_clverify; then mv ./.samhain_file_clverify ./.samhain_file if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv ./.samhain_file_clverify ..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "test -f ./.samhain_file_clverify ..."; return 1 fi ${VALGRIND} ./samhain -t update -p none -l debug 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "update..."; else [ -z "$quiet" ] && log_msg_fail "update..."; return 1 fi } run_check_after_update_CLverify () { rm -rf $LOGFILE run_check_CLverify debug nullok } testrun_internal_CLverify () { [ -z "$verbose" ] || echo Working directory: $PW_DIR [ -z "$verbose" ] || { echo MAKE is $MAKE; echo; } # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } if test -r "Makefile"; then $MAKE distclean >/dev/null fi ${TOP_SRCDIR}/configure ${BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Running test suite${E}"; echo; } tcount=1 POLICY=`eval echo '"$'"TESTPOLICY_$tcount"'"'` until [ -z "$POLICY" ] do prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_testpolicy ${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_sign_file "${RCFILE}" check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_sign_file ./.samhain_file check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval mod_testdata_${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check_CLverify check_err $? ${tcount}; errval=$? fi if [ $testrun1_setup -eq 0 ]; then if [ $errval -eq 0 ]; then prep_sign_file "${RCFILE}" check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_update_CLverify check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_sign_file ./.samhain_file check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check_after_update_CLverify check_err $? ${tcount}; errval=$? fi fi # if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi # let "tcount = tcount + 1" >/dev/null # if [ $tcount -eq 10 ]; then if [ -z "$doall" ]; then log_skip 10 $MAXTEST 'ACL/SELinux test (or use --really-all)' log_skip 11 $MAXTEST 'ACL/SELinux test (or use --really-all)' let "tcount = tcount + 2" >/dev/null else # 'id -u' is posix # if test -f /usr/xpg4/bin/id then my_uid=`/usr/xpg4/bin/id -u` else my_uid=`id -u` fi # if [ ${my_uid} -ne 0 ]; then log_skip 10 $MAXTEST 'ACL/SELinux test (you are not root)' log_skip 11 $MAXTEST 'ACL/SELinux test (you are not root)' let "tcount = tcount + 2" >/dev/null else SETFATTR=`find_path setfattr` if [ -z "$SETFATTR" ]; then log_skip 10 $MAXTEST 'ACL/SELinux test (setfattr not in path)' log_skip 11 $MAXTEST 'ACL/SELinux test (setfattr not in path)' let "tcount = tcount + 2" >/dev/null fi fi fi fi # POLICY=`eval echo '"$'"TESTPOLICY_$tcount"'"'` done return 0 } testrun1f () { log_start "RUN CL Verify" gpg --list-keys | grep 8A0B337A >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "You need to do 'gpg --import test/gnupg/public-key.asc' first" for ff in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17; do log_skip $ff $MAXTEST 'CL verify' done else testrun_internal_CLverify fi log_end "RUN CL Verify" return 0 } samhain-4.1.4/test/testrun_1e.sh0000755000175000017500000002132212615253277013502 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # BUILDOPTS="--quiet $TRUST --enable-debug=gdb --enable-xml-log --enable-port-check --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" export BUILDOPTS MAXTEST=5; export MAXTEST PORTPOLICY_5=" [ReadOnly] file=${BASE} [PortCheck] PortCheckActive = yes PortCheckUDP = no PortCheckInterface = 127.0.0.1 " chk_portdata_5 () { one_sec_sleep if [ -z "$PM" ]; then log_skip 5 $MAXTEST 'prelude-manager not found in $PATH' elif [ -z "$doall" ]; then log_skip 5 $MAXTEST 'logging to prelude (or use --really-all)' else tmp=`egrep 'Service: port=5500 .unknown. protocol=tcp' test_log_prelude 2>/dev/null | wc -l` if [ $tmp -lt 1 ]; then [ -z "$verbose" ] || log_msg_fail "port 5500"; [ -z "$quiet" ] && log_fail 5 ${MAXTEST}; return 1 fi # [ -z "$quiet" ] && log_ok 5 ${MAXTEST}; fi return 0 } refine_portpolicy_5 () { echo "PortCheckIgnore=2026/tcp" >>"${RCFILE}" echo "PortCheckIgnore=2027/udp" >>"${RCFILE}" echo "PortCheckIgnore=2028/tcp" >>"${RCFILE}" echo "PortCheckIgnore=2029/udp" >>"${RCFILE}" } PORTPOLICY_4=" [ReadOnly] file=${BASE} [PortCheck] PortCheckActive = yes PortCheckUDP = no " chk_portdata_4 () { one_sec_sleep egrep 'CRIT.*POLICY \[ServiceNew\]' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || egrep 'CRIT.*POLICY \[ServiceNew\]' $LOGFILE [ -z "$verbose" ] || log_msg_fail "Open ports"; return 1 fi } refine_portpolicy_4 () { cat "$LOGFILE" | grep ServiceNew | sed 's/.*port: //' | awk '{ print $1 }' | \ while read line; do echo "PortCheckSkip=$line" >>"${RCFILE}" done echo "PortCheckIgnore=2026/tcp" >>"${RCFILE}" echo "PortCheckIgnore=2027/udp" >>"${RCFILE}" echo "PortCheckIgnore=2028/tcp" >>"${RCFILE}" echo "PortCheckIgnore=2029/udp" >>"${RCFILE}" } PORTPOLICY_3=" [ReadOnly] file=${BASE} [PortCheck] PortCheckActive = yes PortCheckUDP = no " chk_portdata_3 () { one_sec_sleep egrep 'CRIT.*POLICY \[ServiceNew\]' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "Open ports"; return 1 fi } refine_portpolicy_3 () { cat "$LOGFILE" | grep ServiceNew | sed 's/.*port: //' | awk '{ print $1 }' | \ while read line; do echo "PortCheckIgnore=$line" >>"${RCFILE}" done echo "PortCheckIgnore=2026/tcp" >>"${RCFILE}" echo "PortCheckIgnore=2027/udp" >>"${RCFILE}" echo "PortCheckIgnore=2028/tcp" >>"${RCFILE}" echo "PortCheckIgnore=2029/udp" >>"${RCFILE}" } PORTPOLICY_2=" [ReadOnly] file=${BASE} [PortCheck] PortCheckActive = yes PortCheckUDP = no " chk_portdata_2 () { one_sec_sleep egrep 'CRIT.*POLICY \[ServiceNew\]' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "Open ports"; return 1 fi } refine_portpolicy_2 () { cat "$LOGFILE" | grep ServiceNew | sed 's/.*port: //' | awk '{ print $1 }' | \ while read line; do echo "PortCheckOptional=$line" >>"${RCFILE}" done } PORTPOLICY_1=" [ReadOnly] file=${BASE} [PortCheck] PortCheckActive = yes PortCheckUDP = no " chk_portdata_1 () { one_sec_sleep egrep 'CRIT.*POLICY \[ServiceNew\]' $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "Open ports"; return 1 fi } refine_portpolicy_1 () { cat "$LOGFILE" | grep ServiceNew | sed 's/.*port: //' | awk '{ print $1 }' | \ while read line; do echo "PortCheckRequired=$line" >>"${RCFILE}" done } prep_portpolicy () { test -f "${RCFILE}" || touch "${RCFILE}" eval echo '"$'"PORTPOLICY_$1"'"' >>"${RCFILE}" } run_check_prelude() { ./samhain -t check -p none -l info --set-prelude-severity=info --prelude --server-addr 127.0.0.1:5500 >/dev/null if test x$? = x0; then ./samhain -j -L $LOGFILE >"${LOGFILE}.tmp" && mv "${LOGFILE}.tmp" "${LOGFILE}" if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv logfile..."; return 1 fi [ -z "$verbose" ] || log_msg_ok "check..."; else [ -z "$quiet" ] && log_msg_fail "check..."; return 1 fi } testrun_internal_1e () { [ -z "$verbose" ] || echo Working directory: $PW_DIR [ -z "$verbose" ] || { echo MAKE is $MAKE; echo; } # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } if test -r "Makefile"; then $MAKE distclean >/dev/null fi tcount=1 ${TOP_SRCDIR}/configure ${BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Running test suite${E}"; echo; } POLICY=`eval echo '"$'"PORTPOLICY_$tcount"'"'` until [ -z "$POLICY" ] do prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_portpolicy ${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi # if [ $errval -eq 0 ]; then eval refine_portpolicy_${tcount} check_err $? ${tcount}; errval=$? fi # rm -f "$LOGFILE" # PRELUDEPID=0 # if test ${tcount} -eq 5; then PM=`find_path prelude-manager` if [ -z "$PM" ]; then if [ $errval -eq 0 ]; then run_check check_err $? ${tcount}; errval=$? fi elif [ -z "$doall" ]; then if [ $errval -eq 0 ]; then run_check check_err $? ${tcount}; errval=$? fi else # # ${TOP_SRCDIR}/configure ${BUILDOPTS} --with-prelude # # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # # if ! test -d /var/run/prelude-manager then [ -z "$verbose" ] || log_msg_ok "create /var/run/prelude-manager..."; sudo mkdir /var/run/prelude-manager sudo chown prelude:rainer /var/run/prelude-manager sudo chmod 770 /var/run/prelude-manager fi if ! test -d /var/spool/prelude/samhain/global then [ -z "$verbose" ] || log_msg_ok "create /var/spool/prelude/samhain/global..."; sudo mkdir -p /var/spool/prelude/samhain/global sudo chown prelude:rainer /var/spool/prelude/samhain/global sudo chmod 770 /var/spool/prelude/samhain/global fi # # [ -z "$verbose" ] || { echo " starting prelude-manager.."; echo " ($PM --textmod -l $PW_DIR/test_log_prelude --listen 127.0.0.1:5500 >/dev/null 2>&1 &)"; } "$PM" --textmod -l $PW_DIR/test_log_prelude --listen 127.0.0.1:5500 >/dev/null 2>&1 & PRELUDEPID=$! # # five_sec_sleep # # if [ $errval -eq 0 ]; then run_check_prelude check_err $? ${tcount}; errval=$? fi fi else if [ $errval -eq 0 ]; then run_check check_err $? ${tcount}; errval=$? fi fi # if [ $errval -eq 0 ]; then eval chk_portdata_${tcount} check_err $? ${tcount}; errval=$? fi # if [ $errval -eq 0 ]; then if test ${tcount} -ne 5; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi fi let "tcount = tcount + 1" >/dev/null POLICY=`eval echo '"$'"PORTPOLICY_$tcount"'"'` if test $PRELUDEPID -ne 0; then kill $PRELUDEPID fi done return 0 } testrun1e () { log_start "RUN STANDALONE W/PORTCHECK" testrun_internal_1e log_end "RUN STANDALONE W/PORTCHECK" return 0 } samhain-4.1.4/test/testrun_1c.sh0000755000175000017500000002333612615253277013507 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # BUILDOPTS="--quiet $TRUST --enable-xml-log --enable-suidcheck --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" export BUILDOPTS MAXTEST=7; export MAXTEST ## Quarantine SUID/SGID files if found # # SuidCheckQuarantineFiles = yes ## Method for Quarantining files: # 0 - Delete or truncate the file. # 1 - Remove SUID/SGID permissions from file. # 2 - Move SUID/SGID file to quarantine dir. # # SuidCheckQuarantineMethod = 0 ## For method 0 and 2, really delete instead of truncating # # SuidCheckQuarantineDelete = yes SUIDPOLICY_7=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckExclude = ${BASE}/a/a SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = no SuidCheckQuarantineMethod = 2 SuidCheckQuarantineDelete = yes " mod_suiddata_7 () { one_sec_sleep chmod 4444 "${BASE}/a/a/y" chmod 4444 "${BASE}/a/a/a/y" mkdir "${BASE}/a/abc" touch "${BASE}/a/abc/y" chmod 4444 "${BASE}/a/abc/y" } chk_suiddata_7 () { one_sec_sleep tmp=`ls -l "${BASE}/a/a/y" 2>/dev/null | awk '{ print $1}' | cut -c 1-10` if [ "x$tmp" = "x-r-Sr--r--" ]; then egrep "CRIT.*POLICY \[SuidCheck\].*${BASE}/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y"; return 1 fi else [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (suid not kept)"; return 1 fi tmp=`ls -l "${BASE}/a/a/a/y" 2>/dev/null | awk '{ print $1}' | cut -c 1-10` if [ "x$tmp" = "x-r-Sr--r--" ]; then egrep "CRIT.*POLICY \[SuidCheck\].*${BASE}/a/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/a/y"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/a/y"; return 1 fi else [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/a/y (suid not kept)"; return 1 fi tmp=`ls -l "${BASE}/a/abc/y" 2>/dev/null | awk '{ print $1}' | cut -c 1-10` if [ "x$tmp" = "x-r-Sr--r--" ]; then egrep "CRIT.*POLICY \[SuidCheck\].*${BASE}/a/abc/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/abc/y"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/abc/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/abc/y"; return 1 fi return 0; else [ -z "$verbose" ] || log_msg_fail "${BASE}/a/abc/y (suid not kept)"; return 1 fi } SUIDPOLICY_6=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = no SuidCheckQuarantineMethod = 2 SuidCheckQuarantineDelete = yes " mod_suiddata_6 () { one_sec_sleep chmod 4755 "${BASE}/a/a/y" } chk_suiddata_6 () { one_sec_sleep tmp=`ls -l "${BASE}/a/a/y" 2>/dev/null | awk '{ print $1}' | cut -c 1-10` if [ "x$tmp" = "x-rwsr-xr-x" ]; then egrep "CRIT.*POLICY \[SuidCheck\].*${BASE}/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y"; return 1 fi return 0; else [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (suid not kept)"; return 1 fi } SUIDPOLICY_5=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = yes SuidCheckQuarantineMethod = 2 SuidCheckQuarantineDelete = yes " mod_suiddata_5 () { one_sec_sleep chmod 4755 "${BASE}/a/a/y" } chk_suiddata_5 () { one_sec_sleep if [ ! -f "${BASE}/a/a/x" ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/x (erroneously deleted)"; return 1 fi if [ -f "${BASE}/a/a/y" ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (not deleted)"; return 1 fi if [ -f .quarantine/y ]; then if [ -f .quarantine/y.info ]; then return 0; else [ -z "$verbose" ] || log_msg_fail ".quarantine/y.info (missing)"; return 1 fi else [ -z "$verbose" ] || log_msg_fail ".quarantine/y (missing)"; return 1 fi } SUIDPOLICY_4=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = yes SuidCheckQuarantineMethod = 2 SuidCheckQuarantineDelete = no " mod_suiddata_4 () { one_sec_sleep chmod 4755 "${BASE}/a/a/y" } chk_suiddata_4 () { one_sec_sleep tmp=`cat "${BASE}/a/a/y" 2>/dev/null | wc -c` if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (not truncated)"; return 1 fi if [ -f .quarantine/y ]; then if [ -f .quarantine/y.info ]; then return 0; else [ -z "$verbose" ] || log_msg_fail ".quarantine/y.info (missing)"; return 1 fi else [ -z "$verbose" ] || log_msg_fail ".quarantine/y (missing)"; return 1 fi } SUIDPOLICY_3=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = yes SuidCheckQuarantineMethod = 1 SuidCheckQuarantineDelete = no " mod_suiddata_3 () { one_sec_sleep chmod 4755 "${BASE}/a/a/y" } chk_suiddata_3 () { one_sec_sleep tmp=`ls -l "${BASE}/a/a/y" 2>/dev/null | awk '{ print $1}' | cut -c 1-10` if [ "x$tmp" = "x-rwxr-xr-x" ]; then return 0; else [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (suid not removed)"; return 1 fi } SUIDPOLICY_2=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = yes SuidCheckQuarantineMethod = 0 SuidCheckQuarantineDelete = no " mod_suiddata_2 () { one_sec_sleep chmod 4755 "${BASE}/a/a/y" } chk_suiddata_2 () { one_sec_sleep tmp=`cat "${BASE}/a/a/y" 2>/dev/null | wc -c` if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (not truncated)"; return 1 fi } SUIDPOLICY_1=" [ReadOnly] file=${BASE} [SuidCheck] SuidCheckActive = yes SuidCheckInterval = 10 SeveritySuidCheck = crit SuidCheckQuarantineFiles = yes SuidCheckQuarantineMethod = 0 SuidCheckQuarantineDelete = yes " mod_suiddata_1 () { one_sec_sleep chmod 4755 "${BASE}/a/a/y" } chk_suiddata_1 () { one_sec_sleep if [ -f "${BASE}/a/a/y" ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y (not removed)"; return 1 fi } prep_suidpolicy () { test -f "${RCFILE}" || touch "${RCFILE}" eval echo '"$'"SUIDPOLICY_$1"'"' >>"${RCFILE}" if [ "x$1" = "x5" ]; then chmod 4755 "${BASE}/a/a/x" fi } testrun_internal_1c () { [ -z "$verbose" ] || echo Working directory: $PW_DIR [ -z "$verbose" ] || { echo MAKE is $MAKE; echo; } # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } if test -r "Makefile"; then $MAKE distclean >/dev/null fi ${TOP_SRCDIR}/configure ${BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE 'DBGDEF=-DSH_SUIDTESTDIR=\"${BASE}\"' >/dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make DBGDEF=-DSH_SUIDTESTDIR=${BASE} ..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Running test suite${E}"; echo; } tcount=1 POLICY=`eval echo '"$'"SUIDPOLICY_$tcount"'"'` until [ -z "$POLICY" ] do prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_suidpolicy ${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval mod_suiddata_${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval chk_suiddata_${tcount} check_err $? ${tcount}; errval=$? fi if [ $testrun1_setup -eq 0 ]; then if [ $errval -eq 0 ]; then run_update check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check_after_update check_err $? ${tcount}; errval=$? fi fi # if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi let "tcount = tcount + 1" >/dev/null POLICY=`eval echo '"$'"SUIDPOLICY_$tcount"'"'` done return 0 } testrun1c () { log_start "RUN STANDALONE W/SUIDCHK" testrun_internal_1c log_end "RUN STANDALONE W/SUIDCHK" return 0 } samhain-4.1.4/test/testrun_1b.sh0000755000175000017500000003473112615253277013507 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # MAXTEST=7; export MAXTEST LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE testrun1b_modrc () { ORIGINAL="\[EOF\]" REPLACEMENT="\[PortCheck\]" ex -s $RCFILE <>"$RCFILE" echo "PortCheckInterface = 127.0.0.1" >>"$RCFILE" } testrun1b_internal () { BUILDOPTS="$1" # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean >/dev/null >&1 fi # # Bootstrapping # ${TOP_SRCDIR}/configure >/dev/null 2>/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure (bootstrap)..."; $MAKE > /dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make (bootstrap)..."; else [ -z "$quiet" ] && log_msg_fail "make (bootstrap)..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure (bootstrap)..."; return 1 fi # # ${TOP_SRCDIR}/configure ${BUILDOPTS} 2>/dev/null | \ egrep 'use existing [./[:alnum:]]+ for gpg checksum' >/dev/null # # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi SKIP=`awk '/^__ARCHIVE_FOLLOWS__/ { print NR + 1; exit 0; }' ${SCRIPTDIR}/test.sh` tail -n "+$SKIP" ${SCRIPTDIR}/test.sh >/dev/null 2>&1 if [ $? -eq 0 ]; then tail -n "+$SKIP" ${SCRIPTDIR}/test.sh | gunzip -c - 2>/dev/null | tar xf - && \ mv "./testrc.gpg.asc" "$RCFILE" else tail "+$SKIP" ${SCRIPTDIR}/test.sh | gunzip -c - 2>/dev/null | tar xf - && \ mv "./testrc.gpg.asc" "$RCFILE" fi if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "extract gpg signed files..."; else [ -z "$quiet" ] && log_msg_fail "extract gpg signed files..."; return 1 fi if test "x$2" = "x"; then : else CONVERT="$2" if test -f "${TOP_SRCDIR}/stealth_template.jpg"; then [ -z "$verbose" ] || log_msg_ok "convert..." "${CONVERT}" +compress "${TOP_SRCDIR}/stealth_template.jpg" stealth_template.ps >/dev/null else [ -z "$quiet" ] && log_msg_fail "cannot find file stealth_template.jpg" return 1 fi if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "${CONVERT} +compress ${TOP_SRCDIR}/stealth_template.jpg stealth_template.ps"; return 1 fi [ -z "$verbose" ] || log_msg_ok "hide..." ./samhain_stealth -s stealth_template.ps "$RCFILE" >/dev/null if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "${CONVERT} +compress ${TOP_SRCDIR}/stealth_template.jpg stealth_template.ps"; return 1 fi mv -f stealth_template.ps "$RCFILE" if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv -f stealth_template.ps $RCFILE"; return 1 fi fi rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock ./samhain -t init -p none -l info if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi mv $PW_DIR/.samhain_file.asc $PW_DIR/.samhain_file } testrun1b_nogpg () { BUILDOPTS="$1" # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean >/dev/null >&1 fi ${TOP_SRCDIR}/configure ${BUILDOPTS} 2>/dev/null # # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock cp "${SCRIPTDIR}/testrc_1" "${RCFILE}" if test "x$2" = "xmodrc"; then [ -z "$verbose" ] || log_msg_ok "mod rc..."; testrun1b_modrc fi ./samhain -t init -p none -l info if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi } do_test_1b () { ./samhain -t check -p none -l info if test x$? = x0; then ./samhain -j -L $LOGFILE >"${LOGFILE}.tmp" && mv "${LOGFILE}.tmp" "${LOGFILE}" if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv logfile..."; return 1 fi [ -z "$verbose" ] || log_msg_ok "check..."; else [ -z "$quiet" ] && log_msg_fail "check..."; return 1 fi # tmp=`egrep "Checking.*/etc(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "/etc"; return 1 fi tmp=`egrep "Checking.*(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 10 ]; then [ -z "$verbose" ] || log_msg_fail "checking"; return 1 fi egrep "ADDED" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "init was incomplete"; return 1 fi # return 0 } do_test_1b_2 () { rm -f $PW_DIR/test_log_prelude [ -z "$verbose" ] || { echo " starting prelude-manager.."; echo " ($PM --textmod -l $PW_DIR/test_log_prelude --listen 127.0.0.1:5500 >/dev/null 2>&1 &)"; } "$PM" --textmod -l $PW_DIR/test_log_prelude --listen 127.0.0.1:5500 >/dev/null 2>&1 & PID=$! five_sec_sleep ./samhain -t check -p none -l info --set-prelude-severity=info --prelude --server-addr 127.0.0.1:5500 >/dev/null if test x$? = x0; then ./samhain -j -L $LOGFILE >"${LOGFILE}.tmp" && mv "${LOGFILE}.tmp" "${LOGFILE}" if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv logfile..."; kill $PID return 1 fi [ -z "$verbose" ] || log_msg_ok "check..."; else [ -z "$quiet" ] && log_msg_fail "check..."; kill $PID return 1 fi # tmp=`egrep 'File original:.*name=etc.*path=/etc' test_log_prelude 2>/dev/null | wc -l` if [ $tmp -lt 1 ]; then [ -z "$verbose" ] || log_msg_fail "/etc"; kill $PID return 1 fi tmp=`egrep 'Classification text: Checking' test_log_prelude 2>/dev/null | wc -l` if [ $tmp -lt 1 ]; then [ -z "$verbose" ] || log_msg_fail "checking"; kill $PID return 1 fi # if test "x$2" = "xmodrc"; then tmp=`egrep 'Classification text: Service opened' test_log_prelude 2>/dev/null | wc -l` if [ $tmp -lt 1 ]; then [ -z "$verbose" ] || log_msg_fail "service"; kill $PID return 1 fi tmp=`egrep 'Service: port=5500' test_log_prelude 2>/dev/null | wc -l` if [ $tmp -lt 1 ]; then [ -z "$verbose" ] || log_msg_fail "port 5500"; kill $PID return 1 fi fi # kill $PID return 0 } testrun1b () { log_start "RUN STANDALONE W/STEALTH W/GPG" GPG=`find_path gpg` if [ -z "$GPG" ]; then log_skip 1 $MAXTEST 'gpg not found in $PATH' log_skip 2 $MAXTEST 'gpg not found in $PATH' log_skip 3 $MAXTEST 'gpg not found in $PATH' log_skip 4 $MAXTEST 'gpg not found in $PATH' log_skip 5 $MAXTEST 'gpg not found in $PATH' log_skip 6 $MAXTEST 'gpg not found in $PATH' log_skip 7 $MAXTEST 'gpg not found in $PATH' else eval "$GPG" --list-keys 0F571F6C >/dev/null 2>/dev/null if [ $? -ne 0 ]; then log_skip 1 $MAXTEST 'public PGP key 0x0F571F6C not present' log_skip 2 $MAXTEST 'public PGP key 0x0F571F6C not present' log_skip 3 $MAXTEST 'public PGP key 0x0F571F6C not present' log_skip 4 $MAXTEST 'public PGP key 0x0F571F6C not present' log_skip 5 $MAXTEST 'public PGP key 0x0F571F6C not present' log_skip 6 $MAXTEST 'public PGP key 0x0F571F6C not present' log_skip 7 $MAXTEST 'public PGP key 0x0F571F6C not present' else # # ------------- first test ------------- # BUILDOPTS="--quiet $TRUST --enable-debug --with-gpg=${GPG} --enable-micro-stealth=137 --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_internal "${BUILDOPTS}" do_test_1b if [ $? -eq 0 ]; then log_ok 1 $MAXTEST 'gpg signed config/database files' else log_fail 1 $MAXTEST 'gpg signed config/database files' fi # # ------------- second test ------------- # BUILDOPTS="--quiet $TRUST --enable-debug --with-gpg=${GPG} --with-checksum --enable-micro-stealth=137 --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_internal "${BUILDOPTS}" do_test_1b if [ $? -eq 0 ]; then log_ok 2 $MAXTEST 'gpg signed config/database files' else log_fail 2 $MAXTEST 'gpg signed config/database files' fi # # ------------- third test ------------- # BUILDOPTS="--quiet $TRUST --enable-debug --with-gpg=${GPG} --with-checksum --with-fp=EF6CEF54701A0AFDB86AF4C31AAD26C80F571F6C --enable-micro-stealth=137 --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_internal "${BUILDOPTS}" do_test_1b if [ $? -eq 0 ]; then log_ok 3 $MAXTEST 'gpg signed config/database files' else log_fail 3 $MAXTEST 'gpg signed config/database files' fi # # ------------- fourth test ------------- # PRECONV=`find_path convert` "${PRECONV}" --help | grep ImageMagick >/dev/null 2>&1 && \ CONVERT="${PRECONV}" if [ -z "$CONVERT" ]; then log_skip 2 $MAXTEST 'ImageMagick convert not found in $PATH' else BUILDOPTS="--quiet $TRUST --enable-debug --with-gpg=${GPG} --with-checksum --enable-stealth=137 --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_internal "${BUILDOPTS}" "$CONVERT" do_test_1b if [ $? -eq 0 ]; then log_ok 4 $MAXTEST 'gpg signed config/database files' else log_fail 4 $MAXTEST 'gpg signed config/database files' fi fi # # ------------- fifth test ------------- # if ! test -d /var/run/prelude-manager then [ -z "$verbose" ] || log_msg_ok "create /var/run/prelude-manager..."; sudo mkdir /var/run/prelude-manager sudo chown prelude:rainer /var/run/prelude-manager sudo chmod 770 /var/run/prelude-manager fi # PM=`find_path prelude-manager` if [ -z "$PM" ]; then log_skip 5 $MAXTEST 'prelude-manager not found in $PATH' elif [ -z "$doall" ]; then log_skip 5 $MAXTEST 'logging to prelude (or use --really-all)' else BUILDOPTS="--quiet $TRUST --enable-debug --with-prelude --with-gpg=${GPG} --with-checksum --enable-micro-stealth=137 --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_internal "${BUILDOPTS} CFLAGS=-DSH_NOFAILOVER=1" do_test_1b_2 if [ $? -eq 0 ]; then log_ok 5 $MAXTEST 'logging to prelude' else log_fail 5 $MAXTEST 'logging to prelude' fi fi # # ------------- sixth test ------------- # if ! test -d /var/run/prelude-manager then [ -z "$verbose" ] || log_msg_ok "create /var/run/prelude-manager..."; sudo mkdir /var/run/prelude-manager sudo chown prelude:rainer /var/run/prelude-manager sudo chmod 770 /var/run/prelude-manager fi # PM=`find_path prelude-manager` if [ -z "$PM" ]; then log_skip 6 $MAXTEST 'prelude-manager not found in $PATH' elif [ -z "$doall" ]; then log_skip 6 $MAXTEST 'logging to prelude (or use --really-all)' else BUILDOPTS="--quiet $TRUST --with-prelude --enable-login-watch --enable-mounts-check --enable-process-check --enable-port-check --enable-suidcheck --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_nogpg "${BUILDOPTS} CFLAGS=-DSH_NOFAILOVER=1" do_test_1b_2 if [ $? -eq 0 ]; then log_ok 6 $MAXTEST 'logging to prelude' else log_fail 6 $MAXTEST 'logging to prelude' fi fi # # ------------- seventh test ----------- # if ! test -d /var/run/prelude-manager then [ -z "$verbose" ] || log_msg_ok "create /var/run/prelude-manager..."; sudo mkdir /var/run/prelude-manager sudo chown prelude:rainer /var/run/prelude-manager sudo chmod 770 /var/run/prelude-manager fi # PM=`find_path prelude-manager` if [ -z "$PM" ]; then log_skip 7 $MAXTEST 'prelude-manager not found in $PATH' elif [ -z "$doall" ]; then log_skip 7 $MAXTEST 'logging to prelude (or use --really-all)' else BUILDOPTS="--quiet $TRUST --with-prelude --enable-login-watch --enable-mounts-check --enable-process-check --enable-port-check --enable-suidcheck --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" testrun1b_nogpg "${BUILDOPTS} CFLAGS=-DSH_NOFAILOVER=1" "modrc" do_test_1b_2 if [ $? -eq 0 ]; then log_ok 7 $MAXTEST 'logging to prelude' else log_fail 7 $MAXTEST 'logging to prelude' fi fi fi fi log_end "RUN STANDALONE W/STEALTH W/GPG" return 0 } samhain-4.1.4/test/testtimesrv.sh0000755000175000017500000002163112615253277014005 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE PIDFILE="$PW_DIR/.samhain_lock"; export PIDFILE BASE="${PW_DIR}/testrun_testdata"; export BASE TDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; export TDIRS TFILES="x y z"; export TFILES prep_testdata () { if test -d "$BASE"; then chmod -f -R 0700 "${BASE}" || { [ -z "$quiet" ] && log_msg_fail "chmod -f -R 0700 ${BASE}"; return 1; } fi rm -rf "${BASE}" || { [ -z "$quiet" ] && log_msg_fail "rm -rf ${BASE}"; return 1; } mkdir "${BASE}" || { [ -z "$quiet" ] && log_msg_fail "mkdir ${BASE}"; return 1; } for ff in $TDIRS; do mkdir "${BASE}/${ff}" || { [ -z "$quiet" ] && log_msg_fail "mkdir ${BASE}/${ff}"; return 1; } chmod 0755 "${BASE}/${ff}" for gg in $TFILES; do echo "This is a test file" > "${BASE}/${ff}/${gg}" chmod 0644 "${BASE}/${ff}/${gg}" done done } mkconfig_misc () { test -f "${RCFILE}" || touch "${RCFILE}" cat >> "${RCFILE}" <> "${RCFILE}" <> "${RCFILE}" </dev/null fi # ${TOP_SRCDIR}/configure --quiet --enable-debug --enable-xml-log --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PIDFILE --with-data-file=$PW_DIR/.samhain_file # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi prep_init && prep_testdata && echo "$TESTPOLICY" >>$RCFILE if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "prepare..."; return 1 fi ./samhain -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi chmod 0555 "${BASE}/a/x" chmod 0555 "${BASE}/b/x" ./samhain -t check -p none -l info -D count=0 until [ -f $PIDFILE ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then break; fi done if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "start daemon..."; else [ -z "$quiet" ] && log_msg_fail "start daemon..."; return 1 fi return 0 } MAXTEST=14; export MAXTEST die () { test -z "$stoponerr" && return 0; PID=`cat $PIDFILE` kill -9 $PID } killdaemon () { if [ -f $PIDFILE ]; then PID=`cat $PIDFILE` kill -9 $PID fi } check_err () { if [ ${2} -ne 0 ]; then die; [ -z "$quiet" ] && log_fail ${1} ${MAXTEST} "${3}"; return 1 else [ -z "$quiet" ] && log_ok ${1} ${MAXTEST} "${3}"; fi } daemontest_started () { PID=`cat $PIDFILE` kill -0 $PID check_err ${1} $? "started" } daemontest_sigterm () { PID=`cat $PIDFILE` kill -15 $PID count=0 while [ `kill -0 $PID` ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then check_err ${1} 1 "sigterm" return 1 fi done check_err ${1} 0 "sigterm" } daemontest_sigusr2 () { PID=`cat $PIDFILE` tmp=`grep 'File check completed' $LOGFILE | wc -l` kill -USR2 $PID kill -TTOU $PID count=0 tmp2=`grep 'SUSPEND' $LOGFILE | wc -l` while [ $tmp2 -ne $2 ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then check_err ${1} 1 "sigusr2: suspend" return 1 fi tmp2=`grep 'SUSPEND' $LOGFILE | wc -l` done kill -USR2 $PID count=0 tmp2=$tmp while [ $tmp2 -eq $tmp ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then check_err ${1} 1 "sigusr2: wakeup" return 1 fi tmp2=`grep 'File check completed' $LOGFILE | wc -l` done check_err ${1} 0 "sigusr2" } daemontest_sigttou () { PID=`cat $PIDFILE` tmp=`grep 'File check completed' $LOGFILE | wc -l` kill -TTOU $PID count=0 tmp2=$tmp while [ $tmp2 -eq $tmp ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then check_err ${1} 1 "sigttou" return 1 fi tmp2=`grep 'File check completed' $LOGFILE | wc -l` done check_err ${1} 0 "sigttou" } daemontest_sighup () { if [ $2 -eq 1 ]; then echo "dir=${BASE}/b" >>$RCFILE tmp=`grep CRIT $LOGFILE | grep -v Runtime | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "policy count (before)"; return 1 fi fi PID=`cat $PIDFILE` kill -HUP $PID if [ $2 -eq 1 ]; then kill -TTOU $PID count=0 tmp=`grep CRIT $LOGFILE | grep -v Runtime | wc -l` while [ $tmp -lt 2 ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then [ -z "$verbose" ] || log_msg_fail "policy count (after)"; return 1 fi tmp=`grep CRIT $LOGFILE | grep -v Runtime | wc -l` done fi count=0 tmp2=0 while [ $tmp2 -ne $2 ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then check_err ${1} 1 "sighup" return 1 fi tmp2=`grep 'Runtime configuration reloaded' $LOGFILE | wc -l` done check_err ${1} 0 "sighup" } daemontest_sigabrt () { PID=`cat $PIDFILE` kill -${3} $PID count=0 while [ -f $LOGFILE.lock ]; do one_sec_sleep let "count = count + 1" >/dev/null if [ $count -gt 12 ]; then check_err ${1} 1 "sigabrt" return 1 fi done kill -TTOU $PID five_sec_sleep if [ -f $LOGFILE.lock ]; then tmp=`grep '' $LOGFILE | wc -l` tst=$2; let "tst = tst + 2" >/dev/null; if [ $tmp -eq $tst ]; then check_err ${1} 0 "sigabrt" return 0 fi fi check_err ${1} 1 "sigabrt" } testtime0 () { log_start "DAEMON CONTROL" testtime0_int; tcount=1 trap 'killdaemon' 1 3 15 daemontest_started $tcount; let "tcount = tcount + 1" >/dev/null daemontest_sigttou $tcount; let "tcount = tcount + 1" >/dev/null daemontest_sigttou $tcount; let "tcount = tcount + 1" >/dev/null daemontest_sigttou $tcount; let "tcount = tcount + 1" >/dev/null daemontest_sigusr2 $tcount 1; let "tcount = tcount + 1" >/dev/null daemontest_sigusr2 $tcount 2; let "tcount = tcount + 1" >/dev/null daemontest_sigusr2 $tcount 3; let "tcount = tcount + 1" >/dev/null daemontest_sigabrt $tcount 1 ABRT; let "tcount = tcount + 1" >/dev/null daemontest_sigabrt $tcount 2 TTIN; let "tcount = tcount + 1" >/dev/null daemontest_sigabrt $tcount 3 ABRT; let "tcount = tcount + 1" >/dev/null daemontest_sighup $tcount 1; let "tcount = tcount + 1" >/dev/null daemontest_sighup $tcount 2; let "tcount = tcount + 1" >/dev/null daemontest_sighup $tcount 3; let "tcount = tcount + 1" >/dev/null daemontest_sigterm $tcount; log_end "DAEMON CONTROL" } samhain-4.1.4/test/testrc_1ext.in0000644000175000017500000001061712615253277013654 00000000000000##################################################################### # # Configuration file template for samhain. # ##################################################################### # # -- empty lines and lines starting with '#' are ignored # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # # SETUP for file system checking: # # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) To each policy, you can assign a severity (further below). # (iii) To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### [Attributes] # # for these files, only changes in permissions and ownership are checked # # # There are files in /etc that might change, thus changing the directory # timestamps. Put it here as 'file', and in the ReadOnly section as 'dir'. # [GrowingLogFiles] # # for these files, changes in signature, timestamps, and increase in size # are ignored # [ReadOnly] # # for these files, only access time is ignored # #dir=/usr/bin #dir=/bin #dir=3/etc [EventSeverity] # # Here you can assign severities to policy violations. # If this severity exceeds the treshold of a log facility (see below), # a policy violation will be logged to that facility. # # Severity for verification failures. # SeverityReadOnly=crit SeverityLogFiles=crit SeverityGrowingLogs=crit SeverityIgnoreNone=crit SeverityAttributes=crit # # We have a file in IgnoreAll that might or might not be present. # Setting the severity to 'info' prevents messages about deleted/new file. # SeverityIgnoreAll=info # # Files : file access problems # Dirs : directory access problems # Names : suspect (non-printable) characters in a pathname # SeverityFiles=crit SeverityDirs=crit SeverityNames=warn [Log] # # Set threshold severity for log facilities # Values: debug, info, notice, warn, mark, err, crit, alert, none. # 'mark' is used for timestamps. # # By default, everything equal to and above the threshold is logged. # The specifiers '*', '!', and '=' are interpreted as # 'all', 'all but', and 'only', respectively (like syslogd(8) does, # at least on Linux). # # MailSeverity=* # MailSeverity=!warn # MailSeverity==crit # MailSeverity=none PrintSeverity=none LogSeverity=none SyslogSeverity=none ExportSeverity=none ExternalSeverity=info [Utmp] # # 0 to switch off, 1 to activate # LoginCheckActive=1 # Severity for logins, multiple logins, logouts # SeverityLogin=info SeverityLoginMulti=warn SeverityLogout=info # interval for login/logout checks # LoginCheckInterval=60 [Misc] # # whether to become a daemon process Daemon=no # MessageHeader="%S %T - %F - %L :%C: " # the maximum time between client messages (seconds) # (this is a log server-only option; the default is 86400 sec = 1 day # # SetClientTimeLimit=1800 # time till next file check (seconds) SetFilecheckTime=600 # Only highest-level (alert) reports will be mailed immediately, # others will be queued. Here you can define, when the queue will # be flushed (Note: the queue is automatically flushed after # completing a file check). # # maximum time till next mail (seconds) SetMailTime=86400 # maximum number of queued mails SetMailNum=10 # where to send mail to SetMailAddress=root@localhost # mail relay host # SetMailRelay=relay.yourdomain.de # The binary. Setting the path will allow # samhain to check for modifications between # startup and exit. # # SamhainPath=/usr/local/bin/samhain # where to get time from # SetTimeServer=www.yourdomain.de # where to export logs to SetLogServer=localhost # timer for time stamps SetLoopTime=60 # report in full detail on modified files # ReportFullDetail = no # trusted users (root and the effective user are always trusted) # TrustedUser=bin # whether to test signature of files (init/check/none) # - if 'none', then we have to decide this on the command line - # ChecksumTest=init [External] samhain-4.1.4/test/testrun_1g.sh0000664000175000017500000000563312615253277013512 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # BUILDOPTS="--quiet $TRUST --enable-debug --enable-xml-log --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" export BUILDOPTS MAXTEST=1; export MAXTEST testrun_deltadb () { tcount=1 if test -r "Makefile"; then $MAKE distclean >/dev/null fi ${TOP_SRCDIR}/configure ${BUILDOPTS} if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_testpolicy 1 check_err $? ${tcount}; errval=$? fi rm "${BASE}/a/a/b/x" rm -f file.*.*-*-*-*-* ./samhain --create-database=./tmp_list_file check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then num=$( ./samhain -a -d file.*.*-*-*-*-* | grep "1970-01-01T00:00:00" >/dev/null | wc -l ) if [ $num -ne 1 ]; then [ -z "$verbose" ] || log_msg_ok "list..."; else [ -z "$quiet" ] && log_msg_fail "list..."; log_fail ${tcount} ${MAXTEST}; fi else [ -z "$quiet" ] && log_msg_fail "create..."; log_fail ${tcount} ${MAXTEST}; fi if [ $errval -eq 0 ]; then ./samhain --verify-database file.*.*-*-*-*-* fi check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then echo "o_O" > "${BASE}/a/a/b/y" ./samhain --verify-database file.*.*-*-*-*-* fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_msg_fail "detect modify..."; check_err 1 ${tcount}; errval=1 fi if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi [ -z "$cleanup" ] || rm -f file.*.*-*-*-*-* return 0 } testrun1g () { log_start "RUN CL Create DeltaDB" testrun_deltadb log_end "RUN CL Create DeltaDB" return 0 } samhain-4.1.4/test/testrun_1.sh0000755000175000017500000010436012615253277013341 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # RCFILE="$PW_DIR/testrc_1.dyn"; export RCFILE LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE # --enable-login-watch --enable-xml-log # --enable-debug --enable-suidcheck --with-prelude BUILDOPTS="--quiet $TRUST --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file --enable-debug" export BUILDOPTS BASE="${PW_DIR}/testrun_testdata"; export BASE TDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; export TDIRS TFILES="x y z"; export TFILES ########################################################### # # ---- [Define tests here] ---- # # 1 for testing new tests testrun1_setup=0 MAXTEST=15; export MAXTEST MAXTEST_3=15; export MAXTEST_3 test_dirs () { for ff in $CDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; fi # done for ff in $NDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi done } TESTPOLICY_15=" [Misc] DigestAlgo=SHA1 RedefReadOnly = +TXT [ReadOnly] dir=${BASE} " mod_testdata_15 () { mod_testdata_1 } chk_testdata_15 () { chk_testdata_1 } TESTPOLICY_14=" [Misc] DigestAlgo=MD5 RedefReadOnly = +TXT [ReadOnly] dir=${BASE} " mod_testdata_14 () { mod_testdata_1 } chk_testdata_14 () { chk_testdata_1 } # # combine file check schedule with one-shot mode # TESTPOLICY_13=" [ReadOnly] dir=99${BASE} " mod_testdata_13 () { one_sec_sleep echo "foobar" >"${BASE}/c/x"; # bad chmod 0555 "${BASE}/a/y"; # bad ORIGINAL='SetFilecheckTime=60' REPLACEMENT='FileCheckScheduleOne = 6 12 * * *' ex -s $RCFILE </dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/c/x"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] -----M--T-.*${BASE}/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/y"; return 1 fi CDIRS="a a/a a/b a/c c b a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; NDIRS=""; test_dirs; return $? } TESTPOLICY_12=" [ReadOnly] dir=99${BASE} [IgnoreAll] dir=-1${BASE}/b [Attributes] dir=1${BASE}/a " mod_testdata_12 () { one_sec_sleep echo "foobar" >"${BASE}/b/x"; # ok echo "foobar" >"${BASE}/c/x"; # bad echo "foobar" >"${BASE}/a/x"; # ok chmod 0555 "${BASE}/a/a/x"; # bad chmod 0555 "${BASE}/a/a/a/x";# ok chmod 0555 "${BASE}/a/y"; # bad } chk_testdata_12 () { # CDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 3 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/c/x"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/a/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/x"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/y"; return 1 fi CDIRS="a a/a a/b a/c c"; NDIRS="b a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; test_dirs; return $? } # # --- ACL/SELinux test case # TESTPOLICY_11=" [Misc] UseAclCheck=yes UseSelinuxCheck=yes [ReadOnly] dir=99${BASE} [IgnoreAll] dir=-1${BASE}/b [Attributes] dir=1${BASE}/a [Misc] UseSelinuxCheck = no UseAclCheck = no " mod_testdata_11 () { one_sec_sleep setfacl -m 'user:nobody:r--' "${BASE}/b/x"; # ok (ign) setfacl -m 'user:nobody:r--' "${BASE}/c/x"; # bad setfacl -m 'user:nobody:r--' "${BASE}/a/x"; # bad setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/b/y"; # ok (ign) setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/a/a/a/x";# ok (depth) setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/a/x"; # bad setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/a/y"; # bad } chk_testdata_11 () { # CDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] --------T-.*${BASE}/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/c/x"; return 1 fi CDIRS="a a/a a/b a/c c"; NDIRS="b a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; test_dirs; return $? } TESTPOLICY_10=" [Misc] UseAclCheck=yes UseSelinuxCheck=yes [ReadOnly] dir=99${BASE} [IgnoreAll] dir=-1${BASE}/b [Attributes] dir=1${BASE}/a " mod_testdata_10 () { one_sec_sleep setfacl -m 'user:nobody:r--' "${BASE}/b/x"; # ok (ign) setfacl -m 'user:nobody:r--' "${BASE}/c/x"; # bad setfacl -m 'user:nobody:r--' "${BASE}/a/x"; # bad setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/b/y"; # ok (ign) setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/a/a/a/x";# ok (depth) setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/a/x"; # bad setfattr -n 'security.selinux' -v "system_u:object_r:etc_t\000" "${BASE}/a/y"; # bad } chk_testdata_10 () { # CDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 5 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] -----M--T-.*${BASE}/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/c/x"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/x"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/y"; return 1 fi CDIRS="a a/a a/b a/c c"; NDIRS="b a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; test_dirs; return $? } TESTPOLICY_9=" [ReadOnly] dir=0${BASE}/b [Attributes] dir=2${BASE}/a/a " mod_testdata_9 () { echo "foobar" >"${BASE}/b/x"; echo "foobar" >"${BASE}/a/x"; echo "foobar" >"${BASE}/x"; } chk_testdata_9 () { # CDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi CDIRS="b a/a a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; NDIRS="a c a/b a/c"; test_dirs; return $? } TESTPOLICY_8=" [ReadOnly] dir=1${BASE} [Attributes] dir=1${BASE}/a/a " mod_testdata_8 () { echo "foobar" >"${BASE}/a/x"; chmod 0555 "${BASE}/a/a/a/b/x"; } chk_testdata_8 () { # CDIRS="a b c a/a a/b a/c a/a/a a/a/b a/a/c a/a/a/a a/a/a/b a/a/a/c"; tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi CDIRS="a b c a/a a/a/a a/a/b a/a/c"; NDIRS="a/b a/c a/a/a/a a/a/a/b a/a/a/c"; test_dirs; return $? } TESTPOLICY_7=" [ReadOnly] dir=${BASE} [Attributes] dir=${BASE}/a/a [GrowingLogFiles] dir=${BASE}/a/a/a [IgnoreAll] file=${BASE}/a/a/a/z dir=${BASE}/b [Misc] IgnoreMissing=${BASE}/a/[[:alnum:]]+/[[:alnum:]]+\$ IgnoreAdded=${BASE}/a/(b|c)/[[:alnum:]]+\$ " mod_testdata_7 () { one_sec_sleep echo "foobar" >"${BASE}/a/a/a/z" # ok echo "foobar" >"${BASE}/a/a/a/x" # bad echo "foobar" >"${BASE}/a/a/x" # ok echo "foobar" >"${BASE}/a/x" # bad chmod 0555 "${BASE}/a" # bad chmod 0555 "${BASE}/b" # ok rm "${BASE}/a/c/z" touch "${BASE}/a/c/zz2" } chk_testdata_7 () { tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 4 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi egrep "ERROR.*POLICY MISSING.*${BASE}/a/c/z" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/c/z"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/c/zz2" $LOGFILE >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/c/zz2"; return 1 fi egrep "CRIT.*POLICY \[GrowingLogs\] C--------S.*${BASE}/a/a/a/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/a/x"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] -----M--T-.*${BASE}/a" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/a/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/x"; return 1 fi } TESTPOLICY_6=" [ReadOnly] dir=${BASE} [Attributes] file=${BASE}/a/y file=${BASE}/b/y file=${BASE}/c/y file=${BASE}/a/a/y file=${BASE}/a/b/y file=${BASE}/a/c/y file=${BASE}/a/a/a/y file=${BASE}/a/a/b/y file=${BASE}/a/a/c/y file=${BASE}/a/a/a/a/y file=${BASE}/a/a/a/b/y file=${BASE}/a/a/a/c/y " mod_testdata_6 () { one_sec_sleep for ff in $TDIRS; do echo "foobar" >"${BASE}/${ff}/x" chmod 0555 "${BASE}/${ff}/y" echo "foobar" >"${BASE}/${ff}/z" done } chk_testdata_6 () { count6=0 for ff in $TDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; fi # for gg in $TFILES; do egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (checking)"; fi tmp=`egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (multiple)"; fi done egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/${ff}/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/x"; return 1 fi let "count6 = count6 + 1" >/dev/null egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/${ff}/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/z"; return 1 fi let "count6 = count6 + 1" >/dev/null egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/${ff}/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/y"; return 1 fi let "count6 = count6 + 1" >/dev/null done tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne $count6 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi } TESTPOLICY_5=" [Attributes] dir=${BASE} file=${BASE}/a/a/c/x [ReadOnly] file=${BASE}/a/a/c/y [GrowingLogFiles] dir=${BASE}/a/a/c dir=${BASE}/a/a/b dir=${BASE}/a/b " mod_testdata_5 () { mod_testdata_4 echo "1 This is a xxxx file" > "${BASE}/a/a/b/x" # GrowingLogFiles echo "1 This is a test file" > "${BASE}/a/a/b/y" # GrowingLogFiles echo "2 This is a test file" >> "${BASE}/a/a/b/y" # GrowingLogFiles echo "1 This is a xxxx file bad" > "${BASE}/a/a/b/z" # GrowingLogFiles echo "2 This is a xxxx file bad" >>"${BASE}/a/a/b/z" # GrowingLogFiles echo "3 This is a xxxx file bad" >>"${BASE}/a/a/b/z" # GrowingLogFiles } chk_testdata_5 () { for ff in $TDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; fi # for gg in $TFILES; do egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (checking)"; fi tmp=`egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (multiple)"; fi done done egrep "CRIT.*POLICY \[GrowingLogs\] C---------.*${BASE}/a/a/b/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/b/x"; return 1 fi egrep "CRIT.*POLICY \[GrowingLogs\] C---------.*${BASE}/a/a/b/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/b/z"; return 1 fi egrep "CRIT.*POLICY \[GrowingLogs\] -----M----.*${BASE}/a/b/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/z"; return 1 fi egrep "CRIT.*POLICY \[GrowingLogs\] -----M----.*${BASE}/a/a/c/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/z"; return 1 fi egrep "CRIT.*POLICY \[GrowingLogs\] C--------S.*${BASE}/a/b/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/y"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/a/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/x"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/c/foo" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/foo"; return 1 fi egrep "CRIT.*POLICY ADDED.*033\[1;30m" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/\033[1;30m"; return 1 fi egrep "WARN.*Weird filename.*033\[1;30m" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/\033[1;30m"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/a/a/c/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/y"; return 1 fi tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 9 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi } TESTPOLICY_4=" [Attributes] dir=${BASE} file=${BASE}/a/a/c/x [ReadOnly] file=${BASE}/a/a/c/y [LogFiles] dir=${BASE}/a/a/c dir=${BASE}/a/b " mod_testdata_4 () { one_sec_sleep echo "foobar" >> "${BASE}/a/a/x" # Attributes echo "foobar" > "${BASE}/a/a/c/foo" # new within LogFiles echo "foobar" >> "${BASE}/a/a/c/y" # ReadOnly echo "foobar" >> "${BASE}/a/a/c/x" # Attributes chmod 0555 "${BASE}/a/a/c/x" # Attributes chmod 0555 "${BASE}/a/a/c/z" # LogFiles echo "foobar" >> "${BASE}/a/b/x" # LogFiles echo "" > "${BASE}/a/b/y" # LogFiles chmod 0555 "${BASE}/a/b/z" # LogFiles touch "${BASE}/a/a/" # non-printable character in filename } chk_testdata_4 () { for ff in $TDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; fi # for gg in $TFILES; do egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (checking)"; fi tmp=`egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (multiple)"; fi done done egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/a/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/x"; return 1 fi egrep "CRIT.*POLICY \[LogFiles\] -----M----.*${BASE}/a/b/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/z"; return 1 fi egrep "CRIT.*POLICY \[LogFiles\] -----M----.*${BASE}/a/a/c/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/z"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/c/foo" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/foo"; return 1 fi egrep "CRIT.*POLICY ADDED.*033\[1;30m" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/\033[1;30m"; return 1 fi egrep "WARN.*Weird filename.*033\[1;30m" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/\033[1;30m"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/a/a/c/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/y"; return 1 fi tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 6 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi } TESTPOLICY_3=" [Attributes] dir=${BASE} file=${BASE}/a/a/c/x [ReadOnly] file=${BASE}/a/a/c/y [IgnoreAll] dir=${BASE}/a/a/c " mod_testdata_3 () { one_sec_sleep echo "foobar" > "${BASE}/a/b/foo" # new within Attributes chmod 0555 "${BASE}/a/b" echo "foobar" > "${BASE}/a/a/c/foo" # new within IgnoreAll echo "foobar" > "${BASE}/a/a/c/y" # ReadOnly chmod 0555 "${BASE}/a/a/c/x" # Attributes chmod 0555 "${BASE}/a/a/c/z" # IgnoreAll } chk_testdata_3 () { for ff in $TDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; fi # for gg in $TFILES; do egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (checking)"; fi tmp=`egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (multiple)"; fi done done egrep "CRIT.*POLICY ADDED.*${BASE}/a/b/foo" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/foo"; return 1 fi egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/c/foo" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/foo"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/b" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b"; return 1 fi egrep "CRIT.*POLICY \[Attributes\] -----M----.*${BASE}/a/a/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/x"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/a/a/c/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/y"; return 1 fi tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 5 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi } TESTPOLICY_2=" [ReadOnly] dir=${BASE} file=${BASE}/a/a/c/x [IgnoreAll] dir=${BASE}/a/a/c " mod_testdata_2 () { # mod_testdata_1; one_sec_sleep touch "${BASE}/a/a/x" chmod 0555 "${BASE}/a/a/y" mv "${BASE}/a/b/y" "${BASE}/a/b/yy"; echo "1 This is a test file" > "${BASE}/a/b/y"; echo "2 This is a test file" >> "${BASE}/a/b/y"; echo "4 This is a test file" >> "${BASE}/a/b/z"; rm "${BASE}/a/b/yy"; # mv/rm to force new inode rm "${BASE}/a/b/l_y"; ln -s "${BASE}/a/b/x" "${BASE}/a/b/l_y"; echo "foobar" > "${BASE}/a/c/y" rm "${BASE}/a/a/c/y" echo "foobar" > "${BASE}/a/a/c/foo" chmod 0555 "${BASE}/a/a/c/x" chmod 0555 "${BASE}/a/a/c/z" } chk_testdata_2 () { for ff in $TDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; fi # for gg in $TFILES; do egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then if [ x"${ff}/${gg}" = x"a/a/c/y" ]; then :; else [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (checking)"; return 1 fi fi done done egrep "CRIT.*POLICY ADDED.*${BASE}/a/a/c/foo" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/foo"; return 1 fi egrep "CRIT.*POLICY MISSING.*${BASE}/a/a/c/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/y"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] -----M--T-.*${BASE}/a/a/c/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/c/x"; return 1 fi tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 10 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi } TESTPOLICY_1=" [Misc] RedefReadOnly = +TXT [ReadOnly] dir=${BASE} " mod_testdata_1 () { one_sec_sleep touch "${BASE}/a/a/x" chmod 0555 "${BASE}/a/a/y" mv "${BASE}/a/b/y" "${BASE}/a/b/yy"; echo "1 This is a test file" > "${BASE}/a/b/y"; echo "2 This is a test file" >> "${BASE}/a/b/y"; echo "4 This is a test file" >> "${BASE}/a/b/z"; rm "${BASE}/a/b/yy"; # mv/rm to force new inode rm "${BASE}/a/b/l_y"; ln -s "${BASE}/a/b/x" "${BASE}/a/b/l_y"; echo "foobar" > "${BASE}/a/c/y" # mv "${BASE}/b/x" "${BASE}/b/xx"; # mv/rm to force new inode mkdir "${BASE}/b/x" rm "${BASE}/b/xx"; # mv "${BASE}/b/y" "${BASE}/b/yy"; # mv/rm to force new inode ln -s "${BASE}/b/z" "${BASE}/b/y" rm "${BASE}/b/yy"; # rm "${BASE}/b/l_x"; echo "1 This is a test file" > "${BASE}/b/l_x"; } chk_testdata_1 () { for ff in $TDIRS; do # egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (checking)"; return 1 fi tmp=`egrep "Checking.*${BASE}/${ff}(>|\")" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff} (multiple)"; return 1 fi # for gg in $TFILES; do egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then if [ "${BASE}/${ff}" != "${BASE}/b" ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (checksum)"; return 1 fi fi tmp=`egrep "Checksum.*${BASE}/${ff}/${gg}" $LOGFILE 2>/dev/null | wc -l` if [ $tmp -ne 1 ]; then if [ "${BASE}/${ff}" != "${BASE}/b" ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/${ff}/${gg} (multiple)"; return 1 fi fi done done # # # egrep "CRIT.*POLICY \[ReadOnly\] ----H---T-.*${BASE}/b" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/b"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] CL-I-M--TS.*${BASE}/b/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/b/y"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] CL-.-M--TS.*${BASE}/b/l_x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/b/l_x"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C--IHM--TS.*${BASE}/b/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/b/x"; return 1 fi # # # egrep "CRIT.*POLICY \[ReadOnly\] --------T-.*${BASE}/a/a/x" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/x"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] -----M--T-.*${BASE}/a/a/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/a/y"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] ---I----T-.*${BASE}/a/b/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/y"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] -L-I----T-.*${BASE}/a/b/l_y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/l_y"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] --------T-.*${BASE}/a/b" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/a/b/z" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/b/z"; return 1 fi egrep "CRIT.*POLICY \[ReadOnly\] C-------TS.*${BASE}/a/c/y" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "${BASE}/a/c/y"; return 1 fi tmp=`grep CRIT $LOGFILE | wc -l` if [ $tmp -ne 11 ]; then [ -z "$verbose" ] || log_msg_fail "policy count"; return 1 fi for ff in x y z; do ./samhain --list-file "${BASE}/a/a/${ff}" -d "$PW_DIR/.samhain_file" > "$PW_DIR/.samhain_tmp" diff "$PW_DIR/.samhain_tmp" "${BASE}/a/a/${ff}" >/dev/null if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "diff $PW_DIR/.samhain_tmp ${BASE}/a/a/${ff}" return 1 fi done return 0 } ############################################################## # # Common subroutines # mkconfig_misc () { test -f "${RCFILE}" || touch "${RCFILE}" cat >> "${RCFILE}" <> "${RCFILE}" <> "${RCFILE}" <>"${RCFILE}" } prep_init () { rm -f ./.samhain_file rm -f "${LOGFILE}" rm -f ./.samhain_lock rm -f "${RCFILE}" mkconfig_sev mkconfig_log mkconfig_misc } run_init () { rm -f test_log_valgrind ${VALGRIND} ./samhain -t init -p none 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi } run_check () { if [ "x$1" = "x" ]; then logsev=debug else logsev=$1 fi ${VALGRIND} ./samhain -t check -p none -l $logsev 2>>test_log_valgrind if test x$? = x0; then ./samhain -j -L $LOGFILE >"${LOGFILE}.tmp" && mv "${LOGFILE}.tmp" "${LOGFILE}" if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_msg_fail "mv logfile..."; return 1 fi [ -z "$verbose" ] || log_msg_ok "check..."; else [ -z "$quiet" ] && log_msg_fail "check..."; return 1 fi } run_update () { ${VALGRIND} ./samhain -t update -p none -l debug 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "update..."; else [ -z "$quiet" ] && log_msg_fail "update..."; return 1 fi } run_check_after_update () { rm -rf $LOGFILE ${VALGRIND} ./samhain -t check -p none -l debug 2>>test_log_valgrind if test x$? = x0; then # tmp=`./samhain -j -L $LOGFILE | grep CRIT | wc -l` if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "update not successful(?)"; return 1 fi # # wtmp may not be readable # tmp=`./samhain -j -L $LOGFILE | grep ERR | grep -v wtmp | wc -l` if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "errors during check"; return 1 fi # [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } # [ -z "$verbose" ] || log_msg_ok "check(2)..."; else [ -z "$quiet" ] && log_msg_fail "check(2)..."; return 1 fi } prep_testdata () { if test -d "$BASE"; then if [ -d "${BASE}" ]; then chmod -f -R 0700 "${BASE}" || { [ -z "$quiet" ] && log_msg_fail "chmod -f -R 0700 ${BASE}"; return 1; } fi fi rm -rf "${BASE}" || { [ -z "$quiet" ] && log_msg_fail "rm -rf ${BASE}"; return 1; } mkdir "${BASE}" || { [ -z "$quiet" ] && log_msg_fail "mkdir ${BASE}"; return 1; } echo "${BASE}" > ./tmp_list_file for ff in $TDIRS; do mkdir "${BASE}/${ff}" || { [ -z "$quiet" ] && log_msg_fail "mkdir ${BASE}/${ff}"; return 1; } echo "${BASE}/${ff}" >> ./tmp_list_file chmod 0755 "${BASE}/${ff}" for gg in $TFILES; do echo "1 This is a test file" > "${BASE}/${ff}/${gg}" chmod 0644 "${BASE}/${ff}/${gg}" echo "${BASE}/${ff}/${gg}" >> ./tmp_list_file ln -s "${BASE}/${ff}/${gg}" "${BASE}/${ff}/l_${gg}" echo "${BASE}/${ff}/l_${gg}" >> ./tmp_list_file done echo "2 This is a test file" >> "${BASE}/${ff}/y" echo "2 This is a test file" >> "${BASE}/${ff}/z" echo "3 This is a test file" >> "${BASE}/${ff}/z" done } check_err () { if [ $1 -ne 0 ]; then log_fail ${2} ${MAXTEST}; return 1 fi return 0 } testrun_internal () { [ -z "$verbose" ] || echo Working directory: $PW_DIR [ -z "$verbose" ] || { echo MAKE is $MAKE; echo; } # # test standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } if test -r "Makefile"; then $MAKE distclean >/dev/null fi ${TOP_SRCDIR}/configure ${BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Running test suite${E}"; echo; } tcount=1 POLICY=`eval echo '"$'"TESTPOLICY_$tcount"'"'` until [ ${tcount} -gt ${MAXTEST_3} ] do prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_testpolicy ${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval mod_testdata_${tcount} check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval chk_testdata_${tcount} check_err $? ${tcount}; errval=$? fi if [ $testrun1_setup -eq 0 ]; then if [ $errval -eq 0 ]; then run_update check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check_after_update check_err $? ${tcount}; errval=$? fi fi # if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi # let "tcount = tcount + 1" >/dev/null # if [ $tcount -eq 10 ]; then if [ -z "$doall" ]; then log_skip 10 $MAXTEST 'ACL/SELinux test (or use --really-all)' log_skip 11 $MAXTEST 'ACL/SELinux test (or use --really-all)' let "tcount = tcount + 2" >/dev/null else # 'id -u' is posix # if test -f /usr/xpg4/bin/id then my_uid=`/usr/xpg4/bin/id -u` else my_uid=`id -u` fi # if [ ${my_uid} -ne 0 ]; then log_skip 10 $MAXTEST 'ACL/SELinux test (you are not root)' log_skip 11 $MAXTEST 'ACL/SELinux test (you are not root)' let "tcount = tcount + 2" >/dev/null else SETFATTR=`find_path setfattr` if [ -z "$SETFATTR" ]; then log_skip 10 $MAXTEST 'ACL/SELinux test (setfattr not in path)' log_skip 11 $MAXTEST 'ACL/SELinux test (setfattr not in path)' let "tcount = tcount + 2" >/dev/null fi fi fi fi # POLICY=`eval echo '"$'"TESTPOLICY_$tcount"'"'` done return 0 } testrun1 () { log_start "RUN STANDALONE" testrun_internal log_end "RUN STANDALONE" return 0 } samhain-4.1.4/test/testrun_2.sh0000755000175000017500000005002412665106460013333 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE RCFILE="$PW_DIR/testrc_2"; export RCFILE HTML="$PW_DIR/yule.html"; export HTML do_test_1 () { [ -z "$verbose" ] || { echo; echo "${S}Start Server${E}: ./yule -l info -p none &"; echo; } rm -f test_log_valgrind ${VALGRIND} ./yule.2 -l info -p none >/dev/null 2>>test_log_valgrind & PROC_Y2=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Server #2${E}: ./yule.2 -l info -p none &"; echo; } ${VALGRIND} ./yule -l info -p none -e info --bind-address=127.0.0.1 \ --server-port=49778 >/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -l none -p none -e info -t check"; echo; } ${VALGRIND} ./samhain.new -t check -p none -l none -e info --bind-address=127.0.0.1 >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "samhain.new -t check"; else [ -z "$quiet" ] && log_msg_fail "samhain.new -t check"; kill $PROC_Y kill $PROC_Y2 return 1 fi kill $PROC_Y kill $PROC_Y2 five_sec_sleep # cp ${LOGFILE} triple_test # cp ${LOGFILE}2 triple_test_2 egrep "START(>|\").*Yule(>|\")" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server #2 start"; return 1 fi egrep "remote_host.*Checking.*/bin" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (relayed)"; return 1 fi egrep "remote_host.*EXIT.*Samhain" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit (relayed)"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server #2 exit"; return 1 fi egrep "START(>|\").*Yule(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "remote_host.*Checking.*/bin" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "remote_host.*EXIT.*Samhain" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } return 0 } do_test_2 () { ORIGINAL="UseSeparateLogs=no" REPLACEMENT="UseSeparateLogs=yes" ex -s $RCFILE </dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -l none -p none -e info -t check"; echo; } ${VALGRIND} ./samhain.new -t check -p none -l none -e info --bind-address=127.0.0.1 >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "samhain.new -t check"; else [ -z "$quiet" ] && log_msg_fail "samhain.new -t check"; kill $PROC_Y return 1 fi kill $PROC_Y five_sec_sleep if [ -f ${LOGFILE}.${SH_LOCALHOST} ]; then remhost=${SH_LOCALHOST} else remhost=`echo $SH_LOCALHOST | sed 's,\..*,,'` fi if [ -f ${LOGFILE}.${remhost} ]; then CLIENTLOG="${LOGFILE}.${remhost}" else tail -n 1 ${SCRIPTDIR}/test.sh >/dev/null 2>&1 if [ $? -eq 0 ]; then CLIENTLOG=`ls -1 ${LOGFILE}.* 2>/dev/null | tail -n 1` else CLIENTLOG=`ls -1 ${LOGFILE}.* 2>/dev/null | tail -1` fi fi egrep "START(>|\").*Yule(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "remote_host.*Checking.*/bin" ${CLIENTLOG} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "remote_host.*EXIT.*Samhain" ${CLIENTLOG} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } rm -f ${LOGFILE}.${remhost} return 0 } do_test_3 () { ORIGINAL_1="ExportSeverity=none" REPLACEMENT_1="ExportSeverity=mark" ORIGINAL_2="UseSeparateLogs=yes" REPLACEMENT_2="UseSeparateLogs=no" ORIGINAL_3="LogSeverity=none" REPLACEMENT_3="LogSeverity=debug" ORIGINAL_4="# SetClientTimeLimit=1800" REPLACEMENT_4="SetClientTimeLimit=20" # takes too much time if we leave that in ORIGINAL_5="dir=1" REPLACEMENT_5="#dir=1" ex -s $RCFILE </dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -t check -p none -l none --forever --bind-address=127.0.0.1 &"; echo; } ${VALGRIND} ./samhain.new -t check -p none -l none --forever --bind-address=127.0.0.1 >/dev/null 2>>test_log_valgrind & if test x$? = x0; then PROC_S=$! # echo "PID is ${PROC_S}" [ -z "$verbose" ] || log_msg_ok "samhain.new -t check"; five_sec_sleep # Redirect the shells (un-)helpful job monitoring messages. # The 'disown' buildin is not portable. { kill -9 ${PROC_S}; sleep 40; } >/dev/null 2>&1 else [ -z "$quiet" ] && log_msg_fail "samhain.new -t check"; kill $PROC_Y return 1 fi if [ -t 0 ]; then # enable monitor mode again if interactive set -m fi kill $PROC_Y five_sec_sleep egrep "START(>|\").*Yule(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "remote_host.*File check completed.*" ${LOGFILE} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "Time limit exceeded" ${LOGFILE} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client dead detection"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } rm -f ${LOGFILE} return 0 } do_test_4 () { # don't know what is supported on the test platform, so # prepare for both (password and socket credential) # 'id -u' is posix if test -f /usr/xpg4/bin/id then me=`/usr/xpg4/bin/id -u` else me=`id -u` fi ORIGINAL_1="SetSocketAllowUid=0" REPLACEMENT_1="SetSocketAllowUid=$me" ex -s $RCFILE </dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -l none -p none -e info -t check"; echo; } $MAKE yulectl >/dev/null if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "make yulectl"; kill $PROC_Y return 1 fi ./yulectl -v -c RELOAD foobar1 >test_log_yulectl 2>/dev/null if [ $? -ne 0 ]; then YULECTL_PASSWORD=samhain; export YULECTL_PASSWORD ./yulectl -v -c RELOAD foobar1 >test_log_yulectl if [ $? -ne 0 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "yulectl"; return 1 fi fi ./yulectl -v -c RELOAD foobar2 >test_yulectl_log if [ $? -ne 0 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "yulectl"; return 1 fi ./yulectl -v -c RELOAD foobar3 >test_log_yulectl if [ $? -ne 0 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "yulectl"; return 1 fi ./yulectl -v -c LISTALL dummy >test_log_yulectl if [ $? -ne 0 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "yulectl"; return 1 fi tmp=`cat test_log_yulectl | grep RELOAD | wc -l` if [ $tmp -ne 3 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "command confirmation"; return 1 fi ./yulectl -v -c CANCEL foobar3 >test_log_yulectl if [ $? -ne 0 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "yulectl"; return 1 fi ./yulectl -v -c LISTALL dummy >test_log_yulectl if [ $? -ne 0 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "yulectl"; return 1 fi tmp=`cat test_log_yulectl | grep RELOAD | wc -l` if [ $tmp -ne 2 ]; then kill ${PROC_Y} [ -z "$verbose" ] || log_msg_fail "command confirmation"; return 1 fi kill ${PROC_Y} one_sec_sleep one_sec_sleep kill -9 ${PROC_Y} >/dev/null 2>&1 [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } return 0 } do_test_5 () { [ -z "$verbose" ] || { echo; echo "${S}Start Server${E}: ./yule -l info -p none &"; echo; } ( cat < test Current time: %T
EOF ) >head.html ( cat <
EOF ) >foot.html ( cat < %H %S %T EOF ) >entry.html ${VALGRIND} ./yule -l info -p none -e none \ >/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep egrep '' $HTML >/dev/null 2>&1 if [ $? -ne 0 ]; then # rm -f head.html; rm -f foot.html; rm -f entry.html; kill $PROC_Y [ -z "$verbose" ] || log_msg_fail "head.html (1)"; return 1 fi egrep '' $HTML >/dev/null 2>&1 if [ $? -ne 0 ]; then rm -f head.html; rm -f foot.html; rm -f entry.html; kill $PROC_Y [ -z "$verbose" ] || log_msg_fail "foot.html (1)"; return 1 fi [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -l none -p none -e info -t check"; echo; } ${VALGRIND} ./samhain.new -t check -p none -l none -e info --bind-address=127.0.0.1 >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "samhain.new -t check"; else kill $PROC_Y [ -z "$quiet" ] && log_msg_fail "samhain.new -t check"; return 1 fi cp $HTML ${HTML}.tmp kill $PROC_Y five_sec_sleep # rm -f head.html; rm -f foot.html; rm -f entry.html; egrep "START(>|\").*Yule(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "remote_host.*Checking.*/bin" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "remote_host.*EXIT.*Samhain" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi egrep '' ${HTML}.tmp >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "head.html"; return 1 fi egrep '' ${HTML}.tmp >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "end head.html"; return 1 fi egrep '' ${HTML}.tmp >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "entry.html"; return 1 fi egrep '' ${HTML}.tmp >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "end entry.html"; return 1 fi egrep '' ${HTML}.tmp >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "foot.html"; return 1 fi egrep '' ${HTML}.tmp >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "end foot.html"; return 1 fi [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } rm ${HTML}.tmp return 0 } testrun2_internal () { [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo; } # # [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet $TRUST --enable-debug --enable-network=client --enable-xml-log --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file --enable-encrypt=2 --enable-static # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # save binary and build server2 # cp samhain samhain.build || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure --quiet $TRUST --enable-debug --enable-network=server --enable-xml-log --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=${RCFILE}2 --with-log-file=${LOGFILE}2 --with-pid-file=$PW_DIR/.samhain_lock2 --with-html-file=${HTML}2 --with-state-dir=$PW_DIR --enable-encrypt=2 --with-port=49778 # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # save binary and build server # cp yule yule.2 || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure --quiet $TRUST --enable-debug --enable-network=server --enable-xml-log --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-html-file=$HTML --with-state-dir=$PW_DIR --enable-encrypt=2 # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi ##################################################################### # # rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock cp ${SCRIPTDIR}/testrc_2.in testrc_2 ./samhain.build -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi # Create a password SHPW=`./yule -G` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi # Set in client ./samhain_setpwd samhain.build new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd samhain.build new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd samhain.build new $SHPW"; return 1 fi mv samhain.build.new samhain.new || return 1 # Set in server ./samhain_setpwd yule new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd yule new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd yule new $SHPW"; return 1 fi mv yule.new yule || return 1 # rm -f ./.samhain_log* rm -f ./.samhain_lock* SHCLT=`./yule -P $SHPW` if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "yule -P $SHPW"; else [ -z "$quiet" ] && log_msg_fail "yule -P $SHPW"; return 1 fi SHCLT1=`echo "${SHCLT}" | sed s%HOSTNAME%${SH_LOCALHOST}%` AHOST=`find_hostname` SHCLT2=`echo "${SHCLT}" | sed s%HOSTNAME%${AHOST}%` echo $SHCLT1 >> testrc_2 echo $SHCLT2 >> testrc_2 cp testrc_2 testrc_22 do_test_1 if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Client logging"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Client logging"; fi do_test_2 if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 2 ${MAXTEST} "Client logging, separate logfiles"; else [ -z "$quiet" ] && log_fail 2 ${MAXTEST} "Client logging, separate logfiles"; fi do_test_3 if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 3 ${MAXTEST} "Dead client detection"; else [ -z "$quiet" ] && log_fail 3 ${MAXTEST} "Dead client detection"; fi do_test_4 if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 4 ${MAXTEST} "Server command socket"; else [ -z "$quiet" ] && log_fail 4 ${MAXTEST} "Server command socket"; fi do_test_5 if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 5 ${MAXTEST} "Server status file"; else [ -z "$quiet" ] && log_fail 5 ${MAXTEST} "Server status file"; fi return $? } MAXTEST=5; export MAXTEST testrun2 () { log_start "RUN CLIENT/SERVER" if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi # SH_LOCALHOST=$1; export SH_LOCALHOST # testrun2_internal # log_end "RUN CLIENT/SERVER" return 0 } samhain-4.1.4/test/gnupg/0000775000175000017500000000000012615253277012254 500000000000000samhain-4.1.4/test/gnupg/secring.gpg0000644000175000017500000000252312543560173014321 00000000000000U~*"l!J-vќ83pi< *r}0IؔtRbhSs*]#eǟ CJer"lO=cRf$+do卽Րڐs'*S%0C4Wd+S[&%sܻ௅ОՔZ6躴ZݱY]BpL[YV7k1hV%BR +_7nE@"_v>Aԫ ~/Dd<:,Tc!CK&`24 YiJr3;yϪq⬨v6rNU٦?$'Zeq&k]*fs :?Z@oVnrbUìp_נ@2".x(1=AWrᙶҋƱ8Testsuite Samhain (testing only) "U~   NٞN 3zmw)h0cNz- ݀VK4It1!.l{tw62SP +Q|W˧ulDPF+nBvRoڞ$,G[l3O,*S+焱 |nL+!= ǰU~/s!d- *g)~uK]`-da3=[>x~ZdxMSs U:_gV[\s}u"!PABT m}Ǚe'^=yl^21q&?`a:N)bUue*€ٛK G4לw14n=<ūc'ܲ (em U~ NٞN 3zMIx6IQ͈J HggZi(Pg.×jb!dssamhain-4.1.4/test/gnupg/trustdb.gpg0000644000175000017500000000240012543560173014350 00000000000000gpgU0  ˻f%Y+:NٞN 3z ~B e%D6mdsamhain-4.1.4/test/gnupg/random_seed0000644000175000017500000000113012543560173014364 00000000000000wҨAI531l tl ?_Tϔ\eXOA;)F3N\T6~ݩ7(BHh1qvgG&e??C΋h{6,0+a\EIu! F X6GQޅw lb:Cן@*x[:tX/4'+ S .ߴZVW -k%~ξƱߩ]P{]'\?+f0(ZRjEǍWXݏ>*n/s:@^~F;)'eaSk'^hE |%[ Ax82fkwVPF"gOS,}lhv>RK9t^𭺷0w$Lj-qA.c"YV/عZKoh;p&gDI4]h;H"U~   NٞN 3zmw)h0cNz- ݀VK4It1!.l{tw62SP +Q|W˧ulDPF+nBvRoڞ$,G[l3O,*S+焱 |nL+!= ǰU~/s!d- *g)~uK]`-da3=[>x~ZdxMSs U:_gV[dssamhain-4.1.4/test/gnupg/secret-key.asc0000664000175000017500000000362012543560173014734 00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1 lQHYBFWNfvQBBADIKiKabMHXIdBKyy120Zw4AjMIcGk8nZ7uDcL8gxkqcvt9jg8E gpQwvknYlP7cf4B06hWlUt1iaPSnBIBTc5MqXSNlmMef2QlDSmVyImyS3MBPPZoX +WOBr+r1UmYFt54fjyQrpmRv5Y29F9WQ2pBztNwRECfVHyqPGpC4U50lmwARAQAB AAP+MLRD8DRXZCvnnVNb0CYHr38lgL+tc6Dcu4rgr4WMuY350J6g29WUDlo26Lq0 Wt2xWYFd2/jSQnBMW1lWije8jmuc58sx/Gi3uuNWtSXPQlIK7aa3K6nlX+sXN24C w0VAIpNfpXYPPkHUq8YKyPV+9a32LxxE2gG+ZDzQfzrlLPUCANtU22P0IYtDSyaW 7WCB5rjU7aAywDTC3gXuCVntaZLySpnBcjPlO3n4z6rD/qvsnPqPceKsqLaydrY2 4s/YcscCAOmg9PpOVZ7Zpj+7BYgkGCcT+lrzzGWhFXHtJhCxa10qZuDZc7kKoDo/ /FpAtm9WbuLBu3LuEsC1taiXYhUcoo0CAIcVVYHpw6yGcNpf+NegQDLAudYiCLzK Lvt4KKns7gIQse3PBzGKuNc98X+MQVf2iL/35XIF/eGZtoObrPLSi8axnbQ4VGVz dHN1aXRlIFNhbWhhaW4gKHRlc3Rpbmcgb25seSkgPG5vLXJlcGx5QGxhLXNhbWhu YS5kZT6IuAQTAQIAIgUCVY1+9AIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA CgkQTtmeTooLM3rxvQP8D7KSbXcpaOowY05/pIXqCKt6Lae/EgyQ3YBWSzRJdDEh ty79bO575+F0dzYHMlOeULqH2X/lFQ0rn4Pr41F8V8LLp3VsRKhQyUYrr25CdlJv 2p6miYmizcr0JBqwoCxHW4TWbDNPhLss9yqPUxYrBOeEsQp8bsjmj0wrIT3gC8ed AdgEVY1+9AEEAL37L+v5AKOrFspzgpKj450XIelkLdkKlqqR7yrQZ+nZKZ9+4nWj xs/f+tJLwR9/XeK8YMktpvJkvGHzMz21Wz54iq8EfsTy6fRawfVkePxNAAZTcwf4 DfCCVTpfEtJnVqoWWzy6elqbkgViLB346jLTUenm6cy8OhBfd5DAibfJABEBAAEA A/sE2qaqTlXsWKI/8Pycl5Bowp8MshET0xfvasQkIWgOSwyrtRe/LryVMiFb/zCD iAMTmIGWklKKLfW8QPUFth0LK8c02jIRvCRAc8lr3V+CGmTqxWCPsYWnHxIINc03 wECMbFHLCAUlKelN/DJIKoI0LJJVvzYEy5xt9SvNBJiW6wIAzKgYNJNAgRvQOeb5 MxKjCybYoUjFKOfdAaJkTwE0xuSaxap5ZUUfIADXT/C6SpbAfywIBFj8gYrwyPPo a4eGcwIA7aSTYyglPlzXc9AbfRh1jiIT4/QhUL1BBvtCVAkfbX1/x5llHCf64bJe /j15bBJeGzLAjMIxcSblP4/IYGG90wIA44bpOk4G8Smt3NfDYviixhHSVXXc+GUq woCV09mbSwpHNBek7Nec+c53MTRuoj2XPMWrYyeX3LIVDShlbaWWopiziJ8EGAEC AAkFAlWNfvQCGwwACgkQTtmeTooLM3pNSQP/eDZJ91HczYhKIKdIZ2egWmm5KJP5 sVC8pmfl1i6ww5dqYvOJrCE8TtbYonGd5z/M6IXRa37Rax9c3aFOYZ/hoBobJPRa 4Y9IF2HgUW2eDRNRFFaHmP8X3vE/rkQMWumNHb5c1bAVB9BAHdC+hBlFPhvRHYtk /Nhz7I3mDoPlCOk= =5aNq -----END PGP PRIVATE KEY BLOCK----- samhain-4.1.4/test/gnupg/public-key.asc0000664000175000017500000000201412543560173014721 00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mI0EVY1+9AEEAMgqIppswdch0ErLLXbRnDgCMwhwaTydnu4NwvyDGSpy+32ODwSC lDC+SdiU/tx/gHTqFaVS3WJo9KcEgFNzkypdI2WYx5/ZCUNKZXIibJLcwE89mhf5 Y4Gv6vVSZgW3nh+PJCumZG/ljb0X1ZDakHO03BEQJ9UfKo8akLhTnSWbABEBAAG0 OFRlc3RzdWl0ZSBTYW1oYWluICh0ZXN0aW5nIG9ubHkpIDxuby1yZXBseUBsYS1z YW1obmEuZGU+iLgEEwECACIFAlWNfvQCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B AheAAAoJEE7Znk6KCzN68b0D/A+ykm13KWjqMGNOf6SF6girei2nvxIMkN2AVks0 SXQxIbcu/Wzue+fhdHc2BzJTnlC6h9l/5RUNK5+D6+NRfFfCy6d1bESoUMlGK69u QnZSb9qepomJos3K9CQasKAsR1uE1mwzT4S7LPcqj1MWKwTnhLEKfG7I5o9MKyE9 4AvHuI0EVY1+9AEEAL37L+v5AKOrFspzgpKj450XIelkLdkKlqqR7yrQZ+nZKZ9+ 4nWjxs/f+tJLwR9/XeK8YMktpvJkvGHzMz21Wz54iq8EfsTy6fRawfVkePxNAAZT cwf4DfCCVTpfEtJnVqoWWzy6elqbkgViLB346jLTUenm6cy8OhBfd5DAibfJABEB AAGInwQYAQIACQUCVY1+9AIbDAAKCRBO2Z5Oigszek1JA/94Nkn3UdzNiEogp0hn Z6Baabkok/mxULymZ+XWLrDDl2pi84msITxO1tiicZ3nP8zohdFrftFrH1zdoU5h n+GgGhsk9Frhj0gXYeBRbZ4NE1EUVoeY/xfe8T+uRAxa6Y0dvlzVsBUH0EAd0L6E GUU+G9Edi2T82HPsjeYOg+UI6Q== =C5Xk -----END PGP PUBLIC KEY BLOCK----- samhain-4.1.4/test/testrun_2a.sh0000755000175000017500000002032612666635075013510 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE RCFILE="$PW_DIR/testrc_2"; export RCFILE SERVER_BUILDOPTS="--quiet $TRUST --enable-network=server --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER$PW_DIR/testrc_2 --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-logserver=${SH_LOCALHOST} --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --enable-debug=gdb"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="--quiet $TRUST --enable-network=client --enable-srp --prefix=$PW_DIR --with-tmp-dir=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER$RCFILE --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --enable-suidcheck --enable-debug"; export CLIENT_BUILDOPTS do_test_1_a () { [ -z "$verbose" ] || { echo; echo "${S}Start Server${E}: ./yule -l info -p none &"; echo; } rm -f test_log_valgrind ${VALGRIND} ./yule -l info -p none >/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -l none -p none -e info -t check --bind-address=127.0.0.1 --server-host=localhost"; echo; } ${VALGRIND} ./samhain.new -t check -p none -l none -e info --bind-address=127.0.0.1 --server-host=localhost >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "samhain.new -t check"; else [ -z "$quiet" ] && log_msg_fail "samhain.new -t check"; kill $PROC_Y return 1 fi kill $PROC_Y five_sec_sleep egrep "START(>|\").*Yule(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "Checking.*/etc" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "EXIT.*Samhain" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } return 0 } testrun2a_internal () { [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo; } # # [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure ${CLIENT_BUILDOPTS} # # Limit suid check # BASE="${PW_DIR}"; export BASE # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE 'DBGDEF=-DSH_SUIDTESTDIR=\"${BASE}\"' > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # save binary and build server # cp samhain samhain.build || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure ${SERVER_BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi ##################################################################### # # rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} rm -f "./rc.${ALTHOST}" rm -f "./file.${ALTHOST}" cp ${SCRIPTDIR}/testrc_2.in testrc_2 ./samhain.build -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi # Create a password SHPW=`./yule -G` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi # Set in client ./samhain_setpwd samhain.build new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd samhain.build new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd samhain.build new $SHPW"; return 1 fi mv samhain.build.new samhain.new || return 1 rm -f ./.samhain_log* rm -f ./.samhain_lock SHCLT=`./yule -P $SHPW` if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "yule -P $SHPW"; else [ -z "$quiet" ] && log_msg_fail "yule -P $SHPW"; return 1 fi SHCLT1=`echo "${SHCLT}" | sed s%HOSTNAME%${SH_LOCALHOST}%` AHOST=`find_hostname` SHCLT2=`echo "${SHCLT}" | sed s%HOSTNAME%${AHOST}%` echo $SHCLT1 >> testrc_2 echo $SHCLT2 >> testrc_2 cp ./testrc_2 ./rc.${SH_LOCALHOST} mv ./.samhain_file ./file.${SH_LOCALHOST} chmod 644 ./rc.${SH_LOCALHOST} chmod 644 ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` cp ./testrc_2 "./rc.${ALTHOST}" cp ./file.${SH_LOCALHOST} "./file.${ALTHOST}" 2>/dev/null chmod 644 ./rc.${ALTHOST} chmod 644 ./file.${ALTHOST} echo $SHPW > ./testpw } MAXTEST=4; export MAXTEST testrun2a () { log_start "RUN FULL CLIENT/SERVER"; # if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi # SH_LOCALHOST=$1; export SH_LOCALHOST # testrun2a_internal do_test_1_a if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Client download+logging"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Client download+logging"; fi ####### EXIT HERE FOR TESTING ###### # # SERVER_BUILDOPTS_ORIG="${SERVER_BUILDOPTS}" CLIENT_BUILDOPTS_ORIG="${CLIENT_BUILDOPTS}" # SERVER_BUILDOPTS="${SERVER_BUILDOPTS_ORIG} --disable-srp"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="${CLIENT_BUILDOPTS_ORIG} --disable-srp"; export CLIENT_BUILDOPTS # testrun2a_internal do_test_1_a if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 2 ${MAXTEST} "SRP disabled"; else [ -z "$quiet" ] && log_fail 2 ${MAXTEST} "SRP disabled"; fi # SERVER_BUILDOPTS="${SERVER_BUILDOPTS_ORIG} --disable-encrypt"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="${CLIENT_BUILDOPTS_ORIG} --disable-encrypt"; export CLIENT_BUILDOPTS # testrun2a_internal do_test_1_a if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 3 ${MAXTEST} "Encryption disabled"; else [ -z "$quiet" ] && log_fail 3 ${MAXTEST} "Encryption disabled"; fi # SERVER_BUILDOPTS="${SERVER_BUILDOPTS_ORIG} --disable-ipv6"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="${CLIENT_BUILDOPTS_ORIG} --disable-ipv6"; export CLIENT_BUILDOPTS # testrun2a_internal do_test_1_a if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 4 ${MAXTEST} "IPv6 disabled"; else [ -z "$quiet" ] && log_fail 4 ${MAXTEST} "IPv6 disabled"; fi # if [ -n "$cleanup" ]; then rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` rm -f "./file.${ALTHOST}" rm -f "./rc.${ALTHOST}" fi # log_end "RUN FULL CLIENT/SERVER" } samhain-4.1.4/test/testrun_2b.sh0000755000175000017500000001434212615253277013504 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE RCFILE="$PW_DIR/testrc_2"; export RCFILE RCFILE_C="$PW_DIR/testrc_1.dyn"; export RCFILE_C SERVER_BUILDOPTS="--quiet $TRUST --enable-network=server --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER$PW_DIR/testrc_2 --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-logserver=${SH_LOCALHOST} --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="--quiet $TRUST --enable-micro-stealth=137 --enable-debug --enable-network=client --enable-srp --prefix=$PW_DIR --with-tmp-dir=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER${RCFILE_C} --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-logserver=localhost --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock"; export CLIENT_BUILDOPTS testrun2b_internal () { GPG="$1" [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo GPG is $GPG; echo; } [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } if test -r "Makefile"; then $MAKE distclean fi ${TOP_SRCDIR}/configure --with-gpg=${GPG} --with-checksum=no ${CLIENT_BUILDOPTS} >/dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi SKIP=`awk '/^__ARCHIVE_FOLLOWS__/ { print NR + 1; exit 0; }' ${SCRIPTDIR}/test.sh` tail -n "+$SKIP" ${SCRIPTDIR}/test.sh >/dev/null 2>&1 if [ $? -eq 0 ]; then tail -n "+$SKIP" ${SCRIPTDIR}/test.sh | gunzip -c - 2>/dev/null | tar xf - && \ mv "./testrc.gpg.asc" "${RCFILE_C}" else tail "+$SKIP" ${SCRIPTDIR}/test.sh | gunzip -c - 2>/dev/null | tar xf - && \ mv "./testrc.gpg.asc" "${RCFILE_C}" fi if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "extract gpg signed files..."; else [ -z "$quiet" ] && log_msg_fail "extract gpg signed files..."; return 1 fi # save binary and build server cp samhain samhain.build || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure ${SERVER_BUILDOPTS} if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi ##################################################################### # # rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} cp ${SCRIPTDIR}/testrc_2.in testrc_2 ./samhain.build -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi # Create a password SHPW=`./yule -G` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi # Set in client ./samhain_setpwd samhain.build new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd samhain.build new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd samhain.build new $SHPW"; return 1 fi mv samhain.build.new samhain.new || return 1 rm -f ./.samhain_log* rm -f ./.samhain_lock SHCLT=`./yule -P $SHPW` if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "yule -P $SHPW"; else [ -z "$quiet" ] && log_msg_fail "yule -P $SHPW"; return 1 fi SHCLT1=`echo "${SHCLT}" | sed s%HOSTNAME%${SH_LOCALHOST}%` AHOST=`find_hostname` SHCLT2=`echo "${SHCLT}" | sed s%HOSTNAME%${AHOST}%` echo $SHCLT1 >> testrc_2 echo $SHCLT2 >> testrc_2 cp "${RCFILE_C}" ./rc.${SH_LOCALHOST} mv $PW_DIR/.samhain_file.asc ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` cp "${RCFILE_C}" "./rc.${ALTHOST}" cp ./file.${SH_LOCALHOST} "./file.${ALTHOST}" 2>/dev/null } MAXTEST=1; export MAXTEST testrun2b () { log_start "RUN FULL CLIENT/SERVER W/GPG"; # if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi # GPG=`find_path gpg` if [ -z "$GPG" ]; then log_skip 1 $MAXTEST 'gpg not found in $PATH' else eval "$GPG" --list-keys 0F571F6C >/dev/null 2>/dev/null if [ $? -ne 0 ]; then log_skip 1 $MAXTEST 'public PGP key 0x0F571F6C not present' else SH_LOCALHOST=$1; export SH_LOCALHOST testrun2b_internal "$GPG" SAVE_VALGRIND="${VALGRIND}"; VALGRIND=''; export VALGRIND do_test_1_a VALGRIND="${SAVE_VALGRIND}"; export VALGRIND if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Client download+logging w/gpg"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Client download+logging w/gpg"; fi if [ -n "$cleanup" ]; then rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` rm -f "./file.${ALTHOST}" rm -f "./rc.${ALTHOST}" fi fi fi log_end "RUN FULL CLIENT/SERVER W/GPG" } samhain-4.1.4/test/testtiger.txt0000644000175000017500000000234212615253277013626 00000000000000Test results of the TIGER hash algorithm (use samhain -H string to test) string=<>, hash=<24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A> string=, hash= string=, hash=<9F00F599072300DD276ABB38C8EB6DEC37790C116F9D2BDF> string=, hash=<87FB2A9083851CF7470D2CF810E6DF9EB586445034A5A386> string=, hash=<467DB80863EBCE488DF1CD1261655DE957896565975F9197> string=, hash=<0C410A042968868A1671DA5A3FD29A725EC1E457D3CDB303> string=, hash= string=, hash=<3D9AEB03D1BD1A6357B2774DFD6D5B24DD68151D503974FC> string=, hash=<00B83EB4E53440C576AC6AAEE0A7485825FD15E70A59FFE4> samhain-4.1.4/test/testrc_2.in.asc0000664000175000017500000001164712615253277013707 00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 NotDashEscaped: You need GnuPG to verify this message ##################################################################### # # Configuration file template for samhain. # ##################################################################### # # -- empty lines and lines starting with '#' are ignored # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # # SETUP for file system checking: # # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) To each policy, you can assign a severity (further below). # (iii) To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### [ReadOnly] # # for these files, only access time is ignored # # dir=/usr/bin # dir=/bin file = /var file = /bin file = /usr file = /tmp file = /etc # hopefully does not exist file=/etc/toodleedoo dir=1/usr [EventSeverity] # # Here you can assign severities to policy violations. # If this severity exceeds the treshold of a log facility (see below), # a policy violation will be logged to that facility. # # Severity for verification failures. # SeverityReadOnly=crit SeverityLogFiles=crit SeverityGrowingLogs=crit SeverityIgnoreNone=crit SeverityAttributes=crit # # We have a file in IgnoreAll that might or might not be present. # Setting the severity to 'info' prevents messages about deleted/new file. # SeverityIgnoreAll=info # # Files : file access problems # Dirs : directory access problems # Names : suspect (non-printable) characters in a pathname # SeverityFiles=crit SeverityDirs=crit SeverityNames=warn [Log] # # Set threshold severity for log facilities # Values: debug, info, notice, warn, mark, err, crit, alert, none. # 'mark' is used for timestamps. # # By default, everything equal to and above the threshold is logged. # The specifiers '*', '!', and '=' are interpreted as # 'all', 'all but', and 'only', respectively (like syslogd(8) does, # at least on Linux). # # MailSeverity=* # MailSeverity=!warn # MailSeverity==crit # MailSeverity=none PrintSeverity=info #PRINTClass = "RUN FIL STAMP" LogSeverity=none SyslogSeverity=none ExportSeverity=none DatabaseSeverity=none #databaseseverity=info [Database] # setdbname=samhain # setdbtable=log setdbuser=samhain setdbpassword=samhain #AddToDBHash=log_msg # AddToDBHash=log_host UsePersistent = True [Utmp] # # 0 to switch off, 1 to activate # LoginCheckActive=1 # Severity for logins, multiple logins, logouts # SeverityLogin=info SeverityLoginMulti=warn SeverityLogout=info # interval for login/logout checks # LoginCheckInterval=60 [Misc] # # whether to become a daemon process Daemon=no SetOutgoingIP = 127.0.0.1 SetServerInterface = 127.0.0.1 UseSeparateLogs=no SetUseSocket = yes SetSocketAllowUid=0 SetSocketPassword=samhain SetClientFromAccept = yes SetUdpActive=no # the maximum time between client messages (seconds) # (this is a log server-only option; the default is 86400 sec = 1 day # # SetClientTimeLimit=1800 UseClientSeverity = yes UseClientClass = yes # Format for message headers # # MessageHeader="%S %T %F %L " # priority for peer != address as notified by client # (lookup may fail on firewalled client) # # SeverityLookup = warn # time till next file check (seconds) SetFilecheckTime=600 # Only highest-level (alert) reports will be mailed immediately, # others will be queued. Here you can define, when the queue will # be flushed (Note: the queue is automatically flushed after # completing a file check). # # maximum time till next mail (seconds) SetMailTime=86400 # maximum number of queued mails SetMailNum=10 # where to send mail to SetMailAddress=root@localhost # mail relay host # SetMailRelay=relay.yourdomain.de # The binary. Setting the path will allow # samhain to check for modifications between # startup and exit. # # SamhainPath=/usr/local/bin/samhain # where to get time from # SetTimeServer=www.yourdomain.de # where to export logs to SetLogServer=localhost # timer for time stamps SetLoopTime=10 # trusted users (root and the effective user are always trusted) # TrustedUser=bin # whether to test signature of files (init/check/none) # - if 'none', then we have to decide this on the command line - # ChecksumTest=check [Clients] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEARECAAYFAlUTGCcACgkQGq0myA9XH2zINACfQb/Wfa19OBbHVkw9uBNMB+lF cwUAnR0Geb+sFDcv7JsrrTjY8htjPHd2 =7wXO -----END PGP SIGNATURE----- samhain-4.1.4/test/testcompile.sh0000755000175000017500000006550312615253277013752 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # dnmalloc + cppcheck + flawfinder + (38 * 2) - 8 MAXTEST=79; export MAXTEST run_dnmalloc () { fail=0 if test x$1 = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE clean > /dev/null 2>> test_log $MAKE test_dnmalloc > /dev/null 2>> test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make test_dnmalloc..."; else [ -z "$quiet" ] && log_msg_fail "make test_dnmalloc..."; fail=1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; if [ x"$3" = xskip ]; then [ -z "$quiet" ] && log_skip $2 ${MAXTEST} "test dnmalloc"; fi fail=1 fi if [ $fail -eq 1 ]; then [ -z "$quiet" ] && log_fail $2 ${MAXTEST} "test dnmalloc"; return 1 fi # fail=0 ./test_dnmalloc >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "run 1 completed..."; ./test_dnmalloc 300 12 3000 150000 400 >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "run 2 completed..."; ./test_dnmalloc 1 1 4000 10000000 1000 >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "run 3 completed..."; ./test_dnmalloc 1 1 4000 10000000 1000 >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "run 4 completed..."; else fail=1 fi else fail=1 fi else fail=1 fi else fail=1 fi # if test x$fail = x0; then [ -z "$quiet" ] && log_ok $2 ${MAXTEST} "test dnmalloc"; return 0 else [ -z "$quiet" ] && log_fail $2 ${MAXTEST} "test dnmalloc"; return 1 fi } run_cppcheck () { # CPC=`find_path cppcheck` # if [ -z "$CPC" ]; then log_skip $num ${MAXTEST} 'check w/cppcheck (not in PATH)' return 0 fi # cd src/ stat=`cppcheck --quiet --inline-suppr --force -j 4 --template="{file},{line},{severity},{id},{message}" -I. -I.. -I../include sh_*.c samhain.c slib.c dnmalloc.c zAVLTree.c trustfile.c rijndael-*.c bignum.c 2>&1 | wc -l` if [ $stat -ne 0 ]; then cppcheck --quiet --inline-suppr --force -j 4 --template="{file},{line},{severity},{id},{message}" -I. -I.. -I../include sh_*.c samhain.c slib.c dnmalloc.c zAVLTree.c trustfile.c rijndael-*.c bignum.c >>../test_log 2>&1 retval=1 [ -z "$quiet" ] && log_fail $2 ${MAXTEST} "check w/cppcheck"; else retval=0 [ -z "$quiet" ] && log_ok $2 ${MAXTEST} "check w/cppcheck"; fi cd .. return $retval } run_flawfinder () { flawfinder --minlevel=3 --quiet src/s*.c | \ egrep '^No hits found.' >/dev/null 2>&1 if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok $2 ${MAXTEST} "$TEST"; else flawfinder --minlevel=3 --quiet src/s*.c >test_log 2>&1 [ -z "$quiet" ] && log_fail $2 ${MAXTEST} "$TEST"; return 1 fi } run_clang () { export CDIR=`pwd`; if [ -z "$doall" ]; then [ -z "$quiet" ] && log_skip $2 ${MAXTEST} "$TEST (clang)"; return 0 fi CLANGPATH=`find_path clang` if [ -n "$CLANGPATH" ]; then CLANG_CC="$CLANGPATH"; export CLANG_CC else [ -z "$quiet" ] && log_skip $2 ${MAXTEST} "$TEST (clang)"; return 0 fi SAVE_TEST="$TEST" TEST="$TEST (clang)" testmake $1 $2 retval=$? CLANG_CC=""; export CLANG_CC TEST="$SAVE_TEST" return $retval } testmake () { fail=0 # # Compiler warnings can be OS specific, but at least # on Linux there should be none # isLinux=0 uname -a | grep Linux >/dev/null if [ $? -eq 0 ]; then isLinux=1 sed --in-place 's/-Wall/-Wall -Werror -Wpointer-arith -Wcast-qual/' Makefile fi # if test x$1 = x0; then [ -z "$verbose" ] || log_msg_ok "configure... $TEST"; $MAKE clean > /dev/null 2>> test_log if [ -z "$CLANG_CC" ]; then $MAKE cutest > /dev/null 2>> test_log else sed --in-place 's/-Wno-empty-body/-Wno-empty-body -Wno-invalid-source-encoding/g' Makefile sed --in-place 's/-fno-strength-reduce//g' Makefile $MAKE -e CC=$CLANG_CC -e BUILD_CC=$CLANG_CC cutest > /dev/null 2>> test_log fi if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make cutest... $TEST"; else [ -z "$quiet" ] && log_msg_fail "make cutest... $TEST"; fail=1 fi else [ -z "$quiet" ] && log_msg_fail "configure... $TEST"; if [ x"$3" = xskip ]; then [ -z "$quiet" ] && log_skip $2 ${MAXTEST} "$TEST"; fi fail=1 fi if [ $isLinux -eq 1 ]; then sed --in-place 's/-Wall -Werror/-Wall/' Makefile fi if [ $fail -eq 1 ]; then [ -z "$quiet" ] && log_fail $2 ${MAXTEST} "$TEST"; return 1 fi [ -z "$quiet" ] && log_ok $2 ${MAXTEST} "$TEST"; return 0 } testcompile () { log_start "COMPILE" num=0 numfail=0 C_LOGFILE="" ls /lib/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " else ls /usr/lib/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " else ls /usr/lib/*/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " else ls /usr/local/lib/libpcre* >/dev/null 2>&1 if [ $? -eq 0 ]; then C_LOGFILE=" --enable-logfile-monitor " fi fi fi fi if [ x"${C_LOGFILE}" = x ]; then log_msg_ok "Not testing --enable-logfile-monitor"; fi # # test dnmalloc # TEST="${S}check dnmalloc${E}" # ${TOP_SRCDIR}/configure --quiet > /dev/null 2>> test_log # let "num = num + 1" >/dev/null # run_dnmalloc 0 $num || let "numfail = numfail + 1" >/dev/null # # # test dnmalloc # TEST="${S}check w/cppcheck${E}" # let "num = num + 1" >/dev/null # run_cppcheck 0 $num || let "numfail = numfail + 1" >/dev/null # # # test flawfinder # TEST="${S}check w/flawfinder${E}" # # let "num = num + 1" >/dev/null FLAWFINDER=`find_path flawfinder` # if [ -z "$FLAWFINDER" ]; then log_skip $num $MAXTEST 'check w/flawfinder (not in PATH)' else run_flawfinder 0 $num || let "numfail = numfail + 1" >/dev/null fi # # # test standalone compilation # TEST="${S}standalone w/suidcheck w/procchk${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-suidcheck --enable-process-check > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone static w/suidcheck w/procchk${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-static --enable-suidcheck --enable-process-check ${C_LOGFILE} > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/procchk w/portchk${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-process-check --enable-port-check > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/procchk w/portchk w/static${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-process-check --enable-port-check --enable-static > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/procchk w/portchk w/stealth${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-stealth=164 --enable-process-check --enable-port-check > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/mounts-check w/userfiles${E}" # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-mounts-check --enable-userfiles > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/timeserver and w/msgqueue${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --enable-message-queue --with-timeserver=127.0.0.1 > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation with --with-nocl=PW # TEST="${S}standalone w/nocl w/logmon${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --enable-nocl="owl" --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test ${C_LOGFILE} > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/ debug # TEST="${S}standalone w/debug${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-debug --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num debug || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/ gpg # TEST="${S}standalone w/gpg${E}" # GPG=`find_path gpg` let "num = num + 1" >/dev/null # if [ -z "$GPG" ]; then log_skip $num $MAXTEST 'gpg not in PATH' let "num = num + 1" >/dev/null log_skip $num $MAXTEST 'gpg not in PATH' else if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --with-gpg=$GPG --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null fi # # test standalone compilation w/stealth # TEST="${S}standalone w/stealth${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-stealth=128 --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/loginwatch # TEST="${S}standalone w/login-watch${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/mysql # TEST="${S}standalone w/mysql${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-xml-log --with-database=mysql --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num "skip" || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/mysql and stealth # TEST="${S}standalone w/mysql+stealth${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-xml-log --enable-stealth=128 --with-database=mysql --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num "skip" || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/postgresql # TEST="${S}standalone w/postgresql${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-xml-log --with-database=postgresql --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num "skip" || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation w/postgresql+stealth # TEST="${S}standalone w/postgresql+stealth${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-xml-log --enable-stealth=128 --with-database=postgresql --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num "skip" || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/o mail w/unix_rnd${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --disable-mail --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-rnd=unix > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test standalone compilation # TEST="${S}standalone w/o external${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --disable-external-scripts --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # echo; echo "${S}__ TEST CLIENT/SERVER __${E}"; echo; # # test client/server compilation # TEST="${S}client/server application w/timeserver${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --enable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-timeserver=127.0.0.1 > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-timeserver=127.0.0.1 > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test client/server compilation w/prelude # TEST="${S}client/server application w/prelude${E}" # if [ -z "$doall" ]; then let "num = num + 1" >/dev/null [ -z "$quiet" ] && log_skip $num ${MAXTEST} "$TEST"; let "num = num + 1" >/dev/null [ -z "$quiet" ] && log_skip $num ${MAXTEST} "$TEST (smatch)"; let "num = num + 1" >/dev/null [ -z "$quiet" ] && log_skip $num ${MAXTEST} "$TEST"; let "num = num + 1" >/dev/null [ -z "$quiet" ] && log_skip $num ${MAXTEST} "$TEST (smatch)"; else if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --enable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-prelude > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-prelude > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # fi # # test client/server compilation # TEST="${S}client/server application static w/timeserver${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --enable-static --enable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-timeserver=127.0.0.1 ${C_LOGFILE} > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-static --enable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test --with-timeserver=127.0.0.1 > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test c/s compilation w/ gpg # TEST="${S}client/server application w/gpg${E}" # GPG=`find_path gpg` let "num = num + 1" >/dev/null # if [ -z "$GPG" ]; then log_skip $num $MAXTEST 'gpg not in PATH' let "num = num + 1" >/dev/null log_skip $num $MAXTEST 'gpg not in PATH' let "num = num + 1" >/dev/null log_skip $num $MAXTEST 'gpg not in PATH' let "num = num + 1" >/dev/null log_skip $num $MAXTEST 'gpg not in PATH' else if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-srp --with-gpg=$GPG --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --enable-srp --with-gpg=$GPG --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test ${C_LOGFILE} > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null fi # # test client/server compilation # TEST="${S}client/server application w/o srp, w/udp${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-udp --disable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --disable-srp --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test client/server compilation w/ debug # TEST="${S}client/server application w/debug${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-debug --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num debug || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --enable-debug --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test ${C_LOGFILE} > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num debug || let "numfail = numfail + 1" >/dev/null # # test client/server compilation w/stealth # TEST="${S}client/server application w/stealth${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-srp --enable-stealth=128 --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --enable-srp --enable-stealth=128 --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test client/server compilation w/logwatch # TEST="${S}client/server application w/login-watch,udp,no_ipv6${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --enable-udp --disable-ipv6 --enable-srp --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --disable-ipv6 --enable-srp --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # # test client/server compilation # TEST="${S}client/server application w/o mail${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --disable-mail --enable-srp --enable-stealth=128 --enable-debug --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num debug || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --disable-mail --enable-srp --enable-stealth=128 --enable-debug --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num debug || let "numfail = numfail + 1" >/dev/null # # test client/server compilation # TEST="${S}client/server application w/o external${E}" # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=server --disable-srp --disable-external-scripts --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null # if test -r "Makefile"; then $MAKE clean fi # ${TOP_SRCDIR}/configure --quiet --enable-network=client --disable-srp --disable-external-scripts --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/samhainrc.test > /dev/null 2>> test_log # let "num = num + 1" >/dev/null testmake $? $num || let "numfail = numfail + 1" >/dev/null let "num = num + 1" >/dev/null run_clang $? $num || let "numfail = numfail + 1" >/dev/null log_end "COMPILE" } samhain-4.1.4/test/testext.sh0000755000175000017500000001040412615253277013110 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # MAXTEST=2; export MAXTEST testext0 () { COMP=`which gcc` if test "x$?" = x1 ; then COMP="cc" else COMP=`which gcc | sed -e "s%\([a-z:]\) .*%\1%g"` if test "x$COMP" = x; then COMP="cc" elif test "x$COMP" = xno; then COMP="cc" else if test "x$COMP" = "xwhich:"; then COMP="cc" else COMP="gcc" gcc -v >/dev/null 2>&1 || COMP="gcc" fi fi fi log_start "EXTERNAL PROGRAM" [ -z "$verbose" ] || echo MAKE is $MAKE [ -z "$verbose" ] || { echo COMP is $COMP; echo; } # # standalone compilation # [ -z "$verbose" ] || { echo; echo "${S}Building standalone agent${E}"; echo; } # if test -r "Makefile"; then ${MAKE} distclean >/dev/null fi # ${TOP_SRCDIR}/configure --quiet --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$PW_DIR/testrc_1ext --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # # prepare the program # cat test/test_ext.c.in | sed -e "s%MYPWDIR%$PW_DIR/test_ext.res%g" > test_ext.c ${COMP} -o test_ext test_ext.c if test "x$?" != x0; then log_msg_fail "${COMP} -o test_ext test_ext.c" return 1 fi chmod +rx test_ext if test "x$?" != x0; then log_msg_fail "chmod +rx test_ext" return 1 fi # compute checksum and fix config file # cp test/testrc_1ext.in testrc_1ext CHKSUM=`./samhain -H $PW_DIR/test_ext | awk '{ print $2$3$4$5$6$7}'` echo "OpenCommand=$PW_DIR/test_ext" >> testrc_1ext echo "SetType=log" >> testrc_1ext echo "SetChecksum=$CHKSUM" >> testrc_1ext echo "SetEnviron=TZ=Europe/Berlin" >> testrc_1ext echo "SetFilterOr=ALERT" >> testrc_1ext echo "CloseCommand" >> testrc_1ext echo "OpenCommand=$PW_DIR/test_ext" >> testrc_1ext echo "SetType=log" >> testrc_1ext echo "SetChecksum=$CHKSUM" >> testrc_1ext echo "SetFilterOr=ALERT" >> testrc_1ext echo "CloseCommand" >> testrc_1ext rm -f $PW_DIR/test_ext.res rm -f $PW_DIR/pdbg.child rm -f $PW_DIR/pdbg.main ./samhain -p none # The shell is too fast ... one_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Logged by external C program test_ext (filtered: ALERT only):${E}"; echo; cat $PW_DIR/test_ext.res echo } tmp=`cat $PW_DIR/test_ext.res | wc -l` if [ $tmp -eq 8 ]; then tmp=`egrep 'RECV: \[EOF\]' $PW_DIR/test_ext.res | wc -l` if [ $tmp -eq 4 ]; then tmp=`egrep 'RECV: ALERT' $PW_DIR/test_ext.res | wc -l` if [ $tmp -eq 4 ]; then log_ok 1 ${MAXTEST}; else log_fail 1 ${MAXTEST}; fi else log_fail 1 ${MAXTEST}; fi else log_fail 1 ${MAXTEST}; fi ORIGINAL="SetChecksum=${CHKSUM}" REPLACEMENT="SetChecksum=DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF" ex -s "$PW_DIR/testrc_1ext" < "${BASE}/$dd/change" rm -f "${BASE}/$dd/rmthis" echo "added" > "${BASE}/$dd/addedthis" echo "${BASE}/$dd" >> "${TEST_LIST}" echo "${BASE}/$dd/change" >> "${TEST_LIST}" echo "${BASE}/$dd/rmthis" >> "${TEST_LIST}" echo "${BASE}/$dd/addedthis" >> "${TEST_LIST}" done } do_test_2_g_yule_start () { [ -z "$verbose" ] || { echo; echo "${S}Start Server${E}: ./yule -l info -p none &"; echo; } rm -f test_log_valgrind # SetSocketAllowUid=$(id -u) # if test -f /usr/xpg4/bin/id; then MY_ID=$(/usr/xpg4/bin/id -u) else MY_ID=$(id -u) fi # sed -i -e "s/SetSocketAllowUid=0/SetSocketAllowUid=${MY_ID}/g" $RCFILE # Start server # ${VALGRIND} ./yule -l info -p none >/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -t check -D .. &"; echo; } ${VALGRIND} ./samhain.new -t check -D -p none -l none -e info --bind-address=127.0.0.1 --server-host=localhost >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "starting samhain.new"; else [ -z "$quiet" ] && log_msg_fail "starting samhain.new"; kill $PROC_Y return 1 fi five_sec_sleep PROC_S=$( ps aux | grep samhain.new | grep -v grep | awk '{ print $2; }' ) for ff in 1 2; do five_sec_sleep done egrep "File check completed" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; kill $PROC_S; kill $PROC_Y; return 1 fi NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (1)"; kill $PROC_S; kill $PROC_Y; return 1 fi return 0 } do_test_2_g_two () { # # >>> Modify files # mod_files # if ! test -f ${TEST_LIST}; then [ -z "$verbose" ] || log_msg_fail "No file list created"; kill $PROC_S; kill $PROC_Y; return 1 fi # # # >>> Trigger a scan # kill -TTOU $PROC_S if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Kill -TTOU"; kill $PROC_S; kill $PROC_Y; return 1 fi for ff in 1 2 3; do five_sec_sleep done NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "sigttou"; NR=$( egrep "POLICY" $LOGFILE | grep ReadOnly | wc -l ) if [ $NR -ne 8 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (ReadOnly)"; kill $PROC_S; kill $PROC_Y; return 1 fi NR=$( egrep "POLICY" $LOGFILE | grep ADDED | wc -l ) if [ $NR -ne 4 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (added)"; kill $PROC_S; kill $PROC_Y; return 1 fi NR=$( egrep "POLICY" $LOGFILE | grep MISSING | wc -l ) if [ $NR -ne 4 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (removed)"; kill $PROC_S; kill $PROC_Y; return 1 fi kill $PROC_S; kill $PROC_Y; return 0 } do_test_2_g_one () { # # >>> (1) Modify files, create DeltaDB from file list in ${TEST_LIST} # mod_files # if ! test -f ${TEST_LIST}; then [ -z "$verbose" ] || log_msg_fail "No file list created"; kill $PROC_S; kill $PROC_Y; return 1 fi # ./samhain.new --outfile ./file.delta --create-database "${TEST_LIST}" # if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Create DeltaDB"; kill $PROC_S; kill $PROC_Y; return 1 fi if ! test -f ./file.delta; then [ -z "$verbose" ] || log_msg_fail "No DeltaDB created"; kill $PROC_S; kill $PROC_Y; return 1 fi # # >>> (2) Copy to server and tag with a UUID # UUID=$(uuidgen) mv ./file.delta file.${SH_LOCALHOST}.${UUID} cp file.${SH_LOCALHOST}.${UUID} "./file.${ALTHOST}.${UUID}" # # >>> (3) Tell client to load delta database. # >>> testrc_2: timestamps every 10 sec # grep '^SetLoopTime=10$' rc.${SH_LOCALHOST} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "SetLoopTime != 10 in rc.${SH_LOCALHOST}"; kill $PROC_S; kill $PROC_Y; return 1 fi grep '^SetLoopTime=10$' rc.${ALTHOST} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "SetLoopTime != 10 in rc.${ALTHOST}"; kill $PROC_S; kill $PROC_Y; return 1 fi ./yulectl -c "DELTA:${UUID}" ${SH_LOCALHOST} if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (1)"; kill $PROC_S; kill $PROC_Y; return 1 fi ./yulectl -c "DELTA:${UUID}" ${ALTHOST} if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi NR=$( ./yulectl -c LIST | grep ${UUID} | grep -v grep | wc -l ) if [ $NR -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (3)"; [ -z "$verbose" ] || ./yulectl -c LIST kill $PROC_S; kill $PROC_Y; return 1 fi # Wait and verify that command has been sent # for tt in 1 2 3 4; do five_sec_sleep done # NR=$( ./yulectl -c LIST | grep ${UUID} | grep -v grep | wc -l ) if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (4)"; [ -z "$verbose" ] || ./yulectl -c LISTALL kill $PROC_S; kill $PROC_Y; return 1 fi # # >>> (4) Trigger a scan # kill -TTOU $PROC_S if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Kill -TTOU"; kill $PROC_S; kill $PROC_Y; return 1 fi for ff in 1 2; do five_sec_sleep done NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "sigttou"; NR=$( egrep "POLICY" $LOGFILE | wc -l ) if [ $NR -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (3)"; kill $PROC_S; kill $PROC_Y; return 1 fi # --- The End --- kill $PROC_S; kill $PROC_Y return 0 } do_test_2_g_three () { # # >>> (1) Modify files, create DeltaDB from file list in ${TEST_LIST} # mod_files # if ! test -f ${TEST_LIST}; then [ -z "$verbose" ] || log_msg_fail "No file list created"; kill $PROC_S; kill $PROC_Y; return 1 fi # ./samhain.new --outfile ./file.delta --create-database "${TEST_LIST}" # if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Create DeltaDB"; kill $PROC_S; kill $PROC_Y; return 1 fi if ! test -f ./file.delta; then [ -z "$verbose" ] || log_msg_fail "No DeltaDB created"; kill $PROC_S; kill $PROC_Y; return 1 fi # # >>> (2) Copy to server and tag with a UUID # UUID=$(uuidgen) if [ x"$1" != "xnosig" ]; then scripts/samhainadmin.pl -s ./test/gnupg/ -k 8A0B337A -m E ./file.delta >/dev/null fi if [ x"$1" == "xnodelta" ]; then rm -f ./file.* else mv ./file.delta file.${SH_LOCALHOST}.${UUID} cp file.${SH_LOCALHOST}.${UUID} "./file.${ALTHOST}.${UUID}" fi # # >>> (3) Tell client to load delta database. # >>> testrc_2: timestamps every 10 sec # grep '^SetLoopTime=10$' rc.${SH_LOCALHOST} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "SetLoopTime != 10 in rc.${SH_LOCALHOST}"; kill $PROC_S; kill $PROC_Y; return 1 fi grep '^SetLoopTime=10$' rc.${ALTHOST} >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "SetLoopTime != 10 in rc.${ALTHOST}"; kill $PROC_S; kill $PROC_Y; return 1 fi ./yulectl -c "DELTA:${UUID}" ${SH_LOCALHOST} if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (1)"; kill $PROC_S; kill $PROC_Y; return 1 fi ./yulectl -c "DELTA:${UUID}" ${ALTHOST} if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi NR=$( ./yulectl -c LIST | grep ${UUID} | grep -v grep | wc -l ) if [ $NR -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (3)"; [ -z "$verbose" ] || ./yulectl -c LIST kill $PROC_S; kill $PROC_Y; return 1 fi # Wait and verify that command has been sent # for tt in 1 2 3 4; do five_sec_sleep done # NR=$( ./yulectl -c LIST | grep ${UUID} | grep -v grep | wc -l ) if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "yulectl (4)"; [ -z "$verbose" ] || ./yulectl -c LISTALL kill $PROC_S; kill $PROC_Y; return 1 fi # # >>> (4) Trigger a scan # kill -TTOU $PROC_S if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Kill -TTOU"; kill $PROC_S; kill $PROC_Y; return 1 fi for ff in 1 2; do five_sec_sleep done if [ x"$1" != x ]; then if [ x"$1" = xnodelta ]; then NR=$( egrep "File download failed" $LOGFILE | wc -l ) else NR=$( egrep "No good signature" $LOGFILE | wc -l ) fi if [ $NR -ne 1 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (expected fail)"; kill $PROC_S; kill $PROC_Y; return 1 else [ -z "$verbose" ] || log_msg_ok "Client file check (expected fail)"; kill $PROC_S; kill $PROC_Y; return 0 fi fi NR=$( egrep "File check completed" $LOGFILE | wc -l ) if [ $NR -ne 2 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (2)"; kill $PROC_S; kill $PROC_Y; return 1 fi [ -z "$verbose" ] || log_msg_ok "sigttou"; NR=$( egrep "POLICY" $LOGFILE | wc -l ) if [ $NR -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (3)"; kill $PROC_S; kill $PROC_Y; return 1 fi # --- The End --- kill $PROC_S; kill $PROC_Y return 0 } testrun2g_prepare () { ##################################################################### # # Create test area and initialize database # rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock rm -f ./rc.${SH_LOCALHOST} rm -f ./rc.${ALTHOST} rm -f ./file.* # rm -rf ${BASE} # mkdir ${BASE} 2>/dev/null for dd in ${TEST_DIRS}; do mkdir ${BASE}/$dd for ff in ${TEST_FILES}; do echo "foobar" > ${BASE}/$dd/$ff done done # ./samhain.build -t init -p none if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "init..."; else [ -z "$quiet" ] && log_msg_fail "init..."; return 1 fi } testrun2g_build () { [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo; } # # [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } # if test -r "Makefile"; then $MAKE distclean fi # ${TOP_SRCDIR}/configure ${CLIENT_BUILDOPTS} $1 $2 >/dev/null 2>&1 # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # save binary and build server # cp samhain samhain.build || return 1 $MAKE clean >/dev/null || return 1 ${TOP_SRCDIR}/configure ${SERVER_BUILDOPTS} # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi # Create a password SHPW=`./yule -G` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi # Set in client ./samhain_setpwd samhain.build new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd samhain.build new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd samhain.build new $SHPW"; return 1 fi mv samhain.build.new samhain.new || return 1 rm -f ./.samhain_log* rm -f ./.samhain_lock SHCLT=`./yule -P $SHPW` if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "yule -P $SHPW"; else [ -z "$quiet" ] && log_msg_fail "yule -P $SHPW"; return 1 fi SHCLT1=`echo "${SHCLT}" | sed s%HOSTNAME%${SH_LOCALHOST}%` AHOST=`find_hostname` SHCLT2=`echo "${SHCLT}" | sed s%HOSTNAME%${AHOST}%` cp ${SCRIPTDIR}/testrc_2.in testrc_2 # sed --in-place -e 's,file = /tmp,dir = 99/tmp/testrun_samhain,g' testrc_2 # sed --in-place -e 's,SetUdpActive=no,ReportCheckflags=yes,g' testrc_2 # echo $SHCLT1 >> testrc_2 echo $SHCLT2 >> testrc_2 echo $SHPW > ./testpw } testrun2g_signrc () { scripts/samhainadmin.pl -s ./test/gnupg/ -m R $1 >/dev/null scripts/samhainadmin.pl -s ./test/gnupg/ -k 8A0B337A -m E $1 >/dev/null } testrun2g_signdb () { scripts/samhainadmin.pl -s ./test/gnupg/ -k 8A0B337A -m E ./.samhain_file >/dev/null } copy_rc_db_files () { cp ./testrc_2 ./rc.${SH_LOCALHOST} mv ./.samhain_file ./file.${SH_LOCALHOST} if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "No .samhain_file"; return 1 fi chmod 644 ./rc.${SH_LOCALHOST} chmod 644 ./file.${SH_LOCALHOST} cp ./testrc_2 "./rc.${ALTHOST}" cp ./file.${SH_LOCALHOST} "./file.${ALTHOST}" 2>/dev/null chmod 644 ./rc.${ALTHOST} chmod 644 ./file.${ALTHOST} } MAXTEST=6; export MAXTEST testrun2g () { log_start "RUN CLIENT/SERVER CASE TWO"; # if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi # SH_LOCALHOST=$1; export SH_LOCALHOST # # Test with missing delta # gpg --list-keys | grep 8A0B337A >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "You need to do 'gpg --import test/gnupg/public-key.asc' first" log_skip 1 $MAXTEST 'Case Two w/signed files' else testrun2g_build "--with-gpg=/usr/bin/gpg" "--with-keyid=0x8A0B337A" if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "build.."; testrun2g_signrc ./testrc_2 fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign rc.."; testrun2g_prepare fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "prepare.."; testrun2g_signdb fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign db.."; copy_rc_db_files fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "copy.."; do_test_2_g_yule_start fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "start yule.."; do_test_2_g_three nodelta fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Case Two w/missing delta"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Case Two w/missing delta"; fi fi # Test with unsigned delta # gpg --list-keys | grep 8A0B337A >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "You need to do 'gpg --import test/gnupg/public-key.asc' first" log_skip 1 $MAXTEST 'Case Two w/signed files' else testrun2g_build "--with-gpg=/usr/bin/gpg" "--with-keyid=0x8A0B337A" if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "build.."; testrun2g_signrc ./testrc_2 fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign rc.."; testrun2g_prepare fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "prepare.."; testrun2g_signdb fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign db.."; copy_rc_db_files fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "copy.."; do_test_2_g_yule_start fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "start yule.."; do_test_2_g_three nosig fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Case Two w/unsigned delta"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Case Two w/unsigned delta"; fi fi # Test with signed files, no sig client # gpg --list-keys | grep 8A0B337A >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "You need to do 'gpg --import test/gnupg/public-key.asc' first" log_skip 1 $MAXTEST 'Case Two w/signed files' else testrun2g_build if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "build.."; testrun2g_signrc ./testrc_2 fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign rc.."; testrun2g_prepare fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "prepare.."; testrun2g_signdb fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign db.."; copy_rc_db_files fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "copy.."; do_test_2_g_yule_start fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "start yule.."; do_test_2_g_three fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Case Two w/signed files+nosig client"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Case Two w/signed files+nosig client"; fi fi # Test with signed files # gpg --list-keys | grep 8A0B337A >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "You need to do 'gpg --import test/gnupg/public-key.asc' first" log_skip 1 $MAXTEST 'Case Two w/signed files' else testrun2g_build "--with-gpg=/usr/bin/gpg" "--with-keyid=0x8A0B337A" if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "build.."; testrun2g_signrc ./testrc_2 fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign rc.."; testrun2g_prepare fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "prepare.."; testrun2g_signdb fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "sign db.."; copy_rc_db_files fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "copy.."; do_test_2_g_yule_start fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "start yule.."; do_test_2_g_three fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 1 ${MAXTEST} "Case Two w/signed files"; else [ -z "$quiet" ] && log_fail 1 ${MAXTEST} "Case Two w/signed files"; fi fi # Test with non-signed files # testrun2g_build if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "build.."; testrun2g_prepare fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "prepare.."; copy_rc_db_files fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "copy.."; do_test_2_g_yule_start fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "start yule.."; do_test_2_g_one fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 2 ${MAXTEST} "Case Two w/unsigned files"; else [ -z "$quiet" ] && log_fail 2 ${MAXTEST} "Case Two w/unsigned files"; fi # testrun2g_prepare if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "prepare.."; copy_rc_db_files fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "copy.."; do_test_2_g_yule_start fi if [ $? -eq 0 ]; then [ -z "$verbose" ] || log_msg_ok "start yule.."; do_test_2_g_two fi if [ $? -eq 0 ]; then [ -z "$quiet" ] && log_ok 3 ${MAXTEST} "Case Two w/o delta"; else [ -z "$quiet" ] && log_fail 3 ${MAXTEST} "Case Two w/o delta"; fi log_end "RUN CLIENT/SERVER CASE TWO" } samhain-4.1.4/test/testrun_1a.sh0000755000175000017500000001036312615253277013501 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # PREBUILDOPTS="--quiet $TRUST --enable-debug --enable-static --enable-xml-log --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file" export PREBUILDOPTS MAXTEST=1; export MAXTEST testrun_stealth () { tcount=1 if test -r "Makefile"; then $MAKE distclean >/dev/null fi ${TOP_SRCDIR}/configure ${BUILDOPTS} if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE >/dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi CONVERT=`find_path convert` if [ x"$CONVERT" = x ]; then [ -z "$verbose" ] || log_msg_fail "ImageMagick convert not found"; return 1 fi "$CONVERT" --help | grep ImageMagick >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Convert utility is not ImageMagick convert"; return 1 fi "${CONVERT}" +compress stealth_template.jpg stealth_template.ps if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Converting stealth_template.jpg failed"; return 1 fi $MAKE samhain_stealth >/dev/null 2>>test_log if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "make samhain_stealth"; return 1 fi capacity=`./samhain_stealth -i stealth_template.ps | awk '{ print $7 }'` prep_init check_err $? ${tcount}; errval=$? if [ $errval -eq 0 ]; then prep_testdata check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then prep_testpolicy 1 check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then fill=`cat "${RCFILE}" | wc -c` check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then let "capacity = capacity - fill" >/dev/null let "capacity = capacity - 100" >/dev/null until [ "$capacity" -le 0 ] do echo "###############################" >>"${RCFILE}" let "capacity = capacity - 32" >/dev/null done ./samhain_stealth -s stealth_template.ps "${RCFILE}" >/dev/null check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then cp stealth_template.ps "${RCFILE}" check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_init check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval mod_testdata_1 check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then eval chk_testdata_1 check_err $? ${tcount}; errval=$? fi if [ $testrun1_setup -eq 0 ]; then if [ $errval -eq 0 ]; then run_update check_err $? ${tcount}; errval=$? fi if [ $errval -eq 0 ]; then run_check_after_update check_err $? ${tcount}; errval=$? fi fi if [ $errval -eq 0 ]; then [ -z "$quiet" ] && log_ok ${tcount} ${MAXTEST}; fi return 0 } testrun1a () { log_start "RUN STANDALONE W/STEALTH" # # micro-stealth # #BUILDOPTS="$PREBUILDOPTS --enable-micro-stealth=137"; export BUILDOPTS #testrun_internal CONVERT=`find_path convert` if [ x"$CONVERT" = x ]; then log_skip 1 ${MAXTEST} "ImageMagick convert not found"; return 0 fi BUILDOPTS="$PREBUILDOPTS --enable-stealth=137"; export BUILDOPTS testrun_stealth check_err $? ${tcount}; log_end "RUN STANDALONE W/STEALTH" return 0 } samhain-4.1.4/test/testrun_2c.sh0000755000175000017500000003034512615253277013506 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # LOGFILE="$PW_DIR/.samhain_log"; export LOGFILE RCFILE="$PW_DIR/testrc_2"; export RCFILE HTML="$PW_DIR/yule.html"; export HTML SERVER_BUILDOPTS="--quiet $TRUST --enable-xml-log --enable-debug --enable-network=server --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=REQ_FROM_SERVER$PW_DIR/testrc_2 --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-logserver=${SH_LOCALHOST} --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock --with-database=mysql"; export SERVER_BUILDOPTS CLIENT_BUILDOPTS="--quiet $TRUST --prefix=$PW_DIR --with-tmp-dir=$PW_DIR --localstatedir=$PW_DIR --enable-network=client --disable-mail --disable-external-scripts --enable-login-watch --enable-xml-log --enable-db-reload --with-logserver=localhost --with-config-file=REQ_FROM_SERVER$PW_DIR/testrc_2 --with-data-file=REQ_FROM_SERVER$PW_DIR/.samhain_file --with-log-file=$PW_DIR/.samhain_log --with-pid-file=$PW_DIR/.samhain_lock"; export CLIENT_BUILDOPTS MAXTEST=4; export MAXTEST do_test_1_c () { [ -z "$verbose" ] || { echo; echo "${S}Start Server${E}: ./yule -l info -p none &"; echo; } rm -f test_log_valgrind ${VALGRIND} ./yule.2 -q -l info -p none >/dev/null 2>>test_log_valgrind & PROC_Y2=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Server #2${E}: ./yule.2 -l info -p none &"; echo; } ${VALGRIND} ./yule -l info -p none -e info --bind-address=127.0.0.1 \ --server-port=49778 >/dev/null 2>>test_log_valgrind & PROC_Y=$! five_sec_sleep [ -z "$verbose" ] || { echo; echo "${S}Start Client${E}: ./samhain.new -l none -p none -e info -t check"; echo; } ${VALGRIND} ./samhain.new -t check -p none -l none -e info --bind-address=127.0.0.1 >/dev/null 2>>test_log_valgrind if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "samhain.new -t check"; else [ -z "$quiet" ] && log_msg_fail "samhain.new -t check"; kill $PROC_Y kill $PROC_Y2 return 1 fi kill $PROC_Y kill $PROC_Y2 five_sec_sleep # cp ${LOGFILE} triple_test # cp ${LOGFILE}2 triple_test_2 egrep "START(>|\").*Yule(>|\")" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server #2 start"; return 1 fi egrep "remote_host.*Checking.*/bin" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (relayed)"; return 1 fi egrep "remote_host.*EXIT.*Samhain" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit (relayed)"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" ${LOGFILE}2 >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server #2 exit"; return 1 fi egrep "START(>|\").*Yule(>|\")" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "remote_host.*Checking.*/bin" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "remote_host.*EXIT.*Samhain" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" $LOGFILE >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi [ -z "$VALGRIND" ] || { tmp=`cat test_log_valgrind 2>/dev/null | wc -l`; if [ $tmp -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "valgrind reports errors"; cat test_log_valgrind return 1; fi; } return 0 } testrun_threesockets () { GPG="$1" [ -z "$verbose" ] || { echo; echo Working directory: $PW_DIR; echo MAKE is $MAKE; echo GPG is $GPG; echo; } [ -z "$verbose" ] || { echo; echo "${S}Building client and server${E}"; echo; } if test -r "Makefile"; then $MAKE distclean fi ${TOP_SRCDIR}/configure --with-gpg=${GPG} --with-fp=EF6CEF54701A0AFDB86AF4C31AAD26C80F571F6C --with-checksum=no ${SERVER_BUILDOPTS} >/dev/null 2>&1 if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi rm -f ./.samhain_file rm -f ./.samhain_log rm -f ./.samhain_lock rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} cp ${SCRIPTDIR}/testrc_2.in testrc_2 ORIGINAL="DatabaseSeverity=none" REPLACEMENT="DatabaseSeverity=warn" ex -s $RCFILE < '"${DATE}"';" | mysql --password=samhain -u samhain samhain >test_log_db # egrep "START.*Yule" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start"; return 1 fi egrep "NEW CLIENT" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect"; return 1 fi egrep "Checking.*/bin" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check"; return 1 fi egrep "EXIT.*Samhain" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit"; return 1 fi return 0 } testrun2c () { log_start "RUN FULL CLIENT/SERVER W/MYSQL" # if [ -z "$doall" ]; then log_skip 1 $MAXTEST 'Client/server w/mysql (or use --really-all)' log_skip 2 $MAXTEST 'Client/server w/mysql (or use --really-all)' log_skip 3 $MAXTEST 'Client/server w/mysql (or use --really-all)' log_skip 4 $MAXTEST 'Client/server w/mysql (or use --really-all)' return 0 fi if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi MYSQL=`find_path mysql` if [ -z "$MYSQL" ]; then log_skip 1 $MAXTEST "mysql not found"; log_skip 2 $MAXTEST "mysql not found"; log_skip 3 $MAXTEST "mysql not found"; log_skip 4 $MAXTEST "mysql not found"; return 1 else TEST=`echo "DESCRIBE log;" | mysql --password=samhain -u samhain samhain 2>/dev/null` if [ $? -ne 0 -o -z "$TEST" ]; then log_skip 1 $MAXTEST "mysql not default setup" log_skip 2 $MAXTEST "mysql not default setup" log_skip 3 $MAXTEST "mysql not default setup" log_skip 4 $MAXTEST "mysql not default setup" return 1 fi fi # SH_LOCALHOST=$1; export SH_LOCALHOST # DATE=`date '+%Y-%m-%d %T'` # testrun2a_internal # # BUILD Server 2 # cp ./yule ./yule.orig ${TOP_SRCDIR}/configure --quiet $TRUST --enable-debug --enable-network=server --enable-xml-log --enable-login-watch --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=${RCFILE}2 --with-log-file=${LOGFILE}2 --with-pid-file=$PW_DIR/.samhain_lock2 --with-html-file=${HTML}2 --with-state-dir=$PW_DIR --with-port=49778 --with-database=mysql # if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "configure..."; $MAKE > /dev/null 2>>test_log if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "make..."; else [ -z "$quiet" ] && log_msg_fail "make..."; return 1 fi else [ -z "$quiet" ] && log_msg_fail "configure..."; return 1 fi cp yule yule.2 || return 1 # cp ./yule.orig ./yule # SHPW=`cat ./testpw` if test x"$SHPW" = x; then [ -z "$quiet" ] && log_msg_fail "password not generated -- aborting" return 1 fi rm -f ./testpw ./samhain_setpwd yule new $SHPW >/dev/null if test x$? = x0; then [ -z "$verbose" ] || log_msg_ok "./samhain_setpwd yule new $SHPW"; else [ -z "$quiet" ] && log_msg_fail "./samhain_setpwd yule new $SHPW"; return 1 fi $MAKE clean >/dev/null || return 1 mv yule.new yule || return 1 # ORIGINAL="DatabaseSeverity=none" REPLACEMENT="DatabaseSeverity=info" ex -s $RCFILE </dev/null 2>>test_log five_sec_sleep netstat -pant 2>/dev/null | grep 49777 | grep yule >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_fail 3 ${MAXTEST} "Client/server w/mysql"; else NSOCK=`netstat -pand 2>/dev/null | grep STREAM | grep yule | wc -l` if [ $NSOCK -ne 2 ]; then [ -z "$quiet" ] && log_fail 3 ${MAXTEST} "Three sockets open"; netstat -pand 2>/dev/null | grep yule else [ -z "$quiet" ] && log_ok 3 ${MAXTEST} "Three sockets open"; fi fi PID=`cat .samhain_lock` kill $PID else log_fail 3 ${MAXTEST} "Three sockets open"; fi # cp ${SCRIPTDIR}/testrc_2.in testrc_2 # GPG=`find_path gpg` if [ -z "$GPG" ]; then log_skip 4 $MAXTEST 'gpg not found in $PATH' else eval "$GPG" --list-keys 0F571F6C >/dev/null 2>/dev/null if [ $? -ne 0 ]; then log_skip 4 $MAXTEST 'public PGP key 0x0F571F6C not present' else testrun_threesockets "$GPG" # cp ${SCRIPTDIR}/testrc_2.in testrc_2 # if [ -f ./yule ]; then ./yule -D --set-database-severity=warn >/dev/null 2>>test_log five_sec_sleep netstat -pant 2>/dev/null | grep 49777 | grep yule >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$quiet" ] && log_fail 4 ${MAXTEST} "Three sockets open (gpg) - 1"; else NSOCK=`netstat -pand 2>/dev/null | grep STREAM | grep yule | wc -l` if [ $NSOCK -ne 2 ]; then [ -z "$quiet" ] && log_fail 4 ${MAXTEST} "Three sockets open (gpg) - 2"; netstat -pand 2>/dev/null | grep yule else [ -z "$quiet" ] && log_ok 4 ${MAXTEST} "Three sockets open (gpg)"; fi fi PID=`cat .samhain_lock` kill $PID else log_fail 4 ${MAXTEST} "Three sockets open (gpg) - 3"; fi fi fi # if [ -n "$cleanup" ]; then rm -f ./rc.${SH_LOCALHOST} rm -f ./file.${SH_LOCALHOST} ALTHOST=`find_hostname` rm -f "./file.${ALTHOST}" rm -f "./rc.${ALTHOST}" fi # log_end "RUN FULL CLIENT/SERVER W/MYSQL" } samhain-4.1.4/test/testrc_10000644000175000017500000001355512615253277012532 00000000000000##################################################################### # # Configuration file template for samhain. # ##################################################################### # # -- empty lines and lines starting with '#' are ignored # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # # SETUP for file system checking: # # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) To each policy, you can assign a severity (further below). # (iii) To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### [Misc] RedefUser0=-ATM [Attributes] # # for these files, only changes in permissions and ownership are checked # #file=/etc/mtab #file=/etc/ssh_random_seed #file=/etc/asound.conf #file=/etc/resolv.conf #file=/etc/localtime #file=/etc/ioctl.save #file=/etc/passwd.backup #file=/etc/shadow.backup # # There are files in /etc that might change (see above), # thus changing the timestamps on the directory special file. # Put it here as 'file', and in the ReadOnly section as 'dir'. # file=/etc [GrowingLogFiles] # # for these files, changes in signature, timestamps, and increase in size # are ignored # # Example for shell-style wildcard pattern # #file=/var/log/n* [IgnoreAll] #dir=-1/etc [IgnoreNone] #dir=-1/etc [Attributes] # dir=/opt/gnome/bin/ # file=/usr/bin/ssh [ReadOnly] # # for these files, only access time is ignored # #dir=/dev # dir=/usr/bin #dir=/usr/bin #dir=/lib #dir=/usr/lib #dir=/lib #dir=3/etc #dir=/tmp # file=/usr/bin/ssh # dir=1/home/rainer #[SuidCheck] #SuidCheckActive=T #SuidCheckExclude=/home [EventSeverity] # # Here you can assign severities to policy violations. # If this severity exceeds the treshold of a log facility (see below), # a policy violation will be logged to that facility. # # Severity for verification failures. # SeverityUser0=crit SeverityUser1=crit SeverityReadOnly=crit SeverityLogFiles=crit SeverityGrowingLogs=crit SeverityIgnoreNone=crit SeverityAttributes=crit # # We have a file in IgnoreAll that might or might not be present. # Setting the severity to 'info' prevents messages about deleted/new file. # SeverityIgnoreAll=warn # # Files : file access problems # Dirs : directory access problems # Names : suspect (non-printable) characters in a pathname # SeverityFiles=notice SeverityDirs=info SeverityNames=warn [Log] # # Set threshold severity for log facilities # Values: debug, info, notice, warn, mark, err, crit, alert, none. # 'mark' is used for timestamps. # # By default, everything equal to and above the threshold is logged. # The specifiers '*', '!', and '=' are interpreted as # 'all', 'all but', and 'only', respectively (like syslogd(8) does, # at least on Linux). # # MailSeverity=* # MailSeverity=!warn # MailSeverity==crit # MailSeverity=none LogSeverity=warn SyslogSeverity=none #ExportSeverity=none PrintSeverity=info # Restrict to certain classes of messages # MailClass = RUN #PreludeSeverity = err # Which system calls to log (execve, utime, unlink, dup, chdir, open, kill, # exit, fork, setuid, setgid, pipe) # # LogCalls = open #[Kernel] # # Setings this to 1/true/yes will activate the check for loadable # kernel module rootkits (Linux only) # #KernelCheckActive=1 #KernelCheckInterval = 20 #[Utmp] # # 0 to switch off, 1 to activate # #LoginCheckActive=1 # Severity for logins, multiple logins, logouts # #SeverityLogin=info #SeverityLoginMulti=warn #SeverityLogout=info # interval for login/logout checks # #LoginCheckInterval=60 [Misc] # # whether to become a daemon process Daemon=no # Custom format for message header # # %S severity # %T timestamp # %C class # # %F source file # %L source line # # MessageHeader="%S %T - %F - %L " # MessageHeader=" ~/.pgpass << EOF localhost:*:samhain:samhain:samhain EOF } check_psql_log () { DATE="$1" rm -f test_log_db # PGPASSWORD=samhain; export PGPASSWORD create_pgpass psql -o test_log_db -U samhain -d samhain -c "SELECT * FROM log WHERE entry_status = 'NEW' and log_time > '${DATE}';" # egrep "START.*Yule" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server start (psql)"; return 1 fi egrep "NEW CLIENT" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client connect (psql)"; return 1 fi egrep "Checking.*/bin" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client file check (psql)"; return 1 fi egrep "EXIT.*Samhain" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Client exit (psql)"; return 1 fi egrep "EXIT.*Yule.*SIGTERM" test_log_db >/dev/null 2>&1 if [ $? -ne 0 ]; then [ -z "$verbose" ] || log_msg_fail "Server exit (psql)"; return 1 fi return 0 } MAXTEST=1; export MAXTEST testrun2d () { log_start "RUN FULL CLIENT/SERVER W/POSTGRESQL" # if [ -z "$doall" ]; then log_skip 1 $MAXTEST 'Client/server w/postgresql (or use --really-all)' return 0 fi if [ x"$1" = x ]; then [ -z "$quiet" ] && log_msg_fail "Missing hostname" fi PSQL=`find_path psql` if [ -z "$PSQL" ]; then log_skip 1 $MAXTEST "psql not found"; return 1 else # PGPASSWORD="samhain"; export PGPASSWORD create_pgpass TEST=`psql -U samhain -d samhain -c "SELECT * FROM log LIMIT 1;" 2>/dev/null` if [ $? -ne 0 -o -z "$TEST" ]; then log_skip 1 $MAXTEST "psql not default setup" return 1 fi fi # SH_LOCALHOST=$1; export SH_LOCALHOST # DATE=`date '+%Y-%m-%d %T'` # testrun2a_internal # for ff in ./rc.*; do ORIGINAL="SetUdpActive=no" REPLACEMENT="ReportCheckflags=yes" ex -s rc.morrigan.localdomain < * http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html (v) Support for determining the type of a file system is provided by code from the GNU find(1) utility which includes the following statement: /* fstype.c -- determine type of filesystems that files are on Copyright (C) 1990, 91, 92, 93, 94 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ /* Written by David MacKenzie . */ (vi) Support for the MD5 hash algorithm is provided by code from busybox which is distributed under the GPL. /* md5.c - Functions to compute MD5 message digest of files or memory blocks * according to the definition of MD5 in RFC 1321 from April 1992. * Copyright (C) 1995, 1996 Free Software Foundation, Inc. * * NOTE: The canonical source of this file is maintained with the GNU C * Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ /* Written by Ulrich Drepper , 1995. */ (vi) Support for the SHA-1 hash algorithm is provided by code from mhash which includes the following statement: /* sha.c - Implementation of the Secure Hash Algorithm * * Copyright (C) 1995, A.M. Kuchling * * Distribute and use freely; there are no restrictions on further * dissemination and usage except those imposed by the laws of your * country of residence. * * Adapted to pike and some cleanup by Niels Möller. */ /* $Id: sha1.c,v 1.2 2001/01/24 08:20:29 nmav Exp $ */ /* SHA: NIST's Secure Hash Algorithm */ /* Based on SHA code originally posted to sci.crypt by Peter Gutmann in message <30ajo5$oe8@ccu2.auckland.ac.nz>. Modified to test for endianness on creation of SHA objects by AMK. Also, the original specification of SHA was found to have a weakness by NSA/NIST. This code implements the fixed version of SHA. */ (vii) Support for AVL Trees is provided by code from AVLTree which includes the following statement: /* zAVLTree.h: Header file for zAVLTrees. * Copyright (C) 1998,2001 Michael H. Buselli * This is version 0.1.3 (alpha). * Generated from $Id: xAVLTree.h.sh,v 1.5 2001/06/07 06:58:28 cosine Exp $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * The author of this library can be reached at the following address: * Michael H. Buselli * 30051 N. Waukegan Rd. Apt. 103 * Lake Bluff, IL 60044-5412 * * Or you can send email to . * The official web page for this product is: * http://www.cosine.org/project/AVLTree/ */ (viii) The modules sh_userfiles.c and sh_mounts.c have been contributed by Eircom Net Computer Incident Response Team and are authored by Jerry Connolly and Cian Synnott, respectively. They are released 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: "Feel free to GPL those files - they were fully released by our company to the project. Cian -- Cian Synnott Eircom Net Computer Incident Response Team" (ix) Enhanced functionality for the SUID check has been contributed with a patch copyright by Rob Rati . The patch is licensed under the GPL with the following statement: "Here is the patch with the aforementioned feature enhancements, and I license all changes within this patch under the GNU Public License (GPL) GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version." (x) Unit testing uses the 'cutest' framework by Asim Jalis, (files CuTest.h, CuTest.c, make-tests.sh) which is licensed under the zlib license: * Copyright (c) 2003 Asim Jalis * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. (xi) The dnmalloc library used by samhain is Copyright (C) 2005, Yves Younan, Wouter Joosen and Frank Piessens, and licensed under the LGPL: * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Other ----- Depending on the compilation options used, samhain may use the SRP authentication algorithm (in an independent implementation, without any use of code from the SRP software). The original SRP software contains the following license statement: The SRP License --------------- SRP and all related technologies are free for both commercial and non-commercial use. They are distributed under a standard X11-style Open Source license which is shown below. The SRP distribution contains parts from various freeware packages; these parts fall under both the SRP Open Source license and any existing licenses. Care has been taken to ensure that these licenses are compatible with Open Source distribution, but it is the responsibility of the licensee to comply with these licenses. The file "Copyrights" contains a list of the copyrights incorporated by portions of the software. This software is covered under the following copyright: /* * Copyright (c) 1997-1999 The Stanford SRP Authentication Project * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * In addition, the following conditions apply: * * 1. Any software that incorporates the SRP authentication technology * must display the following acknowlegment: * "This product uses the 'Secure Remote Password' cryptographic * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)." * * 2. Any software that incorporates all or part of the SRP distribution * itself must also display the following acknowledgment: * "This product includes software developed by Tom Wu and Eugene * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)." * * 3. Redistributions in source or binary form must retain an intact copy * of this copyright notice and list of conditions. */ samhain-4.1.4/c_bits.sh0000755000175000017500000000436712615253270011700 00000000000000#! /bin/sh # get bits of $1 # make sure it fits in 16 bit ORIG=`expr $1 \% 65536` # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 N=0 N=`expr $ORIG \/ 32768` N_16=$N if test "x$N" = "x1"; then echo "#define $2_16 1" fi ORIG=`expr $ORIG \- $N_16 \* 32768` N=`expr $ORIG / 16384` N_15=$N if test "x$N" = "x1"; then echo "#define $2_15 1" fi ORIG=`expr $ORIG \- $N_15 \* 16384` N=`expr $ORIG \/ 8192` N_14=$N if test "x$N" = "x1"; then echo "#define $2_14 1" fi ORIG=`expr $ORIG \- $N_14 \* 8192` N=`expr $ORIG \/ 4096` N_13=$N if test "x$N" = "x1"; then echo "#define $2_13 1" fi ORIG=`expr $ORIG \- $N_13 \* 4096` N=`expr $ORIG \/ 2048` N_12=$N if test "x$N" = "x1"; then echo "#define $2_12 1" fi ORIG=`expr $ORIG \- $N_12 \* 2048` N=`expr $ORIG \/ 1024` N_11=$N if test "x$N" = "x1"; then echo "#define $2_11 1" fi ORIG=`expr $ORIG \- $N_11 \* 1024` N=`expr $ORIG \/ 512` N_10=$N if test "x$N" = "x1"; then echo "#define $2_10 1" fi ORIG=`expr $ORIG \- $N_10 \* 512` N=`expr $ORIG \/ 256` N_09=$N if test "x$N" = "x1"; then echo "#define $2_09 1" fi ORIG=`expr $ORIG \- $N_09 \* 256` N=`expr $ORIG \/ 128` N_08=$N if test "x$N" = "x1"; then echo "#define $2_08 1" fi ORIG=`expr $ORIG \- $N_08 \* 128` N=`expr $ORIG \/ 64` N_07=$N if test "x$N" = "x1"; then echo "#define $2_07 1" fi ORIG=`expr $ORIG \- $N_07 \* 64` N=`expr $ORIG \/ 32` N_06=$N if test "x$N" = "x1"; then echo "#define $2_06 1" fi ORIG=`expr $ORIG \- $N_06 \* 32` N=`expr $ORIG \/ 16` N_05=$N if test "x$N" = "x1"; then echo "#define $2_05 1" fi ORIG=`expr $ORIG \- $N_05 \* 16` N=`expr $ORIG \/ 8` N_04=$N if test "x$N" = "x1"; then echo "#define $2_04 1" fi ORIG=`expr $ORIG \- $N_04 \* 8` N=`expr $ORIG \/ 4` N_03=$N if test "x$N" = "x1"; then echo "#define $2_03 1" fi ORIG=`expr $ORIG \- $N_03 \* 4` N=`expr $ORIG \/ 2` N_02=$N if test "x$N" = "x1"; then echo "#define $2_02 1" fi ORIG=`expr $ORIG \- $N_02 \* 2` N=`expr $ORIG \/ 1` N_01=$N if test "x$N" = "x1"; then echo "#define $2_01 1" fi ORIG=`expr $ORIG \- $N_01 \* 1` # # obsolete # # echo ${N_01} ${N_02} ${N_03} ${N_04} ${N_05} ${N_06} ${N_07} ${N_08} ${N_09} ${N_10} ${N_11} ${N_12} ${N_13} ${N_14} ${N_15} ${N_16} exit 0 samhain-4.1.4/dsys/0000755000175000017500000000000012615253270011126 500000000000000samhain-4.1.4/dsys/funcSETUP0000644000175000017500000000363312615253277012561 00000000000000######################################################################### # # Setup test Subroutines # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # test setup # testSETUP1() { test -d "$basedir" || printFATAL "Basedir $basedir does not exist" test -d "$basedir/tmp" || printFATAL "Tmpdir $basedir/tmp does not exist" tmpdir="$basedir/tmp"; export tmpdir return 0 } # test setup # testSETUP2() { test -z "$action" && { promptMENU "Which action do you want to perform" "install" "build" "download" "checksrc" "clean" "info" "uninstall"; action="$MENU"; export action; } if (test x"$action" = xbuild || test x"$action" = xinstall || test x"$action" = xuninstall) then test -z "$host" && { promptINPUT "On which host do you want to $action"; host="$INPUT"; export host; } fi return 0 } setupFORMAT() { tmp_format=`echo "${1}" | sed '/^\(.*\)\.\([0-9a-zA-Z]*\)$/{ s//\2/; q; }'` echo "${tmp_format}" } setupVERSION() { tmp_version=`echo ${DB_version} | sed s%\.run%% | sed s%\.rpm%% | sed s%\.depot%% | sed s%\.deb%% | sed s%\.tbz2%% | sed s%\.pkg%%` echo "${tmp_version}" } samhain-4.1.4/dsys/funcDB0000644000175000017500000001647212615253277012153 00000000000000######################################################################### # # More subroutines for client DB # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # DBFTEST=0 dbSETFLAG() { case "$line" in *\*) DBFTEST=0; return 0; ;; *\${DB_host}\*) DBFTEST=1; return 1; ;; *) return ${DBFTEST}; ;; esac } DB_arch=""; export DB_arch; DB_status=""; export DB_status; DB_version=""; export DB_version; DB_date=""; export DB_date; DB_name=""; export DB_name; dbINFO() { if test "x$1" = x then printFATAL "No host specified, aborting" else DB_host="$1" fi DB_arch=""; export DB_arch; DB_status=""; export DB_status; DB_version=""; export DB_version; DB_date=""; export DB_date; DB_name=""; export DB_name; if test x"$DATABASE" = x then DATABASE="${basedir}/${defdatabase}" fi if test -f "${DATABASE}" then SStr1=`grep '' "${DATABASE}"` if test "x${SStr1}" != "x" then SStr2=`grep "${DB_host}" "${DATABASE}"` SStr3= if test "x${SStr2}" != "x" then exec 3<&0 <"${DATABASE}" while read line do # for some reason, var=xx only works in a function call (why?) # # here we test if we are still in the same client block # (set_flag will return 0 for and following) dbSETFLAG "$line" if test "x$?" = "x1" then case "$line" in *\*\) DB_arch=`echo "$line" | sed '/^\(.*\)\([0-9a-zA-Z_-]*\)<\/client_os_machine>\(.*\)$/{ s//\2/; q; }'` export DB_arch ;; *\*\) DB_status=`echo "$line" | sed '/^\(.*\)\([0-9a-zA-Z_-]*\)<\/client_install_status>\(.*\)$/{ s//\2/; q; }'` export DB_status ;; *\*\) DB_date=`echo "$line" | sed '/^\(.*\)\([ 0-9a-zA-Z_.:,-]*\)<\/client_install_date>\(.*\)$/{ s//\2/; q; }'` export DB_date ;; *\*\) DB_name=`echo "$line" | sed '/^\(.*\)\([0-9a-zA-Z_-]*\)<\/client_install_name>\(.*\)$/{ s//\2/; q; }'` export DB_name ;; *\*\) ;; *\*\) DB_version=`echo "$line" | sed '/^\(.*\)\([0-9a-zA-Z_.-]*\)<\/client_install_version>\(.*\)$/{ s//\2/; q; }'` export DB_version ;; *) ;; esac else : fi done exec 0<&3 3<&- return 0 else printINFO "Host ${DB_host} not found in client database" return 1 fi else printINFO "Client database ${DATABASE} in bad shape" return 1 fi else printINFO "Client database ${DATABASE} not available" return 1 fi } DB_hostlist=""; export DB_hostlist dbHOSTLIST() { DB_hostlist=""; export DB_hostlist if test x"$DATABASE" = x then DATABASE="${basedir}/${defdatabase}" fi if test -f "${DATABASE}" then DB_hostlist=`cat "${DATABASE}" | grep 'client_host' | sed '/^\(.*\)\([0-9a-zA-Z.-]*\)<\/client_host>\(.*\)$/{ s//\2/; }' | sort` export DB_hostlist return 0 else printINFO "Client database ${DATABASE} not available" return 1 fi } dbSHOWHOSTS() { if test "x$1" = x then dbHOSTLIST else DB_hostlist="$1" fi if test "x$?" = x1 then printLOG "No known hosts - database unavailable" fi if test "x${DB_hostlist}" = x then printLOG "No known hosts - database unavailable, empty, or corrupt" fi for ff in ${DB_hostlist} do dbINFO "$ff" if test "x$?" = x1 then : else test -z "${DB_date}" && DB_date="INDEF" test -z "${DB_arch}" && DB_arch="INDEF" test -z "${DB_version}" && DB_version="INDEF" tmp_status="-" if test "x$DB_status" = xinstalled then tmp_status="o" elif test "x$DB_status" = xD2_installed then tmp_status="i" elif test "x$DB_status" = xD2_removed then tmp_status="u" fi out=`echo | awk '{ printf "%1s %14s %-11s %19s %s\n", "'"${tmp_status}"'", "'"${DB_arch}"'", "'"${DB_version}"'", "'"${DB_date}"'", "'"${ff}"'" }'` printINFO "${out}" fi done } dbSHOWPKG() { delete=no show=no if test x"$1" = xshow then show=yes fi if test x"$2" = xdelete then delete=yes fi cd "${basedir}/archpkg" || printFATAL "Cannot cd to ${basedir}/archpkg" dbHOSTLIST if test x"$DATABASE" = x then DATABASE="${basedir}/${defdatabase}" fi LIST=`ls` this_dir=`pwd` for dd in $LIST do if test -d "$dd" then cd "$dd" PKGLIST=`ls samhain-* 2>/dev/null` for ff in $PKGLIST do if test -f "$ff" then version=`echo "$ff" | sed -e 's%samhain-%%'` tmp_status="-" grep "$version" "${DATABASE}" >/dev/null 2>&1 if test "x$?" = x0 then for hh in ${DB_hostlist} do dbINFO "$hh" if test x"${DB_arch}" = x"${dd}" && \ test x"${DB_version}" = x"${version}" then tmp_status="-" if test "x$DB_status" = xinstalled then tmp_status="o" elif test "x$DB_status" = xD2_installed then tmp_status="i" fi break fi done else tmp_status="-" fi if test x"${show}" = xyes then printINFO "${tmp_status} ${dd}/${version}" fi if test x"${delete}" = xyes && test x"${tmp_status}" = "x-" then printLOG "REMOVE ${dd}/${version}" if test x"$simulate" = x0 then rm -f "samhain-${version}" rm -f "install-${version}" rm -f "configure-${version}" else printINFO "rm -f ${dd}/samhain-${version}" printINFO "rm -f ${dd}/install-${version}" printINFO "rm -f ${dd}/configure-${version}" fi fi fi done cd "${this_dir}" fi done } samhain-4.1.4/dsys/comBUILD0000644000175000017500000002230312615253277012336 00000000000000######################################################################### # # Subroutine for the 'build' command # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # commandBUILD() { printINFO "About to run \"$action\"" if test -d "${basedir}/archpkg/${arch}" then : else if test -d "${basedir}/archpkg" then if test x"$simulate" = x0 then mkdir "${basedir}/archpkg/${arch}" else printINFO "mkdir ${basedir}/archpkg/${arch}" fi else if test x"$simulate" = x0 then mkdir "${basedir}/archpkg" && mkdir "${basedir}/archpkg/${arch}" else printINFO "mkdir ${basedir}/archpkg && mkdir ${basedir}/archpkg/${arch}" fi fi fi if test -f "${basedir}/configs/${arch}.configure" then : else printFATAL "Configure options file ${basedir}/configs/${arch}.configure not found." fi local_test=`cat "${basedir}/configs/${arch}.configure" | tr -d '\n' | egrep "^ *'?--with-logserver=FQDN_MISSING"` if test x"${local_test}" = x then : else printFATAL "Your configuration file has a bad --with-logserver option." fi if test x"$bd_packed" = x then printINFO "Building version: ${src_version}, host: ${host}, os: ${arch}, format: ${format}" else printINFO "Building version: ${src_version}, host: ${host}, os: ${arch}, format: ${format}, packed: password=${bd_packed}" fi tmpdir=`eval echo "${temp_dir}/sh_${src_version}_${arch}_${format}_$$"` #--------------------------------------------------------------------- # Create temporary build directory on build host. #--------------------------------------------------------------------- if test x"$simulate" = x0 then ssh -x -l "${bd_user}" "${host}" '(umask 0077; mkdir "'${tmpdir}'")' else printINFO "ssh -x -l ${bd_user} ${host} (umask 0077; mkdir ${tmpdir})" fi if test x"$?" != x0 then printFATAL "Could not create temporary build directory on host ${host}." else printLOG "Build directory ${tmpdir} created on host ${host}" fi #--------------------------------------------------------------------- # Copy source tarball to build host. #--------------------------------------------------------------------- if test x"$simulate" = x0 then rm -f "${basedir}/tmp/samhain-${src_version}.tar" gunzip -c "${basedir}/source/samhain-${src_version}.tar.gz" > "${basedir}/tmp/samhain-${src_version}.tar" else printINFO "rm -f ${basedir}/tmp/samhain-${src_version}.tar" printINFO "gunzip -c ${basedir}/source/samhain-${src_version}.tar.gz > ${basedir}/tmp/samhain-${src_version}.tar" fi if test x"$?" != x0 then printFATAL "Could not gunzip source to ${basedir}/tmp/samhain-${src_version}.tar." fi if test x"$simulate" = x0 then if test x"$silent" = x0 then scp "${basedir}/tmp/samhain-${src_version}.tar" "${bd_user}@${host}:${tmpdir}/" else scp -q "${basedir}/tmp/samhain-${src_version}.tar" "${bd_user}@${host}:${tmpdir}/" fi else if test x"$silent" = x0 then printINFO "scp ${basedir}/tmp/samhain-${src_version}.tar ${bd_user}@${host}:${tmpdir}/" else printINFO "scp -q ${basedir}/tmp/samhain-${src_version}.tar ${bd_user}@${host}:${tmpdir}/" fi fi if test x"$?" != x0 then printFATAL "Could not copy source to host ${host}." else printINFO "Source copied to host ${host}." fi #--------------------------------------------------------------------- # Build the package. #--------------------------------------------------------------------- if test x"$silent" = x0 then config_com='./configure' else config_com='./configure --silent' fi if test -f "${basedir}/configs/${arch}.configure" then while read line do if test -z "`echo $line | awk '/^#/'`" then nline=`echo ${line} | tr -d '\n'` config_com="${config_com} ${nline}" fi done <"${basedir}/configs/${arch}.configure" else printFATAL "Configure options file ${basedir}/configs/${arch}.configure not found." fi printINFO "configure command is ${config_com}" if test x"$bd_packed" = x then command="make clean" else command="make CLIENTPASSWD=${bd_packed} samhain-packed" fi command=`eval echo $command`; if test x"$simulate" = x0 then if test $silent -lt 2 then ssh -x -l "${bd_user}" "${host}" /bin/sh -c \''(PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH}:${bd_addpath}'" && export PATH && cd "'${tmpdir}'" && tar -xf "'samhain-${src_version}.tar'" && cd "'samhain-${src_version}'" && eval "'${config_com}'" && eval "'${command}'" && make "'${format}-light'")'\' else ssh -x -l "${bd_user}" "${host}" /bin/sh -c \''(PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH}:${bd_addpath}'" && export PATH && cd "'${tmpdir}'" && tar -xf "'samhain-${src_version}.tar'" && cd "'samhain-${src_version}'" && eval "'${config_com}'" && eval "'${command}'" && make "'${format}-light'") >/dev/null'\' fi else if test $silent -lt 2 then printINFO "ssh -x -l ${bd_user} ${host} /bin/sh -c '(PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:\${PATH}:${bd_addpath} && export PATH && cd ${tmpdir} && tar -xf samhain-${src_version}.tar && cd samhain-${src_version} && eval ${config_com} && eval ${command} && make ${format}-light)'" else printINFO "ssh -x -l ${bd_user} ${host} /bin/sh -c '(PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:\${PATH}:${bd_addpath} && export PATH && cd ${tmpdir} && tar -xf samhain-${src_version}.tar && cd samhain-${src_version} && eval ${config_com} && eval ${command} && make ${format}-light) >/dev/null'" fi fi if test x"$?" != x0 then printFATAL "Could not build package on host ${host}." else printINFO "Source compiled." fi #--------------------------------------------------------------------- # Fetch package and remove temporary build directory on build host. #--------------------------------------------------------------------- realformat=`echo $format | sed s,solaris-,,` if test x"$simulate" = x0 then ssh -x -l "${bd_user}" "${host}" '(cat "'${tmpdir}/samhain-${src_version}/samhain-install.sh'")' >"${basedir}/archpkg/${arch}/install-${src_version}.${realformat}" else printINFO "ssh -x -l ${bd_user} ${host} (cat ${tmpdir}/samhain-${src_version}/samhain-install.sh) >${basedir}/archpkg/${arch}/install-${src_version}.${realformat}" fi if test x"$?" != x0 then printFATAL "Could not fetch samhain-install.sh script from host ${host}." fi chmod +x "${basedir}/archpkg/${arch}/install-${src_version}.${realformat}" if test x"$simulate" = x0 then ssh -x -l "${bd_user}" "${host}" '(cat "'${tmpdir}/samhain-${src_version}/samhain-${src_version}.${realformat}'" && rm -rf "'${tmpdir}'")' >"${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" else printINFO "ssh -x -l ${bd_user} ${host} (cat ${tmpdir}/samhain-${src_version}/samhain-${src_version}.${realformat} && rm -rf ${tmpdir}) >${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" fi if test x"$?" != x0 then printFATAL "Could not fetch package samhain-${src_version}.${realformat} from host ${host}." else printLOG "Build directory ${tmpdir} deleted on host ${host}." fi chmod +x "${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" if test x"$simulate" = x0 then pkgsize=`ls -l "${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" | awk '{print $5}'` if test "x$pkgsize" = "x0"; then printFATAL "Returned package file is empty." fi else printINFO "ls -l ${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat} | awk '{print $5}'" fi # >> Save password # if test x"$bd_packed" = x then : else if test x"$simulate" = x0 then echo "$bd_packed" >"${basedir}/archpkg/${arch}/PASSWD-${src_version}.${realformat}" fi fi # >> Save configure options # if test x"$simulate" = x0 then cp "${basedir}/configs/${arch}.configure" "${basedir}/archpkg/${arch}/configure-${src_version}.${realformat}" else printINFO "cp ${basedir}/configs/${arch}.configure ${basedir}/archpkg/${arch}/configure-${src_version}.${realformat}" fi printLOG "New package: ${arch}/samhain-${src_version}.${realformat}." } samhain-4.1.4/dsys/comINSTALL0000644000175000017500000005725212615253277012620 00000000000000######################################################################### # # Subroutine for the 'install' command # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # commandINSTALL() { printINFO "About to run \"$action\" on host \"$host\"" # # configuration options we should know about # is_packed=0 is_nocl="start" is_xor="no" if test -f "${basedir}/configs/${arch}.configure" then : else printFATAL "Configure options ${basedir}/configs/${arch}.configure missing." fi if test -f "${basedir}/configs/${arch}.samhainrc" then : else printFATAL "Configuration file ${basedir}/configs/${arch}.samhainrc missing." fi realformat=`echo $format | sed s,solaris-,,`; export realformat if test -f "${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" then : else printFATAL "Binary package OS: ${arch}, version: ${src_version}, format ${format} does not exist." fi if test -f "${basedir}/archpkg/${arch}/install-${src_version}.${realformat}" then : else printFATAL "Binary package OS: ${arch}, version: ${src_version}, format ${format} is incomplete and cannot be installed." fi if test -f "${basedir}/archpkg/${arch}/PASSWD-${src_version}.${realformat}" then printINFO "Binary package OS: ${arch}, version: ${src_version}, format ${format} is packed." is_packed=1 is_passwd=`cat "${basedir}/archpkg/${arch}/PASSWD-${src_version}.${realformat}" | tr -d '\n'` else is_passwd=`eval "${yule_exec}" -G` if test x$? != x0 then printFATAL "Could not generate password. Is yule in your PATH ?" fi fi if test -f "${basedir}/configs/${arch}.preinstall" then cp "${basedir}/configs/${arch}.preinstall" "${tmpD}/preinstall" || \ printFATAL "Could not copy ${basedir}/configs/${arch}.preinstall to ${tmpD}/preinstall" is_preinstall_full="${tmpD}/preinstall" else is_preinstall_full="${basedir}/libexec/preinstall" fi if test -f "${basedir}/configs/${arch}.postinstall" then cp "${basedir}/configs/${arch}.postinstall" "${tmpD}/postinstall" || \ printFATAL "Could not copy ${basedir}/configs/${arch}.postinstall to ${tmpD}/postinstall" is_postinstall_full="${tmpD}/postinstall" else is_postinstall_full="${basedir}/libexec/postinstall" fi if test -f "${basedir}/configs/${arch}.initscript" then cp "${basedir}/configs/${arch}.initscript" "${tmpD}/initscript" || \ printFATAL "Could not copy ${basedir}/configs/${arch}.initscript to ${tmpD}/initscript" is_initscript_full="${tmpD}/initscript" else is_initscript_full="${basedir}/libexec/initscript" fi #--------------------------------------------------------------------- # Get important configuration options. #--------------------------------------------------------------------- getconfopts "${basedir}/archpkg/${arch}/configure-${src_version}.${realformat}" || printFATAL "Could not check config file ${basedir}/archpkg/${arch}/configure-${src_version}.${realformat}" #--------------------------------------------------------------------- # Prepare the configuration file #--------------------------------------------------------------------- if test -f "${basedir}/hosts/${host}/${arch}.samhainrc" then hostconfig="${basedir}/hosts/${host}/${arch}.samhainrc" elif test -f "${basedir}/hosts/${host}/samhainrc" then hostconfig="${basedir}/hosts/${host}/samhainrc" else hostconfig="${basedir}/configs/${arch}.samhainrc" fi test -f "${hostconfig}" || printFATAL "Configuration file ${hostconfig} missing." # Handle the '--enable-stealth' option # if test x"${is_xor}" = xno then : else test -f "${basedir}/private/stealth_template.ps" || \ printFATAL "${basedir}/private/stealth_template.ps not available." ${basedir}/libexec/samhain_stealth -o "${hostconfig}" >/dev/null ||\ printFATAL "Problem reading ${hostconfig}". ccount=`${basedir}/libexec/samhain_stealth -o "${hostconfig}" 2>&1 | awk '{ print $1 }'` ${basedir}/libexec/samhain_stealth -i "${basedir}/private/stealth_template.ps" >/dev/null || \ printFATAL "Problem reading ${basedir}/private/stealth_template.ps" mcount=`${basedir}/libexec/samhain_stealth -i "${basedir}/private/stealth_template.ps" 2>&1 | awk '{ print $7 }'` if test ${mcount} -lt ${ccount} then printFATAL "Configuration file ${hostconfig} too big." fi cp "${basedir}/private/stealth_template.ps" "$tmpD" || \ printFATAL "Could not copy ${basedir}/private/stealth_template.ps to ${tmpD}/" ${basedir}/libexec/samhain_stealth -s "${tmpD}/stealth_template.ps" "${hostconfig}" >/dev/null if test "x$?" = x0 then printINFO "Configuration file hidden into stealth_template.ps" hostconfig="${tmpD}/stealth_template.ps" else printFATAL "Could not run ${basedir}/libexec/samhain_stealth -s ${tmpD}/stealth_template.ps ${hostconfig}" fi fi rm -f "${tmpD}/prepared_samhainrc" cp "${hostconfig}" "${tmpD}/prepared_samhainrc" || \ printFATAL "Could not copy ${hostconfig} to ${tmpD}/prepared_samhainrc" hostconfig="${tmpD}/prepared_samhainrc" #--------------------------------------------------------------------- # Create temporary directory on host. #--------------------------------------------------------------------- tmpdir=`eval echo "${temp_dir}/sh_${src_version}_${arch}_${format}_$$"` if test x"$simulate" = x0 then ssh -x -l "root" "${host}" '(umask 0077; mkdir "'${tmpdir}'")' else printINFO "ssh -x -l root ${host} (umask 0077; mkdir ${tmpdir})" fi if test x"$?" != x0 then printFATAL "Could not create temporary directory ${tmpdir} on host ${host}." else printLOG "Directory ${tmpdir} created on host ${host}." fi #--------------------------------------------------------------------- # Copy to host. #--------------------------------------------------------------------- if test x"$simulate" = x0 then if test x"$silent" = x0 then scp "${is_initscript_full}" "${is_preinstall_full}" "${is_postinstall_full}" "${hostconfig}" "${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" "${basedir}/archpkg/${arch}/install-${src_version}.${realformat}" "root@${host}:${tmpdir}/" else scp -q "${is_initscript_full}" "${is_preinstall_full}" "${is_postinstall_full}" "${hostconfig}" "${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat}" "${basedir}/archpkg/${arch}/install-${src_version}.${realformat}" "root@${host}:${tmpdir}/" fi else if test x"$silent" = x0 then printINFO "scp ${is_initscript_full} ${is_preinstall_full} ${is_postinstall_full} ${hostconfig} ${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat} ${basedir}/archpkg/${arch}/install-${src_version}.${realformat} root@${host}:${tmpdir}/" else printINFO "scp -q ${is_initscript_full} ${is_preinstall_full} ${is_postinstall_full} ${hostconfig} ${basedir}/archpkg/${arch}/samhain-${src_version}.${realformat} ${basedir}/archpkg/${arch}/install-${src_version}.${realformat} root@${host}:${tmpdir}/" fi fi if test x"$?" != x0 then printFATAL "Could not copy package to host ${host}." else printINFO "Package copied to host ${host}." fi #--------------------------------------------------------------------- # Run preinstall script. #--------------------------------------------------------------------- if test x"$simulate" = x0 then ssh -x -l "root" "${host}" '(cd "'${tmpdir}'" && cp "'install-${src_version}.${realformat}'" samhain-install.sh && chmod +x samhain-install.sh && chmod +x preinstall && ./preinstall)' else printINFO "ssh -x -l root ${host} (cd ${tmpdir} && cp install-${src_version}.${realformat} samhain-install.sh && chmod +x samhain-install.sh && chmod +x preinstall && ./preinstall)" fi if test x"$?" != x0 then printFATAL "Could not run preinstall script on host ${host}." else printLOG "Preinstall script executed on host ${host}" fi #--------------------------------------------------------------------- # Install. #--------------------------------------------------------------------- if test "x$format" = "xrun"; then is_command="/bin/sh" elif test "x$format" = "xdeb"; then is_command="dpkg --install --force-downgrade --force-confnew" elif test "x$format" = "xrpm"; then is_command="rpm --upgrade --quiet --oldpackage" elif test "x$format" = "xtbz2"; then is_command="emerge -K" elif test "x$format" = "xsolaris-pkg"; then is_command="pkgadd -n -d" elif test "x$format" = "xdepot"; then is_command="/usr/sbin/swinstall -x fix_explicit_directories=false -v -s " else printFATAL "Don't know how to install package format ${format}" fi if test "x$format" = "xdepot" then tmp_iname=`/bin/sh ${basedir}/archpkg/${arch}/install-${src_version}.${realformat} --print-config name` if test x"$simulate" = x0 then ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && PATH="'/usr/local/sbin:/usr/sbin:/sbin:$PATH'" && export PATH && eval "'${is_command}'" "'${tmpdir}/samhain-${src_version}.${realformat}'" "'${tmp_iname}'") >/dev/null '\' else printINFO "ssh -x -l root ${host} /bin/sh -c '(cd ${tmpdir} && eval ${is_command} ${tmpdir}/samhain-${src_version}.${realformat} ${tmp_iname})'" fi elif test "x$format" = "xsolaris-pkg" then if test x"$simulate" = x0 then ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH'" && export PATH && eval "'${is_command}'" "'samhain-${src_version}.${realformat} all'") >/dev/null '\' else printINFO "ssh -x -l root ${host} /bin/sh -c '(cd ${tmpdir} && eval ${is_command} samhain-${src_version}.${realformat}) all'" fi elif test "x$format" = "xtbz2" then # Gentoo is a PITA # tmp_iname=`/bin/sh ${basedir}/archpkg/${arch}/install-${src_version}.${realformat} --print-config name` if test x"$simulate" = x0 then ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH'" && export PATH && cp "'samhain-${src_version}.${realformat}'" "'/usr/portage/packages/All/${tmp_iname}-${src_version}.tbz2'" && eval "'${is_command}'" "'${tmp_iname}-${src_version}.${realformat}'") >/dev/null '\' else printINFO "ssh -x -l root ${host} /bin/sh -c '(cd ${tmpdir} && cp samhain-${src_version}.${realformat} /usr/portage/packages/${tmp_iname}-${src_version}.tbz2 && eval ${is_command} ${tmp_iname}-${src_version}.${realformat})'" fi else if test x"$simulate" = x0 then ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH'" && export PATH && eval "'${is_command}'" "'samhain-${src_version}.${realformat}'") >/dev/null '\' else printINFO "ssh -x -l root ${host} /bin/sh -c '(cd ${tmpdir} && eval ${is_command} samhain-${src_version}.${realformat})'" fi fi if test x"$?" != x0 then printFATAL "Could not install package on host ${host}." else printLOG "Package installed on host ${host}" fi #--------------------------------------------------------------------- # Run postinstall script to fix the client password. #--------------------------------------------------------------------- if test x"$simulate" = x0 then if test "x${is_packed}" = "x0" then ssh -x -l "root" "${host}" '(cd "'${tmpdir}'" && chmod +x postinstall && ./postinstall "'${is_passwd}'") >/dev/null' else # Dummy argument ssh -x -l "root" "${host}" '(cd "'${tmpdir}'" && chmod +x postinstall && ./postinstall DUMMY ) >/dev/null' fi else if test "x${is_packed}" = "x0" then printINFO "ssh -x -l root ${host} (cd ${tmpdir} && chmod +x postinstall && ./postinstall ${is_passwd})" else # Dummy argument printINFO "ssh -x -l root ${host} (cd ${tmpdir} && chmod +x postinstall && ./postinstall DUMMY )" fi fi if test x"$?" != x0 then printFATAL "Could not run postinstall script on host ${host}." else printLOG "Postinstall script executed on host ${host}" fi #--------------------------------------------------------------------- # Update the rc file #--------------------------------------------------------------------- if test "x${is_rcfile}" = xy then mytest_file=`ls -1 "${yule_data}/rc*" 2>/dev/null | tail -n 1 2>/dev/null` if test "x$mytest_file" = x; then rcfile_perm=640; xgid=`(cat /etc/group; ypcat group) 2>/dev/null |\ grep "^samhain:" | awk -F: '{ print $3; }'` if test "x$xgid" = x; then rcfile_owner=`ls -ld ${yule_data} | awk '{print $3 }'` rcfile_group=`ls -ld ${yule_data} | awk '{print $4 }'` else rcfile_owner=`ls -ld ${yule_data} | awk '{print $3 }'` rcfile_group=samhain fi else mytest_file=`basename $mytest_file` rcfile_perm=`ls -l "${yule_data}/${mytest_file}" | \ awk '{ u= substr($1,2,3); g=substr($1,5,3); o=substr($1,8,3); \ gsub("-","",u); gsub("-","",g); gsub("-","",o); \ print "u=" u ",g=" g ",o=" o; }'` rcfile_perm=`echo ${rcfile_perm} | sed s%g=,%g-rwx,% | sed s%,o=$%,o-rwx%` rcfile_owner=`ls -l "${yule_data}/${mytest_file}" | \ awk '{print $3 }'` rcfile_group=`ls -l "${yule_data}/${mytest_file}" | \ awk '{print $4 }'` fi if test -f "${hostconfig}" then if test x"$simulate" = x0 then ageFILE "${yule_data}/rc.${host}" || printFATAL "Could not backup ${yule_data}/rc.${host}." cp "${hostconfig}" "${yule_data}/rc.${host}" || printFATAL "Could not copy ${hostconfig} to ${yule_data}/rc.${host}" chown ${rcfile_owner}:${rcfile_group} "${yule_data}/rc.${host}" || printFATAL "Could not chown ${rcfile_owner}:${rcfile_group} ${yule_data}/rc.${host}" chmod ${rcfile_perm} "${yule_data}/rc.${host}" || printFATAL "Could not chmod ${rcfile_perm} ${yule_data}/rc.${host}" else printINFO "Backup existing ${yule_data}/rc.${host}" printINFO "Copy ${hostconfig} to ${yule_data}/rc.${host}" fi else printFATAL "${hostconfig} is missing." fi printLOG "Server-side config file ${yule_data}/rc.${host} copied from ${hostconfig}." fi #--------------------------------------------------------------------- # Server entry and restart #--------------------------------------------------------------------- instlock="${yule_conf}.lockdir"; trap "rm -rf ${instlock}" 1 2 13 15 if test x"$simulate" = x0 then # # A lockfile will not work, because 'root' can write anyway. # However, 'mkdir' an existing directory will fail even for root # until (umask 222; mkdir "${instlock}") 2>/dev/null # test & set do printINFO "Waiting for lock" sleep 1 done fi Replace=`"${yule_exec}" -P "${is_passwd}" | sed s%HOSTNAME%${host}%g` if test "x$Replace" = x then rm -rf "${instlock}" printFATAL "Could not execute ${yule_exec} -P ${is_passwd}." fi SearchString="Client=${host}@" Seen=n echo >"$tmpF" || printFATAL "Cannot write new server configuration." while read line do if test "x$Seen" = xn then echo "$line" >>"$tmpF" if test -n "`echo $line | awk '/^\[Clients\]/'`" then Seen=y echo "$Replace" >>"$tmpF" if [ $? -ne 0 ]; then rm -rf "${instlock}" printFATAL "Cannot write new server configuration." fi fi else if test -n "`echo $line | awk '/^'${SearchString}'/'`" then : else echo "$line" >>"$tmpF" if [ $? -ne 0 ]; then rm -rf "${instlock}" printFATAL "Cannot write new server configuration." fi fi fi done <"${yule_conf}" rcfile_perm=`ls -l "${yule_conf}" | \ awk '{ u= substr($1,2,3); g=substr($1,5,3); o=substr($1,8,3); \ gsub("-","",u); gsub("-","",g); gsub("-","",o); \ print "u=" u ",g=" g ",o=" o; }'` rcfile_perm=`echo ${rcfile_perm} | sed s%g=,%g-rwx,% | sed s%,o=$%,o-rwx%` rcfile_owner=`ls -l "${yule_conf}" | \ awk '{print $3 }'` rcfile_group=`ls -l "${yule_conf}" | \ awk '{print $4 }'` if test x"$simulate" = x0 then ageFILE "${yule_conf}" if [ $? -ne 0 ]; then rm -rf "${instlock}" printFATAL "Could not backup ${yule_conf}" fi rm -f "${yule_conf}" && cp "$tmpF" "${yule_conf}" if [ $? -ne 0 ]; then rm -rf "${instlock}" printFATAL "Could not write new server config. Backup is ${yule_conf}.1" fi chown ${rcfile_owner}:${rcfile_group} "${yule_conf}" if [ $? -ne 0 ]; then rm -rf "${instlock}" printFATAL "Could not chown ${rcfile_owner}:${rcfile_group} ${yule_conf}" fi chmod ${rcfile_perm} "${yule_conf}" if [ $? -ne 0 ]; then rm -rf "${instlock}" printFATAL "Could not chmod ${rcfile_perm} ${yule_conf}" fi else printINFO "Backup and update ${yule_conf}" fi if test "x${local_command}" = x then : else if test x"$simulate" = x0 then eval "${local_command}" "${host}" "${arch}" "${basedir}" "${yule_data}" "first" else printINFO "eval ${local_command} ${host} ${arch} ${basedir} ${yule_data} first" fi fi yule_name=`basename "${yule_exec}"` if test x"$simulate" = x0 then if test -f "/etc/init.d/${yule_name}" then eval "/etc/init.d/${yule_name}" reload if test x"$?" != x0 then printWARNING "Could not reload server using: /etc/init.d/${yule_name} reload." fi else eval "${yule_exec}" reload if test x"$?" != x0 then printWARNING "Could not reload server using: ${yule_exec} reload." fi fi # # wait for the server to pick up the new configuration # sleep 5 # rm -rf "${instlock}" else printINFO "Reloading server configuration." fi printLOG "Server configuration updated and reloaded." #--------------------------------------------------------------------- # Write/update client database #--------------------------------------------------------------------- SH_NAME=`/bin/sh ${basedir}/archpkg/${arch}/install-${src_version}.${realformat} --print-config name`; export SH_NAME SH_PREFIX=`/bin/sh ${basedir}/archpkg/${arch}/install-${src_version}.${realformat} --print-config prefix`; export SH_PREFIX if test x"$simulate" = x0 then updateDB else printINFO "Updating client database." fi #--------------------------------------------------------------------- # Initialize and fetch database #--------------------------------------------------------------------- if test "x${is_init}" = xy then if test x"$simulate" = x0 then if test x"$silent" != x0 then ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && chmod +x initscript && ./initscript ${is_nocl} >/dev/null 2>&1 )'\' else ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && chmod +x initscript && ./initscript ${is_nocl} >/dev/null 2>&1 )'\' fi if test x"$?" != x0 then printFATAL "Could not initialize database on host ${host}." else printLOG "Database initialized on host ${host}" fi scp -q "root@${host}:${tmpdir}/data" "$tmpD" || \ printFATAL "Could not retrieve database file root@${host}:${tmpdir}/data" else printINFO "ssh -x -l root ${host} /bin/sh -c '(cd ${tmpdir} && chmod +x initscript && ./initscript ${is_nocl})'" printLOG "Database initialized on host ${host}" printINFO "scp -q root@${host}:${tmpdir}/data $tmpD" fi mytest_file=`ls -1 "${yule_data}/file*" 2>/dev/null | tail -n 1 2>/dev/null` if test "x$mytest_file" = x; then rcfile_perm=640; xgid=`(cat /etc/group; ypcat group) 2>/dev/null |\ grep "^samhain:" | awk -F: '{ print $3; }'` if test "x$xgid" = x; then rcfile_owner=`ls -ld ${yule_data} | awk '{print $3 }'` rcfile_group=`ls -ld ${yule_data} | awk '{print $4 }'` else rcfile_owner=`ls -ld ${yule_data} | awk '{print $3 }'` rcfile_group=samhain fi else mytest_file=`basename $mytest_file` rcfile_perm=`ls -l "${yule_data}/${mytest_file}" | \ awk '{ u= substr($1,2,3); g=substr($1,5,3); o=substr($1,8,3); \ gsub("-","",u); gsub("-","",g); gsub("-","",o); \ print "u=" u ",g=" g ",o=" o; }'` rcfile_perm=`echo ${rcfile_perm} | sed s%g=,%g-rwx,% | sed s%,o=$%,o-rwx%` rcfile_owner=`ls -l "${yule_data}/${mytest_file}" | \ awk '{print $3 }'` rcfile_group=`ls -l "${yule_data}/${mytest_file}" | \ awk '{print $4 }'` fi if test x"$simulate" = x0 then if test -f "$tmpD/data" then ageFILE "${yule_data}/file.${host}" || printFATAL "Could not backup ${yule_conf}." mv "$tmpD/data" "${yule_data}/file.${host}" || printFATAL "Could not move database file to ${yule_data}/file.${host}" chown ${rcfile_owner}:${rcfile_group} "${yule_data}/file.${host}" || printFATAL "Could not chown ${rcfile_owner}:${rcfile_group} ${yule_data}/file.${host}" chmod ${rcfile_perm} "${yule_data}/file.${host}" || printFATAL "Could not chmod ${rcfile_perm} ${yule_data}/file.${host}" else printFATAL "Database file not downloaded from host ${host}" fi else printINFO "Backup and replace ${yule_data}/file.${host}" fi fi #--------------------------------------------------------------------- # Start up. #--------------------------------------------------------------------- if test "x${local_command}" = x then : else if test x"$simulate" = x0 then eval "${local_command}" "${host}" "${arch}" "${basedir}" "${yule_data}" "second" else printINFO "eval ${local_command} ${host} ${arch} ${basedir} ${yule_data} second" fi fi if test "x${is_startup}" = xy then if test x"$simulate" = x0 then ssh -x -l "root" "${host}" '(cd "'${tmpdir}'" && chmod +x initscript && eval "'./initscript ${is_nocl} start'")' else printINFO "Starting remote client now." fi if test x"$?" != x0 then printFATAL "Could not start client on host ${host}." else printLOG "Client started on host ${host}." fi fi #--------------------------------------------------------------------- # Clean up. #--------------------------------------------------------------------- if test x"$simulate" = x0 then ssh -x -l "root" "${host}" '(rm -rf "'${tmpdir}'")' else printINFO "ssh -x -l root ${host} (rm -rf ${tmpdir})" fi if test x"$?" != x0 then printFATAL "Could not remove temporary directory ${tmpdir} on host ${host}." else printLOG "Directory ${tmpdir} deleted on host ${host}." fi } samhain-4.1.4/dsys/comDOWNLOAD0000644000175000017500000001677012615253277012721 00000000000000######################################################################### # # Subroutine for the 'download' command # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # commandDOWNLOAD() { printINFO "About to run \"$action\" for samhain version \"$src_version\"" needEXE du gunzip tar gpg if test x"$simulate" = x0 then cd "${basedir}/tmp" || printFATAL "could not cd to ${basedir}/tmp" rm -f "samhain-${src_version}.tar.gz" else # # -- Simulate only: print what would be done # printINFO "cd ${basedir}/tmp" printINFO "rm -f samhain-${src_version}.tar.gz" fi command="" if test -z "$command" then findEXE wget if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="--quiet" opt2="-O" opt3="-" fi fi if test -z "$command" then findEXE curl if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="--silent" opt2="--show-error" opt3="--fail" fi fi if test -z "$command" then findEXE lynx if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="-source" opt2="" opt3="" fi fi if test -z "$command" then findEXE links if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="-source" opt2="" opt3="" fi fi if test -z "$command" then findEXE lwp-request if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="" opt2="" opt3="" fi fi if test -z "$command" then findEXE fetch if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="-q" opt2="-o" opt3="-" fi fi if test -z "$command" then findEXE fget if test -n "$EXECUTABLE" then command="$EXECUTABLE" opt1="" opt2="" opt3="" fi fi if test -z "$command" then printFATAL "No wget, curl, lynx, links, lwp-request, fetch, fget in your \$PATH, cannot download" fi if test x"${src_version}" = xcurrent then location="http://la-samhna.de/samhain/samhain-current.tar.gz" if test -f /usr/bin/md5sum && test -f /bin/hostname then # # for testing # dl_tmp_hna=`/bin/hostname -f 2>/dev/null` dl_tmp_md5=`echo "x${dl_tmp_hna}" | md5sum` if test x"$dl_tmp_md5" = "xc5f41bf28a7baf12c763f1be27a9b863" then location="http://localhost/samhain-current.tar.gz" fi fi else location="http://la-samhna.de/archive/samhain_signed-${src_version}.tar.gz" if test -f /usr/bin/md5sum && test -f /bin/hostname then # # for testing # dl_tmp_hna=`/bin/hostname -f 2>/dev/null` dl_tmp_md5=`echo "x${dl_tmp_hna}" | /usr/bin/md5sum 2>/dev/null` if test x"$dl_tmp_md5" = "xc5f41bf28a7baf12c763f1be27a9b863" then location="http://localhost/samhain_signed-${src_version}.tar.gz" fi fi fi printINFO "Executing $command $opt1 $opt2 $opt3 $location" if test x"$simulate" = x0 then eval "$command" "$opt1" "$opt2" "$opt3" "$location" 1>"samhain-${src_version}.tar.gz" 2>/dev/null else printINFO "$command" "$opt1" "$opt2" "$opt3" "$location" 1>"samhain-${src_version}.tar.gz" printINFO "du -s -k samhain-${src_version}.tar.gz | awk '{ print $1 }'" printLOG "Downloaded to samhain-${src_version}.tar.gz (XXX kB)" printINFO "gunzip -c samhain-${src_version}.tar.gz | tar -tvf - " printINFO "Source in tarball is version X.X.X" printINFO "Unpacking to ${tmpD}" printINFO "cd ${tmpD}" printINFO "gunzip -c ${basedir}/tmp/samhain-${src_version}.tar.gz | tar -xf -" printINFO "rm -f ${basedir}/tmp/samhain-${src_version}.tar.gz" printINFO "Checking PGP signature" printINFO "(LANG=C; gpg --status-fd 1 --verify samhain-X.X.X.tar.gz.asc samhain-X.X.X.tar.gz 2>&1 | grep 'GOODSIG')" printINFO "cp samhain-X.X.X.tar.gz.asc samhain-X.X.X.tar.gz ${basedir}/source" printLOG "Installed samhain (X.X.X) source" return 0 fi if test -f "samhain-${src_version}.tar.gz" then : else printFATAL "failed: $command $location" fi size=`du -s -k "samhain-${src_version}.tar.gz" | awk '{ print $1 }'` if test $size -lt 100 then rm -f "samhain-${src_version}.tar.gz" printFATAL "failed: $command $location" else printLOG "Downloaded to samhain-${src_version}.tar.gz (${size} kB)" fi files=`gunzip -c "samhain-${src_version}.tar.gz" | tar -tvf - 2>/dev/null` sig=`echo $files | egrep ' samhain.*tar\.gz\.asc$' 2>/dev/null` sig_version=`echo $files | egrep ' samhain.*tar\.gz\.asc$' 2>/dev/null | sed 's/.*samhain\-//g' | sed 's/\.tar\.gz\.asc//g'` if test x"$sig" = x then rm -f "samhain-${src_version}.tar.gz" printFATAL "downloaded file does not contain a PGP signature" fi if test x"${sig_version}" = x then rm -f "samhain-${src_version}.tar.gz" printFATAL "cannot determine samhain version from downloaded file" fi if test x"${src_version}" != xcurrent then if test x"${src_version}" != x"${sig_version}" then rm -f "samhain-${src_version}.tar.gz" printFATAL "downloaded version (${sig_version}) != requested version (${src_version})" fi fi printINFO "Source in tarball is version ${sig_version}" printINFO "Unpacking to ${basedir}/source" cd "${tmpD}" || { rm -f "${basedir}/tmp/samhain-${src_version}.tar.gz" printFATAL "could not cd to ${tmpD}" } gunzip -c "${basedir}/tmp/samhain-${src_version}.tar.gz" | tar -xf - rm -f "${basedir}/tmp/samhain-${src_version}.tar.gz" if test -f "samhain-${sig_version}.tar.gz" then if test -f "samhain-${sig_version}.tar.gz.asc" then : else printFATAL "not found in source: PGP signature samhain-${sig_version}.tar.gz.asc" fi else printFATAL "not found in source: samhain-${sig_version}.tar.gz" fi printINFO "Checking PGP signature" sig_lines=`(LANG="C"; gpg --status-fd 1 --verify "samhain-${sig_version}.tar.gz.asc" "samhain-${sig_version}.tar.gz" 2>/dev/null)` sig_ok=`echo ${sig_lines} | grep 'GOODSIG'` sig_nokey=`echo ${sig_lines} | grep 'NO_PUBKEY'` if test x"${sig_nokey}" != x then printWARNING "Public key (ID 0F571F6C) not found, trying to import it." gpg --import ${basedir}/private/0F571F6C.asc 2>&5 sig_ok=`(LANG="C"; gpg --status-fd 1 --verify "samhain-${sig_version}.tar.gz.asc" "samhain-${sig_version}.tar.gz" 2>/dev/null | grep 'GOODSIG')` fi if test x"${sig_ok}" = x then (LANG="C"; gpg --verify "samhain-${sig_version}.tar.gz.asc" "samhain-${sig_version}.tar.gz") printFATAL "no good signature" fi cp "samhain-${sig_version}.tar.gz" "samhain-${sig_version}.tar.gz.asc" \ ${basedir}/source/ || \ printFATAL "failed: cp samhain-${sig_version}.tar.gz samhain-${sig_version}.tar.gz.asc ${basedir}/source/" printLOG "Installed samhain source (version=${sig_version})" return 0 } samhain-4.1.4/dsys/comCHECKSRC0000644000175000017500000000663612615253277012677 00000000000000######################################################################### # # Subroutine for the 'checksrc' command # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # commandCHECKSRC() { printINFO "About to run \"$action\"" needEXE ls gpg cd "${basedir}/source" || printFATAL "could not cd to ${basedir}/source" LIST=`ls samhain*.tar.gz 2>/dev/null` if test x$? != x0 then printINFO "No sources available." fi for ff in $LIST do sh_version=`echo "$ff" | sed 's/.*samhain\-//g' | sed 's/\.tar\.gz//g'` if test x"${sh_version}" = x then printFATAL "Cannot determine version for $ff" fi if test "$ff" != "samhain-${sh_version}.tar.gz" then printFATAL "Version number not correctly extracted from $ff" fi if test -f "samhain-${sh_version}.tar.gz.asc" then : else printWARNING "No detached signature for $ff found" if test x"$cs_delete" = x1 then if test x"$simulate" = x0 then printLOG "REMOVE $ff: No detached signature found." rm -f "$ff" else printLOG "REMOVE $ff: No detached signature found." printINFO "rm -f $ff" fi else printLOG "BAD: $ff (no signature)" fi continue fi sig_lines=`(LANG="C"; gpg --status-fd 1 --verify "samhain-${sh_version}.tar.gz.asc" "samhain-${sh_version}.tar.gz" 2>/dev/null)` sig_ok=`echo ${sig_lines} | grep 'GOODSIG'` sig_nokey=`echo ${sig_lines} | grep 'NO_PUBKEY'` if test x"${sig_nokey}" != x then printWARNING "Public key (ID 0F571F6C) not found, trying to import it." gpg --import ${basedir}/private/0F571F6C.asc 2>&5 sig_lines=`(LANG="C"; gpg --status-fd 1 --verify "samhain-${sh_version}.tar.gz.asc" "samhain-${sh_version}.tar.gz" 2>/dev/null)` sig_ok=`echo ${sig_lines} | grep 'GOODSIG'` sig_nokey=`echo ${sig_lines} | grep 'NO_PUBKEY'` fi if test x"${sig_nokey}" != x then printFATAL "Importing public key failed." fi if test x"${sig_ok}" = x then printWARNING "File $ff has no good signature" if test x"$cs_delete" = x1 then if test x"$simulate" = x0 then printLOG "REMOVE $ff: No good signature found." rm -f "$ff" else printLOG "REMOVE $ff: No good signature found." printINFO "rm -f $ff" fi else printLOG "BAD: $ff (invalid signature)" fi continue fi printLOG "OK: $ff" done if test x"$cs_delete" = x1 then printLOG "Checked sources in ${basedir}/source/ (delete=on)" else printLOG "Checked sources in ${basedir}/source/ (delete=off)" fi return 0 } samhain-4.1.4/dsys/funcDIALOG0000644000175000017500000001415612615253277012622 00000000000000######################################################################### # # Interaction Subroutines # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # print without newline # printASK() { echo $ECHO_N "$@ $ECHO_C" } # find a 'dialog' program # findDIALOG() { if test x"$DIALOG" = xno then DIALOG=""; return 0 elif test -n "$DIALOG" then return 0 fi PATH=/usr/local/bin:/usr/local/sbin:$PATH; export PATH X="$PATH" progs="dialog"; OLD_IFS=${IFS} IFS=':'; export IFS for dir in $X; do for dia in $progs; do dialog="$dir/$dia" if (test -f "$dialog" || test -f "$dialog.exe") then if "$dialog" 2>&1 | grep tailbox >/dev/null 2>&1 then IFS=${OLD_IFS}; export IFS DIALOG="$dialog"; export DIALOG return 0 fi fi done done IFS=${OLD_IFS}; export IFS DIALOG=""; export DIALOG } # prompt user for yes/no # promptYESNO() { if test $# -lt 1 then printFATAL "promptYESNO: insufficient arguments" fi if test $silent -gt 1 then YESNO=y; export YESNO return 0 fi DEFAULT="" case "$2" in [yY]|[yY][eE][sS]) DEFAULT=y ;; [nN]|[nN][oO]) DEFAULT=n ;; esac YESNO="" if test -n "$DIALOG" then if test x"$assumeyes" = x1 then YESNO="$DEFAULT"; export YESNO return 0 fi "$DIALOG" --title "deploy.sh $version" --yesno "$1" 10 75 2>"$tmpF" mtest=$? if test x"$mtest" = "x-1" then printFATAL "promptYESNO: something went wrong" elif test x"$mtest" = x0 then YESNO=y else YESNO=n fi else while : do if test x"$DEFAULT" = xy then printASK "$1 (Y/n) ?" elif test x"$DEFAULT" = xn then printASK "$1 (N/y) ?" else printASK "$1 (y/n) ?" fi if test x"$assumeyes" = x1 then YESNO="$DEFAULT"; export YESNO echo "$DEFAULT" return 0 fi read YESNO if test -z "$YESNO" then YESNO="$DEFAULT" fi case "$YESNO" in [yY]|[yY][eE][sS]) YESNO=y; break ;; [nN]|[nN][oO]) YESNO=n; break ;; *) YESNO="" ;; esac done fi export YESNO return 0 } # get user input from tmp file # getINPUT() { INPUT=`cat $tmpF` export INPUT return 0 } # info box # promptINFO() { if test $# -lt 1 then printFATAL "promptINPUT: insufficient arguments" fi if test x"$silent" != x0 then return 0 fi if test -n "$DIALOG" then "$DIALOG" --title "deploy.sh $version" --sleep 2 --infobox "$1" 8 75 else echo $1 fi return 0 } # prompt user for input # promptINPUT() { if test $# -lt 1 then printFATAL "promptINPUT: insufficient arguments" fi if test $assumeyes -gt 0 then printFATAL "promptINPUT: user interaction required" fi INPUT="" DEFAULT="$2" if test -n "$DIALOG" then "$DIALOG" --title "deploy.sh $version" --inputbox "$1" 16 75 "$2" 2>"$tmpF" mtest=$? if test x"$mtest" = "x1" then # cancel button (exit 0); exit 0; fi if test x"$mtest" = "x-1" then printFATAL "promptINPUT: something went wrong" else getINPUT fi else while : do if test -z "$DEFAULT" then printASK "$1 ?" else printASK "$1 ? $DEFAULT" fi read INPUT if test -z "$INPUT" then if test -n "$DEFAULT" then locINPUT="$DEFAULT" break fi elif test -n "$INPUT" then break fi done export INPUT fi return 0 } # get MENU from tmp file # getMENU() { MENU=`cat $tmpF` export MENU return 0 } # prompt user for options from menu # promptMENU() { if test $# -lt 2 then printFATAL "promptMENU: insufficient arguments" fi if test $assumeyes -gt 0 then printFATAL "promptMENU: user interaction required" fi TITLE="$1" shift if test -n "$DIALOG" then #command="'$DIALOG' '--title' \\'deploy.sh $version\\' '--backtitle'" #command="$command \'$TITLE\' '--menu' \'$TITLE\' '16' '75' '$#'" argc=$# if test $argc -gt 7 then argc=7 fi command="'$1' '' 'on'" shift for item do command="$command '$item' '' 'off'" done command="$command " # printFATAL "$command" eval $DIALOG '--title' \'deploy.sh $version\' '--backtitle' \'$TITLE\' '--radiolist' \'$TITLE\' '16' '75' $argc $command 2>"$tmpF" mtest=$? if test x"$mtest" = "x1" then # cancel button (exit 0); exit 0; fi if test x"$mtest" = "x-1"; then printFATAL "promptMENU: something went wrong" else getMENU fi else MENU="" INPUT="" while : do clear echo echo "$TITLE" echo echo " 1) $1" test -n "$2" && echo " 2) $2" test -n "$3" && echo " 3) $3" test -n "$4" && echo " 4) $4" test -n "$5" && echo " 5) $5" test -n "$6" && echo " 6) $6" test -n "$7" && echo " 7) $7" test -n "$8" && echo " 8) $8" test -n "$9" && echo " 9) $9" echo printASK "Please enter your choice: " read INPUT if echo "$INPUT" | grep '[^0123456789]' >/dev/null 2>&1 then : elif test $INPUT -gt $# then : else break fi done case "$INPUT" in 1) MENU="$1"; break ;; 2) MENU="$2"; break ;; 3) MENU="$3"; break ;; 4) MENU="$4"; break ;; 5) MENU="$5"; break ;; 6) MENU="$6"; break ;; 7) MENU="$7"; break ;; 8) MENU="$8"; break ;; 9) MENU="$9"; break ;; esac export MENU fi return 0 } samhain-4.1.4/dsys/initscript0000644000175000017500000000643512615253277013200 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # startup=no # arg1: the --enable-nocl=password password (use 'start' for none) # arg2(optional): if 'startup', start the client and exit # # # 'nocl' is used to handle the --enable-nocl=password option. 'start' is a # reserved word, hence cannot be the password. # We are called with one argument, which may be 'start' to indicate that # the --enable-nocl=password option is not used. # if test "x$1" = x then nocl=start else nocl="$1" fi if test "x$2" = x then command="data" else command="$2" fi name=`./samhain-install.sh --print-config name` sbin=`./samhain-install.sh --print-config sbin_dir` # execute and exit for start|stop|restart|reload|status, else fallthrough case $command in start | stop) MONIT="" test -f /usr/local/bin/monit && MONIT="/usr/local/bin/monit" if test x"$MONIT" = x then test -f /usr/bin/monit && MONIT="/usr/bin/monit" if test x"$MONIT" = x then : else zz=`/usr/bin/monit status | grep ${name}` if test x"$zz" = x then : else ${MONIT} "${command}" "${name}" exit 0 fi fi fi retval=0 if test -f /etc/init.d/${name} then /etc/init.d/${name} ${command} retval=$? elif test -f /etc/rc.d/init.d/${name} then /etc/rc.d/init.d/${name} ${command} retval=$? elif test -f "$sbin/$name" then $sbin/$name ${command} retval=$? else exit 1 fi if test x"$command" = xstop then exit 0 fi exit $retval ;; reload | restart | status ) if test -f /etc/init.d/${name} then /etc/init.d/${name} ${command} elif test -f /etc/rc.d/init.d/${name} then /etc/rc.d/init.d/${name} ${command} elif test -f "$sbin/$name" then $sbin/$name ${command} else exit 1 fi exit $? ;; *) ;; esac data=`./samhain-install.sh --print-config data_file` ddir=`./samhain-install.sh --print-config data_dir` remfile=no remdir=no if test -d "$ddir" then test -f "$data" || remfile=yes else ./samhain-install.sh --mkinstalldirs "$ddir" remdir=yes fi if test -f "$sbin/$name" then if test -f "$data" then rm "$data" || exit 1 fi if test x"$nocl" = xstart then $sbin/$name -t init -p err else echo '-t init -p err' | $sbin/$name "$nocl" fi else echo "$sbin/$name not found" >&2 exit 1 fi if test -f "$data" then cp "$data" ./data else echo "$data not found" >&2 exit 1 fi if test x"$remdir" = xyes then rm -rf "$ddir" elif test x"$remfile" = xyes then rm -f "$data" fi exit 0 samhain-4.1.4/dsys/0F571F6C.asc0000644000175000017500000002657712615253277012567 00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.2.1 (GNU/Linux) mQGiBDgcfd0RBADvXitAL1gCXw1yOJsPWJdU6wbgqMWqfMbkFGRiLZut/rwbN3x/ ch8sF+hptcQGH4Hhe25+1WkSO1KO81j6ZQZqhYNHogE3IFsv1TK7vX0r81ZRjinM koQ69kWw+elp1vcLCwHzHDB8MhV3eI3jpQcGgpsRVq4uEumyGfI1v6AUfwCg+RIj aGtvyxFH2UsSUVNaM/008v8D/R56I6qLcixxuWrHUhZBNaiQ0I70PWo92uLHwSvF dnSnkpUc4BvTeq4PVuId6e3LdeonG4OW8jWFK0/9OE+ubuZYJdOmuv+3BzPOktZy 9Cf8QwHpUvQ/c9S5MrIOsFdQAOj6rQvlA7OmnidyW4+MA3IYp8bwq5dx6sHcAy7o 0RBSBADpf5eWfni8Awfcwq7yyGgJFhAAgkoDKAHBj4OepVKhcnCe8+78VpqWtZ9p e45AL/5nhl6CceWWZfCYXgv2Zm8CUnUwxb6XKuGOGJagtRT9d0fQFeEXFlSPE5HA JCXkhbcQpZq1YzyjKMeExBfM5w4XaEhfQ652pjXQieyWETjd17QtUmFpbmVyIFdp Y2htYW5uIDxyd2ljaG1hbm5AaHMudW5pLWhhbWJ1cmcuZGU+iFUEExECABUFAjgc fd0DCwoDAxUDAgMWAgECF4AACgkQGq0myA9XH2y7FwCdEIZRr4gI9vlS7DgcS8mY FjveBncAoLiNO3tE00J4r6LEWm4IpYYUiRUFiQEcBBMBAgAGBQI+UjZjAAoJEAbp c/N5kkHBNjwH/138Qk7NcZT2ar5t4MOyaHM7gaIOaywZHXaGEx7wrvpmD3ImoerE psp19+JqOfzhgpGI8Z37nh+HR5vIYERrMrIBLoHMwyNkJxqRiqNVfZ3AxpZWvKTl AJlwIvPGF6FfR2f05Lvaw06UoOLpIjmzb8rXQ6bvbqSXtgUEU+pmwfjQOPidwNjW ovUTkCpv2LWQxwapYgOZilne+7Zad+nf/asCGfqL9V9WIblrwoFkSlP13UwF4j5f m7iTM9ZAXFUUFvarN2Mz0RP4+58rceb6bRM+agL+dpd5AqgwBgtGYmeO/G4/E/WY PYBLTh+ZbupmvykgdnKR0E0w72KXnLg11M2JARwEEwECAAYFAj5SNakACgkQBz/7 hK/ULUUktggAgbbW4uM9B8jQeavzdMmV3WiF2owqr1MiS+oiWKBK3U6O0xJP5G9Q h5Zj80NEdopDV0G8z1KOFn4v4SMlzSjvq6938end+zvgaPGEGaE94iHp5aI6TMhF ezmbM2MfNphfn2yxmzQefEj8VaJbi+du4n1YmnkMJDkpw+6927/99Sj3A0jNvUxC B5YM9K/t6xI89qlKZlCDHjgEHARAxNWRyE5YSqRkXWgxcHPKkF1oKifD4/eNyQw2 OZnRTFRsk28uEJTysnjsiIUbP13LR6m1VfZQrEpk0RjnlGKVRwy42WWDnOsCXOnM Sy2+a9gYa+ayCGI+NTuUUecvZ7VVxKCHIYhGBBMRAgAGBQI+UjYnAAoJEA86uzhI KF65WpIAn0p+PQe7WaHp15qul2E7AoDD7uuzAJ486FDSWZi92crLJNPnyPi9HXbi DIhGBBMRAgAGBQI+S5Q1AAoJEBwB7TX3s/Rm2QcAn2zwg7uup1JMGqTxSaQ+sjWR 0vEqAJ9xvhAZMOrk51/6T7Oq/DzaZGwT3IhGBBARAgAGBQI4XqDdAAoJEB3kOh0g CZVMC8cAn04Ph20EZH5vbPvVQN9+KdketxyHAKCIhQvT2DiNsadeI7fQwRssLn7a xohGBBMRAgAGBQI+S5NzAAoJEG48dKkHK3yJ8/YAnRTCT5OhC9jPOxL26UKTF/YT t46kAJ9WI3vfQrbKgu32s6E5UTgQS/U4hokBHAQTAQIABgUCPlIpcQAKCRB4oTZL RAPrMfOcCACxIuPyBAxDIDvP3xWzMdlN4AhLIQ1myMHlwA7X90RVKW+saR+gU3QI hBVahKfC7OEXhH/dCft1c64Vy3lZT5vl9W6m0ZukdVSKTVKZYaRk+iGej3+zzD8W CzwDvMvkDGa1/VuOZDvx3byj866/L3Y4n8Qa+66KkqNG3sMgjOfMoxGTvZuxL3Zz YdQWUovd9KcmOl7etDB8rhkz4cBPxXxcIbDhDPJNgDoViby4Bgs1nmfvhPq+RNvK fKysRo9XYWfTRjwqicSMhSTRdgMS1GHCMY3U183p+njorU9gxvxmZhxzop41vwh2 ps6CVpUo9u+fpiDkfWeZIBzdl6+pz8TkiQEcBBMBAgAGBQI+S5OYAAoJEH641Vr2 yhx/sVIH/3MXz2dFzTze2eM9jj8DMJhM6wsuXIxKnGxl7Vd0i/T3jlh+UAQBueHz KtsmyE7xZ8OnoBfC9U4+ypyuKdnd0oULOTChDpY2a0Dv4gp4HZGoO3BR1qcf7LFy 3Ibn37siiJ4WmvgqPx9v1sFZAr+rKeSqhxnD7+GosbyD7qNQTATsorAMgYAdWCAC MsnLdP0K7yTW3X4JGgnRNjVJbYkFVC/j3qedT/Or0iUDDZdzID+vxxlwxa8Y+UTS wR75IPJEw7UObjQMdUixwUsb04rCI5CtPvMdO7nSvC1RvfP5TTSY5Ypu7bO6ArMT iYQfWhz2YCE/ikB8jeT6OovpqXiSKFaInAQTAQIABgUCPkuS/gAKCRCMWj5dyq7Z nSSwBAC2Zbo6lkfoq+ZPYj4hXs+C83aaVwEDEY4MqcEONPlt5tno6Tipt1aE7utf aCT2az5qLcns4cb+UckchEfcqmJc3+YTX97h6Iz55OsFYIXtUkYyys7Q3VmSqDZg Xz2N3YGBR0ttRk/qTNd3BoIWzdlqaLFfkFf5EgdIO5UIB8KPLYkBHAQQAQIABgUC PnHPRAAKCRB7Id4BrmYkJQOVCACpVqEZXDSU/LA1B1y7OtbQvuLOBqkKYvJ6QY+b SUnQA4pIWm1tZuGXckuo7Th/2zUqu+Jthso6zNRzz+FXIPOamHVRqxjbihPCsLA7 1MfVax7shaXswrHbKDt4Ou9834+KY2/G7XFdym2IezSeOrmsSicgQNsqdOIlmgMX YaG/4ddRvbB4V5PomPCz+tKDALXrkRoiS2akyfMgwsMOo9xfXA6j6bHJwHjar6eD ZiWcG24KXbiRYsyXw8v/piuG6rer7VuTFuaJwEAUvZYxAvFtISmxDAysHKwHXK1g ijK3Dh0JSkZrEH3LofAzRtcw+MQUkiD5sBDJ0E6QOr9bk14FiEYEEBECAAYFAj5x 0GwACgkQhfcxbPQmVn3FQACg1wSQt5mdfpwN74PFs6SVpoQ3kFMAoNJORjgHXFyF Gc+2DXq1KFXEUKAtiQEcBBMBAgAGBQI+cc0RAAoJEO67Mb58Bv0ljgYH/RVSwmd+ BufOXhZNfozT8p2M6xVgsEQ1nzdHtAVo+tr00xyHHwLQj1phDXSZtK1iRvLY6GXg Dp0VAGjkjUilR8adfT7uvgu9br32zCx7EZkAOQXp51tPWnD4JDcWB0adJEWwfVo9 +abC/84/Xy0c+IOdNLEePLxlYlezynXTCEgTXMeeROKOQMog/vB8obNi3rYjUKC/ eypJCuMtmnLKhHhbezvJMy+N10iWajpOYInQLP+uee48/ytmbnb+8klx8j3rJ1Ew r4KU+7ewm2eHPzJl1xCbuqePoxciptgtjdwtmGQH+VHDPRAcF+FfoNtF1Fc1p6+8 7qznfNJoLHWsde+JARwEEwECAAYFAj5xzSAACgkQKBTThimyUAFD9gf/RUY5fwxN Qv2N2bnSqmisUEx8XrOGGmzPNKvL1TdIwcc+votQ98nOBEv6De17+HD/jPVD3ReS 71sB1gI5/Duni5h8nx2L2siQxOqNE2YI2oSn8f4ign91ruFSEwPR+nFUDtbuMk4C 0df16i7asVXiKq3GW7Tv20iXnTvjQZCVSFtXxU00pdtmf0FpRSPp7YonQMLv6vCH iZ6j74kkn4+EwroXmWF5nb9/HZOJiZnTv6+vGpFYiI/gAGkOA4SBipUWm2B2E4AV MTo2MeXe+/wbirL43PDiG2kbeet7KH5M+/BTceUjl0alIFeZizYaluvouWo7NahA MLz89pUD25hpl4hGBBIRAgAGBQI+dJKeAAoJEI47c57dK8ydsAoAmwXDmPsbM0Ao 0VkY1q8anK5lhJMqAKDQOIimB3yzFt7koY9MUgFgHX77rYhGBBARAgAGBQI+hde4 AAoJEHFOxoebS5syXOMAn3xCJVsb0IRb42q25sLpHVXvc8+TAJ9Q3RBxdagtPVPx m58Uf4bhGLuBdohGBBMRAgAGBQI+iDOzAAoJEJJVvZ/mhE25CQYAn0j2H3sUfjao iTML5QF057ZfwzwoAKDBulEh0SChQQ2KbHdlpAVP+Io+U4g/AwUQPtSY59vSRfyz sqEsEQIDSQCfVPYWXSS2qbCI0BZm1jNI/D3WndIAoLmDomrFc+B+9Hp6id8B8kxy /IRdiEYEEBECAAYFAj74SAgACgkQ36XkltcZWyKb6ACg6XOdq03pvSlA0AqBZLQV wmeItVcAnRpHJt7znvfrxPpI4vfnkRR1Lt/yiEYEExECAAYFAj+f3koACgkQxcDF xyGNGNeCuwCfRP034939xTTTLWp+hQUE/O6NfbIAoJ7IbYA3YQmfDQukotNGypzH uo1aiEYEExECAAYFAkBbXgcACgkQ01u8mbx9Agqs9QCfTRKAxpfPhFz0kL2cODz6 Eo/TbMUAoIyztog7I3BTwu22eTPv6pXUTQEliEYEExECAAYFAkBbJ/0ACgkQSvFU KpY6VLBbHwCdHlFGr+t5aNg9SWqFfLs2N38awXkAoIW0bSz0MOPCkUHtY1o+wfjo J+DPiEYEExECAAYFAkBqj9AACgkQECqmVFXwdrOgIgCeNTva96TnQPlkIcpRE2hs oHITahAAoIEk77c6+Cr9CsS46WGvf1ePJW0yiEYEExECAAYFAkBytVYACgkQGyfX UvpJphr6dwCgkB330qWc6xjgounXSXbCvR7Dry4An3MzbcU/YS/OH7IBZMopWJbo Vr6KiEYEExECAAYFAkByunAACgkQA5e1oKh+NRxEmgCbBOyZmLeti3aysxi6yYEz JRkBGe4AmgPMOK8nxNjqa2KTrvsdH+XJSnGOiEYEExECAAYFAkB0A6AACgkQzAoJ I8gDfT8aMgCcCqTKT9sTVsk6UYIvYB6aBbmQIvYAn1gYeX6HTIo4+CfPC2c6bc80 iO+ViEYEExECAAYFAkB0ZUsACgkQr/RnCw96jQEetgCgnJatrM9Co+6JunHUl58L PswEAdAAoIFqNka9tvPrk8ZOJkfxJJEujrIgiEYEEBECAAYFAkCKrbQACgkQ9yNf So1Tr57J0wCfdZB/pGW/wyjHP2rpEQ/xV8bc/94AoKnbj0KC+glYM3pDOwjKbEZH /WAfiEYEEhECAAYFAkBzpsUACgkQ78vN/2HwW4wcDwCfYPlVzDJ0jfI+mMR+tHP8 n6Guj98An252IGC/eIB1I4nCi5TqqeVEvIeZtChSYWluZXIgV2ljaG1hbm4gPHJ3 aWNobWFubkBsYS1zYW1obmEuZGU+iFYEExECABYFAjoDPmkECwoEAwMVAwIDFgIB AheAAAoJEBqtJsgPVx9sNHAAoOPNgUXL+qRFyHU8wyDEeOHWALErAJoD2eIs0r7R 4UH+q+3J+v2EDbrHQYkBHAQTAQIABgUCPlI2awAKCRAG6XPzeZJBwcA2B/4sQlDm NMykYdYPY/MZ2b/O6S/2rZts+W3htjMEMvSzTM96koCJEpJCaHbmMehqZGUh/V97 oj4+rTfeKtKQBSVaBU2Bj8Zy2YjlqBUs2ShilVMR14RSOgmKr8FSvJVSegWf62T+ yFisLZdhQMTImSkKMB2oWkZPS9Su9dtk7j9gfHKwPIx3O8MCNf2dnaksHCpUMa3o AcXBZprMYE31zbrre2pi9E1jRFyq2zr0Ywkw1/LO4GUi3Zstg1gffLEku+ZpIBaw NH+WO+kkfoNmS03Ffxoo+Y5LLXAkm/dfn/KsbVy/WKHCiXfhWnyAxGxZhUAcgMwW VFcN53kQ1Twq8S3HiQEcBBMBAgAGBQI+UjWwAAoJEAc/+4Sv1C1FzQUH/j03htOj wiBSi/S3KcRCjrX9gem3RwCVTVbOKoGhAuA2cd45ZlT3E1ivvPAg2MzNzGQt1Fai CsQ/3Xy/1JzfnwVijHGXDZFrV7/ZClA4sj/bO36KNSoVNHeE7n1dsrfd1N2s9WgT JkB/LdRCcTqiUubxy+pWghdAEpSOAO/KacxhZ9Bbf1cjOcWJBbMWZSMLBTddUCcx cxzi3hpIfNOjwuZwYWlIe7KLI6YdjrdNUQZHPBTivTiZMzQ2kc7jPoSS/h5s9cvo hLa/9QqARih0V+ilTl8RFwYuPFWvIy4aTCSHWkzYO110KiLhz54Z1P0z5nWe/IfS XJRFgrAd2xKkpd+IRgQTEQIABgUCPlI2TwAKCRAPOrs4SCheuVwuAJ9q/3m2ZuG/ RpbNISA1zTi1239CbwCghqx5M2MClODQ4YRF+I/be6j8ub+IRQQTEQIABgUCPkuU OgAKCRAcAe0197P0Zp3gAJjpxPKU0GFcYhaE/ED/jI+h65HKAJwOwYPmGuU4dR3I nN+iHBnqY/9s2ohGBBMRAgAGBQI+S5N5AAoJEG48dKkHK3yJd5sAnjIKbVSpWM6v aEYdrWKF55rlXwo1AJ99RNP00MRpBa7IiVcXBR3KOurRsIkBHAQTAQIABgUCPlIp eAAKCRB4oTZLRAPrMUAfCADAz95sXsxdUYAS+jejVuf1EYA+5TEgSIi5uhSOlgdu WyUAzGuWSplc6kjoqwysUmnwthJON5Y4DSIes5YsDs93k+X0bZxDkzghqiFU5LWE 266bN7MvWmYXh7DfAz3V262dqa2IvvxSHtxmiYLPn5mZ2pLsXnWYTZUBZ4BSdArB t0pfHOOjZaixqfK7DYzyripm9259552aYOrmso8lSnAq2a+ekD9tQ9e2m8gkPbei 5sF1kawoYkyedEr+r4j0h1Sf24LVJinLPnavtDGUynt+v0NobzqBUHgI5lnSmlDt WWUU23YvAko73aJwlW1cDkRfcsR+TdA+IiECbFcipOd1iQEcBBMBAgAGBQI+S5Op AAoJEH641Vr2yhx/sN0H/1kWbhVnnkqC1LvOdqP9bx7S3UDUkQw0xEf1DC2lUALV zioDt9PvarRh47bcaUis+x/9k9AYsPFDhBiYPYek6VcxT86LPVUKz/gELOmHNcAq 3aUl35NKC97JVxYqMix1+hS8UY+m5zezSDdLAz1G8UKZ1d6tx3daikOPzKmpIY50 wMBdA3jITr6J4eWZ/ptfL0GDdlXFOVKFURMIn6t5AAjKdqQHYySxhuWn+S3QQxDz Ulv9vAUW4VS+6lzWB1thmRxwawbfJ+05kO/hGD+alWiJxyW/PXRwEiqdVzAIIocM mHmGtEIONcNyRdjIsDIyZTMavFJOE0hMHftp8a7vbTuInAQTAQIABgUCPkuTAwAK CRCMWj5dyq7ZncE6A/9tzn5ZST0cgPqQEywAcTeQeja7Qxxl7/CJ3gHqnK8eZu2D MmSINdRgPjDknn9hWhKu2aDjfhl/a/sIbD8cHtvWza0Z9a12tZZ5+kDOand/U3rn RLRUO8MnhLxHif5vEtQvC54jxmpOl05J2o5QT0pFs9BHW3tDGlR4CWPrwUC2W4kB HAQQAQIABgUCPnHPTAAKCRB7Id4BrmYkJaWCB/41LdB1IdcPLraASItBLqfKb46+ fOoU1teYrM3J7zE5r1z79Mu7slT5JRP3i5iD+TjbqDI4LitZ2lrbmGTI/uQ0R9T8 PBWcs+SBroVCDziCO2nTVQldvqtmXCx0Rpu8iZacKotEz9nVQxouUiskgNn/v0p2 Ng1gUK5g3CripcYXUpkEpmYkyTYAbokeeKsF3cCe9czVT9l/nB/OJIus31eKa8x0 9+1EMdu/GJIxa/tDQh7vkNKSP09qtKrCsSxzpfmwIj1PBTT8oDkBkheuTaKTTWPE 0jWP3aNMTHZUkLpRVNf1htus7utSm1O+W6hTYQLL0OPMylBTWZ33vN2Nb0fliEYE EBECAAYFAj5x0HIACgkQhfcxbPQmVn3c8ACgyIVKF4Fjl2vCc3VgAcPvNZ8p5lYA nj2/t1pja5FPd89R7I1ZS4Ctb12uiQEcBBMBAgAGBQI+cc0VAAoJEO67Mb58Bv0l t48IAIWzONERcs+QPNZ3NbMU3Um5s43XxZcql6mOIc0I7eBLl/bn+UTh4F5PuAbh mgTkVR5l9KF1PKswHfbzYxDSGTYqSXOCXRnbU4sByoSaV6xlGJAM9ivi/vEom6uE v6pQEZslNDNt4IfYx35+8WLhjXb7OM0HF5ZqpLqXF5BGAYGx9vDKs4SEo5HNslTT q1JgDMJNXKVyQxOAewICq+VaqbztwGf8nhcNz5Di4G5IbKi6BKOvlkPt4TkRsppJ Gq+1rAM6Fh34FqaKshuubOuoZwXKrmMHGEYgoE7XLXW5998GmE4dZh8fO7iaPjH4 3f/qcmn5joko+HQw9visZymSxgiJARwEEwECAAYFAj5xzSQACgkQKBTThimyUAFv NQgAthIAnR7+dtVcrH51R4J+8Li30yi04E0VGLhJ6KnGCpzv8eSp2HMiaRe1JAss Zy7S+dpcL6MDjcYR6HaNP49V9RtTfiARFgZWQ6SD5nOdmMe3Nb6kmfYnZO3YHwiW NXtncNHHnvSS1bDM5o3hitEPHvnQbOB/k6BpilsKzPl/bvRa8hT1/b4hQjhmv5Hf LxI6suLyOqz6ESWL2enFXTmthOOAan0yLkhLNvIsHZue3Kd7OP7+7uzmCF+mEIL7 eL9EheCa+4hWUEltdEdBtX5kcgJdTJQZZCuyz7aZ1JSZwr0G+4x6K5J9WAzI7BzI TD0rZ0LSOilyuDTYQChRDJPe8ohGBBIRAgAGBQI+dJKhAAoJEI47c57dK8ydmcAA oJa36CvpFHhq9VH0BRAgk6whGRFpAJ9J+VP1AmA3tjmzV3R7Ls5TMJRs4YhGBBAR AgAGBQI+hyNZAAoJEHFOxoebS5syxQEAn0XqPZdIJqSzqFq7ElQMK7khAxuwAKCA qlcHbWvhqxN7mAmC/wfYebKbZ4hGBBMRAgAGBQI+iDO2AAoJEJJVvZ/mhE25bioA ni6Vz0lqdlCdJG9KpeWUGtPcwUFDAJ9281Qpt6+9PW5TJOrcBO7OJW8UIokBHAQT AQIABgUCPsoYKQAKCRAcU5jLRuk3pDzVB/wP5SA6Dq168ItTQoOhNmx4k4sm5sJP bbPPFOKjYhPjnBKSNmU2l+Z4lNrI9BxEhTwGCc3NpTV8E7G5I6PtWaeTgFgdd2B/ eZCSui82yQmBOh/CFk5WW8deB4Bd4MDCCjhx2nZz7ivB0Dv9FlMyLqChjARrJQGD u2XfAvYyXhW+4UNOPI0D/SkJgeCRoVQi8ASbgt6SlHn7wkdvrDltJy1CfbqiYBr3 Y5TG4JaGceW8vfMCEdbw21MxPK/nP08J7ES5oMRcFHCA82+TvuCOErOnq/naPqHC vjpbpLqYl5qtv8cN7kV/eb/sAXBL41AM0bQoM/KY7Bv/Qldk0R7w/4XmiD8DBRA+ 1Jj029JF/LOyoSwRAmdiAJ4iGUh4PlFl2QLC2HBdOk+gnZdFSQCeOTZ5bFIRg0YU OCpuvgkifys5L2mIRgQQEQIABgUCPvhICgAKCRDfpeSW1xlbIibpAKCfTI1e8MXw BbGPVPYGPEWfF5Dl2wCffBaai8FxqWhzHRek00rxLgEqCfiIRgQSEQIABgUCP51G YwAKCRAdqzxE2iYyGBerAJ9utXaBGuKbOLW1N3EAFVPUsMl1pwCeJWmBUvaZ6Z18 UitAdRn+c3tcEE2IRgQTEQIABgUCP5/eRgAKCRDFwMXHIY0Y17qSAKCoOhCWYphZ tuwgAiglspzyXyUPGgCg0Fjhhq8KfNQujv5LJEKgP5EUrv6IRgQTEQIABgUCQFsn +QAKCRBK8VQqljpUsEajAKCRBtUxFnh+w5YdYU971cbT54sQQACfVg1gozhfClAw XhPGML85ne/WatuIRgQTEQIABgUCQFteAwAKCRDTW7yZvH0CCn+BAJ4959iKUXvk dYpmtNKZyulsCGj9ygCgxA8Qo/1WffxrWeCnL9jK106qkMuIRgQTEQIABgUCQGqP yAAKCRAQKqZUVfB2s5CAAKCYZGG8v9mlYwGZd62fLcuqh28kvgCcCzpEb0xQaoTV Y1LdcKlnrQyLg9qIRgQTEQIABgUCQHK1UwAKCRAbJ9dS+kmmGjF1AKCdX/0pvL7J Q9QIpk37clvuTjdk9ACfW5CPmsBTo4QebFLvrXjPA2BS2OyIRgQTEQIABgUCQHK6 ZgAKCRADl7WgqH41HMhvAKCHhiRvXGhAd7DS5nvCURhUde6/QgCfZQgEtHFSLhpj KacnyMkg6xF2dSeIRgQTEQIABgUCQHQDnQAKCRDMCgkjyAN9P+W9AJ9OQZ3++gB1 KDNRxmsj/W/KHLQ2SQCdHUEhkuCKURe7upjXUOhExaIKTdKIRgQTEQIABgUCQHRl RwAKCRCv9GcLD3qNAWt5AJ9t8EbD+ZoZP6ZcJRIH0byTXSvaIACgtcC7OUBQayGD eKpkyyTpUTTJFpyIRgQQEQIABgUCQIqtrgAKCRD3I19KjVOvnhkdAKCLJygVD/kJ lQWaJkxgU5ykneSklQCeN8508dGDEY0gmq+uJPtdgDCusy6IRgQSEQIABgUCQHOm twAKCRDvy83/YfBbjGClAJ9kF+WHOy0ctth6wvisP04IH8YCBwCeLYt5p8KLLZ9v T/+kn5KNrNmZJay5AQ0EOBx96RAEAMnQiAMYTglVoIciiw5l0YIuE/Uh4KSPhf1X TY4CqZrjpv56QSlhndyM5Q9vhC/bpnzMCl4A1YCb2MPMO5QYD1URI13KkG7HX6hz eW/ANfs/DJ6o1odOu3deSIzgb/TEqLV6rr7IcY/hkn3IuAiBCrMR/3kKx5AkyKOQ ZNsd40sHAAMFA/4jrzq9HoWmeEFG25U7s43NvoDFtrlt8IaS/BVdVCx599yT+BPT RmwRfpkV7TAKghgXp0SKYgo1Bp6tdyymTiZ8Ly14CUiuPYBOBifjsFoeVXWj1arW FmmQWd4d59scGoITMh39f0XTxpgGjVVxNbdqSMS+khzP5acQ27DsFMbtMIhGBBgR AgAGBQI4HH3pAAoJEBqtJsgPVx9stTUAnikTmI5ST+k6VhT2gltex+sDmr6NAJoC qkfo4qjAQCyqTx5Eg3NKuxafqQ== =jITK -----END PGP PUBLIC KEY BLOCK----- samhain-4.1.4/dsys/preinstall0000644000175000017500000000257112615253277013162 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # name=`./samhain-install.sh --print-config name` sbin=`./samhain-install.sh --print-config sbin_dir` MONIT="" test -f /usr/local/bin/monit && MONIT="/usr/local/bin/monit" if test x"$MONIT" = x then test -f /usr/bin/monit && MONIT="/usr/bin/monit" if test x"$MONIT" = x then : else zz=`/usr/bin/monit status | grep ${name}` if test x"$zz" = x then : else ${MONIT} stop "${name}" exit 0 fi fi fi if test -f /etc/init.d/${name} then /etc/init.d/${name} stop elif test -f /etc/rc.d/init.d/${name} then /etc/rc.d/init.d/${name} stop else if test -f $sbin/$name then $sbin/$name stop fi fi exit 0 samhain-4.1.4/dsys/funcPRINT0000644000175000017500000000345612615253277012560 00000000000000######################################################################### # # Printing/logging Subroutines # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Fatal error # printFATAL() { printERROR ${1+"$@"} main_exit_status=1 echo '1' > "$tmpERR" (exit 1); exit 1; } # Print a message to stderr # printERROR() { echo "ERROR:" ${1+"$@"} >&2 } # Print a message to stderr # printWARNING() { echo "WARNING:" ${1+"$@"} >&2 } # Print a message to stdout # printLOG() { if test $silent -lt 2 then now=`date` if test -z "$logfile" then if test x"$simulate" = x0 then echo "${now}:" ${1+"$@"} else echo "${now}: (simulate)" ${1+"$@"} fi else if test x"$simulate" = x0 then echo "${now}:" ${1+"$@"} >"$logfile" else echo "${now}: (simulate)" ${1+"$@"} >"$logfile" fi fi fi } # Print a message to stdout # printINFO() { if test x"$silent" = x0 then if test x"$simulate" = x0 then echo ${1+"$@"} else echo "(simulate)" ${1+"$@"} fi fi } samhain-4.1.4/dsys/funcEXE0000644000175000017500000000311312615253277012273 00000000000000######################################################################### # # Subroutines for determining existence of / path to executables # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # findEXE() { if test $# -lt 1 then printFATAL "findEXE: insufficient arguments" fi X="$PATH"; prog="$1"; OLD_IFS=${IFS} IFS=':'; export IFS for dir in $X; do exe="$dir/$1" if (test -f "$exe" || test -f "${exe}.exe") then EXECUTABLE="$exe"; export EXECUTABLE IFS=${OLD_IFS}; export IFS return 0 fi done IFS=${OLD_IFS}; export IFS printINFO "Command $1 not found in \$PATH" EXECUTABLE=""; export EXECUTABLE } needEXE() { # printINFO "Checking for $@" for arg do findEXE "$arg" test -z "$EXECUTABLE" && printFATAL "Need \"$arg\" in \$PATH" done return 0 } samhain-4.1.4/dsys/comUNINSTALL0000644000175000017500000001606312615253277013056 00000000000000######################################################################### # # Subroutine for the 'uninstall' command # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # commandUNINSTALL() { printINFO "About to run \"$action\" on host \"$host\"" format=`setupFORMAT ${DB_version}` realformat="$format" src_version=`setupVERSION ${DB_version}` test -f "${basedir}/archpkg/${DB_arch}/install-${DB_version}" || \ printFATAL "Install script ${DB_arch}/install-${DB_version} not found" name=`/bin/sh "${basedir}/archpkg/${DB_arch}/install-${DB_version}" '--print-config' 'name'` test x"$name" = x"${DB_name}" || \ printFATAL "Client database and installer files are inconsistent" arch="${DB_arch}" #--------------------------------------------------------------------- # Uninstall. #--------------------------------------------------------------------- if test "x$format" = "xrun"; then is_command="./samhain-install.sh --force --express purge" target="uninstall" elif test "x$format" = "xdeb"; then is_command="dpkg --purge" target="${DB_name}" elif test "x$format" = "xrpm"; then is_command="rpm --erase" target="${DB_name}" elif test "x$format" = "xtbz2"; then is_command="emerge unmerge" target="${DB_name}" elif test "x$realformat" = "xpkg"; then is_command="pkgremove" target="${DB_name}" elif test "x$realformat" = "xdepot"; then is_command="/usr/sbin/swremove" target="${DB_name}" else printFATAL "Don't know how to uninstall package format ${format}" fi if test x"$silent" = x0 then is_rmboot="./samhain-install.sh --force --express uninstall-boot" else is_rmboot="./samhain-install.sh --force --express --verbose uninstall-boot" fi #--------------------------------------------------------------------- # Create temporary directory on host. #--------------------------------------------------------------------- tmpdir=`eval echo "${temp_dir}/sh_${src_version}_${arch}_${format}_$$"` if test x"$simulate" = x0 then ssh -x -l "root" "${host}" '(umask 0077; mkdir "'${tmpdir}'")' else printINFO "ssh -x -l root ${host} (umask 0077; mkdir ${tmpdir})" fi if test x"$?" != x0 then printFATAL "Could not create temporary directory ${tmpdir} on host ${host}." else printLOG "Directory ${tmpdir} created on host ${host}." fi #--------------------------------------------------------------------- # Copy to host. #--------------------------------------------------------------------- if test -f "${basedir}/configs/${arch}.initscript" then cp "${basedir}/configs/${arch}.initscript" "${tmpD}/initscript" || \ printFATAL "Could not copy ${basedir}/configs/${arch}.initscript to ${tmpD}/initscript" is_initscript_full="${tmpD}/initscript" else is_initscript_full="${basedir}/libexec/initscript" fi if test x"$simulate" = x0 then if test x"$silent" = x0 then scp "${is_initscript_full}" "${basedir}/archpkg/${arch}/install-${src_version}.${format}" "root@${host}:${tmpdir}/" else scp -q "${is_initscript_full}" "${basedir}/archpkg/${arch}/install-${src_version}.${format}" "root@${host}:${tmpdir}/" fi else if test x"$silent" = x0 then printINFO "scp ${is_initscript_full} ${basedir}/archpkg/${arch}/install-${src_version}.${format} root@${host}:${tmpdir}/" else printINFO "scp -q ${is_initscript_full} ${basedir}/archpkg/${arch}/install-${src_version}.${format} root@${host}:${tmpdir}/" fi fi if test x"$?" != x0 then printFATAL "Could not copy uninstall script to host ${host}." else printINFO "Script copied to host ${host}." fi #--------------------------------------------------------------------- # Run uninstall script. #--------------------------------------------------------------------- if test x"$simulate" = x0 then # # No, this is not a bug; the first 'start' argument to 'initscript' # is a required dummy argument. # if test x"$silent" = x0 then ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH'" && export PATH && cp "'install-${src_version}.${format}'" samhain-install.sh && chmod +x samhain-install.sh && chmod +x initscript && ./initscript start stop; eval "'${is_command}'" "'${target}'"; eval "'${is_rmboot}'")'\' else ssh -x -l "root" "${host}" /bin/sh -c \''(cd "'${tmpdir}'" && PATH="'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH'" && export PATH && cp "'install-${src_version}.${format}'" samhain-install.sh && chmod +x samhain-install.sh && chmod +x initscript && ./initscript start stop; eval "'${is_command}'" "'${target}'"; eval "'${is_rmboot}'") >/dev/null'\' fi else printINFO "ssh -x -l root ${host} (cd ${tmpdir} && && PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:\$PATH && export PATH cp install-${src_version}.${realformat} samhain-install.sh && chmod +x samhain-install.sh && chmod +x initscript && ./initscript start stop; eval "${is_command}" "${target}"; eval "${is_rmboot}")" fi if test x"$?" != x0 then printFATAL "Could not complete uninstall on host ${host}." else printLOG "Uninstall executed on host ${host}" fi #--------------------------------------------------------------------- # Clean up. #--------------------------------------------------------------------- if test x"$simulate" = x0 then ssh -x -l "root" "${host}" '(rm -rf "'${tmpdir}'")' else printINFO "ssh -x -l root ${host} (rm -rf ${tmpdir})" fi if test x"$?" != x0 then printFATAL "Could not remove temporary directory ${tmpdir} on host ${host}." else printLOG "Directory ${tmpdir} deleted on host ${host}." fi #--------------------------------------------------------------------- # Write/update client database #--------------------------------------------------------------------- SH_NAME="$name"; export SH_NAME SH_PREFIX=`/bin/sh ${basedir}/archpkg/${DB_arch}/install-${DB_version} --print-config prefix`; export SH_PREFIX if test x"$simulate" = x0 then updateDB D2_removed else printINFO "Updating client database." fi } samhain-4.1.4/dsys/funcINSTALL0000644000175000017500000003231712615253277012770 00000000000000######################################################################### # # Subroutines for installing # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # getconfopts () { fconf="$1" if test -f "$fconf" then # # check if readable # cat "$fconf" >/dev/null 2>&1 || return 1 # # empty string if no --enable-nocl=..., else password # is_nocl=`cat "$fconf" | tr -d '\n' | egrep "^ *'?--enable-nocl=" | sed -e "s%^ *%%" | sed -e "s%^'%%" | sed -e "s%^--enable-nocl=%%" | sed -e "s% *$%%" | sed -e "s%'$%%"` if test x"${is_nocl}" = x then is_nocl="start" else printINFO "Option --enable-nocl=${is_nocl} used." fi # # # is_xor=`cat "$fconf" | tr -d '\n' | egrep "^ *'?--enable-stealth=" | sed -e "s%^ *%%" | sed -e "s%^'%%" | sed -e "s%^--enable-nocl=%%" | sed -e "s% *$%%" | sed -e "s%'$%%"` if test x"${is_xor}" = x then is_xor="no" else printINFO "Option --enable-stealth=${is_xor} used." fi return 0 else return 1 fi } writerecord () { IDATE=`date +"%Y-%m-%d %H:%M:%S"` echo " " echo " ${host}" echo " ${hostgroup}" echo " ${arch}" echo " ${install_entry}" echo " ${IDATE}" echo " ${SH_NAME}" echo " ${SH_PREFIX}" echo " ${src_version}.${realformat}" echo " " } FTEST=0 set_flag () { case "$line" in *\*) FTEST=0; return 0; ;; *\${host}\*) FTEST=1; return 1; ;; *) return ${FTEST}; ;; esac } #------------------------------------------------------------------------ # Update client db #------------------------------------------------------------------------ updateDB() { if test "x$1" = x then install_entry="D2_installed" else install_entry="$1" fi export install_entry if test x"$DATABASE" = x then DATABASE="${basedir}/${defdatabase}" fi updlock="${DATABASE}.lockdir" trap "rm -rf ${updlock}" 1 2 13 15 # # A lockfile will not work, because 'root' can write anyway. # However, 'mkdir' an existing directory will fail even for root # until (umask 222; mkdir "${updlock}") 2>/dev/null # test & set do printINFO "Waiting for lock" sleep 1 done IDATE=`date +"%Y-%m-%d %H:%M:%S"` rm -f "$tmpF"; touch "$tmpF" if test -f "$DATABASE"; then rcfile_perm=`ls -l "${DATABASE}" | \ awk '{ u= substr($1,2,3); g=substr($1,5,3); o=substr($1,8,3); \ gsub("-","",u); gsub("-","",g); gsub("-","",o); \ print "u=" u ",g=" g ",o=" o; }'` rcfile_perm=`echo ${rcfile_perm} | sed s%g=,%g-rwx,% | sed s%,o=$%,o-rwx%` rcfile_owner=`ls -l "${DATABASE}" | \ awk '{print $3 }'` rcfile_group=`ls -l "${DATABASE}" | \ awk '{print $4 }'` else rcfile_perm=640; rcfile_owner=`ls -ld ${basedir} | awk '{print $3 }'` rcfile_group=`ls -ld ${basedir} | awk '{print $4 }'` fi if test -f "${DATABASE}" then SStr1=`grep '' "${DATABASE}"` if test "x${SStr1}" != "x" then SStr2=`grep "${host}" "${DATABASE}"` SStr3= if test "x${SStr2}" != "x" then # REPLACE printINFO "Replace ${host} in ${DATABASE}" exec 3<&0 <"${DATABASE}" while read line do # for some reason, var=xx only works in a function call (why?) # # here we test if we are still in the same client block # (set_flag will return 0 for and following) set_flag "$line" if test "x$?" = "x1" then # # Write the full entry when client_os_machine is found # case "$line" in *\*\) echo " ${hostgroup}" >>"${tmpF}" echo " ${arch}" >>"${tmpF}" echo " ${install_entry}" >>"${tmpF}" echo " ${IDATE}" >>"${tmpF}" echo " ${SH_NAME}" >>"${tmpF}" echo " ${SH_PREFIX}" >>"${tmpF}" echo " ${src_version}.${realformat}" >>"${tmpF}" ;; *\*\) : ;; *\*\) : ;; *\*\) : ;; *\*\) : ;; *\*\) : ;; *\*\) : ;; *) echo "$line" >>"${tmpF}" ;; esac else echo "$line" >>"${tmpF}" fi done exec 0<&3 3<&- cp "${tmpF}" "${DATABASE}" else # WRITE NEW CLIENT RECORD printINFO "Write record for ${host} in ${DATABASE}" exec 3<&0 <"${DATABASE}" while read line do if test "x$line" = "x" then echo "$line" >>"${tmpF}" writerecord >>"${tmpF}" else echo "$line" >>"${tmpF}" fi done exec 0<&3 3<&- cp "${tmpF}" "${DATABASE}" fi else # COMPLAIN printLOG "File ${DATABASE} exists, but has wrong format"; fi else # WRITE XML FROM SCRATCH printINFO "Write ${DATABASE} from scratch" echo '' >"${tmpF}" echo '' \ >>"${tmpF}" echo "" >>"${tmpF}" writerecord >>"${tmpF}" echo "" >>"${tmpF}" cp "${tmpF}" "${DATABASE}" fi chown ${rcfile_owner}:${rcfile_group} "${DATABASE}" if [ $? -ne 0 ]; then rm -rf "${updlock}" printFATAL "Could not chown ${rcfile_owner}:${rcfile_group} ${DATABASE}" fi chmod ${rcfile_perm} "${DATABASE}" if [ $? -ne 0 ]; then rm -rf "${updlock}" printFATAL "Could not chmod ${rcfile_perm} ${DATABASE}" fi rm -rf "${updlock}" } ageFILE() { file="$1" if test -f "${file}" then test -f "${file}.9" && { rm -f "${file}.9" || printFATAL "rm -f ${file}.9 failed."; } test -f "${file}.8" && { mv "${file}.8" "${file}.9" || printFATAL "mv ${file}.8 ${file}.9 failed."; } test -f "${file}.7" && { mv "${file}.7" "${file}.8" || printFATAL "mv ${file}.7 ${file}.8 failed."; } test -f "${file}.6" && { mv "${file}.6" "${file}.7" || printFATAL "mv ${file}.6 ${file}.7 failed."; } test -f "${file}.5" && { mv "${file}.5" "${file}.6" || printFATAL "mv ${file}.5 ${file}.6 failed."; } test -f "${file}.4" && { mv "${file}.4" "${file}.5" || printFATAL "mv ${file}.4 ${file}.5 failed."; } test -f "${file}.3" && { mv "${file}.3" "${file}.4" || printFATAL "mv ${file}.3 ${file}.4 failed."; } test -f "${file}.2" && { mv "${file}.2" "${file}.3" || printFATAL "mv ${file}.2 ${file}.3 failed."; } test -f "${file}.1" && { mv "${file}.1" "${file}.2" || printFATAL "mv ${file}.1 ${file}.2 failed."; } test -f "${file}" && { mv "${file}" "${file}.1" || printFATAL "mv ${file} ${file}.1 failed."; } fi return 0; } #------------------------------------------------------------------------ # The path to yule data #------------------------------------------------------------------------ pathYDATA() { if test "x${yule_data}" = x then promptINPUT "Please enter the path to your yule executable" yule_data="$INPUT"; export yule_data fi if test -d "${yule_data}" then : else printFATAL "Path to yule data directory not given." fi } #------------------------------------------------------------------------ # The path to yule #------------------------------------------------------------------------ pathYULE() { if test "x${yule_exec}" = x then findEXE yule if test -n "$EXECUTABLE" then yule_exec="$EXECUTABLE" export yule_exec fi else if test -f "${yule_exec}" then : else yule_exec="" findEXE yule if test -n "$EXECUTABLE" then yule_exec="$EXECUTABLE" export yule_exec fi fi fi if test "x${yule_exec}" = x then promptINPUT "Please enter the path to your yule executable" yule_exec="$INPUT"; export yule_exec fi if test -f "${yule_exec}" then if "${yule_exec}" --help 2>&1 | grep qualified >/dev/null 2>&1 then : else printFATAL "${yule_exec} is not Yule, or not executable." fi else printFATAL "Path to yule executable directory not given." fi } #------------------------------------------------------------------------ # Select operating system #------------------------------------------------------------------------ selbinARCH() { #--------------------------------------------------------------------- # Select arch to build #--------------------------------------------------------------------- if test x"$arch" = x then if test x"$assumeyes" = x1 then printFATAL "No operating system selected, aborting." fi cd "$basedir/archpkg" || printFATAL "Cannot cd to $basedir/archpkg !" LIST=`ls 2>/dev/null` if test x"$LIST" = x then printFATAL "No OS directories found in ${basedir}/archpkg." fi n=0 command="promptMENU 'Please select operating system of host' " ALIST="" FLIST="" for ff in $LIST do haspkg=`ls $ff/samhain-* 2>/dev/null` if test x"$haspkg" = x then : else n=`expr $n + 1` osp="$ff" ALIST="$ALIST $ff" FLIST="$FLIST $ff" if test $n -lt 8 then command="$command '${ff}'" fi fi done if test $n -ge 8 then command="$command other" fi eval ${command} m=$? if test x$m = x1 then (exit 0); exit 0; elif test x$m = "x-1" then printFATAL "Something went wrong !" else arch="$MENU"; export arch if test x"$arch" = xother then promptINPUT "Please select operating system of host from $FLIST" if test x$m = x1 then (exit 0); exit 0; elif test x$m = "x-1" then printFATAL "Something went wrong !" else found=`echo $FLIST | sed -n /$INPUT/p 2>/dev/null` if test x"$found" = x then printFATAL "There is no package for $INPUT" fi arch="$INPUT"; export arch fi fi fi fi # arch selected or exited } selbinVERSION() { OKVERLIST="" #--------------------------------------------------------------------- # Select version #--------------------------------------------------------------------- if test x"$src_version" = x then if test x"$assumeyes" = x1 then printFATAL "No version selected, aborting." fi cd "${basedir}/archpkg/${arch}" || printFATAL "Cannot cd to ${basedir}/archpkg/${arch} !" LIST=`ls samhain-* 2>/dev/null` if test x"$LIST" = x then printFATAL "No binary package found in ${basedir}/archpkg/${arch}." fi # -------------------------------------------------- # Build a list of ${version}.${format} # -------------------------------------------------- for ff in $LIST do sh_version=`echo "$ff" | sed 's/samhain\-//g'` if test -f "install-${sh_version}" then OKVERLIST="$OKVERLIST ${sh_version}" fi done rm -f "$tmpF" && touch "$tmpF" for dd in $OKVERLIST do echo "$dd" >>"$tmpF" done OKVERLIST=`cat "$tmpF" | sort -r` rm -f "$tmpF" && touch "$tmpF" command="promptMENU 'Please select version to install' " for word in $OKVERLIST do command="$command '${word}'" done eval ${command} m=$? if test x$m = x1 then (exit 0); exit 0; elif test x$m = "x-1" then printFATAL "Something went wrong !" else first_version="$MENU"; fi src_version=`echo ${first_version} | sed s%\.run%% | sed s%\.rpm%% | sed s%\.deb%% | sed s%\.tbz2%% | sed s%\.depot%% | sed s%\.pkg%%` export src_version format=`echo ${first_version} | sed '/^\(.*\)\.\([0-9a-zA-Z]*\)$/{ s//\2/; q; }'` if test "x$format" = xpkg then format="solaris-pkg" fi export format fi } samhain-4.1.4/dsys/comCLEAN0000644000175000017500000000432612615253277012326 00000000000000######################################################################### # # Subroutine for the 'clean' command # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # commandCLEAN() { printINFO "About to run \"$action\"" cd "${basedir}/source" || printFATAL "could not cd to ${basedir}/source" LIST=`ls samhain*.tar.gz 2>/dev/null` if test x$? != x0 then printINFO "No sources available." fi for ff in $LIST do sh_version=`echo "$ff" | sed 's/.*samhain\-//g' | sed 's/\.tar\.gz//g'` if test x"${sh_version}" = x then printFATAL "Cannot determine version for $ff" fi if test "$ff" != "samhain-${sh_version}.tar.gz" then printFATAL "Version number not correctly extracted from $ff" fi if test -f "samhain-${sh_version}.tar.gz.asc" then printINFO "REMOVE samhain-${sh_version}.tar.gz.asc" if test x"$simulate" = x0 then rm -f "samhain-${sh_version}.tar.gz.asc" else printINFO "rm -f samhain-${sh_version}.tar.gz.asc" fi fi if test -f "samhain-${sh_version}.tar.gz" then printINFO "REMOVE samhain-${sh_version}.tar.gz" if test x"$simulate" = x0 then rm -f "samhain-${sh_version}.tar.gz" else printINFO "rm -f samhain-${sh_version}.tar.gz" fi fi done printLOG "Cleaned sources in ${basedir}/source/" dbSHOWPKG dontshow delete printLOG "Cleaned unused packages in ${basedir}/archpkg/" return 0 } samhain-4.1.4/dsys/postinstall0000644000175000017500000000305012615253277013352 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # name=`./samhain-install.sh --print-config name` sbin=`./samhain-install.sh --print-config sbin_dir` rcfi=`./samhain-install.sh --print-config config_file` passwd=$1 setpwd="./${name}_setpwd" # Install the prepared configuration file. # test -f ./prepared_samhainrc || exit 1 ./samhain-install.sh --install-sh -m 600 ./prepared_samhainrc "$rcfi" || exit 1 # Gentoo noise # rm -f /etc/init.d/._cfg????_${name} rm -f /etc/._cfg????_${name}rc # Set the password within the executable. # if test "x${passwd}" = "xDUMMY" then rm -f "$sbin/${name}_setpwd" else current=`pwd` cd "$sbin" || exit 1 eval "$setpwd" "$name" new "$passwd" || exit 1 if test -f "${name}.new" then rm "$name" || exit 1 mv "${name}.new" "$name" || exit 1 rm -f "./${name}_setpwd" fi cd "$current" fi exit 0 samhain-4.1.4/dsys/funcBUILD0000644000175000017500000001425712615253277012524 00000000000000######################################################################### # # Subroutine for bulding from source # ######################################################################### # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # #------------------------------------------------------------------------ # List available sources #------------------------------------------------------------------------ listSRC() { OKSRCLIST=""; export OKSRCLIST echo > $tmpF; needEXE ls gpg cd "${basedir}/source" || printFATAL "could not cd to ${basedir}/source" LIST=`ls samhain*.tar.gz 2>/dev/null` if test x"$LIST" = x then printFATAL "No source tarball found in ${basedir}/source. Please use 'deploy.sh download'." fi for ff in $LIST do sh_version=`echo "$ff" | sed 's/.*samhain\-//g' | sed 's/\.tar\.gz//g'` if test x"${sh_version}" = x then printFATAL "Cannot determine version for $ff" fi if test "$ff" != "samhain-${sh_version}.tar.gz" then printFATAL "Version number not correctly extracted from $ff" fi if test -f "samhain-${sh_version}.tar.gz.asc" then : else printWARNING "No detached signature for $ff found" continue fi sig_lines=`(LANG="C"; gpg --status-fd 1 --verify "samhain-${sh_version}.tar.gz.asc" "samhain-${sh_version}.tar.gz" 2>/dev/null)` sig_ok=`echo ${sig_lines} | grep 'GOODSIG'` sig_nokey=`echo ${sig_lines} | grep 'NO_PUBKEY'` if test x"${sig_nokey}" != x then printWARNING "Public key (ID 0F571F6C) not found, trying to import it." gpg --import ${basedir}/private/0F571F6C.asc 2>&5 sig_lines=`(LANG="C"; gpg --status-fd 1 --verify "samhain-${sh_version}.tar.gz.asc" "samhain-${sh_version}.tar.gz" 2>/dev/null)` sig_ok=`echo ${sig_lines} | grep 'GOODSIG'` sig_nokey=`echo ${sig_lines} | grep 'NO_PUBKEY'` fi if test x"${sig_nokey}" != x then printFATAL "Importing public key failed." fi if test x"${sig_ok}" = x then printWARNING "File $ff has no good signature" continue fi if test x"$1" = x then OKSRCLIST="$OKSRCLIST ${sh_version}" else if test x"$1" = x"${sh_version}" then OKSRCLIST="${sh_version}" return 0 fi fi done if test x"$OKSRCLIST" = x then printFATAL "No source tarball found. Please use 'deploy.sh download'." fi for dd in $OKSRCLIST do echo $dd >> "$tmpF" done OKSRCLIST=`cat "$tmpF" | sort -r | sed 9q` export OKSRCLIST rm -f "$tmpF" && touch "$tmpF" echo $OKSRCLIST > "$tmpF" return 0 } selBVERSION() { #--------------------------------------------------------------------- # Select version to build #--------------------------------------------------------------------- if test x"$src_version" = x then if test x"$assumeyes" = x1 then printFATAL "No version selected, aborting." fi promptINFO "Checking which versions are available" ((listSRC | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 OKSRCLIST=`cat "$tmpF"` n=0 for word in $OKSRCLIST do n=`expr $n + 1` eval part$n="$word" done command="promptMENU 'Please select version to build' " for word in $OKSRCLIST do command="$command '${word}'" done eval ${command} m=$? if test x$m = x1 then (exit 0); exit 0; elif test x$m = "x-1" then printFATAL "Something went wrong !" else src_version="$MENU"; export src_version fi else ((listSRC "$src_version" | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 fi } selBARCH() { #--------------------------------------------------------------------- # Select arch to build #--------------------------------------------------------------------- if test x"$arch" = x then if test x"$assumeyes" = x1 then printFATAL "No operating system selected, aborting." fi cd "$basedir"/configs || printFATAL "Cannot cd to $basedir/configs !" LIST=`ls *.configure 2>/dev/null` if test x"$LIST" = x then printFATAL "No config files found in ${basedir}/configs." fi n=0 command="promptMENU 'Please select operating system of build host' " ALIST="" FLIST="" for ff in $LIST do n=`expr $n + 1` osp=`echo $ff | sed s/\.configure//` ALIST="$ALIST $osp" FLIST="$FLIST $osp" if test $n -lt 8 then command="$command '${osp}'" fi done command="$command other" eval ${command} m=$? if test x$m = x1 then (exit 0); exit 0; elif test x$m = "x-1" then printFATAL "Something went wrong !" else arch="$MENU"; export arch if test x"$arch" = xother then promptINPUT "Please select operating system of build host from $FLIST or enter new one" if test x$m = x1 then (exit 0); exit 0; elif test x$m = "x-1" then printFATAL "Something went wrong !" else found=`echo $FLIST | sed -n /$INPUT/p 2>/dev/null` if test x"$found" = x then printLOG "Copy configuration for $INPUT from generic" cp generic.configure "${INPUT}.configure" fi arch="$INPUT"; export arch fi fi fi fi # arch selected or exited } selBFORMAT() { if test x"$format" = x then promptMENU "Please select format of binary package" "run" "rpm" "deb" "tbz2" "solaris-pkg" "depot" if test x$m = x1 then (exit 0); exit 0 elif test x$m = "x-1" then printFATAL "Something went wrong !" else format="$MENU"; export format fi fi } samhain-4.1.4/include/0000755000175000017500000000000012623614070011565 500000000000000samhain-4.1.4/include/sh_userfiles.h0000644000175000017500000000136212615253277014364 00000000000000/* * File: sh_userfiles.h * Desc: A module for Samhain; adds files in user directories to the check list * Auth: Jerry Connolly */ #ifndef SH_USERFILES_H #define SH_USERFILES_H #ifdef SH_USE_USERFILES int sh_userfiles_init (struct mod_type * arg); int sh_userfiles_timer (time_t tcurrent); int sh_userfiles_check (void); int sh_userfiles_end (void); int sh_userfiles_cleanup (void); int sh_userfiles_reconf (void); int sh_userfiles_set_uid (const char * str); int sh_userfiles_add_file(const char *c); int sh_userfiles_set_interval(const char *c); int sh_userfiles_set_active(const char *c); int sh_userfiles_check_internal(void); extern sh_rconf sh_userfiles_table[]; #endif /* #ifndef SH_USERFILES_H */ #endif samhain-4.1.4/include/sh_dbIO_int.h0000664000175000017500000001112212615253277014047 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_DBIO_INT_H #define SH_DBIO_INT_H #define SH_DEADFILE 0x44454144 typedef struct store_info_old { UINT32 mode; UINT32 linkmode; UINT64 dev; UINT64 rdev; UINT32 hardlinks; UINT32 ino; UINT64 size; UINT64 atime; UINT64 mtime; UINT64 ctime; UINT32 owner; UINT32 group; UINT32 attributes; char c_attributes[ATTRBUF_SIZE]; /* 16 = 2*UINT64 */ unsigned short mark; char c_owner[USER_MAX+2]; char c_group[GROUP_MAX+2]; char c_mode[CMODE_SIZE]; char checksum[KEY_LEN+1]; } sh_filestore_old_t; typedef struct store_info { UINT32 mode; UINT32 linkmode; UINT64 dev; UINT64 rdev; UINT32 hardlinks; UINT32 ino; UINT64 size; UINT64 atime; UINT64 mtime; UINT64 ctime; UINT32 owner; UINT32 group; UINT32 attributes; char c_attributes[ATTRBUF_SIZE]; /* 16 = 2*UINT64 */ unsigned short mark; char c_owner[USER_MAX+2]; char c_group[GROUP_MAX+2]; char c_mode[CMODE_SIZE]; char checksum[KEY_LEN+1]; /* If 'checkflags' is elsewhere, the compiler would still use * a 6-byte padding to align the whole struct to an 8-byte boundary. * ipad, opad: make explicit what the compiler does on a 64-byte system. */ char ipad[2]; UINT32 checkflags; char opad[4]; } sh_filestore_t; typedef struct file_info { sh_filestore_t theFile; char * fullpath; char * linkpath; char * attr_string; int fflags; unsigned long modi_mask; struct file_info * next; } sh_file_t; //* must fit an int */ #define TABSIZE 65536 /* must fit an unsigned short */ /* changed for V0.8, as the */ /* database format has changed */ /* changed again for V0.9 */ /* #define REC_MAGIC 19 */ /* changed again for V1.3 */ /* #define REC_MAGIC 20 */ /* changed again for V1.4 */ /* #define REC_MAGIC 21 */ #define OLD_REC_MAGIC 21 /* changed again for V3.2 */ #define REC_MAGIC 22 #define REC_FLAGS_ATTR (1<<8) #define REC_FLAGS_MASK 0xFF00 /* Insert into database table */ void hashinsert (sh_file_t * tab[TABSIZE], sh_file_t * s); /* Internal conversion function */ file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash); /* Print what's in the link path */ int sh_hash_printcontent(char * linkpath); /* List database entry */ void sh_hash_list_db_entry (sh_file_t * p); /* get the location of the default/main database table */ sh_file_t ** get_default_data_table(); /* Write whole database */ int sh_dbIO_writeout(sh_file_t * mtab[TABSIZE], const char * outpath, int truncate); /* Load from the default source into hash table 'tab' */ int sh_dbIO_load_db(sh_file_t * tab[TABSIZE]); /* Load from the file 'filepath' into hash table 'tab' */ int sh_dbIO_load_db_file(sh_file_t * tab[TABSIZE], const char * filepath); #endif samhain-4.1.4/include/sh_inotify.h0000644000175000017500000000323612622132314014030 00000000000000#ifndef SH_INOTIFY_H #define SH_INOTIFY_H #define SH_INOTIFY_MAX 128 typedef struct { void * list_of_watches; void * dormant_watches; /* int watch[SH_INOTIFY_MAX]; int flag[SH_INOTIFY_MAX]; char * file[SH_INOTIFY_MAX]; */ int count; int max_count; } sh_watches; /* #define SH_INOTIFY_INITIALIZER { { 0 }, { 0 }, { NULL}, 0, 0 } */ #define SH_INOTIFY_INITIALIZER { NULL, NULL, 0, 0 } #define SH_INOTIFY_FILE 0 #define SH_INOTIFY_DIR 1 int sh_inotify_wait_for_change(char * filename, sh_watches * watches, int * errnum, int waitsec); int sh_inotify_rm_watch (sh_watches * watches, sh_watches * save, int wd); int sh_inotify_add_watch(char * filename, sh_watches * watches, int * errnum, int class, unsigned long check_flags, int type, int rdepth); int sh_inotify_add_watch_later(const char * filename, sh_watches * watches, int * errnum, int class, unsigned long check_flags, int type, int rdepth); char * sh_inotify_pop_dormant(sh_watches * watches, int * class, unsigned long * check_flags, int * type, int * rdepth); void sh_inotify_purge_dormant(sh_watches * watches); void sh_inotify_remove(sh_watches * watches); void sh_inotify_init(sh_watches * watches); void sh_inotify_close(); char * sh_inotify_search_item(sh_watches * watches, int watch, int * class, unsigned long * check_flags, int * type, int * rdepth); ssize_t sh_inotify_read(char * buffer, size_t count); ssize_t sh_inotify_read_timeout(char * buffer, size_t count, int timeout); int sh_inotify_recheck_watches (sh_watches * watches, sh_watches * save); #define SH_INOTIFY_ERROR(a) (a != 0) #endif samhain-4.1.4/include/sh_portcheck.h0000644000175000017500000000040712615253277014344 00000000000000 #ifndef SH_PORTCHECK_H #define SH_PORTCHECK_H int sh_portchk_init(struct mod_type * arg); int sh_portchk_timer(time_t tcurrent); int sh_portchk_check(void); int sh_portchk_reconf(void); int sh_portchk_cleanup(void); extern sh_rconf sh_portchk_table[]; #endif samhain-4.1.4/include/sh_static.h0000644000175000017500000000320212615253277013645 00000000000000#ifndef SH_STATIC_H #define SH_STATIC_H #include "config_xor.h" #if defined(SH_COMPILE_STATIC) && defined(__linux__) #ifdef SH_NEED_PWD_GRP int sh_initgroups(const char *user, gid_t gid); struct group * sh_getgrent(void); struct passwd * sh_getpwent(void); void sh_endgrent(void); void sh_setgrent(void); void sh_endpwent(void); void sh_setpwent(void); struct group * sh_getgrnam(const char *name); int sh_getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp); struct passwd * sh_getpwnam(const char *name); int sh_getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); struct group * sh_getgrgid(gid_t gid); int sh_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp); struct passwd * sh_getpwuid(uid_t uid); int sh_getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); #endif #ifdef SH_NEED_GETHOSTBYXXX struct hostent * sh_gethostbyaddr (const void *addr, socklen_t len, int type); struct hostent * sh_gethostbyname(const char *name); #endif #else #define sh_initgroups initgroups #define sh_getgrnam getgrnam #define sh_getgrnam_r getgrnam_r #define sh_getgrgid getgrgid #define sh_getgrgid_r getgrgid_r #define sh_getpwnam getpwnam #define sh_getpwnam_r getpwnam_r #define sh_getpwuid getpwuid #define sh_getpwuid_r getpwuid_r #define sh_getpwent getpwent #define sh_endpwent endpwent #define sh_setpwent setpwent #define sh_gethostbyaddr gethostbyaddr #define sh_gethostbyname gethostbyname #endif #endif samhain-4.1.4/include/sh_tools.h0000644000175000017500000000575012615253277013530 00000000000000#ifndef SH_TOOLS_H #define SH_TOOLS_H #define SH_DO_WRITE 0 #define SH_DO_READ 1 /* protocols */ #define SH_PROTO_SRP (1 << 0) #define SH_PROTO_IVA (1 << 1) #define SH_PROTO_MSG (1 << 2) #define SH_PROTO_BIG (1 << 3) #define SH_PROTO_END (1 << 4) #define SH_PROTO_EN1 (1 << 5) #define SH_PROTO_EN2 (1 << 6) #define SH_PROTO_ENC (SH_PROTO_EN1|SH_PROTO_EN2) #define SH_MASK_ENC (SH_PROTO_ENC|SH_PROTO_EN2) #ifdef SH_ENCRYPT /* returns pointer to errbuf */ char * errorExplain (int err_num, char * errbuf, size_t len); #endif /* Returns non-zero if interface exists */ int sh_tools_iface_is_present(char *str); /* returns allocated buffer */ char * sh_tools_safe_name(const char * str, int flag); int connect_port (char * address, int port, char * ecall, int * errnum, char * errmsg, int errsiz); int connect_port_2 (char * address1, char * address2, int port, char * ecall, int * errnum, char * errmsg, int errsiz); void delete_cache(void); /* returns pointer to errbuf */ char * sh_tools_errmessage (int tellme, char * errbuf, size_t len); void sh_tools_show_header (unsigned char * head, char sign); #if defined (SH_WITH_SERVER) unsigned char sh_tools_probe_store(unsigned char protocol, int * probe_flag); int get_open_max (void); void put_header (/*@out@*/unsigned char * head, const int protocol, unsigned long * length, char * u); int check_request_s (char * have, char * need, char * clt); int check_request_nerr (char * have, char * need); /* returns allocated buffer */ char * hash_me (char * key, char * buf, int buflen); int sh_tools_hash_vfy(char * key, char * buf, int buflen); /* returns allocated buffer */ char * get_client_conf_file (const char * peer, unsigned long * length); /* returns allocated buffer */ char * get_client_data_file (const char * peer, unsigned long * length); /* returns allocated buffer */ char * get_client_uuid_file (const char * peer, unsigned long * length, const char * uuid); #endif unsigned long read_port (int sockfd, char *buf, unsigned long nbytes, int * w_error, int timeout); #if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER) void sh_tools_probe_reset(); unsigned long write_port (int sockfd, char *buf, unsigned long nbytes, int * w_error, int timeout); int check_request (char * have, char * need); int check_request_nerr (char * have, char * need); void get_header (unsigned char * head, unsigned long * bytes, char * u); void put_header (unsigned char * head, int protocol, unsigned long * length, char * u); /* SL_TICKET open_tmp (void); int close_tmp (SL_TICKET fd); int rewind_tmp (SL_TICKET fd); */ void sh_tools_server_cmd(const char * srvcmd); int hash_check(char * key, char * buf, int buflen); int sh_tools_hash_add(char * key, char * buf, int buflen); #endif #if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP) SL_TICKET open_tmp (void); int close_tmp (SL_TICKET fd); int rewind_tmp (SL_TICKET fd); #endif #endif samhain-4.1.4/include/sh_tiger.h0000644000175000017500000000245112615253277013475 00000000000000 #ifndef SH_TIGER_H #define SH_TIGER_H #include "config_xor.h" #include "slib.h" #include "samhain.h" typedef long int TigerType; #define TIGER_FILE -1 #define TIGER_DATA -2 /**************** typedef long int TigerType; typedef enum { TIGER_FILE, TIGER_FD, TIGER_DATA } TigerType; *****************/ #define TIGER_NOLIM ((UINT64)-1) /* the checksum function */ char * sh_tiger_hash (const char * filename, TigerType what, UINT64 Length, char * out, size_t len); /* NEW Thu Oct 18 19:59:08 CEST 2001 */ int sh_tiger_hashtype (const char * c); char * sh_tiger_generic_hash (char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len); UINT32 * sh_tiger_hash_uint32 (char * filename, TigerType what, UINT64 Length, UINT32 * out, size_t len); /* get the type of hash function used * 0 = tiger192, 1 = sha1, 2 = md5 */ int sh_tiger_get_hashtype (void); /* set the hash fuction in use in the mask */ void sh_tiger_get_mask_hashtype(unsigned long * mask); /* reset the hash function to the one in the mask */ void sh_tiger_set_hashtype_mask(unsigned long mask); /* GnuPG-like format, returns allocated memory */ /*@owned@*/ char * sh_tiger_hash_gpg (const char * filename, TigerType what, UINT64 Length); #endif samhain-4.1.4/include/sh_getopt.h0000644000175000017500000000274312615253277013671 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_GETOPT_H #define SH_GETOPT_H int sh_getopt_get (int argc, char * argv[]); #endif samhain-4.1.4/include/trustfile.h0000644000175000017500000000576612615253277013726 00000000000000/* * This is the header file for the trust function * * 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. */ /* * trustfile return codes */ #define TF_ERROR -1 /* can't check -- error */ #define TF_NO 0 /* file isn't trustworthy */ #define TF_YES 1 /* file is trustworthy */ /* * error codes */ #define TF_BADFILE 1 /* file name illegal */ #define TF_BADNAME 2 /* name not valid (prob. ran out of room) */ #define TF_BADSTAT 3 /* stat of file failed (see errno for why) */ #define TF_NOROOM 4 /* not enough allocated space */ /* * untrustworthy codes */ #define TF_BADUID 10 /* owner nmot trustworthy */ #define TF_BADGID 11 /* group writeable and member not trustworthy */ #define TF_BADOTH 12 /* anyone can write it */ /* * the basic constant -- what is the longest path name possible? * It should be at least the max path length as defined by system * + 4 ("/../") + max file name length as defined by system; this * should rarely fail (I rounded it up to 2048) */ #define MAXFILENAME 2048 /* * function declaration * * #ifdef __STDC__ * extern int trustfile(char *, int *, int *); * #else * extern int trustfile(); * #endif */ /* * these are useful global variables * * first set: who you gonna trust, by default? * if the user does not specify a trusted or untrusted set of users, * all users are considered untrusted EXCEPT: * UID 0 -- root as root can do anything on most UNIX systems, this * seems reasonable * tf_euid -- programmer-selectable UID * if the caller specifies a specific UID by putting * it in this variable, it will be trusted; this is * typically used to trust the effective UID of the * process (note: NOT the real UID, which will cause all * sorts of problems!) By default, this is set to -1, * so if it's not set, root is the only trusted user */ extern uid_t tf_euid; /* space for EUID of process */ /* * second set: how do you report problems? * tf_errno on return when an error has occurred, this is set * to the code indicating the reason for the error: * TF_BADFILE passed NULL for pointer to file name * TF_BADNAME could not expand to full path name * TF_BADSTAT stat failed; usu. file doesn't exist * TF_BADUID owner untrusted * TF_BADGID group untrusted & can write * TF_BADOTH anyone can write * the value is preserved across calls where no error * occurs, just like errno(2) * tf_path if error occurs and a file name is involved, this * contains the file name causing the problem */ extern char tf_path[MAXFILENAME]; /* error path for trust function */ extern uid_t rootonly[]; extern int EUIDSLOT; samhain-4.1.4/include/sh_gpg_chksum.h0000644000175000017500000000164312615253277014514 00000000000000#ifndef CHKSUM_H #define CHKSUM_H char gpgchk[50]; gpgchk[0] = '4'; gpgchk[1] = '0'; gpgchk[2] = '7'; gpgchk[3] = '8'; gpgchk[4] = '4'; gpgchk[5] = '6'; gpgchk[6] = '0'; gpgchk[7] = '1'; gpgchk[8] = '7'; gpgchk[9] = '5'; gpgchk[10] = 'D'; gpgchk[11] = '0'; gpgchk[12] = '1'; gpgchk[13] = 'B'; gpgchk[14] = '4'; gpgchk[15] = '4'; gpgchk[16] = 'B'; gpgchk[17] = '5'; gpgchk[18] = 'E'; gpgchk[19] = '3'; gpgchk[20] = 'A'; gpgchk[21] = '4'; gpgchk[22] = '0'; gpgchk[23] = 'E'; gpgchk[24] = '4'; gpgchk[25] = '4'; gpgchk[26] = '0'; gpgchk[27] = '1'; gpgchk[28] = '6'; gpgchk[29] = '3'; gpgchk[30] = '3'; gpgchk[31] = '3'; gpgchk[32] = 'C'; gpgchk[33] = 'F'; gpgchk[34] = '3'; gpgchk[35] = 'C'; gpgchk[36] = '5'; gpgchk[37] = '6'; gpgchk[38] = 'A'; gpgchk[39] = '7'; gpgchk[40] = 'A'; gpgchk[41] = 'B'; gpgchk[42] = 'D'; gpgchk[43] = '9'; gpgchk[44] = '1'; gpgchk[45] = '9'; gpgchk[46] = '6'; gpgchk[47] = '6'; gpgchk[48] = '\0'; #endif samhain-4.1.4/include/lzoconf.h0000644000175000017500000003070112615253277013342 00000000000000/* lzoconf.h -- configuration for the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer The LZO library 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. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html */ #ifndef __LZOCONF_H #define __LZOCONF_H #define LZO_VERSION 0x1060 /* * Unfortunately, these are somewhat counterproductive, as * there should be no strings in the compiled executable. * - Rainer Wichmann, 26. July 2000 - * * #define LZO_VERSION_STRING "1.06" * #define LZO_VERSION_DATE "Nov 29 1999" */ #define LZO_VERSION_STRING "" #define LZO_VERSION_DATE "" /* internal Autoconf configuration file - only used when building LZO */ #if defined(LZO_HAVE_CONFIG_H) # include #endif #include #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // LZO requires a conforming ************************************************************************/ #if !defined(CHAR_BIT) || (CHAR_BIT != 8) # error "invalid CHAR_BIT" #endif #if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) # error "check your compiler installation" #endif #if (USHRT_MAX < 1 ) || (UINT_MAX < 1) || (ULONG_MAX < 1) # error "your limits.h macros are broken" #endif /* workaround a cpp bug under hpux 10.20 */ #define LZO_0xffffffffL 4294967295ul /*********************************************************************** // architecture defines ************************************************************************/ #if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) # if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) # define __LZO_WIN # elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) # define __LZO_WIN # elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) # define __LZO_WIN # elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) # define __LZO_DOS # elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) # define __LZO_OS2 # elif defined(__palmos__) # define __LZO_PALMOS # elif defined(__TOS__) || defined(__atarist__) # define __LZO_TOS # endif #endif #if (UINT_MAX < LZO_0xffffffffL) # if defined(__LZO_WIN) # define __LZO_WIN16 # elif defined(__LZO_DOS) # define __LZO_DOS16 # elif defined(__LZO_PALMOS) # define __LZO_PALMOS16 # elif defined(__LZO_TOS) # define __LZO_TOS16 # elif defined(__C166__) # else # error "16-bit target not supported - contact me for porting hints" # endif #endif #if !defined(__LZO_i386) # if defined(__LZO_DOS) || defined(__LZO_WIN16) # define __LZO_i386 # elif defined(__i386__) || defined(__386__) || defined(_M_IX86) # define __LZO_i386 # endif #endif #if defined(__LZO_STRICT_16BIT) # if (UINT_MAX < LZO_0xffffffffL) # include # endif #endif /*********************************************************************** // integral and pointer types ************************************************************************/ /* Integral types with 32 bits or more */ #if !defined(LZO_UINT32_MAX) # if (UINT_MAX >= LZO_0xffffffffL) typedef unsigned int lzo_uint32; typedef int lzo_int32; # define LZO_UINT32_MAX UINT_MAX # define LZO_INT32_MAX INT_MAX # define LZO_INT32_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) typedef unsigned long lzo_uint32; typedef long lzo_int32; # define LZO_UINT32_MAX ULONG_MAX # define LZO_INT32_MAX LONG_MAX # define LZO_INT32_MIN LONG_MIN # else # error "lzo_uint32" # endif #endif /* lzo_uint is used like size_t */ #if !defined(LZO_UINT_MAX) # if (UINT_MAX >= LZO_0xffffffffL) typedef unsigned int lzo_uint; typedef int lzo_int; # define LZO_UINT_MAX UINT_MAX # define LZO_INT_MAX INT_MAX # define LZO_INT_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) typedef unsigned long lzo_uint; typedef long lzo_int; # define LZO_UINT_MAX ULONG_MAX # define LZO_INT_MAX LONG_MAX # define LZO_INT_MIN LONG_MIN # else # error "lzo_uint" # endif #endif /* Memory model that allows to access memory at offsets of lzo_uint. */ #if !defined(__LZO_MMODEL) # if (LZO_UINT_MAX <= UINT_MAX) # define __LZO_MMODEL # elif defined(__LZO_DOS16) || defined(__LZO_WIN16) # define __LZO_MMODEL __huge # define LZO_999_UNSUPPORTED # elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) # define __LZO_MMODEL # else # error "__LZO_MMODEL" # endif #endif /* no typedef here because of const-pointer issues */ #define lzo_byte unsigned char __LZO_MMODEL #define lzo_bytep unsigned char __LZO_MMODEL * #define lzo_charp char __LZO_MMODEL * #define lzo_voidp void __LZO_MMODEL * #define lzo_shortp short __LZO_MMODEL * #define lzo_ushortp unsigned short __LZO_MMODEL * #define lzo_uint32p lzo_uint32 __LZO_MMODEL * #define lzo_int32p lzo_int32 __LZO_MMODEL * #define lzo_uintp lzo_uint __LZO_MMODEL * #define lzo_intp lzo_int __LZO_MMODEL * #define lzo_voidpp lzo_voidp __LZO_MMODEL * #define lzo_bytepp lzo_bytep __LZO_MMODEL * typedef int lzo_bool; #ifndef lzo_sizeof_dict_t # define lzo_sizeof_dict_t sizeof(lzo_bytep) #endif /*********************************************************************** // function types ************************************************************************/ /* linkage */ #if !defined(__LZO_EXTERN_C) # ifdef __cplusplus # define __LZO_EXTERN_C extern "C" # else # define __LZO_EXTERN_C extern # endif #endif /* calling conventions */ #if !defined(__LZO_CDECL) # if defined(__LZO_DOS16) || defined(__LZO_WIN16) # define __LZO_CDECL __far __cdecl # elif defined(__LZO_i386) && defined(_MSC_VER) # define __LZO_CDECL __cdecl # elif defined(__LZO_i386) && defined(__WATCOMC__) # define __LZO_CDECL __near __cdecl # else # define __LZO_CDECL # endif #endif #if !defined(__LZO_ENTRY) # define __LZO_ENTRY __LZO_CDECL #endif /* DLL export information */ #if !defined(__LZO_EXPORT1) # define __LZO_EXPORT1 #endif #if !defined(__LZO_EXPORT2) # define __LZO_EXPORT2 #endif /* calling convention for C functions */ #if !defined(LZO_PUBLIC) # define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY #endif #if !defined(LZO_EXTERN) # define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) #endif #if !defined(LZO_PRIVATE) # define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY #endif /* cdecl calling convention for assembler functions */ #if !defined(LZO_PUBLIC_CDECL) # define LZO_PUBLIC_CDECL(_rettype) \ __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL #endif #if !defined(LZO_EXTERN_CDECL) # define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) #endif typedef int (__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem ); typedef int (__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem ); typedef int (__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem ); typedef int (__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem, const lzo_byte *dict, lzo_uint dict_len ); typedef int (__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem, const lzo_byte *dict, lzo_uint dict_len ); /* a progress indicator callback function */ typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); /*********************************************************************** // error codes and prototypes ************************************************************************/ /* Error codes for the compression/decompression functions. Negative * values are errors, positive values will be used for special but * normal events. */ #define LZO_E_OK 0 #define LZO_E_ERROR (-1) #define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ #define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ #define LZO_E_INPUT_OVERRUN (-4) #define LZO_E_OUTPUT_OVERRUN (-5) #define LZO_E_LOOKBEHIND_OVERRUN (-6) #define LZO_E_EOF_NOT_FOUND (-7) #define LZO_E_INPUT_NOT_CONSUMED (-8) /* lzo_init() should be the first function you call. * Check the return code ! * * lzo_init() is a macro to allow checking that the library and the * compiler's view of various types are consistent. */ #define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ (int)sizeof(lzo_compress_t)) LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); /* version functions (useful for shared libraries) */ LZO_EXTERN(unsigned) lzo_version(void); LZO_EXTERN(const char *) lzo_version_string(void); LZO_EXTERN(const char *) lzo_version_date(void); LZO_EXTERN(const lzo_charp) _lzo_version_string(void); LZO_EXTERN(const lzo_charp) _lzo_version_date(void); /* string functions */ LZO_EXTERN(int) lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); LZO_EXTERN(lzo_voidp) lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); LZO_EXTERN(lzo_voidp) lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); LZO_EXTERN(lzo_voidp) lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); /* checksum functions */ LZO_EXTERN(lzo_uint32) lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); LZO_EXTERN(lzo_uint32) lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); /* memory allocation functions */ LZO_EXTERN(lzo_bytep) lzo_alloc(lzo_uint _nelems, lzo_uint _size); LZO_EXTERN(lzo_bytep) lzo_malloc(lzo_uint _size); LZO_EXTERN(void) lzo_free(lzo_voidp _ptr); extern lzo_bytep (__LZO_ENTRY *lzo_alloc_hook) (lzo_uint,lzo_uint); extern void (__LZO_ENTRY *lzo_free_hook) (lzo_voidp); /* misc. */ LZO_EXTERN(lzo_bool) lzo_assert(int _expr); LZO_EXTERN(int) _lzo_config_check(void); typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; /* align a char pointer on a boundary that is a multiple of `size' */ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); #define LZO_PTR_ALIGN_UP(_ptr,_size) \ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) /* deprecated - only for backward compatibility */ #define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) #ifdef __cplusplus } /* extern "C" */ #endif #endif /* already included */ samhain-4.1.4/include/sh_ignore.h0000644000175000017500000000054312615253277013646 00000000000000#ifndef SH_IGNORE_H #define SH_IGNORE_H int sh_ignore_add_del (const char * addpath); int sh_ignore_add_new (const char * addpath); int sh_ignore_add_mod (const char * addpath); int sh_ignore_chk_del (const char * chkpath); int sh_ignore_chk_new (const char * chkpath); int sh_ignore_chk_mod (const char * chkpath); int sh_ignore_clean (void); #endif samhain-4.1.4/include/sh_database.h0000644000175000017500000000076512615253277014135 00000000000000#ifndef SH_DATABASE_H #define SH_DATABASE_H void sh_database_reset(void); int sh_database_insert (char * message); int sh_database_use_persistent (const char * str); int sh_database_set_database (const char * str); int sh_database_set_table (const char * str); int sh_database_set_host (const char * str); int sh_database_set_user (const char * str); int sh_database_set_password (const char * str); int sh_database_add_to_hash (const char * str); int set_enter_wrapper (const char * str); #endif samhain-4.1.4/include/sh_nmail.h0000644000175000017500000000114412615253277013461 00000000000000#ifndef SH_NMAIL_H #define SH_NMAIL_H int sh_nmail_pushstack (int level, const char * message, const char * alias); int sh_nmail_msg (int level, const char * message, const char * alias); int sh_nmail_flush (); void sh_nmail_free(); int sh_nmail_set_severity (const char * str); int sh_nmail_add_not (const char * str); int sh_nmail_add_and (const char * str); int sh_nmail_add_or (const char * str); int sh_nmail_close_recipient(const char * str); int sh_nmail_add_compiled_recipient(const char * str); int sh_nmail_add_recipient(const char * str); int sh_nmail_add_alias(const char * str); #endif samhain-4.1.4/include/rijndael-alg-fst.h0000644000175000017500000000346712615253277015024 00000000000000/* $NetBSD: rijndael-alg-fst.h,v 1.4 2005/12/11 12:20:52 christos Exp $ */ /* $KAME: rijndael-alg-fst.h,v 1.5 2003/07/15 10:47:16 itojun Exp $ */ /** * rijndael-alg-fst.h * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. */ #ifndef __RIJNDAEL_ALG_FST_H #define __RIJNDAEL_ALG_FST_H #define RIJNDAEL_MAXKC (256/32) #define RIJNDAEL_MAXKB (256/8) #define RIJNDAEL_MAXNR 14 #ifdef SH_ENCRYPT int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]); /* SH_ENCRYPT */ #endif #endif /* __RIJNDAEL_ALG_FST_H */ samhain-4.1.4/include/sh_utmp.h0000644000175000017500000000210112615253277013340 00000000000000 #ifndef SH_UTMP_H #define SH_UTMP_H #include "sh_modules.h" #ifdef SH_USE_UTMP int sh_utmp_init (struct mod_type * arg); int sh_utmp_timer (time_t tcurrent); int sh_utmp_check (void); int sh_utmp_end (void); int sh_utmp_reconf (void); int sh_utmp_set_login_activate (const char * c); int sh_utmp_set_login_solo (const char * c); int sh_utmp_set_login_multi (const char * c); int sh_utmp_set_logout_good (const char * c); int sh_utmp_set_login_timer (const char * c); extern sh_rconf sh_utmp_table[]; /* >> Login tracking << */ /* 'yes', 'no', 'paranoid' */ int sh_login_set_siglevel (const char * c); /* 'yes', 'no', 'domain' */ int sh_login_set_checklevel (const char * c); /* 'always' 'never' workdays(..) sunday(..) */ int sh_login_set_def_allow (const char * c); /* user:'always' 'never' workdays(..) */ int sh_login_set_user_allow (const char * c); /* Reset everything to defaults. */ void sh_login_reset (void); #endif /* #ifndef SH_UTMP_H */ #endif samhain-4.1.4/include/sh_checksum.h0000664000175000017500000000167312615253277014174 00000000000000#ifndef SH_CHECKSUM_H #define SH_CHECKSUM_H typedef unsigned char sha2_byte ; typedef UINT32 sha2_word32; typedef UINT64 sha2_word64; #define SHA256_BLOCK_LENGTH 64 #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) #define SHA256_DIGEST_LENGTH 32 #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) typedef struct _SHA256_CTX { sha2_word32 state[8]; sha2_word64 bitcount; sha2_byte buffer[SHA256_BLOCK_LENGTH]; } SHA256_CTX; void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX*, const sha2_byte*, size_t); void SHA256_Final(sha2_byte[SHA256_DIGEST_LENGTH], SHA256_CTX*); char* SHA256_End(SHA256_CTX*, char[KEYBUF_SIZE]); char* SHA256_Data(const sha2_byte*, size_t, char[KEYBUF_SIZE]); char* SHA256_Base2Hex(char * b64digest, char * hexdigest); char * SHA256_ReplaceBaseByHex(const char * str, char * before, char after); #endif samhain-4.1.4/include/sh_logmon.h0000644000175000017500000000041612615253277013655 00000000000000#ifndef SH_LOGMON_H #define SH_LOGMON_H extern sh_rconf sh_log_check_table[]; int sh_log_check_init (struct mod_type * arg); int sh_log_check_timer(time_t tcurrent); int sh_log_check_check(void); int sh_log_check_reconf(void); int sh_log_check_cleanup(void); #endif samhain-4.1.4/include/rijndael-api-fst.h0000644000175000017500000001170712615253277015026 00000000000000/* $NetBSD: rijndael-api-fst.h,v 1.8 2007/01/21 23:00:08 cbiere Exp $ */ /** * rijndael-api-fst.h * * @version 2.9 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. * * Acknowledgements: * * We are deeply indebted to the following people for their bug reports, * fixes, and improvement suggestions to this implementation. Though we * tried to list all contributions, we apologise in advance for any * missing reference. * * Andrew Bales * Markus Friedl * John Skodon */ #ifndef __RIJNDAEL_API_FST_H #define __RIJNDAEL_API_FST_H /* Blocksize: 16 * 8 = 128; 128 * 1 = 128 */ #define B_SIZ 16 #define BNUM 1 #if defined(UINT32) typedef unsigned char u8; typedef UINT32 u32; #else typedef unsigned char u8; #if defined(HAVE_INT_32) typedef unsigned int u32; #elif defined(HAVE_LONG_32) typedef unsigned long u32; #elif defined(HAVE_SHORT_32) typedef unsigned short u32; #else #error "No 32 bit integer type found" #endif #endif #include "rijndael-alg-fst.h" /* Generic Defines */ #define DIR_ENCRYPT 0 /* Are we encrpyting? */ #define DIR_DECRYPT 1 /* Are we decrpyting? */ #define MODE_ECB 1 /* Are we ciphering in ECB mode? */ #define MODE_CBC 2 /* Are we ciphering in CBC mode? */ #define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define BITSPERBLOCK 128 /* Default number of bits in a cipher block */ /* Error Codes */ #define BAD_KEY_DIR -1 /* Key direction is invalid, e.g., unknown value */ #define BAD_KEY_MAT -2 /* Key material not of correct length */ #define BAD_KEY_INSTANCE -3 /* Key passed is not valid */ #define BAD_CIPHER_MODE -4 /* Params struct passed to cipherInit invalid */ #define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not initialized) */ #define BAD_BLOCK_LENGTH -6 #define BAD_CIPHER_INSTANCE -7 #define BAD_DATA -8 /* Data contents are invalid, e.g., invalid padding */ #define BAD_OTHER -9 /* Unknown error */ /* Algorithm-specific Defines */ #define RIJNDAEL_MAX_KEY_SIZE 64 /* # of ASCII char's needed to represent a key */ #define RIJNDAEL_MAX_IV_SIZE 16 /* # bytes needed to represent an IV */ #ifdef SH_ENCRYPT /* Typedefs */ typedef unsigned char BYTE; /* The structure for key information */ typedef struct { u32 rk[4*(RIJNDAEL_MAXNR + 1)]; /* key schedule */ u32 ek[4*(RIJNDAEL_MAXNR + 1)]; /* CFB1 key schedule (encryption only) */ BYTE direction; /* Key used for encrypting or decrypting? */ int keyLen; /* Length of the key */ char keyMaterial[RIJNDAEL_MAX_KEY_SIZE+1]; /* Raw key data in ASCII, e.g., user input or KAT values */ int Nr; /* key-length-dependent number of rounds */ } keyInstance; /* The structure for cipher information */ typedef struct { /* changed order of the components */ u32 IV[RIJNDAEL_MAX_IV_SIZE / sizeof(u32)]; /* A possible Initialization Vector for ciphering */ BYTE mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */ } cipherInstance; /* Function prototypes */ int rijndael_makeKey(keyInstance *, BYTE, int, const char *); int rijndael_cipherInit(cipherInstance *, BYTE, const char *); int rijndael_blockEncrypt(cipherInstance *, keyInstance *, const BYTE *, int, BYTE *); int rijndael_padEncrypt(cipherInstance *, keyInstance *, const BYTE *, int, BYTE *); int rijndael_blockDecrypt(cipherInstance *, keyInstance *, const BYTE *, int, BYTE *); int rijndael_padDecrypt(cipherInstance *, keyInstance *, const BYTE *, int, BYTE *); /* SH_ENCRYPT */ #endif #endif /* __RIJNDAEL_API_FST_H */ samhain-4.1.4/include/sh_mail_int.h0000644000175000017500000000160512615253277014157 00000000000000#ifndef SH_MAIL_INT_H #define SH_MAIL_INT_H extern int sh_mail_all_in_one; /* MX Resolver Struct */ typedef struct mx_ { int pref; char * address; } mx; typedef struct dnsrep_ { int count; mx * reply; } dnsrep; int free_mx (dnsrep * answers); /* adress struct */ struct alias { sh_string * recipient; struct alias * recipient_list; dnsrep * mx_list; int severity; short send_mail; short isAlias; sh_filter_type * mail_filter; struct alias * next; struct alias * all_next; }; extern struct alias * all_recipients; int sh_mail_msg (const char * message); /* Per recipient mail key */ int sh_nmail_get_mailkey (const char * alias, char * buf, size_t bufsiz, time_t * id_audit); SH_MUTEX_EXTERN(mutex_listall); SH_MUTEX_EXTERN(mutex_fifo_mail); extern SH_FIFO * fifo_mail; #endif samhain-4.1.4/include/sh_gpg.h0000644000175000017500000000353312615253277013142 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #if (defined(WITH_GPG) || defined(WITH_PGP)) #ifndef SH_GPG_H #define SH_GPG_H #define SIG_CONF 1 #define SIG_DATA 2 /* Top level function to verify file. */ SL_TICKET sh_gpg_extract_signed(SL_TICKET fd); /* this function exits if configuration file * and/or database cannot be verified; otherwise returns 0 */ int sh_gpg_check_sign (long file, int what); /* log successful startup */ void sh_gpg_log_startup (void); #endif /* #ifdef WITH_GPG */ #endif samhain-4.1.4/include/sh_utils.h0000644000175000017500000001437012615253277013526 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_UTILS_H #define SH_UTILS_H #include #include "slib.h" #include "sh_error.h" #include "sh_unix.h" #define S_FMT_STRING 1 #define S_FMT_ULONG 2 #define S_FMT_TIME 3 #define S_FMT_LONG 4 typedef struct ft_struc { char fchar; int type; unsigned long data_ulong; long data_long; char *data_str; } st_format; /* returns allocated string */ char * sh_util_formatted (const char * fmt, st_format * ftab); typedef struct sh_timeout_struct { UINT64 time_last; UINT64 time_dist; int flag_ok; } SH_TIMEOUT; int sh_util_timeout_check (SH_TIMEOUT * sh_timer); /* This is a maximally equidistributed combined Tausworthe * generator. */ UINT32 taus_get (void); double taus_get_double (void *vstate); /* fast */ int taus_seed (void); /* returns allocated memory */ char * sh_util_strdup (const char * str) SH_GNUC_MALLOC; char * sh_util_strdup_track (const char * str, char * file, int line) SH_GNUC_MALLOC; /* returns allocated memory */ char * sh_util_strdup_l (const char * str, size_t len) SH_GNUC_MALLOC; /* returns pointer within str */ char * sh_util_strsep (char **str, const char *delim); /* compactify verbose acl text, returns allocated memory */ char * sh_util_acl_compact (char * buf, ssize_t len); /* set signature type HASH-TIGER/HMAC-TIGER */ int sh_util_sigtype (const char * c); /* compute a signature */ char * sh_util_siggen (char * hexkey, char * text, size_t textlen, char * sigbuf, size_t sigbuflen); /* eval boolean input */ int sh_util_flagval(const char * c, int * fval); /* ask if a file should be updated (returns S_TRUE/S_FALSE) */ int sh_util_ask_update(const char * path); int sh_util_set_interactive(const char * str); int sh_util_update_file (const char * str); /* don't log output files */ int sh_util_hidesetup(const char * c); /* valif utf-8 string */ int sh_util_valid_utf8 (const unsigned char * str); /* filenames are utf8 */ int sh_util_obscure_utf8 (const char * c); /* exceptions to obscure name check */ int sh_util_obscure_ok (const char * str); /* output a hexchar[2]; i2h must be char[2] */ char * sh_util_charhex( unsigned char c, char * i2h ); /* read a hexchar, return int value (0-15) */ int sh_util_hexchar( char c ) SH_GNUC_CONST; /* change verifier */ int sh_util_set_newkey (const char * str); /* server mode */ int sh_util_setserver (const char * dummy); /* a simple compressor */ size_t sh_util_compress (char * dest, char * src, size_t dest_size); /* an even simpler en-/decoder */ void sh_util_encode (char * data, char * salt, int mode, char fill); /* copy len ( < 4) bytes from (char *) (long src) to (char *) dest, * determine the four LSB's and use them (independent of sizeof(long)) */ void sh_util_cpylong (char * dest, const char * src, int len ); /* set timer for main loop */ int sh_util_setlooptime (const char * str); /* whether init or check the database */ int sh_util_setchecksum (const char * str); /* compare an in_string against a regular expression regex_str return GOOD on successful match */ int sh_util_regcmp (char * regex_str, char * in_str); /* returns freshly allocated memory, return value should be free'd. * Argument list must be NULL terminated. */ char * sh_util_strconcat (const char * arg1, ...) SH_GNUC_MALLOC SH_GNUC_SENTINEL; /* check if string is numeric only */ int sh_util_isnum (const char *str) SH_GNUC_PURE; /* init a key w/random string */ int sh_util_keyinit (char * buf, long size); /* returns freshly allocated memory, return value should be free'd */ char * sh_util_dirname(const char * fullpath); /* returns freshly allocated memory, return value should be free'd */ char * sh_util_safe_name (const char * name) SH_GNUC_MALLOC SH_GNUC_PURE; char * sh_util_safe_name_keepspace (const char * name) SH_GNUC_MALLOC SH_GNUC_PURE; /* check max size of printf result string */ int sh_util_printf_maxlength (const char * fmt, va_list vl); /* check for obscure filenames */ int sh_util_obscurename (ShErrLevel level, const char * name, int flag); /* returns freshly allocated memory, return value should be free'd */ char * sh_util_basename(const char * fullpath); /* required size (including terminating NULL) for string of strlen l */ #define SH_B64_SIZ(l) (1 + ((((l) + 2) / 3) * 4)) /* return len of encoded string */ size_t sh_util_base64_enc (unsigned char * out, const unsigned char * instr, size_t lin); /* return allocated encoded string in out, return its len */ size_t sh_util_base64_enc_alloc (char **out, const char *in, size_t inlen); /* return len of decoded string */ size_t sh_util_base64_dec (unsigned char *out, const unsigned char *in, size_t lin); /* return allocated decoded string in out, return its len */ size_t sh_util_base64_dec_alloc (unsigned char **out, const unsigned char *in, size_t lin); #endif samhain-4.1.4/include/sh_log_evalrule.h0000644000175000017500000000255312615253277015046 00000000000000#ifndef SH_EVALRULE_H #define SH_EVALRULE_H /* Clean up everything. */ void sh_eval_cleanup(); /* Define a new reporting queue, str := label:interval:(report|sum):severity */ int sh_eval_qadd (const char * str); /* Add a new rule, str := queue:regex * If there is an open group, add it to its rules. * ..else, add it to the currently open host (open the * default host, if there is no open one) */ int sh_eval_radd (const char * str); /* Open a new host group definition. */ int sh_eval_hadd (const char * str); /* * End the host definition */ int sh_eval_hend (const char * str); /* Open a new group definition. If a host is currently open, * the new group will automatically be added to that host. */ int sh_eval_gadd (const char * str); /* * End the group definition */ int sh_eval_gend (const char * str); /* Process a single log record */ int sh_eval_process_msg(struct sh_logrecord * record); enum policies { EVAL_REPORT, EVAL_SUM }; struct sh_qeval /* Queue with definitions */ { sh_string * label; enum policies policy; int severity; sh_string * alias; time_t interval; /* if EVAL_SUM, interval */ struct sh_qeval * next; }; struct sh_qeval * sh_log_find_queue(const char * str); int sh_log_lookup_severity(const char * str); sh_string * sh_log_lookup_alias(const char * str); #endif samhain-4.1.4/include/sh_fifo.h0000644000175000017500000000532512615253277013311 00000000000000 #ifndef SH_FIFO_H #define SH_FIFO_H /***************************************************** * * the maximum number of entries the fifo will hold * - additional entries are simply not accepted - * *****************************************************/ #define SH_FIFO_MAX 16384 /***************************************************** * * the type definitions for the fifo * *****************************************************/ struct dlist { struct dlist * next; char * data; char * s_xtra; int i_xtra; int transact; struct dlist * prev; }; typedef struct fifo_str { struct dlist * head_ptr; struct dlist * tail_ptr; int fifo_cts; } SH_FIFO; #define SH_FIFO_INITIALIZER { NULL, NULL, 0 } /***************************************************** * * fifo functions * *****************************************************/ /* Initialize the list. * */ #define fifo_init(fifo_p) { (fifo_p)->fifo_cts = 0; (fifo_p)->head_ptr = NULL; \ (fifo_p)->tail_ptr = NULL; } /* Push an item on the head of the list. * * Returns: -1 if the list is full, 0 on success */ int push_list (SH_FIFO * fifo, const char * indat, int in_i, const char * in_str); #define sh_fifo_push(a, b) push_list((a), (b), 0, NULL) /* Push an item on the tail of the list. * * Returns: -1 if the list is full, 0 on success */ int push_tail_list (SH_FIFO * fifo, const char * indat, int in_i, const char * in_str); #define sh_fifo_push_tail(a, b) push_tail_list((a), (b), 0, NULL) /* pop an item from the tail of the list * * Returns: NULL if the list is empty, * freshly allocated memory on success (should be free'd by caller) */ char * pop_list (SH_FIFO * fifo); #define sh_fifo_pop(a) pop_list((a)) /* ---- Special functions -------------------------------------------------*/ /* This is for eMail where different recipients may be eligible for * * different subsets of messages. We need to delete all that were sent * * to all intended recipients, and keep all with at least one failure. */ /* Iterate over list and check for each if it is valid for 'tag'; * i.e. (item->s_extra == tag). If yes, add to the returned string. * If (okNull == False) then item->s_xtra must be defined */ sh_string * tag_list (SH_FIFO * fifo, char * tag, int(*check)(int, const char*, const char*, const void*), const void * info, int okNull); /* Flag all tagged as candidate to keep */ void rollback_list (SH_FIFO * fifo); /* Flag all tagged as candidate to delete */ void mark_list (SH_FIFO * fifo); /* Remove all flags */ void reset_list (SH_FIFO * fifo); /* Delete all marked for delete that are not flagged for keep */ int commit_list (SH_FIFO * fifo); #endif samhain-4.1.4/include/sh_mem.h0000644000175000017500000000456312615253277013147 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_MEM_H #define SH_MEM_H #ifdef MEM_DEBUG void sh_mem_openf (char * file, int fd); void sh_mem_closef (int fd); void sh_mem_check (void); void sh_mem_dump (void); void sh_mem_free (void * a, char * file, int line); void * sh_mem_malloc (size_t size, char * file, int line); void sh_mem_stat (void); #define SH_FREE(a) sh_mem_free((a), FIL__, __LINE__) #define SH_ALLOC(a) sh_mem_malloc((a), FIL__, __LINE__) #define SH_OALLOC(a,b,c) sh_mem_malloc((a), (b), (c)) #else #if defined(__GNUC__) && (__GNUC__ >= 3) #undef SH_GNUC_MALLOC #define SH_GNUC_MALLOC __attribute__((malloc)) #else #undef SH_GNUC_MALLOC #define SH_GNUC_MALLOC #endif void sh_mem_free (/*@only@*//*@out@*//*@null@*/ void * a); /*@only@*//*@notnull@*/void * sh_mem_malloc (size_t size) SH_GNUC_MALLOC; #define SH_FREE(a) sh_mem_free(a) #define SH_ALLOC(a) sh_mem_malloc(a) #define SH_OALLOC(a,b,c) ((void) (b), \ (void) (c), \ sh_mem_malloc(a)) \ #endif /* #ifndef SH_MEM_H */ #endif samhain-4.1.4/include/sh_xfer.h0000644000175000017500000000644312615253277013334 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_XFER_H #define SH_XFER_H #ifndef SH_STANDALONE int sh_xfer_set_strip (const char * str); #endif /* generate a random password */ int sh_xfer_create_password (const char * dummy); /* set timeout for active client connections */ int sh_xfer_set_timeout (const char * c); /* set time limit after which client is reported dead */ int sh_xfer_set_time_limit(const char * str); /* error level for lookup failure */ int sh_xfer_lookup_level (const char * c); /* create client entry for given password */ int sh_xfer_make_client (const char * str); /* set port to which we connect */ int sh_xfer_server_port (const char * str); #ifdef SH_WITH_SERVER #ifdef INET_SYSLOG int set_syslog_active(const char * c); #endif /* create socket and start listening */ void create_server_tcp_socket (void); /* whether to use client address as known to the communication layer * and set by accept() */ int set_socket_peer (const char * c); /* whether to use client severity */ int sh_xfer_use_clt_sev (const char * c); /* whether to use client class */ int sh_xfer_use_clt_class (const char * c); /* server port */ int sh_xfer_set_port(const char * c); /* server interface */ int sh_xfer_set_interface(const char * c); /* a wrapper function */ void sh_xfer_html_write(void); /* register a client */ int sh_xfer_register_client (const char * str); /* start server */ void sh_xfer_start_server(void); /* free() everything */ void sh_xfer_free_all (void); #endif #if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) /* talk to server */ long sh_xfer_report (char * errmsg); /* set log server */ int sh_xfer_set_logserver (const char * address); void reset_count_dev_server(void); #endif #ifdef SH_WITH_CLIENT /* Throttle file download */ int sh_xfer_set_throttle_delay (const char * c); /* request file from server. file may be "CONF" or "DATA" or a UUID. */ long sh_xfer_request_file (const char * file); #endif #endif samhain-4.1.4/include/sh_html.h0000644000175000017500000000331112615253277013323 00000000000000#ifndef SH_HTML_H #define SH_HTML_H #ifdef SH_WITH_SERVER #define CLT_INACTIVE 0 #define CLT_STARTED 1 #define CLT_ILLEGAL 2 #define CLT_FAILED 3 #define CLT_EXITED 4 #define CLT_PANIC 5 #define CLT_POLICY 6 #define CLT_FILE 7 #define CLT_MSG 8 #define CLT_TOOLONG 9 #define CLT_SUSPEND 10 #define CLT_CHECK 11 #define CLT_MAX 12 /************************ char * clt_stat[] = { N_("Inactive"), N_("Started"), N_("ILLEGAL"), N_("FAILED"), N_("Exited"), N_("PANIC"), N_("POLICY"), N_("File transfer"), N_("Message"), N_("TIMEOUT_EXCEEDED"), }; **************************/ extern char * clt_stat[]; #ifdef SH_ENCRYPT #include "rijndael-api-fst.h" #endif /* --- client status --- */ typedef struct client_entry { char * hostname; char * salt; char * verifier; char session_key[KEY_LEN+1]; time_t session_key_timer; time_t last_connect; int exit_flag; int dead_flag; int encf_flag; int ency_flag; int ivst_flag; int status_now; int status_arr[CLT_MAX]; char timestamp[CLT_MAX][TIM_MAX]; #ifdef SH_ENCRYPT keyInstance keyInstE; keyInstance keyInstD; #endif } client_t; /* --- server status --- */ typedef struct _s_stat { time_t start; time_t last; int conn_open; int conn_max; long conn_total; } s_stat; extern s_stat server_status; /* write html report. Expects (client_t *) inptr. */ int sh_html_write(void * inptr); #endif #endif samhain-4.1.4/include/sh_sem.h0000664000175000017500000000037512615253277013154 00000000000000#ifndef SH_SEM_H #define SH_SEM_H #define SH_SEM_LOCK -1 #define SH_SEM_UNLOCK 1 void sh_sem_open(); void sh_sem_trylock(); void sh_sem_lock(); void sh_sem_unlock(long val); void sh_sem_close(); int sh_sem_wait(const char * wait); #endif samhain-4.1.4/include/sh_srp.h0000644000175000017500000000346512615253277013175 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ void sh_srp_x (char * salt, char * password); int sh_srp_make_a (void); char * sh_srp_M (char * x1, char * x2, char * x3, char * buf, size_t size); char * sh_srp_verifier (void); int sh_srp_check_zero (char * AB_str); int sh_srp_init(void); void sh_srp_exit(void); char * sh_srp_A (void); char * sh_srp_B (char * verifier); char * sh_srp_S_c (char * u_str, char * B_str); char * sh_srp_S_s (char * u_str, char * A_str, char * v_str); samhain-4.1.4/include/sh_log_correlate.h0000644000175000017500000000105712615253277015205 00000000000000#ifndef SH_LOG_CORRELATE_H #define SH_LOG_CORRELATE_H /* Clean up everything. */ void sh_keep_destroy(); /* Add an event */ int sh_keep_add(sh_string * label, unsigned long delay, time_t last); /* Add an event sequence matching rule */ int sh_keep_match_add(const char * str, const char * queue, const char * pattern); /* Delete the list of event sequence matching rules */ void sh_keep_match_del(); /* Try to find correlated events */ void sh_keep_match(); /* Deadtime for a correlation rule */ int sh_keep_deadtime (const char * str); #endif samhain-4.1.4/include/sh_processcheck.h0000644000175000017500000000040712615253277015036 00000000000000 #ifndef SH_PROCESSCHECK_H #define SH_PROCESSCHECK_H int sh_prochk_init(struct mod_type * arg); int sh_prochk_timer(time_t tcurrent); int sh_prochk_check(void); int sh_prochk_reconf(void); int sh_prochk_cleanup(void); extern sh_rconf sh_prochk_table[]; #endif samhain-4.1.4/include/sh_entropy.h0000644000175000017500000000307212615253277014063 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_ENTROPY_H #define SH_ENTROPY_H /* Deliver nbytes Bytes of system entropy (= noise). * Returns 0 on success, -1 on failure. */ int sh_entropy(int nbytes, char * nbuf); #endif samhain-4.1.4/include/sh_prelink.h0000644000175000017500000000076312615253277014033 00000000000000#ifndef SH_PRELINK_H #define SH_PRELINK_H /* path: full path to file; * file_hash: allocated storage for checksum; * alert_timeout: timeout for read */ int sh_prelink_run (char * path, char * file_hash, int alert_timeout, unsigned long mask); /* return S_TRUE if ELF file, S_FALSE otherwise */ int sh_prelink_iself (SL_TICKET fd, off_t size, int alert_timeout, char * path); /* configuration */ int sh_prelink_set_path (const char * str); int sh_prelink_set_hash (const char * str); #endif samhain-4.1.4/include/sh_hash.h0000644000175000017500000001267112615253277013313 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_HASH_H #define SH_HASH_H #include #include "samhain.h" #include "sh_unix.h" #include "sh_error.h" /* the report_checkflags flag */ int get_report_checkflags(); /* whether to report checkflags */ int set_report_checkflags(const char * c); /* convert to policy string */ const char * sh_hash_getpolicy(int class); /* format a uint64 */ char * sh_hash_size_format(void); /* report on a missing file */ int hashreport_missing( char *fullpath, int level); /* remove internal db record for a file (checks for some flags). */ void sh_hash_remove (const char * path); /* remove internal db record for a file */ void sh_hash_remove_unconditional (const char * path); /* Insert a "null" record in-memory (representing a missing file). */ void sh_hash_insert_null(char * str); #ifdef SH_DBIO_INT_H /* Check for "null" record */ int sh_hash_is_null_record(sh_filestore_t * theFile); #endif /* Dont report on ctm/mtm change for directories */ int sh_hash_loosedircheck(const char * str); /* List database content for a single file */ int set_list_file (const char * c); /* Set the path of that file */ char * get_list_file(); /* List database content with full detail */ int set_full_detail (const char * c); /* List database content with full detail, comma delimited */ int set_list_delimited (const char * c); /* Read the database from disk. */ void sh_hash_init (void); /* Check init status */ int sh_hash_get_initialized(); /* Read the database from disk and fill sh.data.hash with checksum. */ void sh_hash_init_and_checksum(); /* Set status to 'database is read in'. */ void sh_hash_set_initialized(); /* Check whether a file is present in the database. */ int sh_hash_have_it (const char * newname); /* Get a file if it is present in the database. * If fileHash != NULL also return checksum. */ int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash); /* Delete the database from memory. */ void sh_hash_hashdelete (void); /* Insert a file into the database. */ void sh_hash_pushdata (file_type * buf, char * fileHash); /* reset sh_hash_pushdata to use 'update' in daemon mode */ void sh_hash_pushdata_reset (void); /* Insert a file into the in-memory database. */ void sh_hash_pushdata_memory (file_type * theFile, char * fileHash); /* Get file flags from in-memory database */ int sh_hash_getflags (char * filename); /* Set file flags in in-memory database */ int sh_hash_setflags (char * filename, int flags); /* Set a file flag in in-memory database */ void sh_hash_set_flag (char * filename, int flag); /* Unset a file flag in in-memory database */ void sh_hash_clear_flag (char * filename, int flag_to_set); /* Compare a file with its status in the database. */ int sh_hash_compdata (int class, file_type * theFile, char * fileHash, char * policy_override, int severity_override); /* Search for files in the database that have been deleted from disk. */ void sh_hash_unvisited (ShErrLevel level); /* Search for unvisited entries in the database, custom error handler. */ void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key)); /* Set a file's status to 'visited'. This is required for * files that should be ignored, and may be present in the * database, but not on disk. */ int sh_hash_set_visited (char * newname); /* As above, but only set the 'visited' flag */ int sh_hash_set_visited_true (char * newname); /* cause the record to be deleted without a 'missing' message */ int sh_hash_set_missing (char * newname); /* Make a complete directory tree invisible */ int hash_remove_tree (char * s); /* Make every entry visible */ int hash_full_tree (void); /* Insert data. * 'key' -> path * 'str' -> binary with size 'size' */ struct store2db { UINT64 val0; UINT64 val1; UINT64 val2; UINT64 val3; char checksum[KEY_LEN+1]; unsigned char * str; int size; }; void sh_hash_push2db (const char * key, struct store2db * save); /* Retrieve data */ char * sh_hash_db2pop (const char * key, struct store2db * get); /* Write out database */ int sh_hash_writeout(void); #endif samhain-4.1.4/include/sh_ipvx.h0000644000175000017500000000364612615253277013360 00000000000000#ifndef SH_IPVX_H #define SH_IPVX_H #include #include #include #include #include #if defined(USE_IPVX) #define SH_SSP_LEN(a) ((a)->ss_family == AF_INET) ? \ sizeof(struct sockaddr_in) : \ sizeof(struct sockaddr_in6) #define SH_SS_LEN(a) ((a).ss_family == AF_INET) ? \ sizeof(struct sockaddr_in) : \ sizeof(struct sockaddr_in6) #else #define SH_SSP_LEN(a) sizeof(struct sockaddr_in) #define SH_SS_LEN(a) sizeof(struct sockaddr_in) #endif struct sh_sockaddr { int ss_family; struct sockaddr_in sin; #if defined(USE_IPVX) struct sockaddr_in6 sin6; #endif }; /* Cast a sockaddress */ struct sockaddr * sh_ipvx_sockaddr_cast (struct sh_sockaddr * ss); /* Compare with any_address */ int sh_ipvx_isany (struct sh_sockaddr * a); /* Compare two addresses */ int sh_ipvx_cmp(struct sh_sockaddr * a, struct sh_sockaddr * b); /* Set the port */ int sh_ipvx_set_port(struct sh_sockaddr * ss, int port); /* Get the port */ int sh_ipvx_get_port(struct sockaddr * ss, int sa_family); /* Save a sockaddress */ void sh_ipvx_save(struct sh_sockaddr * ss, int sa_family, struct sockaddr * sa); /* Ascii numerical sockaddress */ char * sh_ipvx_print_sockaddr (struct sockaddr * sa, int sa_family); /* Determine whether the given address is numeric */ int sh_ipvx_is_numeric (const char * addr); /* Convert a network address to an ascii numeric address */ int sh_ipvx_ntoa (char * name, size_t name_size, struct sh_sockaddr * ss); /* Convert an ascii numeric address to a network address */ int sh_ipvx_aton (const char * name, struct sh_sockaddr * ss); /* Try to find canonical hostname */ char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen); /* Convert address to hostname */ char * sh_ipvx_addrtoname(struct sh_sockaddr * ss); /* Try a reverse lookup */ int sh_ipvx_reverse_check_ok (char * peer, int port, struct sh_sockaddr * ss); #endif samhain-4.1.4/include/sh_restrict.h0000644000175000017500000000037312615253277014223 00000000000000#ifndef SH_RESTRICT_H #define SH_RESTRICT_H int sh_restrict_define(const char * str); void sh_restrict_purge (); int sh_restrict_this(const char * path, UINT64 size, UINT64 perm, SL_TICKET fh); int sh_restrict_add_ftype(const char * str); #endif samhain-4.1.4/include/slib.h0000644000175000017500000004115012615253277012621 00000000000000/* -------------------------------------------------------------- * * The developement of this library has been stimulated by reading * a paper on 'Robust Programming' by Matt Bishop, although * not all of his ideas might be implemented in the same * strictness as discussed in the paper. * * -------------------------------------------------------------- */ #ifndef SL_SLIB_H #define SL_SLIB_H #include #include #include #include #include #include "config_xor.h" #ifdef HAVE_UNISTD_H #include #endif #include "sh_string.h" /**************** -- Defined in config.h. -- #ifndef _(string) #define _(string) string #endif #ifndef N_(string) #define N_(string) string #endif *****************/ /* -------------------------------------------------------------- * * Typedefs, global variables, macros. * * -------------------------------------------------------------- */ extern long int sl_errno; /* Global error variable. */ /* The ticketing system; used to hide internals from the * programmer. */ typedef long int SL_TICKET; /* Unique ID for opened files. */ /* * TRUE, FALSE */ #if !defined(S_TRUE) #define S_TRUE 1 #define S_FALSE 0 #endif #define SH_GRBUF_SIZE 4096 #define SH_PWBUF_SIZE 32768 #if defined(__GNUC__) && (__GNUC__ >= 3) #undef SL_GNUC_CONST #define SL_GNUC_CONST __attribute__((const)) #else #undef SL_GNUC_CONST #define SL_GNUC_CONST #endif /* * The following macros are provided: * * SL_ISERROR(x) TRUE if return status of 'x' is an error code. * SL_REQUIRE(x, xstr) Abort if 'x' is false. * SL_ENTER(s) Trace entry in function 's'. * SL_RETURN(x, s) Trace return from function 's'. */ /* * The error codes. */ #define SL_ENONE 0 #define SL_ENULL -1024 /* Invalid use of NULL pointer. */ #define SL_ERANGE -1025 /* Argument out of range. */ #define SL_ETRUNC -1026 /* Result truncated. */ #define SL_EREPEAT -1027 /* Illegal repeated use of function. */ #define SL_EINTERNAL -1028 /* Internal error. */ #define SL_ETICKET -1029 /* Bad ticket. */ #define SL_EBADFILE -1030 /* File access error. Check errno. */ #define SL_EBOGUS -1031 /* Bogus file. */ #define SL_EMEM -1032 /* Out of memory. */ #define SL_EUNLINK -1033 /* Unlink error. Check errno. */ #define SL_EREWIND -1034 /* Rewind error. Check errno. */ #define SL_EFORWARD -1035 /* Forward error. Check errno. */ #define SL_EREAD -1036 /* Read error. Check errno. */ #define SL_EWRITE -1037 /* Write error. Check errno. */ #define SL_ESYNC -1038 /* Write error. Check errno. */ #define SL_EBADNAME -1040 /* Invalid name. */ #define SL_ESTAT -1041 /* stat of file failed. Check errno. */ #define SL_EFSTAT -1042 /* fstat of file failed. Check errno. */ #define SL_EBADUID -1050 /* Owner not trustworthy. */ #define SL_EBADGID -1051 /* Group writeable and not trustworthy.*/ #define SL_EBADOTH -1052 /* World writeable. */ #define SL_TOOMANY -1053 /* Too many open files */ #define SL_TIMEOUT -1054 /* Timeout in read */ #define SL_EISDIR -1055 /* Is a directory */ #define SL_EINTERNAL01 -1061 /* Internal error. */ #define SL_EINTERNAL02 -1062 /* Internal error. */ #define SL_EINTERNAL03 -1063 /* Internal error. */ #define SL_EINTERNAL04 -1064 /* Internal error. */ #define SL_EINTERNAL05 -1065 /* Internal error. */ #define SL_EINTERNAL06 -1066 /* Internal error. */ #define SL_EINTERNAL07 -1067 /* Internal error. */ #define SL_EINTERNAL08 -1068 /* Internal error. */ #define SL_EINTERNAL09 -1069 /* Internal error. */ #define SL_EINTERNAL10 -1070 /* Internal error. */ #define SL_EINTERNAL11 -1071 /* Internal error. */ #define SL_EINTERNAL12 -1072 /* Internal error. */ /* * All int functions return SL_NONE on success. */ #ifdef __cplusplus extern "C" { #endif int dlog (int flag, const char * file, int line, const char *fmt, ...); char * sl_get_errmsg(void); /* ---------------------------------------------------------------- * * Heap consistency routines * * ---------------------------------------------------------------- */ int sl_test_heap(void); /* ---------------------------------------------------------------- * * Capability routines * * ---------------------------------------------------------------- */ extern int sl_useCaps; int sl_drop_cap (void); int sl_drop_cap_sub(void); int sl_get_cap_sub(void); int sl_drop_cap_qdel(void); int sl_get_cap_qdel(void); /* ---------------------------------------------------------------- * * String handling routines * * ---------------------------------------------------------------- */ /* * A memset that does not get optimized away */ void *sl_memset(void *s, int c, size_t n); #if !defined(SH_REAL_SET) #undef memset #define memset sl_memset #endif /* * Copy src to dst. siz is the length of dst. */ int sl_strlcpy(char * dst, /*@null@*/const char * src, size_t siz); /* * Append src to dst. siz is the length of dst. */ int sl_strlcat(char * dst, /*@null@*/const char *src, size_t siz); /* * An implementation of vsnprintf. va_start/va_end are in the caller * function. */ int sl_vsnprintf(char *str, size_t n, const char *format, va_list vl ); /* * An implementation of snprintf. */ int sl_snprintf(char *str, size_t n, const char *format, ... ); /* * A robust drop-in replacement of strncpy. strlcpy is preferable. */ char * sl_strncpy(/*@out@*/char *dst, const char *src, size_t size); /* * Robust strncat. */ char * sl_strncat(char *dst, const char *src, size_t n); /* * strstr */ char * sl_strstr (const char * haystack, const char * needle); /* * robust strn[case]cmp replacement */ int sl_strncmp(const char * a, const char * b, size_t n); int sl_strncasecmp(const char * a, const char * b, size_t n); /* * robust strcmp replacement */ int sl_strcmp(const char * a, const char * b); /* * robust strcasecmp replacement */ int sl_strcasecmp(const char * one, const char * two); /* * robust strlen replacement */ #define sl_strlen(arg) ((arg == NULL) ? 0 : (strlen(arg))) /* ---------------------------------------------------------------- * * Privilege handling routines * * ---------------------------------------------------------------- */ /* * ONE OF THE FOLLOWING THREE FUNCTIONS * SHOULD BE CALLED BEFORE ANY OTHER OF THE * UID HANDLING FUNCTIONS. */ int sl_policy_get_user(const char *username); /* drop SUID to */ int sl_policy_get_real(char *username); /* drop privs to */ int sl_policy_get_root(void); /* drop SUID to root */ /* * If not using one of the above, use this function, * and then call sh_unset_suid(). * This function saves the uid's. * It calls abort() on error. */ int sl_save_uids(void); /* * This function returns the saved euid. * It calls abort() if the uid's are not saved already. */ int sl_get_euid(/*@out@*/uid_t * ret); uid_t sl_ret_euid(void); /* * This function returns the saved egid. * It calls abort() if the uid's are not saved already. */ int sl_get_egid(/*@out@*/gid_t * ret); /* * This function returns the saved current ruid. * It calls abort() if the uid's are not saved already. */ int sl_get_ruid(/*@out@*/uid_t * ret); /* * This function returns the saved current rgid. * It calls abort() if the uid's are not saved already. */ int sl_get_rgid(gid_t * ret); /* * This function returns the saved original ruid. * It calls abort() if the uid's are not saved already. */ int sl_get_ruid_orig(uid_t * ret); /* * This function returns the saved original rgid. * It calls abort() if the uid's are not saved already. */ int sl_get_rgid_orig(gid_t * ret); /* * This function returns true if the program is SUID. * It calls abort() if the uid's are not saved already. */ int sl_is_suid(void); /* * This function sets the effective uid * to the saved effective uid. */ int sl_set_suid (void); /* * This function sets the effective uid to the real uid. */ int sl_unset_suid (void); /* * This function drops SUID privileges irrevocably. */ int sl_drop_privileges(void); /* ---------------------------------------------------------------- * * File handling routines * * ---------------------------------------------------------------- */ #define SL_OFILE_SIZE 32 char * sl_check_badfd(); char * sl_check_stale(); /* Create a file record for an open file */ SL_TICKET sl_make_ticket (const char * ofile, int oline, int fd, const char * filename, FILE * stream); /* Get the pointer to a stream. If none exists yet, open it */ FILE * sl_stream (SL_TICKET ticket, char * mode); /* Open for writing. */ SL_TICKET sl_open_write (const char * ofile, int oline, const char * fname, int priviledge_mode); /* Open for reading. */ SL_TICKET sl_open_read (const char * ofile, int oline, const char * fname, int priviledge_mode); /* Drop from cach when closing */ int sl_set_drop_cache(const char * str); /* Open for reading w/minimum checking. */ SL_TICKET sl_open_fastread (const char * ofile, int oline, const char * fname, int priviledge_mode); /* Open for read and write. */ SL_TICKET sl_open_rdwr (const char * ofile, int oline, const char * fname, int priviledge_mode); /* Open for read and write, fail if file exists. */ SL_TICKET sl_open_safe_rdwr (const char * ofile, int oline, const char * fname, int priv); /* Open for write, truncate. */ SL_TICKET sl_open_write_trunc (const char * ofile, int oline, const char * fname, int priviledge_mode); /* Open for read and write, truncate. */ SL_TICKET sl_open_rdwr_trunc (const char * ofile, int oline, const char * fname, int priviledge_mode); /* Initialize the content sh_string. */ int sl_init_content (SL_TICKET ticket, size_t size); /* Get the (pointer to) the content sh_string. */ sh_string * sl_get_content (SL_TICKET ticket); /* Lock file (uses fcntl F_SETLK). */ int sl_lock (SL_TICKET ticket); /* Close file. */ int sl_close (SL_TICKET ticket); /* Close file descriptor. */ int sl_close_fd (const char * file, int line, int fd); /* Close stream. */ int sl_fclose (const char * file, int line, FILE * fp); /* Unlink file. */ int sl_unlink (SL_TICKET ticket); /* Rewind file. */ int sl_rewind (SL_TICKET ticket); /* Seek file. */ int sl_seek (SL_TICKET ticket, off_t off_data); /* Forward file. */ int sl_forward (SL_TICKET ticket); /* Sync file. */ int sl_sync (SL_TICKET ticket); /* Read file. */ int sl_read (SL_TICKET ticket, void * buf, size_t count); int sl_read_timeout_prep (SL_TICKET ticket); int sl_read_timeout_fd (int fd, void * buf, size_t count, int timeout, int is_nonblocking); int sl_read_timeout (SL_TICKET ticket, void * buf, size_t count, int timeout, int is_nonblocking); int sl_read_fast (SL_TICKET ticket, void * buf_in, size_t count); /* Write file. */ int sl_write (SL_TICKET ticket, const void * msg, long nbytes); /* Write file, terminate with newline. */ int sl_write_line (SL_TICKET ticket, const void * msg, long nbytes); /* As above, but only for non-constant strings. */ int sl_write_line_fast (SL_TICKET ticket, void * msg, long nbytes); /* Drop all metadata for file descriptors >= fd. */ int sl_dropall(int fd, int except); int sl_dropall_dirty(int fd, int except); /* don't deallocate */ /* Check whether file is trustworthy. */ int sl_trustfile(const char * path, uid_t * ok, uid_t * bad); /* Check whether file is trustworthy. */ int sl_trustfile_euid(const char * filename, uid_t euid); /* purge list of trusted users */ int sl_trust_purge_user (void); /* Add a trusted user. */ int sl_trust_add_user (uid_t pwid); /* Get error string. */ char * sl_error_string(int errorcode); /* Get error file. */ char * sl_trust_errfile(void); /* Overflow tests */ int sl_ok_muli (int a, int b) SL_GNUC_CONST; int sl_ok_divi (int a, int b) SL_GNUC_CONST; int sl_ok_addi (int a, int b) SL_GNUC_CONST; int sl_ok_subi (int a, int b) SL_GNUC_CONST; int sl_ok_muls (size_t a, size_t b) SL_GNUC_CONST; int sl_ok_adds (size_t a, size_t b) SL_GNUC_CONST; #ifdef __cplusplus } #endif /* Privilege modes for file access. */ #define SL_YESPRIV 0x33 #define SL_NOPRIV 0x34 /* Suitable for Linux */ #define MAXFILENAME 4096 /* * This macro is TRUE if (x) < 0. */ #define SL_ISERROR(x) ((long)(x) < 0) #if defined(WITH_TPT) #define TPT(arg) dlog arg ; #else #define TPT(arg) #endif /* * The 'require' macro. */ #define SL_REQUIRE(assertion, astext) \ do { \ /*@i@*/ if (assertion) ; \ else { \ dlog(0, FIL__, __LINE__, SDG_AFAIL, \ FIL__, __LINE__, astext); \ _exit(EXIT_FAILURE); \ } \ } while (0) /* * The enter macro. Prints the trace if TRACE is on. */ extern int slib_do_trace; extern int slib_trace_fd; #if defined(SL_DEBUG) #define SL_ENTER(s) sl_stack_push(s, FIL__, __LINE__); #else #define SL_ENTER(s) if (slib_do_trace != 0) sl_trace_in(s, FIL__, __LINE__); #endif /* * The return macro. */ #if defined(SL_DEBUG) #ifndef S_SPLINT_S #define SL_RETURN(x, s) \ do { \ sl_stack_pop(s, FIL__, __LINE__); \ return(x); \ } while(0) #else /*@notfunction@*/ #define SL_RETURN(x, s) return(x); #endif /* S_SPLINT_S */ #else #ifndef S_SPLINT_S #define SL_RETURN(x, s) \ do { \ if (slib_do_trace != 0) \ sl_trace_out(s, FIL__, __LINE__); \ return(x); \ } while(0) #else /*@notfunction@*/ #define SL_RETURN(x, s) return(x); #endif /* S_SPLINT_S */ #endif /* SL_RETURN macro */ #if defined(SL_DEBUG) #define SL_RET0(s) \ do { \ sl_stack_pop(s, FIL__, __LINE__); \ return; \ } while(0) #else #ifndef S_SPLINT_S #define SL_RET0(s) \ do { \ if (slib_do_trace != 0) \ sl_trace_out(s, FIL__, __LINE__); \ return; \ } while(0) #else /*@notfunction@*/ #define SL_RET0(s) return; #endif /* S_SPLINT_S */ #endif /* SL_RETURN macro */ #if defined(SL_DEBUG) void sl_stack_push(char * c, char * file, int line); void sl_stack_pop(char * c, char * file, int line); void sl_stack_print(void); #endif void sl_trace_in (const char * str, const char * file, int line); void sl_trace_out (const char * str, const char * file, int line); int sl_trace_file (const char * str); int sl_trace_use (const char * str); /* * The internal return macro. Sets sl_errno to the return value. */ #if defined(SL_DEBUG) #define SL_IRETURN(x, s) \ do { \ if((long)(x) < 0) { \ TPT((0, FIL__, __LINE__, SDG_ERROR, (long)(x))) \ sl_errno=(x); \ } \ sl_stack_pop(s, FIL__, __LINE__); \ if (1) return(x); \ } while(0) #else #define SL_IRETURN(x, s) \ do { \ if ((long)(x) < 0) sl_errno=(x); \ if (slib_do_trace) \ sl_trace_out(s, FIL__, __LINE__); \ if (1) return(x); \ } while(0) #endif /* SL_IRETURN macro */ /* slib.h */ #endif samhain-4.1.4/include/sh_trace.h0000644000175000017500000000143012615253277013455 00000000000000#ifndef SH_TRACE_H #define SH_TRACE_H /* This file should be included via samhain.h only. */ #ifdef SL_DEBUG #define ASSERT(expr, expr1) \ if (!(expr)) \ { \ fprintf(stderr, \ SDG_AERRO, \ FIL__, __LINE__, expr1 ); \ abort(); \ } #define ASSERT_RET(expr, expr1, rr) \ if (!(expr)) \ { \ fprintf(stderr, \ SDG_AERRO, \ FIL__, __LINE__, expr1 ); \ TPT(( (-1), FIL__, __LINE__, SDG_0RETU)) \ return (rr); \ } #else #define ASSERT(expr, expr1) #define ASSERT_RET(expr, expr1, rr) \ if (!(expr)) return (rr); #endif #ifdef SL_DEBUG #define TX1(expr1) \ fprintf(stderr, \ SDG_TERRO, \ FIL__, __LINE__, expr1 ); #else #define TX1(expr1) #endif /* #ifndef SH_TRACE_H */ #endif samhain-4.1.4/include/sh_ks.h0000644000175000017500000000025112615253277012774 00000000000000#ifndef SH_KERN_CALLS_H #define SH_KERN_CALLS_H /* Dummy header. */ typedef struct _sh_syscall_t { unsigned long addr; char * name; } sh_syscall_t; #endif samhain-4.1.4/include/sh_socket.h0000644000175000017500000000141112615253277013646 00000000000000#ifndef SH_SOCKET_H #define SH_SOCKET_H /* 63 (cmd) + 1 (':') + 63 (host) + 1 ('\0') + 81 */ #define SH_MAXMSG 209 #define SH_MAXMSGLEN 64 #if defined (SH_WITH_CLIENT) char * sh_socket_get_uuid(int * errflag, unsigned int * count, time_t * last); int sh_socket_store_uuid(const char * cmd); int sh_socket_return_uuid(const char * uuid, unsigned int count, time_t last); void sh_socket_server_cmd(const char * srvcmd); int set_delta_retry_interval(const char * str); int set_delta_retry_count(const char * str); #endif #if defined (SH_WITH_SERVER) int sh_socket_open_int (void); int sh_socket_remove (void); char * sh_socket_check(const char * client_name); int sh_socket_poll(void); void sh_socket_add2reload (const char * clt); #endif #endif samhain-4.1.4/include/sh_cat.h0000644000175000017500000001334712615253277013140 00000000000000 #ifndef SH_CAT_H #define SH_CAT_H typedef struct foo_cat_entry { unsigned long id; unsigned long priority; unsigned long class; const char * format; } cat_entry; extern cat_entry msg_cat[]; extern const char * class_cat[]; #define AUD 0 #define PANIC 1 #define RUN 2 #define FIL 3 #define TCP 4 #define ERR 5 #define STAMP 6 #define ENET 7 #define EINPUT 8 #define EVENT 9 #define START 10 #define LOGKEY 11 #define OTHER_CLA ((1 << RUN)|(1 << FIL)|(1 << TCP)) #define RUN_NEW ((1 << RUN)|(1 << EVENT)|(1 << START)|(1 << LOGKEY)) #define FIL_NEW ((1 << FIL)|(1 << EVENT)) #define ERROR_CLA ((1 << ERR)|(1 << PANIC)|(1 << ENET)|(1 << EINPUT)) #define SH_CLA_RAW_MAX 12 #define SH_CLA_MAX 16 #if 0 enum { SH_CLA_AUD = (1 << 0), SH_CLA_PANIC = (1 << 1), SH_CLA_RUN = (1 << 2), SH_CLA_FIL = (1 << 3), SH_CLA_TCP = (1 << 4), SH_CLA_ERR = (1 << 5), SH_CLA_STAMP = (1 << 6), SH_CLA_ENET = (1 << 7), SH_CLA_EINPUT = (1 << 8) }; #endif enum { MSG_EXIT_ABORTS, MSG_START_SRV, MSG_EXIT_ABORT1, MSG_EXIT_NORMAL, MSG_START_KEY_MAIL, MSG_START_KEY, MSG_START_0H, MSG_START_1H, MSG_START_2H, MSG_START_GH, MSG_START_GH2, MSG_SUSPEND, MSG_MLOCK, MSG_W_SIG, MSG_W_CHDIR, MSG_MOD_FAIL, MSG_MOD_OK, MSG_MOD_EXEC, MSG_RECONF, MSG_CHECK_0, MSG_CHECK_1, MSG_CHECK_2, MSG_STAMP, MSG_D_START, MSG_D_DSTART, MSG_D_FAIL, MSG_D_DELTAOK, MSG_D_DELTAFAIL, #ifndef HAVE_URANDOM MSG_ENSTART, MSG_ENEXEC, MSG_ENFAIL, MSG_ENTOUT, MSG_ENCLOS, MSG_ENCLOS1, MSG_ENREAD, #endif #ifdef SH_USE_SUIDCHK MSG_SUID_POLICY, MSG_SUID_FOUND, MSG_SUID_SUMMARY, MSG_SUID_QREPORT, MSG_SUID_ERROR, #endif #ifdef SH_USE_UTMP MSG_UT_CHECK, MSG_UT_LG1X, MSG_UT_LG2X, MSG_UT_LG3X, MSG_UT_LG1A, MSG_UT_LG1B, MSG_UT_LG2A, MSG_UT_LG2B, MSG_UT_LG3A, MSG_UT_LG3B, MSG_UT_LG3C, MSG_UT_ROT, MSG_UT_BAD, MSG_UT_FIRST, MSG_UT_OUTLIER, #endif #ifdef SH_USE_PROCESSCHECK MSG_PCK_CHECK, MSG_PCK_OK, MSG_PCK_P_HIDDEN, MSG_PCK_HIDDEN, MSG_PCK_FAKE, MSG_PCK_MISS, #endif #ifdef SH_USE_PORTCHECK MSG_PORT_MISS, MSG_PORT_NEW, MSG_PORT_RESTART, MSG_PORT_NEWPORT, #endif #ifdef SH_USE_MOUNTS MSG_MNT_CHECK, MSG_MNT_MEMLIST, MSG_MNT_MNTMISS, MSG_MNT_OPTMISS, #endif #ifdef SH_USE_USERFILES MSG_USERFILES_SUMMARY, #endif #ifdef USE_LOGFILE_MONITOR MSG_LOGMON_CHKS, MSG_LOGMON_CHKE, MSG_LOGMON_MISS, MSG_LOGMON_EOPEN, MSG_LOGMON_EREAD, MSG_LOGMON_REP, MSG_LOGMON_SUM, MSG_LOGMON_COR, MSG_LOGMON_MARK, MSG_LOGMON_BURST, #endif #ifdef USE_REGISTRY_CHECK MSG_REG_MISS, MSG_REG_NEW, MSG_REG_CHANGE, #endif #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) MSG_FI_TOOLATE, MSG_FI_CSUM, MSG_FI_DSUM, MSG_FI_CHK, MSG_FI_NULL, MSG_FI_FAIL, MSG_FI_GLOB, MSG_FI_COLL, MSG_FI_DOUBLE, MSG_FI_2LONG, MSG_FI_2LONG2, MSG_FI_NOPATH, MSG_FI_DLNK, MSG_FI_RDLNK, MSG_FI_NOGRP, MSG_FI_NOUSR, MSG_FI_STAT, MSG_FI_OBSC, MSG_FI_OBSC2, MSG_FI_LIST, MSG_FI_LLNK, MSG_FI_MISS, /* #ifdef SH_USE_XML */ MSG_FI_MISS2, MSG_FI_ADD2, /* #endif */ MSG_FI_ADD, MSG_FI_CHAN, MSG_FI_NODIR, MSG_FI_DBEX, #endif MSG_TCP_NETRP, #ifndef SH_STANDALONE #ifdef INET_SYSLOG MSG_INET_SYSLOG, MSG_ERR_SYSLOG, #endif MSG_TCP_MISMATCH, MSG_TCP_MISENC, MSG_TCP_NONAME, MSG_TCP_UNEXP, MSG_TCP_EFIL, MSG_TCP_NOCONF, MSG_TCP_NOAUTH, MSG_TCP_CONF, MSG_TCP_AUTH, MSG_TCP_FOK, MSG_TCP_FBAD, MSG_TCP_ECONN, MSG_TCP_EZERO, MSG_TCP_EBGN, MSG_TCP_CREG, MSG_TCP_FAUTH, MSG_TCP_TIMOUT, MSG_TCP_RESCLT, MSG_TCP_RESPEER, MSG_TCP_LOOKERS, MSG_TCP_LOOKUP, MSG_TCP_TIMEXC, MSG_TCP_NOCLT, MSG_TCP_BADCONN, MSG_TCP_FFILE , MSG_TCP_NFILE , MSG_TCP_FINV , MSG_TCP_OKFILE, MSG_TCP_OKMSG, MSG_TCP_MSG, MSG_TCP_NEW, MSG_TCP_ILL, MSG_TCP_SYNC, MSG_TCP_RESET, MSG_TCP_CNEW, MSG_E_HTML, #endif MSG_E_AUTH, MSG_ACCESS, MSG_TRUST, MSG_NOACCESS, MSG_P_NODATA, #ifndef MEM_DEBUG MSG_E_MNULL, MSG_E_MMEM, #else MSG_MSTAMP, MSG_MSTAMP2, MSG_E_MNULL, MSG_E_MMEM, MSG_E_MREC, MSG_E_MOVER, MSG_E_MUNDER, MSG_E_NOTFREE, #endif MSG_E_TRUST, MSG_E_HASH, MSG_E_ACCESS, MSG_E_READ, MSG_E_NOTREG, MSG_E_TIMEOUT, MSG_NODEV, MSG_LOCKED, MSG_PIDFILE, MSG_NOEXEC, MSG_ES_ENT, MSG_ES_KEY1, MSG_ES_KEY2, MSG_E_GPG, MSG_E_GPG_FP, MSG_E_GPG_CHK, MSG_E_SUBGEN, MSG_E_SUBGPATH, MSG_E_UNLNK, MSG_E_REGEX, MSG_E_OPENDIR, MSG_E_TRUST1, MSG_E_TRUST2, MSG_E_PWNULL, MSG_E_PWLONG, MSG_E_GRNULL, MSG_E_NET, MSG_E_NETST, MSG_E_NETST1, MSG_E_NLOST, MSG_E_NEST, MSG_EINVALHEAD, MSG_EINVALCONF, MSG_EINVALS, MSG_EINVALL, MSG_EINVALD, MSG_EINVALDD, MSG_SRV_FAIL, MSG_QUEUE_FULL, MSG_AUD_OPEN, MSG_AUD_DUP, MSG_AUD_PIPE, MSG_AUD_FORK, MSG_AUD_EXIT, MSG_AUD_SETUID, MSG_AUD_SETGID, MSG_AUD_UTIME, MSG_AUD_EXEC, MSG_AUD_CHDIR, MSG_AUD_UNLINK, MSG_AUD_KILL, MSG_ERR_OPEN, MSG_ERR_DUP, MSG_ERR_PIPE, MSG_ERR_FORK, MSG_ERR_SETUID, MSG_ERR_SETGID, MSG_ERR_UTIME, MSG_ERR_EXEC, MSG_ERR_CHDIR, MSG_ERR_UNLINK, MSG_ERR_KILL, MSG_ERR_SIGACT, MSG_ERR_CONNECT, MSG_ERR_ACCEPT, MSG_ERR_LSTAT, MSG_ERR_FSTAT, MSG_ERR_STAT, MSG_ERR_FCNTL }; #endif samhain-4.1.4/include/sh_calls.h0000644000175000017500000000656712615253277013475 00000000000000#ifndef SH_CALLS_H #define SH_CALLS_H #define AUD_CHDIR (1UL << 0) #define AUD_CHMOD (1UL << 1) #define AUD_CHOWN (1UL << 2) #define AUD_CREAT (1UL << 3) #define AUD_DUP (1UL << 4) #define AUD_EXEC (1UL << 5) #define AUD_EXIT (1UL << 6) #define AUD_FORK (1UL << 7) #define AUD_KILL (1UL << 8) #define AUD_LINK (1UL << 9) #define AUD_MKDIR (1UL << 10) #define AUD_MKFIFO (1UL << 11) #define AUD_OPEN (1UL << 12) #define AUD_PIPE (1UL << 13) #define AUD_RENAME (1UL << 14) #define AUD_RMDIR (1UL << 15) #define AUD_SETGID (1UL << 16) #define AUD_SETUID (1UL << 17) #define AUD_UNLINK (1UL << 18) #define AUD_UTIME (1UL << 19) #include #include #include #include #include /*@-fixedformalarray@*/ #include "config_xor.h" #if defined(__GNUC__) && (__GNUC__ >= 3) #undef SH_GNUC_NORETURN #define SH_GNUC_NORETURN __attribute__((noreturn)) #else #undef SH_GNUC_NORETURN #define SH_GNUC_NORETURN #endif /* Set aud functions */ int sh_aud_set_functions(const char * str_s); #ifdef SH_IPVX_H long int retry_accept(const char * file, int line, int fd, struct sh_sockaddr *serv_addr, int * addrlen); #endif void sh_calls_enable_sub(); int sh_calls_set_sub (const char * str); long int retry_stat (const char * file, int line, const char *file_name, struct stat *buf); long int retry_fstat(const char * file, int line, int filed, struct stat *buf); long int retry_lstat_ns(const char * file, int line, const char *file_name, struct stat *buf); long int retry_lstat(const char * file, int line, const char *file_name, struct stat *buf); long int retry_fcntl(const char * file, int line, int fd, int cmd, long arg); long int retry_msleep (int sec, int millisec); long int retry_sigaction(const char * file, int line, int signum, const struct sigaction *act, struct sigaction *oldact); int sh_calls_set_bind_addr (const char *); long int retry_connect(const char * file, int line, int fd, struct sockaddr *serv_addr, int addrlen); long int retry_aud_dup2 (const char * file, int line, int fd, int fd2); long int retry_aud_execve (const char * file, int line, const char *dateiname, char * argv[], char *envp[]); long int retry_aud_dup (const char * file, int line, int fd); long int retry_aud_chdir (const char * file, int line, const char *path); long int retry_aud_unlink (const char * file, int line, char * path); long int retry_aud_utime (const char * file, int line, char * path, struct utimbuf *buf); long int aud_open (const char * file, int line, int privs, const char *pathname, int flags, mode_t mode); long int aud_open_noatime (const char * file, int line, int privs, const char *pathname, int flags, mode_t mode, int * o_noatime); /*@noreturn@*/ void aud_exit (const char * file, int line, int fd) SH_GNUC_NORETURN; /*@noreturn@*/ void aud__exit (const char * file, int line, int fd) SH_GNUC_NORETURN; pid_t aud_fork (const char * file, int line); int aud_pipe (const char * file, int line, int modus[2]); int aud_setuid (const char * file, int line, uid_t uid); int aud_setgid (const char * file, int line, gid_t gid); long int aud_kill (const char * file, int line, pid_t pid, int sig); #endif samhain-4.1.4/include/sh_log_mark.h0000644000175000017500000000045712615253277014162 00000000000000#ifndef SH_LOG_MARK_H #define SH_LOG_MARK_H void sh_log_mark_destroy(); int sh_log_mark_add (const char * label, time_t interval, const char * qlabel); void sh_log_mark_update (sh_string * label, time_t timestamp); void sh_log_mark_check(); int sh_log_set_mark_severity (const char * str); #endif samhain-4.1.4/include/sh_dbCreate.h0000664000175000017500000000273012615253277014076 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_DBCREATE_H #define SH_DBCREATE_H int sh_dbCreate (const char * path); #endif samhain-4.1.4/include/sh_log_check.h0000644000175000017500000000675412615253277014313 00000000000000#ifndef SH_LOGCHECK_H #define SH_LOGCHECK_H #include #include /* Convert a struct tm to unix timestamp with caching */ time_t conv_timestamp (struct tm * btime, struct tm * old_tm, time_t * old_time); /* Definition of a log record entry, to be returned from parsing function. */ #define PID_INVALID 0 struct sh_logrecord { char * filename; sh_string * host; sh_string * timestr; pid_t pid; time_t timestamp; sh_string * message; }; #define SH_LOGFILE_MOVED (1<<0) #define SH_LOGFILE_REWIND (1<<1) #define SH_LOGFILE_PIPE (1<<2) #define SH_LOGFILE_NOFILE (1<<3) struct sh_logfile { FILE * fp; int flags; char * filename; dev_t device_id; ino_t inode; fpos_t offset; /* Info for the parser, e.g. a regular expression */ void * fileinfo; /* Callback function to read the next record */ sh_string * (*get_record) (sh_string * record, struct sh_logfile * logfile); /* Callback function to parse the record into standard format */ struct sh_logrecord * (*parse_record)(sh_string * logline, void * fileinfo); struct sh_logfile * next; }; /* Generic callback function to parse fileinfo. */ void * sh_eval_fileinfo_generic(char * str); /* Generic parser info. */ struct sh_logrecord * sh_parse_generic (sh_string * logline, void * fileinfo); /**************************************************************** ** ** Parsing and reading functions **/ /* Open file, position at stored offset. */ int sh_open_for_reader (struct sh_logfile * logfile); /* Simple line reader for executed shell command */ sh_string * sh_command_reader (sh_string * record, struct sh_logfile * logfile); /* Wrapper for sh_command_reader */ sh_string * sh_read_shell (sh_string * record, struct sh_logfile * logfile); /* Parses a shell command reply. */ struct sh_logrecord * sh_parse_shell (sh_string * logline, void * fileinfo); /* Simple line reader. */ sh_string * sh_default_reader (sh_string * record, struct sh_logfile * logfile); /* Continued line reader. */ sh_string * sh_cont_reader (sh_string * record, struct sh_logfile * logfile, char * cont); /* Binary reader */ sh_string * sh_binary_reader (void * s, size_t size, struct sh_logfile * logfile); /* Parses a syslog-style line. */ struct sh_logrecord * sh_parse_syslog (sh_string * logline, void * fileinfo); /* Format info for apache log. */ void * sh_eval_fileinfo_apache(char * str); /* Parses a apache-style line. */ struct sh_logrecord * sh_parse_apache (sh_string * logline, void * fileinfo); /* Get a pacct record */ sh_string * sh_read_pacct (sh_string * record, struct sh_logfile * logfile); /* Parses a pacct record. */ struct sh_logrecord * sh_parse_pacct (sh_string * logline, void * fileinfo); /* Get a samba record */ sh_string * sh_read_samba (sh_string * record, struct sh_logfile * logfile); /* Parses a samba record. */ struct sh_logrecord * sh_parse_samba (sh_string * logline, void * fileinfo); /** *****************************************************************/ int sh_get_hidepid(); int sh_set_hidepid(const char *s); #define SH_MAX_LCODE_SIZE 16 struct sh_logfile_type { char code[SH_MAX_LCODE_SIZE]; /* read callback */ /*@null@*/sh_string * (*get_record) (sh_string * record, struct sh_logfile * logfile); /* parsing callback */ struct sh_logrecord * (*parse_record)(sh_string * logline, void * fileinfo); /* evaluate fileinfo */ void * (*eval_fileinfo)(char * str); }; #endif samhain-4.1.4/include/sh_filter.h0000644000175000017500000000134212615253277013646 00000000000000#ifndef SH_FILTER_H #define SH_FILTER_H /* Filtering */ #define SH_FILT_NUM 32 #define SH_FILT_OR 0 #define SH_FILT_AND 1 #define SH_FILT_NOT 2 #define SH_FILT_INIT { 0, { NULL }, 0, { NULL }, 0, { NULL }} /* Pattern storage is of type void since it may be a char* * or a regex_t* */ typedef struct _sh_filter_type { int for_c; void * for_v[SH_FILT_NUM]; int fand_c; void * fand_v[SH_FILT_NUM]; int fnot_c; void * fnot_v[SH_FILT_NUM]; } sh_filter_type; int sh_filter_add (const char * str, sh_filter_type * filter, int type); void sh_filter_free (sh_filter_type * filter); int sh_filter_filter (const char * message, sh_filter_type * filter); sh_filter_type * sh_filter_alloc(void); #endif samhain-4.1.4/include/sh_fInotify.h0000644000175000017500000000041312615253277014146 00000000000000 #ifndef SH_F_INOTIFY_H #define SH_F_INOTIFY_H int sh_fInotify_init(struct mod_type * arg); int sh_fInotify_timer(time_t tcurrent); int sh_fInotify_run(void); int sh_fInotify_reconf(void); int sh_fInotify_cleanup(void); extern sh_rconf sh_fInotify_table[]; #endif samhain-4.1.4/include/sh_pthread.h0000644000175000017500000001557112615253277014021 00000000000000#ifndef SH_PTHREAD_H #define SH_PTHREAD_H #ifdef HAVE_PTHREAD #include #define SH_MUTEX(M) pthread_mutex_t M #define SH_MUTEX_INIT(M,I) pthread_mutex_t M = I #define SH_MUTEX_STATIC(M,I) static pthread_mutex_t M = I #define SH_MUTEX_EXTERN(M) extern pthread_mutex_t M #define SH_SETSIGMASK(A, B, C) sh_pthread_setsigmask(A,B,C) int sh_pthread_setsigmask(int how, const void *set, void *oldset); /* pthread_mutex_unlock() has the wrong type (returns int), so * we need to wrap it in this function. */ extern void sh_pthread_mutex_unlock (void *arg); #define SH_MUTEX_LOCK(M) \ do { \ int oldtype; \ int executeStack = 1; \ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); \ pthread_cleanup_push(sh_pthread_mutex_unlock, (void*)&(M));\ pthread_mutex_lock(&(M)) #define SH_MUTEX_TRYLOCK(M) \ do { \ int oldtype; \ volatile int executeStack = 0; \ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); \ pthread_cleanup_push(sh_pthread_mutex_unlock, (void*)&(M));\ if (0 == pthread_mutex_trylock(&(M))) { \ executeStack = 1 #define SH_MUTEX_TRYLOCK_UNLOCK(M) \ } \ pthread_cleanup_pop(executeStack); \ pthread_setcanceltype(oldtype, NULL); \ } while (0) #define SH_MUTEX_UNLOCK(M) \ pthread_cleanup_pop(executeStack); \ pthread_setcanceltype(oldtype, NULL); \ } while (0) #define SH_MUTEX_LOCK_UNSAFE(M) pthread_mutex_lock(&(M)) #define SH_MUTEX_TRYLOCK_UNSAFE(M) pthread_mutex_trylock(&(M)) #define SH_MUTEX_UNLOCK_UNSAFE(M) pthread_mutex_unlock(&(M)) /* * ---- Recursive mutex ---- */ #if defined(HAVE_PTHREAD_MUTEX_RECURSIVE) #define SH_MUTEX_RECURSIVE(M) \ static pthread_mutex_t M; \ static void M ## _init (void) \ { \ pthread_mutexattr_t mta; \ pthread_mutexattr_init(&mta); \ pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); \ pthread_mutex_init(&(M), &mta); \ pthread_mutexattr_destroy(&mta); \ return; \ } \ static pthread_once_t M ## _initialized = PTHREAD_ONCE_INIT #define SH_MUTEX_RECURSIVE_INIT(M) \ (void) pthread_once(&(M ## _initialized), (M ## _init)) #define SH_MUTEX_RECURSIVE_LOCK(M) \ do { \ int oldtype; \ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); \ pthread_cleanup_push(sh_pthread_mutex_unlock, (void*)&(M));\ pthread_mutex_lock(&(M)) #define SH_MUTEX_RECURSIVE_UNLOCK(M) \ pthread_cleanup_pop(1); \ pthread_setcanceltype(oldtype, NULL); \ } while (0) #else /* !defined(PTHREAD_MUTEX_RECURSIVE) */ struct sh_RMutex { pthread_mutex_t lock; unsigned int held; unsigned int waiters; pthread_t tid; pthread_cond_t cv; }; void sh_RMutexLock(struct sh_RMutex * tok); void sh_RMutexUnlock(void * arg); void sh_InitRMutex(struct sh_RMutex * tok); #define SH_MUTEX_RECURSIVE(M) \ static struct sh_RMutex M; \ static void M ## _init (void) \ { \ sh_InitRMutex(&(M)); \ return; \ } \ static pthread_once_t M ## _initialized = PTHREAD_ONCE_INIT #define SH_MUTEX_RECURSIVE_INIT(M) \ (void) pthread_once(&(M ## _initialized), (M ## _init)) #define SH_MUTEX_RECURSIVE_LOCK(M) \ do { \ int oldtype; \ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); \ pthread_cleanup_push(sh_RMutexUnlock, (void*)&(M)); \ sh_RMutexLock(&(M)) #define SH_MUTEX_RECURSIVE_UNLOCK(M) \ pthread_cleanup_pop(1); \ pthread_setcanceltype(oldtype, NULL); \ } while (0) #endif /* * ---- Global mutexes ---- */ SH_MUTEX_EXTERN(mutex_skey); SH_MUTEX_EXTERN(mutex_resolv); SH_MUTEX_EXTERN(mutex_pwent); SH_MUTEX_EXTERN(mutex_readdir); /* Prevent threads from logging while we are in suspend */ SH_MUTEX_EXTERN(mutex_thread_nolog); /* * ---- Initialize thread-specific conversion area ---- */ extern int sh_g_thread(void); /* * ---- Functions for threaded modules ---- */ int sh_pthread_create(void *(*start_routine)(void*), void *arg); int sh_pthread_cancel_all(void); void sh_threaded_module_reconf(void *arg); void * sh_threaded_module_run(void *arg); #else #define SH_SETSIGMASK(A, B, C) sh_pthread_setsigmask(A,B,C) int sh_pthread_setsigmask(int how, const void *set, void *oldset); #define PTHREAD_MUTEX_INITIALIZER NULL #define SH_MUTEX(M) void *SH_MUTEX_DUMMY_ ## M #define SH_MUTEX_INIT(M,I) extern void *SH_MUTEX_DUMMY_ ## M #define SH_MUTEX_STATIC(M,I) extern void *SH_MUTEX_DUMMY_ ## M #define SH_MUTEX_EXTERN(M) extern void *SH_MUTEX_DUMMY_ ## M #define SH_MUTEX_LOCK(M) ((void)0) #define SH_MUTEX_TRYLOCK(M) ((void)0) #define SH_MUTEX_UNLOCK(M) ((void)0) #define SH_MUTEX_TRYLOCK_UNLOCK(M) ((void)0) #define SH_MUTEX_LOCK_UNSAFE(M) ((void)0) #define SH_MUTEX_TRYLOCK_UNSAFE(M) (0) #define SH_MUTEX_UNLOCK_UNSAFE(M) ((void)0) #define SH_MUTEX_RECURSIVE(M) extern void *SH_MUTEX_DUMMY_ ## M #define SH_MUTEX_RECURSIVE_INIT(M) ((void)0) #define SH_MUTEX_RECURSIVE_LOCK(M) ((void)0) #define SH_MUTEX_RECURSIVE_UNLOCK(M) ((void)0) /* #ifdef HAVE_PTHREAD */ #endif /* #ifndef SH_PTHREAD_H */ #endif samhain-4.1.4/include/sh_error_min.h0000644000175000017500000000211512615253277014354 00000000000000#ifndef SH_ERROR_MIN_H #define SH_ERROR_MIN_H /* Level of severity */ typedef enum { SH_ERR_ALL = (1 << 0), /* debug */ SH_ERR_INFO = (1 << 1), /* info */ SH_ERR_NOTICE = (1 << 2), /* notice */ SH_ERR_WARN = (1 << 3), /* warning */ SH_ERR_STAMP = (1 << 4), /* mark */ SH_ERR_ERR = (1 << 5), /* error */ SH_ERR_SEVERE = (1 << 6), /* crit */ SH_ERR_FATAL = (1 << 7), /* alert */ SH_ERR_NOT = (1 << 8), SH_ERR_INET = (1 << 9), SH_ERR_MAX = (1 << 9) } ShErrLevel; /* this function should be called to report an error */ void sh_error_handle (int flag, const char * file, long line, long errnum, unsigned long msg_index, ...); /* this function should be called to (only) send mail */ void sh_error_mail (const char * alias, int sev, const char * file, long line, long status, unsigned long msg_id, ...); /* convert a string to a numeric priority */ int sh_error_convert_level (const char * str_s); /* error messages */ char * sh_error_message (int tellme, char * str, size_t len); #endif samhain-4.1.4/include/sh_mail.h0000644000175000017500000000434512615253277013311 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_MAIL_H #define SH_MAIL_H #define MAIL_IMMEDIATE 1 #define MAIL_LATER 0 /* set a relay server */ int sh_mail_set_relay (const char * str_s); /* send to all recpts. in one mail */ int sh_mail_setFlag (const char * str); /* set the subject string */ int set_mail_subject (const char * str); /* test mailbox */ int sh_mail_sigverify (const char * s); /* maximum number of mail attempts */ #define SH_MAX_FAIL 48 int sh_mail_setNum (const char * str); int sh_mail_setaddress (const char * address); void reset_count_dev_mail(void); int sh_mail_setaddress_int (const char * address); /* call if not urgent */ int sh_mail_pushstack (int severity, const char * msg, const char * alias); /* Set the port to use (default 25) */ int sh_mail_set_port (const char * str); /* set sender of mail */ int sh_mail_set_sender (const char *str); #endif samhain-4.1.4/include/sh_schedule.h0000644000175000017500000000126612615253277014162 00000000000000#ifndef SH_SCHEDULE_H #define SH_SCHEDULE_H /************************************************ * * Scheduler class - public definitions * ************************************************/ typedef struct sh_schedule_ { int max[5]; int min[5]; int step[5]; int min_step; time_t last_exec; int first; struct sh_schedule_ * next; } sh_schedule_t; /* This function parses a crontab-like schedule and fills a * sh_schedule_t structure provided by the caller. */ int create_sched (const char * ssched, sh_schedule_t * isched); /* This function returns 1 if the scheduled event should be executed, * else 0 */ int test_sched (sh_schedule_t * isched); #endif samhain-4.1.4/include/sh_unix.h0000644000175000017500000002642312615253277013353 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_UNIX_H #define SH_UNIX_H /* For PATH_MAX */ #include #if !defined(PATH_MAX) #define PATH_MAX 1024 #endif #include #include "samhain.h" #include "sh_error.h" typedef enum { SH_ISLOG, SH_ISFILE, SH_ISDIR, SH_ISDATA } ShOpenType; typedef enum { SH_DATA_RAW, SH_DATA_LINE } ShDataType; typedef enum { SH_FILE_REGULAR, SH_FILE_SYMLINK, SH_FILE_DIRECTORY, SH_FILE_CDEV, SH_FILE_BDEV, SH_FILE_FIFO, SH_FILE_SOCKET, SH_FILE_DOOR, SH_FILE_PORT, SH_FILE_UNKNOWN } ShFileType; /* -- Attributes to check. -- */ /* checksum */ #define MODI_CHK (1 << 0) /* link */ #define MODI_LNK (1 << 1) /* inode */ #define MODI_INO (1 << 2) /* user */ #define MODI_USR (1 << 3) /* group */ #define MODI_GRP (1 << 4) /* mtime */ #define MODI_MTM (1 << 5) /* ctime */ #define MODI_CTM (1 << 6) /* atime */ #define MODI_ATM (1 << 7) /* size */ #define MODI_SIZ (1 << 8) /* file mode */ #define MODI_MOD (1 << 9) /* hardlinks */ #define MODI_HLN (1 << 10) /* device type */ #define MODI_RDEV (1 << 11) /* size may grow */ #define MODI_SGROW (1 << 12) /* use prelink */ #define MODI_PREL (1 << 13) /* get content */ #define MODI_TXT ((1 << 14)|MODI_CHK) #define MODI_TXT_ENABLED(a) (((a)&(1 << 14))!=0) /* get audit record */ #define MODI_AUDIT (1 << 15) #define MODI_AUDIT_ENABLED(a) (((a)&(1 << 15))!=0) /* do not check */ #define MODI_NOCHECK (1 << 16) /* do not check */ #define MODI_ALLIGNORE (1 << 17) #define MODI_TIGER192 0x01000000UL #define MODI_SHA1 0x02000000UL #define MODI_MD5 0x03000000UL #define MODI_SHA256 0x04000000UL #define MODI_HASHTYPE 0x0F000000UL #define MODI_INIT 0xD0000000UL #define MODI_INITIALIZED(a) (((a) & 0xF0000000UL) == MODI_INIT) #define MODI_SET(a, b) ((a) |= (b)) #define MODI_CLEAR(a, b) ((a) &= ~(b)) #define MODI_ISSET(a, b) (((a) & (b)) != 0) #define SH_TXT_MAX 9200 #define MASK_ALLIGNORE_ 0 extern unsigned long mask_ALLIGNORE; #define MASK_ATTRIBUTES_ (MODI_MOD|MODI_USR|MODI_GRP|MODI_RDEV) extern unsigned long mask_ATTRIBUTES; #define MASK_LOGFILES_ (MASK_ATTRIBUTES_|MODI_HLN|MODI_LNK|MODI_INO) extern unsigned long mask_LOGFILES; #define MASK_LOGGROW_ (MASK_LOGFILES_|MODI_SIZ|MODI_SGROW|MODI_CHK) extern unsigned long mask_LOGGROW; #define MASK_READONLY_ (MASK_LOGFILES_|MODI_CHK|MODI_SIZ|MODI_MTM|MODI_CTM) extern unsigned long mask_READONLY; #define MASK_NOIGNORE_ (MASK_LOGFILES_|MODI_CHK|MODI_SIZ|MODI_ATM|MODI_MTM) extern unsigned long mask_NOIGNORE; #define MASK_USER_ (MASK_READONLY_|MODI_ATM) extern unsigned long mask_USER0; extern unsigned long mask_USER1; extern unsigned long mask_USER2; extern unsigned long mask_USER3; extern unsigned long mask_USER4; /* like READONLY, but without MTM,CTM,SIZ,INO, and with PREL) */ #define MASK_PRELINK_ (MASK_ATTRIBUTES_|MODI_HLN|MODI_LNK|MODI_CHK|MODI_PREL) extern unsigned long mask_PRELINK; typedef struct file_struct { unsigned long check_flags; int file_reported; char fullpath[PATH_MAX]; ShFileType type; dev_t dev; ino_t ino; mode_t mode; nlink_t hardlinks; #if defined(__linux__) || defined(HAVE_STAT_FLAGS) unsigned long attributes; char c_attributes[ATTRBUF_SIZE]; #endif char c_mode[CMODE_SIZE]; uid_t owner; char c_owner[USER_MAX+2]; gid_t group; char c_group[GROUP_MAX+2]; dev_t rdev; off_t size; unsigned long blksize; unsigned long blocks; time_t atime; time_t mtime; time_t ctime; char * link_path; mode_t linkmode; char link_c_mode[11]; int linkisok; char * attr_string; } file_type; extern int sh_unix_check_selinux; extern int sh_unix_check_acl; /* destroy userid cache */ void sh_userid_destroy (); /* --- run a command, securely --- */ int sh_unix_run_command (const char * str); /* Ignore SIGPIPE */ void sh_unix_ign_sigpipe(); /* mlock utilities */ int sh_unix_mlock(const char * file, int line, void * addr, size_t len); int sh_unix_munlock(void * addr, size_t len); int sh_unix_count_mlock(void); /* public for unit tests */ int sh_unix_pagesize(void); unsigned long sh_unix_lookup_page(void * in_addr, size_t len, int * num_pages); /* chroot directory */ int sh_unix_set_chroot(const char * str); /* whether to use localtime for file timesatams in logs */ int sh_unix_uselocaltime (const char * c); /* whether to perform selinux/acl checks */ #ifdef USE_XATTR int sh_unix_setcheckselinux (const char * c); #endif #ifdef USE_ACL int sh_unix_setcheckacl (const char * c); #endif /* set I/O limit */ int sh_unix_set_io_limit (const char * c); void sh_unix_io_pause (void); /* get file type */ int sh_unix_get_ftype(char * fullpath); /* reset masks for policies */ int sh_unix_maskreset(void); /* return true if database is remote */ int file_is_remote (void); /* return the path to the configuration/database file */ char * file_path(char what, char flag); /* return current time as unsigned long */ unsigned long sh_unix_longtime (void); /* close all files >= fd, except possibly one */ void sh_unix_closeall (int fd, int except, int inchild); /* Check whether directory for pid file exists */ int sh_unix_check_piddir (char * pidpath); /* write lock for filename */ int sh_unix_write_lock_file(char * filename); /* rm lock(s) for log file(s) */ int sh_unix_rm_lock_file(char * filename); /* write the PID file */ int sh_unix_write_pid_file(void); /* rm the PID file */ int sh_unix_rm_pid_file(void); /* checksum of own binary */ int sh_unix_self_hash (const char * c); /* return BAD on failure */ int sh_unix_self_check (void); /* add a trusted user to the list */ int tf_add_trusted_user(const char *); /* check a file */ int tf_trust_check (const char * file, int mode); /* initialize group vector */ #ifdef HOST_IS_OSF int sh_unix_initgroups ( char * in_user, gid_t in_gid); #else int sh_unix_initgroups (const char * in_user, gid_t in_gid); #endif int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid); /* set the timeserver address */ int sh_unix_settimeserver (const char * address); void reset_count_dev_time(void); /* lock the key */ void sh_unix_memlock(void); /* deamon mode */ int sh_unix_setdeamon (const char * dummy); int sh_unix_setnodeamon(const char * dummy); /* Test whether file exists */ int sh_unix_file_exists(char * path); /* test whether file exists with proper attributes */ int sh_unix_device_readable(int fd); /* local host */ void sh_unix_localhost(void); /* check whether /proc exists and is a proc filesystem */ int sh_unix_test_proc(void); /* check whether a directory is secure * (no symlink in path, not world-writeable) */ /* int sh_unix_is_secure_dir (ShErrLevel level, char * tmp); */ /* check whether there's a rotated log with the correct inode and checksum */ int sh_check_rotated_log (const char * path, UINT64 old_size, UINT64 old_inode, const char * old_hash, unsigned long mask); /* obtain file info */ int sh_unix_getinfo (int level, const char * filename, file_type * theFile, char * fileHash, int flagrel); /* read file, return length read */ int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline); /* call with goDaemon == 1 to make daemon process */ int sh_unix_init(int goDaemon); /* for local time use thetime = 0, returns pointer to buffer */ char * sh_unix_time (time_t thetime, char * buffer, size_t len); /* convert to GMT time, returns pointer to buffer */ char * sh_unix_gmttime (time_t thetime, char * buffer, size_t len); /* effective user info */ int sh_unix_getUser (void); /* get home directory, , returns pointer to out */ char * sh_unix_getUIDdir (int level, uid_t uid, char * out, size_t len); /* get a group GID */ long sh_group_to_gid (const char * g, int * fail); #ifdef HAVE_GETTIMEOFDAY unsigned long sh_unix_notime (void); #endif /* check whether a directory */ int sh_unix_isdir (char * dirName, int level); #ifdef SH_STEALTH int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len); void sh_unix_xor_code (char * str, int len); #endif #if defined(SCREW_IT_UP) /* for raise() */ #include #include void sh_sigtrap_handler (int signum); #ifdef HAVE_GETTIMEOFDAY #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #endif struct sh_sigtrap_variables { int not_traced; #ifdef HAVE_GETTIMEOFDAY struct timeval save_tv; #endif }; struct sh_sigtrap_variables * sh_sigtrap_variables_get(); int sh_sigtrap_max_duration_set (const char * str); static inline int sh_sigtrap_prepare() { struct sigaction act_trap; int val_retry; act_trap.sa_handler = &sh_sigtrap_handler; /* signal action */ act_trap.sa_flags = 0; /* init sa_flags */ sigemptyset ( &act_trap.sa_mask ); /* set an empty mask */ do { val_retry = sigaction(SIGTRAP, &act_trap, NULL); } while (val_retry < 0 && errno == EINTR); return 0; } /*@unused@*/ static inline int sh_derr(void) { struct sh_sigtrap_variables * sigtrap_variables; sigtrap_variables = sh_sigtrap_variables_get(); if (sigtrap_variables == NULL) { /* Perhaps, its better to not die, and to continue using Samhain, even if this part does not work. */ return (0); } sigtrap_variables->not_traced = 0; #ifdef HAVE_GETTIMEOFDAY gettimeofday(&sigtrap_variables->save_tv, NULL); #endif /* raise() sends to same thread, like pthread_kill(pthread_self(), sig); */ raise(SIGTRAP); if (sigtrap_variables->not_traced == 0) _exit(5); sigtrap_variables->not_traced = 0; return (0); } #else /*@unused@*/ static inline int sh_derr(void) { return 0; } /* #if defined(SCREW_IT_UP) */ #endif #endif samhain-4.1.4/include/sh_string.h0000644000175000017500000000742312615253277013675 00000000000000#ifndef SH_STRING_H #define SH_STRING_H #include /* String definition and utility functions. */ typedef struct sh_str_struct { char * str; /* always NULL terminated */ size_t len; /* without terminating \0 */ size_t siz; /* size of allocated buffer */ } sh_string; sh_string * sh_string_new(size_t size); void sh_string_destroy(sh_string ** s); #define sh_string_str(a) ((a)->str) #define sh_string_len(a) ((a)->len) /* concat string to sh_string */ sh_string * sh_string_cat_lchar(sh_string * s, const char * str, size_t len); /* add char array to end of string */ sh_string * sh_string_add_from_char(sh_string * s, const char * str); /* set sh_string from string */ sh_string * sh_string_set_from_char(sh_string * s, const char * str); /* create new sh_string from array of given length */ sh_string * sh_string_new_from_lchar(const char * str, size_t len); #define sh_string_copy(a) ((a) ? sh_string_new_from_lchar(((a)->str), ((a)->len)) : NULL) #define sh_string_add(a,b) ((a && b) ? sh_string_cat_lchar((a), ((b)->str), ((b)->len)) : NULL) /* create new sh_string from three arrays of given length */ sh_string * sh_string_new_from_lchar3(const char * str1, size_t len1, const char * str2, size_t len2, const char * str3, size_t len3); /* Truncate to desired length. */ sh_string * sh_string_truncate(sh_string * s, size_t len); /* If requested increase is zero, increase by default amount. */ sh_string * sh_string_grow(sh_string * s, size_t increase); /* Read a string from a file, with maxlen. Return 0 on EOF, * -1 on error, and -2 if a line exceeds maxlen. */ size_t sh_string_read(sh_string * s, FILE * fp, size_t maxlen); /* Read a string from a file, with maxlen. Return 0 on EOF, * -1 on error, and -2 if a line exceeds maxlen. * If 'cont' != NULL, continuation lines starting with a char * in 'cont' are concatenated. */ size_t sh_string_read_cont(sh_string * s, FILE * fp, size_t maxlen, char *cont); /* Split array at delim in at most nfields fields. * Empty fields are returned as empty (zero-length) strings. * Leading and trailing WS are removed from token. * The number of fields is returned in 'nfields', their * lengths in 'lengths'. * A single delimiter will return two empty fields. */ char ** split_array(char *line, unsigned int * nfields, char delim, size_t * lengths); /* Split array at whitespace in at most nfields fields. * Multiple whitespaces are collapsed. * Empty fields are returned as empty (zero-length) strings. * The number of fields is returned in nfields. * An empty string will return zero fields. * If nfields < actual fields, last string will be remainder. */ char ** split_array_ws(char *line, unsigned int * nfields, size_t * lengths); /* Same as above, but split on [space, tab, comma] */ char ** split_array_list(char *line, unsigned int * nfields, size_t * lengths); /* Same as above, but split on delimiter list (token) */ char ** split_array_token (char *line, unsigned int * nfields, size_t * lengths, const char * token); /* Return a split_array_list() of a list contained in 'PREFIX\s*( list ).*' */ char ** split_array_braced (char *line, const char * prefix, unsigned int * nfields, size_t * lengths); /* Replaces fields in s with 'replacement'. Fields are given * in the ordered array ovector, comprising ovecnum pairs * ovector[i], ovector[i+1] which list offset of first char * of field, offset of first char after field (this is how * the pcre library does it). */ sh_string * sh_string_replace(const sh_string * s, const int * ovector, int ovecnum, const char * replacement, size_t rlen); #endif samhain-4.1.4/include/CuTest.h0000644000175000017500000001136712615253277013106 00000000000000/******************* LICENSE Copyright (c) 2003 Asim Jalis This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. **********************/ #ifndef CU_TEST_H #define CU_TEST_H #include #include /* CuString */ char* CuStrAlloc(int size); char* CuStrCopy(const char* old); #define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) #define HUGE_STRING_LEN 8192 #define STRING_MAX 256 #define STRING_INC 256 typedef struct { int length; int size; char* buffer; } CuString; void CuStringInit(CuString* str); CuString* CuStringNew(void); void CuStringRead(CuString* str, const char* path); void CuStringAppend(CuString* str, const char* text); void CuStringAppendChar(CuString* str, char ch); void CuStringAppendFormat(CuString* str, const char* format, ...); void CuStringInsert(CuString* str, const char* text, int pos); void CuStringResize(CuString* str, int newSize); /* CuTest */ typedef struct CuTest CuTest; typedef void (*TestFunction)(CuTest *); struct CuTest { const char* name; TestFunction function; int failed; int ran; const char* message; jmp_buf *jumpBuf; }; void CuTestInit(CuTest* t, const char* name, TestFunction function); CuTest* CuTestNew(const char* name, TestFunction function); void CuTestRun(CuTest* tc); /* Internal versions of assert functions -- use the public versions */ void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual); void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual); void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta); void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual); /* public assert functions */ #define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) #define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) #define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) #define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) #define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) #define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) #define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) /* CuSuite */ #define MAX_TEST_CASES 1024 #define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) typedef struct { int count; CuTest* list[MAX_TEST_CASES]; int failCount; } CuSuite; void CuSuiteInit(CuSuite* testSuite); CuSuite* CuSuiteNew(void); void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); void CuSuiteRun(CuSuite* testSuite); void CuSuiteSummary(CuSuite* testSuite, CuString* summary); void CuSuiteDetails(CuSuite* testSuite, CuString* details); #endif /* CU_TEST_H */ samhain-4.1.4/include/sh_suidchk.h0000644000175000017500000000206412615253277014015 00000000000000 #ifndef SH_SUIDCHK_H #define SH_SUIDCHK_H #include "sh_modules.h" #ifdef SH_USE_SUIDCHK int sh_suidchk_init (struct mod_type * arg); int sh_suidchk_timer (time_t tcurrent); int sh_suidchk_check (void); int sh_suidchk_end (void); int sh_suidchk_reconf (void); int sh_suidchk_set_activate (const char * c); int sh_suidchk_set_severity (const char * c); int sh_suidchk_set_timer (const char * c); int sh_suidchk_set_schedule (const char * c); int sh_suidchk_set_exclude (const char * c); int sh_suidchk_set_fps (const char * c); int sh_suidchk_set_yield (const char * c); int sh_suidchk_set_nosuid (const char * c); int sh_suidchk_set_quarantine (const char * c); int sh_suidchk_set_qmethod (const char * c); int sh_suidchk_set_qdelete (const char * c); extern sh_rconf sh_suidchk_table[]; /* Quarantine Methods */ typedef enum { SH_Q_DELETE = 0, /* delete */ SH_Q_CHANGEPERM = 1, /* remove suid/sgid permissions */ SH_Q_MOVE = 2 /* move */ } ShQuarantineMethod; #endif /* #ifndef SH_SUIDCHK_H */ #endif samhain-4.1.4/include/sh_dbCheck.h0000664000175000017500000000273712615253277013717 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_DBCHECK_H #define SH_DBCHECK_H int sh_dbCheck_verify (const char * db_file); #endif samhain-4.1.4/include/sh_registry.h0000644000175000017500000000041712615253277014233 00000000000000 #ifndef SH_REGISTRY_H #define SH_REGISTRY_H int sh_reg_check_init(struct mod_type * arg); int sh_reg_check_timer(time_t tcurrent); int sh_reg_check_run(void); int sh_reg_check_reconf(void); int sh_reg_check_cleanup(void); extern sh_rconf sh_reg_check_table[]; #endif samhain-4.1.4/include/sh_ks_xor.h0000644000175000017500000000025112615253277013664 00000000000000#ifndef SH_KERN_CALLS_H #define SH_KERN_CALLS_H /* Dummy header. */ typedef struct _sh_syscall_t { unsigned long addr; char * name; } sh_syscall_t; #endif samhain-4.1.4/include/sh_readconf.h0000644000175000017500000000311212615253277014137 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_READCONFIG_H #define SH_READCONFIG_H /* set the config file */ int sh_readconf_setcfgfile (char * filename); /* read the configuration file */ int sh_readconf_read (void); #endif samhain-4.1.4/include/sh_modules.h0000644000175000017500000000266012622126376014032 00000000000000 #ifndef SH_MODULE_H #define SH_MODULE_H #include "sh_pthread.h" enum { SH_MODFL_NOTIMER = (1 << 0), SH_MODFL_NEEDPAUSED = (1 << 1), SH_MODFL_ISPAUSED = (1 << 2) }; typedef struct rconf { char * the_opt; int (*func)(const char * opt); } sh_rconf; typedef struct mod_type { /* The name of the module */ char * name; /* Set by samhain to 1 on successful initialization, else 0 */ int initval; /* Flags: SH_MOD_NOTIMER */ int flags; /* The initialization function. Return 0 on success. */ int (* mod_init) (struct mod_type * arg); /* The timer function. Return 0 if NOT time to check. */ int (* mod_timer) (time_t tcurrent); /* The check function. Return 0 on success. */ /* Return nonzero on fatal error or if module is disabled. */ int (* mod_check) (void); /* The cleanup function. Return 0 on success. */ int (* mod_cleanup) (void); /* The preparation for reconfiguration. Return 0 on success. */ int (* mod_reconf) (void); /* Section header in config file */ char * conf_section; /* A table of key/handler_function for config file entries */ sh_rconf * conf_table; SH_MUTEX(mod_mutex); } sh_mtype; extern sh_mtype modList[]; /* #ifndef SH_MODULE_H */ #endif samhain-4.1.4/include/sh_error.h0000644000175000017500000001250612615253277013516 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Public interface for error routines */ #ifndef SH_ERROR_H #define SH_ERROR_H #include "sh_error_min.h" enum { SH_ERR_T_START = 0, /* 1-13 = SH_LEVEL_XXX */ SH_ERR_T_RO = SH_LEVEL_READONLY, SH_ERR_T_LOGS = SH_LEVEL_LOGFILES, SH_ERR_T_GLOG = SH_LEVEL_LOGGROW, SH_ERR_T_NOIG = SH_LEVEL_NOIGNORE, SH_ERR_T_ALLIG = SH_LEVEL_ALLIGNORE, SH_ERR_T_ATTR = SH_LEVEL_ATTRIBUTES, SH_ERR_T_USER0 = SH_LEVEL_USER0, SH_ERR_T_USER1 = SH_LEVEL_USER1, SH_ERR_T_USER2 = SH_LEVEL_USER2, SH_ERR_T_USER3 = SH_LEVEL_USER3, SH_ERR_T_USER4 = SH_LEVEL_USER4, SH_ERR_T_PRELINK = SH_LEVEL_PRELINK, SH_ERR_T_DIR = 13, SH_ERR_T_FILE = 14, SH_ERR_T_NAME = 15, SH_ERR_T_END = 16 }; typedef struct _errFlags { int debug; int HaveLog; int loglevel; int loglevel_temp; int printlevel; int maillevel; int exportlevel; int sysloglevel; int externallevel; int databaselevel; int log_class; int print_class; int mail_class; int export_class; int syslog_class; int external_class; int database_class; /* HAVE_LIBPRELUDE */ int preludelevel; int prelude_class; } blurb_errFlags; extern int ShDFLevel[SH_ERR_T_END]; /* set mask for message class */ int sh_error_log_mask (const char * c); int sh_error_print_mask (const char * c); int sh_error_mail_mask (const char * c); int sh_error_export_mask (const char * c); int sh_error_syslog_mask (const char * c); int sh_error_external_mask (const char * c); int sh_error_database_mask (const char * c); int sh_error_prelude_mask (const char * c); int sh_error_verify (const char * s); int sh_error_logverify_mod (const char * s); /* just list, don't verify */ int sh_error_logverify (const char * s); void sh_error_dbg_switch(void); #ifdef SH_WITH_SERVER void sh_error_set_peer(const char * str); #ifdef HAVE_LIBPRELUDE void sh_error_set_peer_ip(const char * str); #endif int set_flag_sep_log (const char * str); #endif /* init or re-init log facilities that need it */ void sh_error_fixup(void); /* only to stderr (GOOD/BAD) */ void sh_error_only_stderr (int flag); /* facilities unsafe for closeall() */ void sh_error_enable_unsafe (int flag); /* set syslog facility */ int sh_log_set_facility (const char * c); /* map heartbeat messages */ int sh_log_set_stamp_priority (const char * c); /* define message header */ int sh_error_ehead (/*@null@*/const char * s); /* set level for error logging */ int sh_error_setlog(const char * str_s); /* set severity levels */ int sh_error_set_iv (int iv, const char * severity_s); /* set priorities */ int sh_error_set_level(const char * str_s, int *facility); /* set level for TCP export */ int sh_error_setexport(const char * str_s); /* set level for syslog */ int sh_error_set_syslog (const char * flag_s); /* set level for printing */ int sh_error_setprint(const char * flag_s); /* set severity for external */ int sh_error_set_external (const char * str_s); /* set severity for external */ int sh_error_set_database (const char * str_s); /* set severity for external */ int sh_error_set_prelude (const char * str_s); /* set level for mailing */ int sh_error_setseverity (const char * flag); /* set debug level */ int sh_error_setdebug (char * debug_s); /* switch on/off log to file temporarily */ void sh_error_logoff(void); void sh_error_logrestore(void); /* short errfile */ void sh_efile_report(); int sh_efile_path(const char * str); int sh_efile_group(const char * str); /* (re)set the console device(s) */ int sh_log_set_console (const char * address); void reset_count_dev_console(void); /* close the message queue [no-op if !defined(WITH_MESSAGE_QUEUE)] */ void close_ipc (void); #ifdef WITH_MESSAGE_QUEUE /* enable message queue */ int enable_msgq(const char * foo); #endif #endif samhain-4.1.4/include/sh_guid.h0000664000175000017500000000311212615253277013310 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_GUID_H #define SH_GUID_H #define SH_UUID_BUF 37 char * sh_uuid_generate_random(char * out, size_t len); /* return 0 if it looks like a uuid */ int sh_uuid_check(const char * in); #endif samhain-4.1.4/include/sh_sub.h0000644000175000017500000000025612615253277013155 00000000000000#ifndef SH_SUB_H #define SH_SUB_H void sh_kill_sub (); int sh_sub_stat (const char *path, struct stat *buf); int sh_sub_lstat (const char *path, struct stat *buf); #endif samhain-4.1.4/include/sh_extern.h0000644000175000017500000000564012615253277013673 00000000000000#ifndef SH_EXTERN_H #define SH_EXTERN_H #include typedef struct { char * command; int argc; char * argv[32]; int envc; char * envv[32]; char checksum[KEY_LEN + 1]; #if 0 uid_t trusted_users[32]; #endif uid_t run_user_uid; gid_t run_user_gid; int privileged; int pipeFD; SL_TICKET pipeTI; pid_t pid; FILE * pipe; char rw; int exit_status; int fork_twice; int com_fd; SL_TICKET com_ti; } sh_tas_t; /* * -- generic safe popen; returns 0 on success, -1 otherwise */ int sh_ext_popen (sh_tas_t * task); /* * -- generic simple safe popen; returns 0 on success, -1 otherwise, * executes shell command */ int sh_ext_popen_init (sh_tas_t * task, const char * command, char * argv0, ...) SH_GNUC_SENTINEL; /* * -- Execute command, return first line of output */ int sh_ext_system (char * command, char * argv0, ...) SH_GNUC_SENTINEL; /* * -- Execute command, return first line of output */ char * sh_ext_popen_str (const char * command); /* * -- close the pipe, clear and return task->exit_status */ int sh_ext_pclose (sh_tas_t * task); /* * -- add CL argument, return # of arguments */ int sh_ext_tas_add_argv(sh_tas_t * tas, const char * val); /* * -- remove last CL argument */ int sh_ext_tas_rm_argv(sh_tas_t * tas); /* * -- add environment variable, return # of variables */ int sh_ext_tas_add_envv(sh_tas_t * tas, const char * key, const char * val); /* * -- set command */ void sh_ext_tas_command(sh_tas_t * tas, const char * command); /* * -- initialize task structure */ void sh_ext_tas_init (sh_tas_t * tas); /* * -- free task structure */ void sh_ext_tas_free(sh_tas_t * tas); #if defined(WITH_EXTERNAL) /* * -- start a new external command, and add it to the list */ int sh_ext_setcommand(const char * cmd); /* * -- explicitely close a command */ int sh_ext_close_command (const char * str); /* * -- clean up the command list */ int sh_ext_cleanup(void); /* * -- set deadtime */ int sh_ext_deadtime (const char * str); /* * -- add keywords to the OR filter */ int sh_ext_add_or (const char * str); /* * -- add keywords to the AND filter */ int sh_ext_add_and (const char * str); /* * -- add keywords to the NOT filter */ int sh_ext_add_not (const char * str); /* * -- add keywords to the CL argument list */ int sh_ext_add_argv (const char * str); /* * -- add a path to the environment */ int sh_ext_add_default (const char * str); /* * -- add an environment variable */ int sh_ext_add_environ (const char * str); /* * -- define type */ int sh_ext_type (const char * str); /* * -- define checksum */ int sh_ext_checksum (const char * str); /* * -- choose privileges */ int sh_ext_priv (const char * c); /* * -- execute external script/program */ int sh_ext_execute (char t1, char t2, char t3, /*@null@*/char * message, size_t msg_siz); #endif #endif samhain-4.1.4/include/zAVLTree.h0000644000175000017500000000506512615253277013331 00000000000000/* * zAVLTree.h: Header file for zAVLTrees. * Copyright (C) 1998,2001 Michael H. Buselli * This is version 0.1.3 (alpha). * Generated from $Id: xAVLTree.h.sh,v 1.5 2001/06/07 06:58:28 cosine Exp $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The author of this library can be reached at the following address: * Michael H. Buselli * 30051 N. Waukegan Rd. Apt. 103 * Lake Bluff, IL 60044-5412 * * Or you can send email to . * The official web page for this product is: * http://www.cosine.org/project/AVLTree/ */ #ifndef _ZAVLTREE_H_ #define _ZAVLTREE_H_ /* typedef the keytype */ typedef const void * zAVLKey; /* Comparison function for strings is strcmp(). */ /* #define zAVLKey_cmp(tree, a, b) (strcmp((a), (b))) */ #define zAVL_KEY_STRING 0 #define zAVL_KEY_INT 1 typedef struct _zAVLNode { zAVLKey key; long depth; void *item; struct _zAVLNode *parent; struct _zAVLNode *left; struct _zAVLNode *right; } zAVLNode; typedef struct { zAVLNode *top; long count; zAVLKey (*getkey)(const void *item); int keytype; } zAVLTree; typedef struct { const zAVLTree *avltree; const zAVLNode *curnode; } zAVLCursor; extern zAVLTree *zAVLAllocTree (zAVLKey (*getkey)(void const *item), int keytype); extern void zAVLFreeTree (zAVLTree *avltree, void (freeitem)(void *item)); extern int zAVLInsert (zAVLTree *avltree, void *item); extern void *zAVLSearch (zAVLTree const *avltree, zAVLKey key); extern int zAVLDelete (zAVLTree *avltree, zAVLKey key); extern void *zAVLFirst (zAVLCursor *avlcursor, zAVLTree const *avltree); extern void *zAVLNext (zAVLCursor *avlcursor); extern char * zAVL_string_get (zAVLTree * tree, const char * key); /* uses strdup to insert a copy */ extern int zAVL_string_set (zAVLTree ** tree, const char * key); extern void zAVL_string_reset (zAVLTree * tree); extern void zAVL_string_del (zAVLTree * tree, const char * key); #endif samhain-4.1.4/include/sh_log_repeat.h0000644000175000017500000000045612615253277014507 00000000000000#ifndef SH_LOG_REPEAT_H #define SH_LOG_REPEAT_H int sh_repeat_set_trigger (const char * str); int sh_repeat_set_queue (const char * str); int sh_repeat_set_cron (const char * str); int sh_repeat_message_check (const sh_string * host, const sh_string * msg, time_t ltime); #endif samhain-4.1.4/include/sh_prelude.h0000644000175000017500000000100512615253277014015 00000000000000#ifndef SH_PRELUDE_H #define SH_PRELUDE_H void sh_prelude_reset(void); void sh_prelude_stop(void); int sh_prelude_init(void); int sh_prelude_set_profile(const char *arg); int sh_prelude_alert (int priority, int class, char * message, long msgflags, unsigned long msgid, char * inet_peer_ip); /* map severity levels */ int sh_prelude_map_info (const char * str); int sh_prelude_map_low (const char * str); int sh_prelude_map_medium (const char * str); int sh_prelude_map_high (const char * str); #endif samhain-4.1.4/include/minilzo.h0000644000175000017500000000560712615253277013360 00000000000000/* minilzo.h -- mini subset of the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer The LZO library 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. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html */ /* * NOTE: * the full LZO package can be found at * http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html */ #ifndef __MINILZO_H #define __MINILZO_H #define MINILZO_VERSION 0x1060 #ifdef __LZOCONF_H # error "you cannot use both LZO and miniLZO" #endif #undef LZO_HAVE_CONFIG_H #include "lzoconf.h" #if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) # error "version mismatch in header files" #endif #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // ************************************************************************/ /* Memory required for the wrkmem parameter. * When the required size is 0, you can also pass a NULL pointer. */ #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS #define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) #define LZO1X_MEM_DECOMPRESS (0) /* compression */ LZO_EXTERN(int) lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem ); /* decompression */ LZO_EXTERN(int) lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem /* NOT USED */ ); /* safe decompression with overrun testing */ LZO_EXTERN(int) lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, lzo_byte *dst, lzo_uint *dst_len, lzo_voidp wrkmem /* NOT USED */ ); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* already included */ samhain-4.1.4/include/sh_MK.h0000644000175000017500000000067712615253277012702 00000000000000#ifndef SH_MK_H #define SH_MK_H #define MKB_16 1 #define MKB_14 1 #define MKB_13 1 #define MKB_12 1 #define MKB_11 1 #define MKB_10 1 #define MKB_09 1 #define MKB_08 1 #define MKB_06 1 #define MKB_05 1 #define MKB_04 1 #define MKB_03 1 #define MKA_08 1 #define MKA_02 1 #define MKA_01 1 #define MKC_16 1 #define MKC_15 1 #define MKC_08 1 #define MKC_06 1 #define MKC_05 1 #define MKC_01 1 #define MKD_15 1 #define MKD_07 1 #define MKD_06 1 #endif samhain-4.1.4/include/samhain.h0000644000175000017500000003674612615253277013327 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SAMHAIN_H #define SAMHAIN_H #include #include "slib.h" #ifdef SH_ENCRYPT #include "rijndael-api-fst.h" #endif #if defined(__GNUC__) && (__GNUC__ >= 4) #define SH_GNUC_SENTINEL __attribute__((__sentinel__)) #else #define SH_GNUC_SENTINEL #endif #if defined(__GNUC__) && (__GNUC__ >= 3) #undef SH_GNUC_PURE #define SH_GNUC_PURE __attribute__((pure)) #undef SH_GNUC_CONST #define SH_GNUC_CONST __attribute__((const)) #undef SH_GNUC_NORETURN #define SH_GNUC_NORETURN __attribute__((noreturn)) #undef SH_GNUC_MALLOC #define SH_GNUC_MALLOC __attribute__((malloc)) #else #undef SH_GNUC_PURE #define SH_GNUC_PURE #undef SH_GNUC_CONST #define SH_GNUC_CONST #undef SH_GNUC_NORETURN #define SH_GNUC_NORETURN #undef SH_GNUC_MALLOC #define SH_GNUC_MALLOC #endif /************************************************** * * STANDARD DEFINES * **************************************************/ /* IPv6 */ #if defined(HAVE_GETNAMEINFO) && defined(HAVE_GETADDRINFO) #if defined(SH_COMPILE_STATIC) && defined(__linux__) #undef USE_IPVX #define SH_SOCKMAX 1 #else #if defined(USE_IPV4) #undef USE_IPVX #else #define USE_IPVX 1 #endif #define SH_SOCKMAX 8 #endif #else #undef USE_IPVX #define SH_SOCKMAX 1 #endif /* end IPv6 */ /* Standard buffer sizes. * IPv6 is 8 groups of 4 hex digits seperated by colons. */ #define SH_IP_BUF 48 #define SH_MINIBUF 64 #define SH_BUFSIZE 1024 #define SH_MAXBUF 4096 #define SH_PATHBUF 256 #define SH_MSG_BUF 64512 #define SH_ERRBUF_SIZE 64 /* MAX_PATH_STORE must be >= KEY_LEN */ #define MAX_PATH_STORE 12287 /* Sizes for arrays (user, group, timestamp). */ #define SOCKPASS_MAX 14 #define USER_MAX 20 #define GROUP_MAX 20 #define TIM_MAX 32 #define CMODE_SIZE 11 #define ATTRBUF_SIZE 16 #define ATTRBUF_USED 12 /* The number of bytes in a key, * the number of chars in its hex repesentation, * and the block size of the hash algorithm. */ #define KEY_BYT 24 #define KEY_LEN 48 #define KEY_BLOCK 24 #define KEYBUF_SIZE (KEY_LEN+1) /* The length of the compiled-in password. */ #define PW_LEN 8 #undef S_TRUE #define S_TRUE 1 #undef S_FALSE #define S_FALSE 0 #undef GOOD #define GOOD S_TRUE #undef BAD #define BAD S_FALSE #define SH_SILENT_FULL 2 #define SH_SILENT_STD 1 #ifdef HAVE_INTTYPES_H #include #endif #ifdef HAVE_STDINT_H #include #endif #if !defined(HAVE_UINT16_T) #define UINT16 unsigned short #else #define UINT16 uint16_t #endif #if !defined(HAVE_UINT32_T) /* An unsigned integer guaranteed to be 32 bit. */ #if defined(HAVE_INT_32) #define UINT32 unsigned int #define SINT32 int #elif defined(HAVE_LONG_32) #define UINT32 unsigned long #define SINT32 long #elif defined(HAVE_SHORT_32) #define UINT32 unsigned short #define SINT32 short #else #error "No 32 bit integer type found" #endif #else #define UINT32 uint32_t #define SINT32 int32_t #endif #if !defined(HAVE_UINT64_T) #ifdef HAVE_LONG_LONG_64 #define UINT64 unsigned long long #else #ifdef HAVE_LONG_64 #define UINT64 unsigned long #else #error "no 64bit type found" #endif #endif #else #define UINT64 uint64_t #endif #define UBYTE unsigned char enum { SH_TIGER192 = 0, SH_SHA1 = 1, SH_MD5 = 2, SH_SHA256 = 3 }; enum { SH_CHECK_NONE = 0, SH_CHECK_INIT = 1, SH_CHECK_CHECK = 2 }; #define SH_MOD_THREAD 1 #define SH_MOD_ACTIVE 0 #define SH_MOD_FAILED -1 #define SH_MOD_OFFSET 10 /* Flags for file status */ #define SH_FFLAG_ALLIGNORE (1<<0) #define SH_FFLAG_VISITED (1<<1) #define SH_FFLAG_CHECKED (1<<3) #define SH_FFLAG_REPORTED (1<<3) #define SH_FFLAG_SUIDCHK (1<<4) #define SH_FFLAG_ENOENT (1<<5) #define SH_FFLAG_ALLIGNORE_SET(a) (((a) & SH_FFLAG_ALLIGNORE) != 0) #define SET_SH_FFLAG_ALLIGNORE(a) ((a) |= SH_FFLAG_ALLIGNORE) #define CLEAR_SH_FFLAG_ALLIGNORE(a) ((a) &= ~SH_FFLAG_ALLIGNORE) #define SH_FFLAG_VISITED_SET(a) (((a) & SH_FFLAG_VISITED) != 0) #define SET_SH_FFLAG_VISITED(a) ((a) |= SH_FFLAG_VISITED) #define CLEAR_SH_FFLAG_VISITED(a) ((a) &= ~SH_FFLAG_VISITED) #define SH_FFLAG_CHECKED_SET(a) (((a) & SH_FFLAG_VISITED) != 0) #define SET_SH_FFLAG_CHECKED(a) ((a) |= SH_FFLAG_VISITED) #define CLEAR_SH_FFLAG_CHECKED(a) ((a) &= ~SH_FFLAG_VISITED) #define SH_FFLAG_REPORTED_SET(a) (((a) & SH_FFLAG_REPORTED) != 0) #define SET_SH_FFLAG_REPORTED(a) ((a) |= SH_FFLAG_REPORTED) #define CLEAR_SH_FFLAG_REPORTED(a) ((a) &= ~SH_FFLAG_REPORTED) #define SH_FFLAG_SUIDCHK_SET(a) (((a) & SH_FFLAG_SUIDCHK) != 0) #define SET_SH_FFLAG_SUIDCHK(a) ((a) |= SH_FFLAG_SUIDCHK) #define CLEAR_SH_FFLAG_SUIDCHK(a) ((a) &= ~SH_FFLAG_SUIDCHK) #define SH_FFLAG_ENOENT_SET(a) (((a) & SH_FFLAG_ENOENT) != 0) #define SET_SH_FFLAG_ENOENT(a) ((a) |= SH_FFLAG_ENOENT) #define CLEAR_SH_FFLAG_ENOENT(a) ((a) &= ~SH_FFLAG_ENOENT) /* Flags for inotify */ #define SH_INOTIFY_USE (1<<0) #define SH_INOTIFY_DOSCAN (1<<1) #define SH_INOTIFY_NEEDINIT (1<<2) #define SH_INOTIFY_INSCAN (1<<3) #define SH_INOTIFY_IFUSED(a) if ((sh.flag.inotify & SH_INOTIFY_USE) != 0) { a } /************************************************** * * TYPEDEFS * **************************************************/ enum { SH_LEVEL_READONLY = 1, SH_LEVEL_LOGFILES = 2, SH_LEVEL_LOGGROW = 3, SH_LEVEL_NOIGNORE = 4, SH_LEVEL_ALLIGNORE = 5, SH_LEVEL_ATTRIBUTES = 6, SH_LEVEL_USER0 = 7, SH_LEVEL_USER1 = 8, SH_LEVEL_USER2 = 9, SH_LEVEL_USER3 = 10, SH_LEVEL_USER4 = 11, SH_LEVEL_PRELINK = 12 }; typedef struct { time_t alarm_interval; time_t alarm_last; } sh_timer_t; typedef struct { char path[SH_PATHBUF]; char hash[KEY_LEN+1]; } sh_sh_df; typedef struct { char user[USER_MAX]; char group[GROUP_MAX]; char home[SH_PATHBUF]; uid_t uid; gid_t gid; } sh_sh_user; typedef struct { char name[SH_PATHBUF]; /* local hostname */ char system[SH_MINIBUF]; /* system */ char release[SH_MINIBUF]; /* release */ char machine[SH_MINIBUF]; /* machine */ } sh_sh_local; typedef struct { char name[SH_PATHBUF]; char alt[SH_PATHBUF]; } sh_sh_remote; typedef struct { unsigned long bytes_hashed; /* bytes last check */ unsigned long bytes_speed; /* bytes/sec last check */ unsigned long mail_success; /* mails sent */ unsigned long mail_failed; /* mails not sent */ time_t time_start; /* start last check */ time_t time_check; /* time last check */ unsigned long dirs_checked; /* #dirs last check */ unsigned long files_checked; /* #files last check */ unsigned long files_report; /* #file reports */ unsigned long files_error; /* #file access error */ unsigned long files_nodir; /* #file not a directory*/ } sh_sh_stat; typedef struct { int exit; /* exit value */ int checkSum; /* whether to init/check checksums */ int update; /* update db */ int opts; /* reading cl options */ int started; /* finished with startup stuff */ int isdaemon; /* daemon or not */ int loop; /* go in loop even if not daemon */ int nice; /* desired nicety */ int isserver; /* server or not */ int islocked; /* BAD if logfile not locked */ int smsg; /* GOOD if end message sent */ int log_start; /* TRUE if new audit trail */ int reportonce; /* TRUE if bad files only once rep.*/ int fulldetail; /* TRUE if full details requested */ int client_severity; /* TRUE if client severity used */ int client_class; /* TRUE if client class used */ int hidefile; /* TRUE if file not shown in log */ int inotify; /* Flags for inotify */ int audit; unsigned long aud_mask; } sh_sh_flag; typedef struct { char prg_name[8]; UINT64 pid; sh_sh_df exec; sh_sh_df conf; sh_sh_df data; sh_sh_user real; sh_sh_user effective; sh_sh_user run; sh_sh_local host; sh_sh_remote srvtime; sh_sh_remote srvmail; sh_sh_remote srvexport; sh_sh_remote srvcons; sh_sh_remote srvlog; sh_sh_stat statistics; sh_sh_flag flag; #ifdef SH_STEALTH unsigned long off_data; #endif sh_timer_t mailNum; sh_timer_t mailTime; sh_timer_t fileCheck; int looptime; /* timing for main loop */ /*@null@*//*@out@*/ char * timezone; int delayload; #ifdef SCREW_IT_UP int sigtrap_max_duration; #endif char * outpath; } sh_struct; extern volatile int sig_raised; extern volatile int sig_urgent; extern volatile int sig_debug_switch; /* SIGUSR1 */ extern volatile int sig_suspend_switch; /* SIGUSR2 */ extern volatile int sh_global_suspend_flag; extern volatile int sig_fresh_trail; /* SIGIOT */ extern volatile int sh_thread_pause_flag; extern volatile int sig_config_read_again; /* SIGHUP */ extern volatile int sig_terminate; /* SIGQUIT */ extern volatile int sig_termfast; /* SIGTERM */ extern volatile int sig_force_check; /* SIGTTOU */ extern volatile int sig_force_silent; /* SIGTSTP */ extern volatile int sh_global_check_silent; extern volatile int sh_load_delta_flag; extern long int eintr__result; extern int sh_argc_store; extern char ** sh_argv_store; #include "sh_calls.h" typedef struct { char sh_sockpass[2*SOCKPASS_MAX+2]; char sigkey_old[KEY_LEN+1]; char sigkey_new[KEY_LEN+1]; char mailkey_old[KEY_LEN+1]; char mailkey_new[KEY_LEN+1]; char crypt[KEY_LEN+1]; char session[KEY_LEN+1]; char vernam[KEY_LEN+1]; int mlock_failed; char pw[PW_LEN]; char poolv[KEY_BYT]; int poolc; int rngI; UINT32 rng0[3]; UINT32 rng1[3]; UINT32 rng2[3]; UINT32 res_vec[6]; UINT32 ErrFlag[2]; #ifdef SH_ENCRYPT /*@out@*/ keyInstance keyInstE; /*@out@*/ keyInstance keyInstD; #endif } sh_key_t; extern sh_struct sh; /*@null@*/ extern sh_key_t *skey; /************************************************** * * macros * **************************************************/ #if defined(SH_ABORT_ON_ERROR) #define SH_ABORT abort() #else #define SH_ABORT #endif /* The semantics of the built-in are that it is expected that expr == const * for __builtin_expect ((expr), const) */ #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) #define SH_LIKELY(expr) (__builtin_expect((expr), 1)) #define SH_UNLIKELY(expr) (__builtin_expect((expr), 0)) #else #define SH_LIKELY(expr) (expr) #define SH_UNLIKELY(expr) (expr) #endif /* signal-safe log function */ int safe_logger (int thesignal, int method, char * details); void safe_fatal (const char * details, const char *f, int l); #define SH_VALIDATE_EQ(a,b) \ do { \ if ((a) != (b)) safe_fatal(#a " != " #b, FIL__, __LINE__);\ } while (0) #define SH_VALIDATE_NE(a,b) \ do { \ if ((a) == (b)) safe_fatal(#a " == " #b, FIL__, __LINE__);\ } while (0) #define SH_VALIDATE_GE(a,b) \ do { \ if ((a) < (b)) safe_fatal(#a " < " #b, FIL__, __LINE__);\ } while (0) #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #ifdef USE_SUID #define MLOCK(a, b) \ if ((skey != NULL) && skey->mlock_failed == S_FALSE){ \ (void) sl_set_suid(); \ if (sh_unix_mlock(FIL__, __LINE__, a, b) < 0) skey->mlock_failed = S_TRUE; \ (void) sl_unset_suid(); } #else #define MLOCK(a, b) \ if ((skey != NULL) && skey->mlock_failed == S_FALSE){ \ if (sh_unix_mlock(FIL__, __LINE__, a, b) < 0) skey->mlock_failed = S_TRUE; } #endif #else #define MLOCK(a, b) \ ; #endif #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #ifdef USE_SUID #define MUNLOCK(a, b) \ if ((skey != NULL) && skey->mlock_failed == S_FALSE){ \ (void) sl_set_suid(); \ (void) sh_unix_munlock( a, b );\ (void) sl_unset_suid(); } #else #define MUNLOCK(a, b) \ if ((skey != NULL) && skey->mlock_failed == S_FALSE){ \ (void) sh_unix_munlock( a, b ); } #endif #else #define MUNLOCK(a, b) \ ; #endif #ifdef SH_STEALTH void sh_do_encode (char * str, int len); #define sh_do_decode sh_do_encode #endif /* #if defined(SCREW_IT_UP) * extern volatile int sh_not_traced; * inline int sh_sigtrap_prepare(); * inline int sh_derr(); * #endif */ #if defined(SCREW_IT_UP) && (defined(__FreeBSD__) || defined(__linux__)) && defined(__i386__) #define BREAKEXIT(expr) \ do { \ int ixi; \ for (ixi = 0; ixi < 8; ++ixi) { \ if ((*(volatile unsigned *)((unsigned) expr + ixi) & 0xff) == 0xcc) \ _exit(EXIT_FAILURE); \ } \ } \ while (1 == 0) #else #define BREAKEXIT(expr) #endif #include "sh_cat.h" #include "sh_trace.h" #include "sh_mem.h" #endif /* CRIT: */ /* NEW_CLIENT */ /* BAD_CLIENT --
*/ /* ERR_CLIENT --
*/ /* ALERT: */ /* LOG_KEY samhain|yule */ /* STARTUP samhain|yule -- user */ /* EXIT samhain|yule */ /* GOODSIG */ /* FP_KEY */ /* GOODSIG_DAT */ /* FP_KEY_DAT */ /* TIGER_CFG */ /* TIGER_DAT */ /* PANIC --
*/ /* ERROR --
*/ /* Policy */ /* POLICY */ /* = MISSING || ADDED || NOT_A_DIRECTORY || */ samhain-4.1.4/include/sh_files.h0000644000175000017500000001611512615253277013467 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_FILES_H #define SH_FILES_H void sh_audit_mark (const char * file); void sh_audit_commit (); void sh_audit_delete_all (); char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize); struct sh_dirent { char * sh_d_name; struct sh_dirent * next; }; /* Fix the check flags */ void sh_files_fixup_mask (int class, unsigned long * check_flags); /* Dequote a filename in the config file */ char * sh_files_parse_input(const char * str_s, size_t * len); /* Check whether a file is in the config */ char * sh_files_findfile(const char * path); /* Find the most specific directory in the config */ char * sh_files_find_mostspecific_dir(const char * path); /* free a directory listing */ void kill_sh_dirlist (struct sh_dirent * dirlist); #ifdef NEED_ADD_DIRENT /* add an entry to a directory listing */ struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry, struct sh_dirent * dirlist); #endif /* register exceptions to hardlink check */ int sh_files_hle_reg (const char * str); /* Check for new files/dirs matching configured glob patterns. */ void sh_files_check_globPatterns(); /* Check for new files (only) matching configured glob patterns. */ void sh_files_check_globFilePatterns(); /* check the setup */ int sh_files_test_setup (void); /* check if allignore */ int sh_files_is_allignore (char * str); /* activate hardlink check */ int sh_files_check_hardlinks (const char * opt); /* check rsrc fork (Mac OS X) */ int sh_files_use_rsrc(const char * str); /* set recursion depth */ int sh_files_setrec (void); /* report only once */ int sh_files_reportonce(const char * c); /* report full details */ int sh_files_fulldetail(const char * c); /* reset the 'checked' flag */ void sh_dirs_reset(void); /* reset the 'checked' flag */ void sh_files_reset(void); /* set maximum recursion level */ int sh_files_setrecursion (const char * flag_s); /* select a directory stack 2=Two, else One (standard) */ int set_dirList (int which); /* push a directory on the stack USER0 */ int sh_files_pushdir_user0 (const char * dirName); /* push a directory on the stack USER1 */ int sh_files_pushdir_user1 (const char * dirName); /* push a directory on the stack USER2 */ int sh_files_pushdir_user2 (const char * dirName); /* push a directory on the stack USER3 */ int sh_files_pushdir_user3 (const char * dirName); /* push a directory on the stack USER4 */ int sh_files_pushdir_user4 (const char * dirName); /* push a directory on the stack PRELINK */ int sh_files_pushdir_prelink (const char * dirName); /* push a directory on the stack ATTR */ int sh_files_pushdir_attr (const char * dirName); /* push a directory on the stack READONLY */ int sh_files_pushdir_ro (const char * dirName); /* push a directory on the stack LOGFILE */ int sh_files_pushdir_log (const char * dirName); /* push a directory on the stack GROWING LOGFILE */ int sh_files_pushdir_glog (const char * dirName); /* push a directory on the stack IGNORE NONE */ int sh_files_pushdir_noig (const char * dirName); /* push a directory on the stack IGNORE ALL */ int sh_files_pushdir_allig (const char * dirName); /* push a file on the stack USER0 */ int sh_files_pushfile_user0 (const char * dirName); /* push a file on the stack USER1 */ int sh_files_pushfile_user1 (const char * dirName); /* push a file on the stack USER2 */ int sh_files_pushfile_user2 (const char * dirName); /* push a file on the stack USER3 */ int sh_files_pushfile_user3 (const char * dirName); /* push a file on the stack USER4 */ int sh_files_pushfile_user4 (const char * dirName); /* push a file on the stack PRELINK */ int sh_files_pushfile_prelink (const char * dirName); /* push a file on the stack ATTR */ int sh_files_pushfile_attr (const char * dirName); /* push a file on the stack READONLY */ int sh_files_pushfile_ro (const char * dirName); /* push a file on the stack LOGFILE */ int sh_files_pushfile_log (const char * dirName); /* push a file on the stack GROWING LOGFILE */ int sh_files_pushfile_glog (const char * dirName); /* push a file on the stack IGNORE NONE */ int sh_files_pushfile_noig (const char * dirName); /* push a file on the stack IGNORE ALL */ int sh_files_pushfile_allig (const char * dirName); /* check directories on the stack */ unsigned long sh_dirs_chk (int which); /* check files on the stack */ unsigned long sh_files_chk (void); int sh_files_delglobstack (void); int sh_files_deldirstack (void); int sh_files_delfilestack (void); /* redefine policies */ int sh_files_redef_user0(const char * str); int sh_files_redef_user1(const char * str); int sh_files_redef_user2(const char * str); int sh_files_redef_user3(const char * str); int sh_files_redef_user4(const char * str); int sh_files_redef_prelink(const char * str); int sh_files_redef_readonly(const char * str); int sh_files_redef_loggrow(const char * str); int sh_files_redef_logfiles(const char * str); int sh_files_redef_attributes(const char * str); int sh_files_redef_noignore(const char * str); int sh_files_redef_allignore(const char * str); ShFileType sh_files_filecheck (int class, unsigned long check_flags, const char * dirName, const char * infileName, int * reported, int rsrcflag); int sh_files_checkdir (int iclass, unsigned long check_flags, int idepth, char * iname, char * relativeName); int sh_files_search_file(char * name, int * class, unsigned long *check_flags, int * reported); int sh_files_search_dir(char * name, int * class, unsigned long *check_flags, int *reported, int * rdepth); void sh_files_set_file_reported(const char * name); void sh_files_clear_file_reported(const char * name); #endif samhain-4.1.4/include/bignum.h0000644000175000017500000000463212615253277013155 00000000000000#ifndef _BIGNUM_H_ #define _BIGNUM_H_ #include "internal.h" typedef struct big_struct bignum; #define BIG_SIGN_0 0 #define BIG_SIGN_PLUS 1 #define BIG_SIGN_MINUS -1 #define BIG_OK 0 #define BIG_MEMERR 1 #define BIG_DIV_ZERO 2 #define BIG_ARGERR 3 #ifdef BIG_SHORT_NAMES #define big_set_big big_sb #define big_set_long big_sl #define big_set_ulong big_usl #define big_string big_rs #define big_leqp big_lq #define big_expt big_x #endif /* External variables to take care about when using the bignums */ typedef int bigerr_t; extern int big_errno; extern char *big_end_string; /* External functions to enable use of bignums */ extern bigerr_t big_init_pkg(void); extern void big_release_pkg(void); extern bigerr_t big_create(bignum *a); extern void big_destroy(bignum *a); extern unsigned long big_bitcount(bignum *a); extern bigerr_t big_set_big(bignum *a, bignum *b); extern void big_set_long(long n, bignum *a); extern void big_set_ulong(unsigned long n, bignum *a); extern bigerr_t big_set_string(char *numstr, int base, bignum *a); extern int big_long(bignum *a, long *n); extern int big_ulong(bignum *a, unsigned long *n); extern char *big_string(bignum *a, int base); extern int big_sign(bignum *a); extern bigerr_t big_abs(bignum *a, bignum *b); extern bigerr_t big_negate(bignum *a, bignum *b); extern int big_compare(bignum *a, bignum *b); extern int big_lessp(bignum *a, bignum *b); extern int big_leqp(bignum *a, bignum *b); extern int big_equalp(bignum *a, bignum *b); extern int big_geqp(bignum *a, bignum *b); extern int big_greaterp(bignum *a, bignum *b); extern int big_zerop(bignum *a); extern int big_evenp(bignum *a); extern int big_oddp(bignum *a); extern bigerr_t big_add(bignum *a, bignum *b, bignum *c); extern bigerr_t big_sub(bignum *a, bignum *b, bignum *c); extern bigerr_t big_mul(bignum *a, bignum *b, bignum *c); extern bigerr_t big_trunc(bignum *a, bignum *b, bignum *c, bignum *r); extern bigerr_t big_floor(bignum *a, bignum *b, bignum *c, bignum *r); extern bigerr_t big_ceil(bignum *a, bignum *b, bignum *c, bignum *r); extern bigerr_t big_round(bignum *a, bignum *b, bignum *c, bignum *r); extern bigerr_t big_random(bignum *a, bignum *b); extern bigerr_t big_expt(bignum *a, unsigned long z, bignum *x); extern bigerr_t big_exptmod(bignum *a_in, bignum *z_in, bignum *n, bignum *x); extern bigerr_t big_gcd(bignum *a, bignum *b, bignum *g); #ifndef NULL #define NULL 0 #endif #endif /* _BIGNUM_H_ */ samhain-4.1.4/include/sh_dbIO.h0000664000175000017500000000431212615253277013200 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SH_DBIO_H #define SH_DBIO_H /* Read one line, trim newline. Return char count, or -1 on error or eof. */ int sh_dbIO_getline (FILE * fd, char * line, const size_t sizeofline); /* Read given database file for listing */ int sh_dbIO_list_db (const char * db_file); /* Write single record to database */ void sh_dbIO_data_write (file_type * buf, char * fileHash); /* Write whole default database */ int sh_dbIO_writeout_update (); /* write database to given path */ int sh_dbIO_writeout_to_path(const char * path); /* write database to stdout */ int sh_dbIO_writeout_stdout (const char * str); /* version string for database */ int sh_dbIO_version_string(const char * str); /* Load a delta database */ int sh_dbIO_load_delta(); int sh_dbIO_list_binary (const char * c); int sh_dbIO_list_filter (const char * c); #endif samhain-4.1.4/include/sh_mounts.h0000644000175000017500000000075212615253277013712 00000000000000/* * File: sh_mounts.h * Desc: A module for Samhain; checks for mounts present and options on them. * Auth: Cian Synnott */ #ifndef SH_MOUNTS_H #define SH_MOUNTS_H #include "sh_modules.h" #ifdef SH_USE_MOUNTS int sh_mounts_init (struct mod_type * arg); int sh_mounts_timer (time_t tcurrent); int sh_mounts_check (void); int sh_mounts_cleanup (void); int sh_mounts_reconf (void); extern sh_rconf sh_mounts_table[]; #endif /* #ifndef SH_MOUNTS_H */ #endif samhain-4.1.4/yulerc.template0000644000175000017500000002033012615253270013122 00000000000000##################################################################### # # Configuration file template for yule. # ##################################################################### # # NOTE: This is a log server-only configuration file TEMPLATE. # # NOTE: The log server ('yule') will look for THAT configuration file # that has been defined at compile time with the configure option # ./configure --with-config-file=FILE # The default is "/usr/local/etc/.samhainrc" (NOT "yulerc"). # ##################################################################### # # -- empty lines and lines starting with '#', ';' or '//' are ignored # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### [Log] ## ## Switch on/OFF log facilities and set their threshold severity ## ## Values: debug, info, notice, warn, mark, err, crit, alert, none. ## 'mark' is used for timestamps. ## ## ## Use 'none' to SWITCH OFF a log facility ## ## By default, everything equal to and above the threshold is logged. ## The specifiers '*', '!', and '=' are interpreted as ## 'all', 'all but', and 'only', respectively (like syslogd(8) does, ## at least on Linux). Examples: ## MailSeverity=* ## MailSeverity=!warn ## MailSeverity==crit ## E-mail ## # MailSeverity=none ## Console ## PrintSeverity=none ## Logfile ## LogSeverity = warn ## Syslog ## # SyslogSeverity=none ## External script or program ## # ExternalSeverity = none ## Logging to a database ## # DatabaseSeverity = none # [Database] ## ## --- Logging to a relational database ## ## Database name # # SetDBName = samhain ## Database table # # SetDBTable = log ## Database user # # SetDBUser = samhain ## Database password # # SetDBPassword = (default: none) ## Database host # # SetDBHost = localhost ## Log the server timestamp for received messages # # SetDBServerTstamp = True ## Use a persistent connection # # UsePersistent = True # [External] ## ## Interface to call external scripts/programs for logging ## ## The absolute path to the command ## - Each invocation of this directive will end the definition of the ## preceding command, and start the definition of ## an additional, new command # # OpenCommand = (no default) ## Type (log or rv) ## - log for log messages, srv for messages received by the server # # SetType = log ## The command (full command line) to execute # # SetCommandLine = (no default) ## The environment (KEY=value; repeat for more) # # SetEnviron = TZ=(your timezone) ## The TIGER192 checksum (optional) # # SetChecksum = (no default) ## User who runs the command # # SetCredentials = (default: samhain process uid) ## Words not allowed in message # # SetFilterNot = (none) ## Words required (ALL of them) # # SetFilterAnd = (none) ## Words required (at least one) # # SetFilterOr = (none) ## Deadtime between consecutive calls # # SetDeadtime = 0 ## Add default environment (HOME, PATH, SHELL) # # SetDefault = no ##################################################### # # Miscellaneous configuration options # ##################################################### [Misc] # whether to become a daemon process Daemon=yes ## Interval between time stamp messages # # SetLoopTime = 60 SetLoopTime = 600 ## Normally, client messages are regarded as data within a ## server message of fixed severity. The following two ## options cause the server to use the original severity/class ## of client messages for logging. # # UseClientSeverity = False # UseClientClass = False ## The maximum time between client messages (seconds) ## This allows the server to flag clients that have exceeded ## the timeout limits; i.e. might have died for some reason. # # SetClientTimeLimit = 86400 ## Use client address as known to the communication layer (might be ## incorrect if the client is behind NAT). The default is to use ## the client name as claimed by the client, and verify it against ## the former (might be incorrect if the client has several ## interfaces, and its hostname resolves to the wrong interface). # # SetClientFromAccept = False ## If SetClientFromAccept is False (default), severity of a ## failure to resolve the hostname claimed by the client ## to the IP address of the socket peer. # # SeverityLookup = crit ## The console device (can also be a file or named pipe) ## - There are two console devices. Accordingly, you can use ## this directive a second time to set the second console device. ## If you have not defined the second device at compile time, ## and you don't want to use it, then: ## setting it to /dev/null is less effective than just leaving ## it alone (setting to /dev/null will waste time by opening ## /dev/null and writing to it) # # SetConsole = /dev/console ## Use separate logfiles for individual clients # # UseSeparateLogs = False ## Enable listening on port 514/udp for logging of remote syslog ## messages (if optionally compiled with support for this) # # SetUDPActive = False ## Activate the SysV IPC message queue # # MessageQueueActive = False ## If false, skip reverse lookup when connecting to a host known ## by name rather than IP address (i.e. trust the DNS) # # SetReverseLookup = True ## If true, open a Unix domain socket to listen for commands that should ## be passed to clients upon next connection. Only works on systems ## that support passing of peer credentials (for authentication) via sockets. ## Use yulectl to access the socket. # # SetUseSocket = False ## The UID of the user that is allowed to pass commands to the server ## via the Unix domain socket. # # SetSocketAllowUid = 0 ## --- E-Mail --- # Only highest-level (alert) reports will be mailed immediately, # others will be queued. Here you can define, when the queue will # be flushed (Note: the queue is automatically flushed after # completing a file check). # # SetMailTime = 86400 ## Maximum number of mails to queue # # SetMailNum = 10 ## Recipient (max. 8) # # SetMailAddress=root@localhost ## Mail relay (IP address) # # SetMailRelay = NULL ## Custom subject format # # MailSubject = NULL ## --- end E-Mail --- # The binary. Setting the path will allow # samhain to check for modifications between # startup and exit. # # SamhainPath=/usr/local/bin/yule ## The IP address of the time server # # SetTimeServer = (default: compiled-in) ## Trusted Users (comma delimited list of user names) # # TrustedUser = (no default; this adds to the compiled-in list) ## Custom format for message header. ## CAREFUL if you use XML logfile format. ## ## %S severity ## %T timestamp ## %C class ## ## %F source file ## %L source line # # MessageHeader="%S %T " ## Don't log path to config/database file on startup # # HideSetup = False ## The syslog facility, if you log to syslog # # SyslogFacility = LOG_AUTHPRIV ## The message authentication method ## - If you change this, you *must* change it ## on client *and* server # # MACType = HMAC-TIGER [Clients] ## ## This is a sample registry entry for a client at host 'HOSTNAME'. This entry ## is valid for the default password. ## You are STRONGLY ADVISED to reset te password (see the README) and ## compute your own entries using 'samhain -P ' ## ## Usually, HOSTNAME should be a fully qualified hostname, ## no numerical address. ## -- exception: if the client (samhain) cannot determine the ## fully qualified hostname of its host, ## the numerical address may be required. ## You will know if you get a message like: ## 'Invalid connection attempt: Not in ## client list what.ever.it.is' ## ## First entry is for challenge/response, second one for SRP authentication. # # Client=HOSTNAME@00000000@C39F0EEFBC64E4A8BBF72349637CC07577F714B420B62882 # Client=HOSTNAME@8F81BA58956F8F42@8932D08C49CA76BD843C51EDD1D6640510FA032A7A2403E572BBDA2E5C6B753991CF7E091141D20A2499C5CD3E14C1639D17482E14E1548E5246ACF4E7193D524CDDAC9C9D6A9A36C596B4ECC68BEB0C5BB7082224946FC98E3ADE214EA1343E2DA8DF4229D4D8572AD8679228928A787B6E5390D3A713102FFCC9D0B2188C92 samhain-4.1.4/samhainrc.freebsd0000644000175000017500000003370312615253270013373 00000000000000##################################################################### # # FreeBSD Configuration file for samhain. # ##################################################################### # # -- empty lines and lines starting with '#', ';' or '//' are ignored # -- boolean options can be Yes/No or True/False or 1/0 # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # SETUP for file system checking: # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) Section [EventSeverity]: # To each policy, you can assign a severity (further below). # (iii) Section [Log]: # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). ##################################################################### ##################################################################### # # Files are defined with: file = /absolute/path # # Directories are defined with: dir = /absolute/path # or with an optional recursion depth (N <= 99): dir = N/absolute/path # # Directory inodes are checked. If you only want to check files # in a directory, but not the directory inode itself, use (e.g.): # # [ReadOnly] # dir = /some/directory # [IgnoreAll] # file = /some/directory # # You can use shell-style globbing patterns, like: file = /path/foo* # ###################################################################### [Misc] ## ## Add or subtract tests from the policies ## - if you want to change their definitions, ## you need to do that before using the policies ## # RedefReadOnly = (no default) # RedefAttributes=(no default) # RedefLogFiles=(no default) # RedefGrowingLogFiles=(no default) # RedefIgnoreAll=(no default) # RedefIgnoreNone=(no default) # RedefUser0=(no default) # RedefUser1=(no default) # # --------- / -------------- # [ReadOnly] dir = 0/ [Attributes] file = / file = /proc file = /entropy file = /tmp file = /var # # --------- /dev ----------- # [Attributes] dir = 99/dev [IgnoreAll] file = /dev/ttyp? [Misc] ## ## pseudo terminals are created/removed as needed ## IgnoreAdded = /dev/(p|t)typ.* IgnoreMissing = /dev/(p|t)typ.* # # --------- /etc ----------- # [ReadOnly] ## ## for these files, only access time is ignored ## dir = 99/etc # # --------- /boot ----------- # [ReadOnly] dir = 99/boot # # --------- /bin, /sbin ----------- # [ReadOnly] dir = 99/bin dir = 99/sbin # # --------- /lib ----------- # [ReadOnly] dir = 99/lib # # --------- /libexec ----------- # [ReadOnly] dir = 99/libexec # # --------- /rescue ----------- # [ReadOnly] dir = 99/rescue # # --------- /root ----------- # [Attributes] ## ## for these files, only changes in permissions and ownership are checked ## dir = 99/root # # --------- /stand ----------- # [ReadOnly] dir = 99/stand # # --------- /usr ----------- # [ReadOnly] dir = 99/usr [Attributes] dir = /usr/.snap dir = /usr/share/man/cat? file = /usr/compat/linux/etc file = /usr/compat/linux/etc/ld.so.cache [IgnoreAll] dir = -1/usr/home # # --------- /var ----------- # [Attributes] dir = 0/var [LogFiles] ## ## for these files, changes in signature, timestamps, and size are ignored ## file=/var/run/utmp [GrowingLogFiles] ## ## For these files, changes in signature, timestamps, and increase in size ## are ignored. Logfile rotation will cause a report because of shrinking ## size and different inode. ## dir = 99/var/log [Attributes] # # rotated logs will change inode # file = /var/log/*.[0-9].bz2 file = /var/log/*.[0-9].log file = /var/log/*.[0-9] file = /var/log/*.[0-9][0-9] file = /var/log/*.old file = /var/log/sendmail.st [Misc] # # Various naming schemes for rotated logs # IgnoreAdded = /var/log/.*\.[0-9]+$ IgnoreAdded = /var/log/.*\.[0-9]+\.gz$ IgnoreAdded = /var/log/.*\.[0-9]+\.bz2$ IgnoreAdded = /var/log/.*\.[0-9]+\.log$ [IgnoreNone] ## ## for these files, all modifications (even access time) are reported ## - you may create some interesting-looking file (like /etc/safe_passwd), ## just to watch whether someone will access it ... ## [User0] [User1] ## User0 and User1 are sections for files/dirs with user-definable checking ## (see the manual) [EventSeverity] ## ## Here you can assign severities to policy violations. ## If this severity exceeds the treshold of a log facility (see below), ## a policy violation will be logged to that facility. ## # # Severity for verification failures. # # SeverityReadOnly=crit # SeverityLogFiles=crit # SeverityGrowingLogs=crit # SeverityIgnoreNone=crit # SeverityAttributes=crit # SeverityUser0=crit # SeverityUser1=crit ## We have a file in IgnoreAll that might or might not be present. ## Setting the severity to 'info' prevents messages about deleted/new file. ## # SeverityIgnoreAll=crit SeverityIgnoreAll=info ## Files : file access problems # SeverityFiles=crit ## Dirs : directory access problems # SeverityDirs=crit ## Names : suspect (non-printable) characters in a pathname # SeverityNames=crit [Log] ## ## Switch on/OFF log facilities and set their threshold severity ## ## Values: debug, info, notice, warn, mark, err, crit, alert, none. ## 'mark' is used for timestamps. ## ## Use 'none' to SWITCH OFF a log facility ## ## By default, everything equal to and above the threshold is logged. ## The specifiers '*', '!', and '=' are interpreted as ## 'all', 'all but', and 'only', respectively (like syslogd(8) does, ## at least on Linux). Examples: ## MailSeverity=* ## MailSeverity=!warn ## MailSeverity==crit ## E-mail ## # MailSeverity=none ## Console ## # PrintSeverity=info ## Logfile ## # LogSeverity=mark ## Syslog ## # SyslogSeverity=none ## Remote server (yule) ## # ExportSeverity=none ## External script or program ## # ExternalSeverity = none ## Logging to a database ## # DatabaseSeverity = none ## Logging to a Prelude-IDS ## # PreludeSeverity = crit ##################################################### # # Optional modules # ##################################################### # [SuidCheck] ## ## --- Check the filesystem for SUID/SGID binaries ## ## Switch on # # SuidCheckActive = yes ## Interval for check (seconds) # # SuidCheckInterval = 7200 ## Alternative: crontab-like schedule # # SuidCheckSchedule = NULL ## Directory to exclude # # SuidCheckExclude = NULL ## Limit on files per second (0 == no limit) # # SuidCheckFps = 0 ## Alternative: yield after every file # # SuidCheckYield = no ## Severity of a detection # # SeveritySuidCheck = crit ## Quarantine SUID/SGID files if found # # SuidCheckQuarantineFiles = yes ## Method for Quarantining files: # 0 - Delete the file. # 1 - Remove SUID/SGID permissions from file. # 2 - Move SUID/SGID file to quarantine dir. # # SuidCheckQuarantineMethod = 0 ## For method 1 and 3, really delete instead of truncating # # SuidCheckQuarantineDelete = yes # [Utmp] ## ## --- Logging of login/logout events ## ## Switch on/off # # LoginCheckActive = True ## Severity for logins, multiple logins, logouts # # SeverityLogin=info # SeverityLoginMulti=warn # SeverityLogout=info ## Interval for login/logout checks # # LoginCheckInterval = 300 # [Database] ## ## --- Logging to a relational database ## ## Database name # # SetDBName = samhain ## Database table # # SetDBTable = log ## Database user # # SetDBUser = samhain ## Database password # # SetDBPassword = (default: none) ## Database host # # SetDBHost = localhost ## Log the server timestamp for received messages # # SetDBServerTstamp = True ## Use a persistent connection # # UsePersistent = True # [External] ## ## Interface to call external scripts/programs for logging ## ## The absolute path to the command ## - Each invocation of this directive will end the definition of the ## preceding command, and start the definition of ## an additional, new command # # OpenCommand = (no default) ## Type (log or srv) ## - log for log messages, srv for messages received by the server # # SetType = log ## The command (full command line) to execute # # SetCommandLine = (no default) ## The environment (KEY=value; repeat for more) # # SetEnviron = TZ=(your timezone) ## The TIGER192 checksum (optional) # # SetChecksum = (no default) ## User who runs the command # # SetCredentials = (default: samhain process uid) ## Words not allowed in message # # SetFilterNot = (none) ## Words required (ALL of them) # # SetFilterAnd = (none) ## Words required (at least one) # # SetFilterOr = (none) ## Deadtime between consecutive calls # # SetDeadtime = 0 ## Add default environment (HOME, PATH, SHELL) # # SetDefault = no ##################################################### # # Miscellaneous configuration options # ##################################################### [Misc] ## whether to become a daemon process ## (this is not honoured on database initialisation) # # Daemon = no Daemon = yes # whether to test signature of files (init/check/none) # - if 'none', then we have to decide this on the command line - # # ChecksumTest = none ChecksumTest=check # Set nice level (-19 to 19, see 'man nice'), # and I/O limit (kilobytes per second; 0 == off) # to reduce load on host. # # SetNiceLevel = 0 # SetIOLimit = 0 ## The version string to embed in file signature databases # # VersionString = NULL ## Interval between time stamp messages # # SetLoopTime = 60 SetLoopTime = 600 ## Interval between file checks # # SetFileCheckTime = 600 SetFileCheckTime = 7200 ## Alternative: crontab-like schedule # # FileCheckScheduleOne = NULL ## Alternative: crontab-like schedule(2) # # FileCheckScheduleTwo = NULL ## Report only once on modified files ## Setting this to 'FALSE' will generate a report for any policy ## violation (old and new ones) each time the daemon checks the file system. # # ReportOnlyOnce = True ## Report in full detail # # ReportFullDetail = False ## Report file timestamps in local time rather than GMT # # UseLocalTime = No ## The console device (can also be a file or named pipe) ## - There are two console devices. Accordingly, you can use ## this directive a second time to set the second console device. ## If you have not defined the second device at compile time, ## and you don't want to use it, then: ## setting it to /dev/null is less effective than just leaving ## it alone (setting to /dev/null will waste time by opening ## /dev/null and writing to it) # # SetConsole = /dev/console ## Activate the SysV IPC message queue # # MessageQueueActive = False ## If false, skip reverse lookup when connecting to a host known ## by name rather than IP address (i.e. trust the DNS) # # SetReverseLookup = True ## --- E-Mail --- # Only highest-level (alert) reports will be mailed immediately, # others will be queued. Here you can define, when the queue will # be flushed (Note: the queue is automatically flushed after # completing a file check). # # SetMailTime = 86400 ## Maximum number of mails to queue # # SetMailNum = 10 ## Recipient (max. 8) # # SetMailAddress=root@localhost ## Mail relay (IP address) # # SetMailRelay = NULL ## Custom subject format # # MailSubject = NULL ## --- end E-Mail --- ## Path to the executable. If set, will be checksummed after startup ## and before exit. # # SamhainPath = (no default) ## The IP address of the log server # # SetLogServer = (default: compiled-in) ## The IP address of the time server # # SetTimeServer = (default: compiled-in) ## Trusted Users (comma delimited list of user names) # # TrustedUser = (no default; this adds to the compiled-in list) ## Path to the file signature database # # SetDatabasePath = (default: compiled-in) ## Path to the log file # # SetLogfilePath = (default: compiled-in) ## Path to the PID file # # SetLockfilePath = (default: compiled-in) ## The digest/checksum/hash algorithm # # DigestAlgo = TIGER192 ## Custom format for message header. ## CAREFUL if you use XML logfile format. ## ## %S severity ## %T timestamp ## %C class ## ## %F source file ## %L source line # # MessageHeader="%S %T " ## Don't log path to config/database file on startup # # HideSetup = False ## The syslog facility, if you log to syslog # # SyslogFacility = LOG_AUTHPRIV SyslogFacility=LOG_LOCAL2 ## The message authentication method ## - If you change this, you *must* change it ## on client *and* server # # MACType = HMAC-TIGER ## The Prelude-IDS profile to use for reporting ## default value is "samhain" # # PreludeProfile = samhain ## Map these samhain severities to impact severity 'info' severity # # PreludeMapToInfo = ## Map these samhain severities to impact severity 'low' severity # # PreludeMapToLow = debug info ## Map these samhain severities to impact severity 'medium' severity # # PreludeMapToMedium = notice warn err ## Map these samhain severities to impact severity 'high' severity # # PreludeMapToHigh = crit alert # everything below is ignored [EOF] ##################################################################### # This would be the proper syntax for parts that should only be # included for certain hosts. # You may enclose anything in a @HOSTNAME/@end bracket, as long as the # result still has the proper syntax for the config file. # You may have any number of @HOSTNAME/@end brackets. # HOSTNAME should be the fully qualified 'official' name # (e.g. 'nixon.watergate.com', not 'nixon'), no aliases. # No IP number - except if samhain cannot determine the # fully qualified hostname. # # @HOSTNAME # file=/foo/bar # @end # # These are two examples for conditional inclusion/exclusion # of a machine based on the output from 'uname -srm' # $Linux:2.*.7:i666 # file=/foo/bar3 # $end # # !$Linux:2.*.7:i686 # file=/foo/bar2 # $end # ##################################################################### samhain-4.1.4/samhainrc.aix5.2.00000644000175000017500000001274012615253270013123 00000000000000##################################################################### # # AIX 5.2.0 configuration file for Samhain. # #################################################################### # # Date : 23.10.2003 # Author : Christoph Kiefer (chkiefer@intergga.ch) # Comment : Samhain client configuration file. Should work # for AIX 5.1.0. The Samhain version is 1.7.12 # This configuration fits MY needs, YOU will # probably have to modify it. # # Changes : Date Name Remarks # 23.10.2003 Christoph Kiefer Initial Version # ##################################################################### # # -- empty lines and lines starting with '#', ';' or '//' are ignored # -- boolean options can be Yes/No or True/False or 1/0 # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # SETUP for file system checking: # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) Section [EventSeverity]: # To each policy, you can assign a severity (further below). # (iii) Section [Log]: # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). ##################################################################### ##################################################################### # # Files are defined with: file = /absolute/path # # Directories are defined with: dir = /absolute/path # or with an optional recursion depth (N <= 99): dir = N/absolute/path # # Directory inodes are checked. If you only want to check files # in a directory, but not the directory inode itself, use (e.g.): # # [ReadOnly] # dir = /some/directory # [IgnoreAll] # file = /some/directory # # You can use shell-style globbing patterns, like: file = /path/foo* # ###################################################################### [Misc] MessageHeader="" RedefLogFiles=-INO SetFilecheckTime=3600 SetLoopTime=3600 SetRecursionLevel=99 DigestAlgo=SHA1 ChecksumTest=check SetTimeServer=localhost ReportFullDetail=no Daemon=yes HideSetup=yes ReportOnlyOnce=yes UseLocalTime=yes ## The Prelude-IDS profile to use for reporting ## default value is "samhain" # # PreludeProfile = samhain ## Map these samhain severities to impact severity 'info' severity # # PreludeMapToInfo = ## Map these samhain severities to impact severity 'low' severity # # PreludeMapToLow = debug info ## Map these samhain severities to impact severity 'medium' severity # # PreludeMapToMedium = notice warn err ## Map these samhain severities to impact severity 'high' severity # # PreludeMapToHigh = crit alert [IgnoreAll] dir=-1/etc/objrepos dir=-1/etc/vg dir=-1/dev/.SRC-unix dir=-1/dev/pts dir=-1/opt dir=-1/tmp dir=-1/usr/share/lib/objrepos dir=-1/usr/share/man dir=-1/var/adm/cron dir=-1/var/tmp file=/dev/log* [Attributes] file=/etc/lpp/diagnostics/data/* file=/audit/auditb file=/dev # file=/etc/bootpd.dump file=/etc/bootptab file=/etc/inittab file=/etc/xtab dir=/dev dir=/usr/dt dir=/usr/lib/instl dir=/usr/lib/lpd dir=/usr/lib/mh dir=/usr/lib/sa dir=/usr/lpp [LogFiles] file=/etc/rmtab file=/etc/security/failedlogin file=/etc/security/lastlog file=/etc/security/portlog file=/etc/utmp # file=/smit.log file=/var/adm/*log* file=/var/adm/ras/*log* file=/var/adm/wtmp file=/var/log/*log* [IgnoreNone] file=/etc/tsh_profile [ReadOnly] dir=/etc/security/ldap file=/etc/*.cnf file=/etc/*conf* file=/etc/aliases file=/etc/dumpdates file=/etc/environment file=/etc/exports file=/etc/filesystems file=/etc/ftpusers file=/etc/group file=/etc/hosts* file=/etc/motd file=/etc/passwd file=/etc/profile file=/etc/protocols file=/etc/publickey file=/etc/rc.* file=/etc/rpc file=/etc/security/acl file=/etc/security/environ file=/etc/security/group file=/etc/security/limits file=/etc/security/login.cfg file=/etc/security/passwd file=/etc/security/roles file=/etc/security/smitacl.* file=/etc/security/user* file=/etc/sendmail.cf file=/etc/services file=/etc/sudoers file=/etc/swapspaces file=/etc/vfs # file=/smit.script dir=/etc/mail dir=/etc/rc.d dir=/etc/security/audit dir=/home/root dir=/sbin dir=/usr/X11R6 dir=/usr/bin dir=/usr/ccs dir=/usr/etc dir=/usr/include dir=/usr/lib/boot dir=/usr/lib/methods dir=/usr/lib/microcode dir=/usr/lib/security dir=/usr/lib/smit dir=/usr/local/bin dir=/usr/sbin dir=/usr/share dir=/usr/ucb [EventSeverity] SeverityAttributes=crit SeverityDirs=err SeverityFiles=err SeverityGrowingLogs=warn SeverityIgnoreNone=crit SeverityLogFiles=crit SeverityReadOnly=crit SeverityIgnoreAll=info SeverityNames=info [Log] ExportClass=RUN FIL PANIC ERR ENET EINPUT LogSeverity=none MailSeverity=none PrintSeverity=none ExportSeverity=warn SyslogSeverity=warn ## Logging to a Prelude-IDS ## # PreludeSeverity = crit [SuidCheck] SuidCheckExclude=/proc SuidCheckActive=1 SuidCheckInterval=1800 SuidCheckFps=250 #SuidCheckYield=no SeveritySuidCheck=alert #SuidCheckQuarantineFiles=yes #SuidCheckQuarantineMethod=0 # SuidCheckQuarantineDelete = yes [Utmp] LoginCheckActive=1 LoginCheckInterval=30 SeverityLogin=info SeverityLogout=info SeverityLoginMulti=warn [EOF] samhain-4.1.4/samhain-install.sh.in0000644000175000017500000012043312615253270014114 00000000000000#! /bin/sh purge= verbose= express= force= act= prefix=@prefix@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ samhain=@install_name@ mandir=@mandir@ sysconfdir=@sysconfdir@ configfile=@myconffile@ pid_file=@mylockfile@ pid_dir=@mylockdir@ data_root=@mydataroot@ mydatafile=@mydatafile@ mylogfile=@mylogfile@ mylogdir=@mylogdir@ myhtmlfile=@myhtmlfile@ datarootdir=@datarootdir@ INSTALL_SHELL="$0 --install-sh -m 700" INSTALL_DATA="$0 --install-sh -m 600" mkinstalldirs="$0 --mkinstalldirs" DESTDIR= user= # # Only call rmdir with an absolute path # SH_RMDIR=echo SPATH="/bin:/usr/bin:/sbin:/usr/sbin" OLD_IFS=${IFS} IFS=':'; export IFS for ff in ${SPATH}; do if test -x $ff/rmdir; then SH_RMDIR=`eval echo ${ff}/rmdir` fi done IFS=${OLD_IFS}; export IFS case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if [ x"$1" = x ] then echo 'samhain-install.sh [--destdir=DESTDIR][--verbose][--express][--force] action' echo 'action = install-boot|install-data|install-user' echo ' uninstall|purge|uninstall-boot' echo ' uninstall-data|uninstall-man|uninstall-program' echo 'samhain-install.sh --print-config ' echo 'item = name | basekey | prefix | exec_prefix | sbin_dir | man_dir' echo ' config_dir | config_file | pid_dir | log_dir | log_file' echo ' data_dir | data_file' exit 1 fi while [ x"$1" != x ]; do case $1 in -v|--verbose) verbose=yes shift continue;; -e|--express) express=yes shift continue;; -f|--force) force=yes shift continue;; -d) shift DESTDIR="$1" if test "x${DESTDIR}" = "x/"; then DESTDIR= fi shift continue;; --destdir=*) DESTDIR=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` if test "x${DESTDIR}" = "x/"; then DESTDIR= fi shift continue;; --install-sh) shift # 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=: 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 # ----- END OF INSTALL-SH ----- ;; --mkinstalldirs) shift # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman 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" 1>&2 mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here ;; install-deploy) if test -f ./samhainrc.USEME then tmpconfigfile=`echo ${configfile} | sed 's%^REQ_FROM_SERVER%%'` if test x"${tmpconfigfile}" = x then echo " No local path for configfile defined." exit 0 else cp samhainrc.USEME "${tmpconfigfile}" && chmod 0600 "${tmpconfigfile}" fi fi if test -f postinstall.USEME then /bin/sh ./postinstall.USEME fi exit 0 ;; print-config|--print-config) shift pwhat=$1 if test x"$1" = x then echo "$0: Missing argument to print-config" exit 1 fi case $pwhat in basekey) echo "@mykeybase@" ;; prefix) echo $prefix ;; exec_prefix) echo $exec_prefix ;; sbin_dir) echo $sbindir ;; name) echo $samhain ;; man_dir) echo $mandir ;; config_dir) echo $sysconfdir ;; config_file) echo $configfile | sed 's%^REQ_FROM_SERVER%%' ;; pid_file) echo ${pid_file} ;; pid_dir) echo ${pid_dir} ;; data_dir) echo @mydataroot@ ;; data_file) echo @mydatafile@ | sed 's%^REQ_FROM_SERVER%%' ;; log_file) echo @mylogfile@ ;; log_dir) echo @mylogdir@ ;; *) echo "$0: Unknown item \"$pwhat\"" exit 1 ;; esac exit 0 ;; install-user) act=user shift user=$1 break;; install-boot) act=boot break;; uninstall-boot) act=uboot break;; install-data) act=data break;; uninstall-data) act=udata break;; uninstall-man) act=uman break;; uninstall-program) act=uprogram break;; uninstall | remove | purge) opts= test x"$verbose" = "xyes" && opts="$opts --verbose" test x"$express" = "xyes" && opts="$opts --express" test x"$force" = "xyes" && opts="$opts --force" test x"$DESTDIR" = "x" || opts="$opts --destdir=$DESTDIR" test x"$1" = "xpurge" && purge=yes echo "$0 $opts uninstall-program" eval $0 $opts uninstall-program echo "$0 $opts uninstall-man" eval $0 $opts uninstall-man if test x"$force" = "x"; then test "x$purge" = xyes && opts="$opts --force" fi echo "$0 $opts uninstall-data" eval $0 $opts uninstall-data echo echo " To uninstall the runlevel scripts, use $0 $opts uninstall-boot" echo exit 0 ;; *) echo "Unknown option $1" exit 1 ;; esac done if test x"$act" = xuser then # -- the routines for installing a new user are adapted from # the OpenPKG bootstrap installation script, which is distributed # under the following license: ## Shell-based package for OpenPKG BINARY bootstrap installation ## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH ## Copyright (c) 2000-2002 The OpenPKG Project ## Copyright (c) 2000-2002 Ralf S. Engelschall ## ## Permission to use, copy, modify, and distribute this software for ## any purpose with or without fee is hereby granted, provided that ## the above copyright notice and this permission notice appear in all ## copies. ## ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR ## 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. if test x"$user" = x then echo "**ERROR**: No username specified" exit 1 fi s=`uname -s 2>/dev/null` || s='Unknown' r=`uname -r 2>/dev/null` || r='0.0' platform="${s}/${r}" if test x"$user" = xnobody; then case "$platform" in HP-UX/* ) group="nogroup" ;; *) group="nobody" ;; esac else group="$user" fi shell=/bin/false if test -f /etc/shells then grep "^/usr/bin/false" /etc/shells >/dev/null 2>&1 && shell=/usr/bin/false grep "^/bin/nologin" /etc/shells >/dev/null 2>&1 && shell=/bin/nologin grep "^/sbin/nologin" /etc/shells >/dev/null 2>&1 && shell=/sbin/nologin fi home="${data_root}" xuid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${user}:" | awk -F: '{ print $3; }'` if test "x$xuid" = x then # seek for a reasonable uid/gid pair xuid=1000 ok=0 while test "x$ok" = x0 do eval "u_exists=\$u_exists_$xuid" if test "x$u_exists" = x then u_exists=`(cat /etc/passwd; ypcat passwd) 2>/dev/null | grep "^[^:]*:[^:]*:$xuid:"` fi eval "g_exists=\$g_exists_$xuid" if test "x$g_exists" = x then g_exists=`(cat /etc/group; ypcat group) 2>/dev/null | grep "^[^:]*:[^:]*:$xuid:"` fi if [ "x$u_exists" = x -a "x$g_exists" = x ]; then ok=1 break fi xuid=`expr $xuid + 1` done eval "u_exists_$xuid=yes" eval "g_exists_$xuid=yes" else # user exists xgid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${user}:" | awk -F: '{ print $4; }'` fi if test "x$xgid" = x then xgid=`(cat /etc/group; ypcat group) 2>/dev/null |\ grep "^${group}:" | awk -F: '{ print $3; }'` fi if test "x$xgid" = x then xgid="$xuid" g_exists=no else g_exists=yes fi uid=$xuid gid=$xgid if test -f /etc/shells then exists=`cat /etc/shells 2>/dev/null | grep "^$shell"` if test "x$exists" = x; then echo "${shell}" >>/etc/shells test -z "$verbose" || echo " Added ${shell} to /etc/shells" fi fi exists=`(cat /etc/passwd; ypcat passwd) 2>/dev/null | grep "^$user:"` if test x"$exists" = x; then # add entry to passwd database realname="$user" case "$platform" in FreeBSD/* | NetBSD/* | OpenBSD/* ) file=/etc/master.passwd entry="${user}:*:${uid}:${gid}::0:0:${realname}:${home}:${shell}" update="(PATH=\$PATH:/usr/sbin; pwd_mkdb -p /etc/master.passwd)" break ;; Linux/* | GNU/kFreeBSD/* | GNU/* ) file=/etc/passwd entry="${user}:*:${uid}:${gid}:${realname}:${home}:${shell}" update="(PATH=\$PATH:/usr/sbin; pwconv)" break ;; SunOS/5.* ) file=/etc/passwd entry="${user}:*:${uid}:${gid}:${realname}:${home}:${shell}" update="(PATH=\$PATH:/usr/sbin; pwconv)" break ;; OSF1/V5.* ) file=/etc/passwd entry="${user}:*:${uid}:${gid}:${realname}:${home}:${shell}" update="(PATH=\$PATH:/usr/sbin; mkpasswd /etc/passwd)" break ;; HP-UX/* ) file=/etc/passwd entry="${user}:*:${uid}:${gid}:${realname}:${home}:${shell}" update=":" break ;; IRIX*/* ) file=/etc/passwd entry="${user}:*:${uid}:${gid}:${realname}:${home}:${shell}" update=":" break ;; *) echo "install-user: Unsupported system $platform" echo "Please add user $user / group $group manually" echo " and re-run make install-user" exit 1 ;; esac cp $file $file.bak && \ (grep -v '^+:' $file.bak; echo $entry; grep '^+:' $file.bak) >$file rm -f $file.bak >/dev/null 2>&1 eval $update test -z "$verbose" || echo " Added user: ${user} uid: ${uid} shell: ${shell}" else test -z "$verbose" || echo " User ${user} exists already" fi # check whether group already exists # FIXME exists=`(cat /etc/group; ypcat group) 2>/dev/null | grep "^$group:"` if test x"$exists" = x then # # user has a valid GID # if test g_exists = xyes; then exists=yes fi fi if test x"$exists" = x then # add entry to group database file=/etc/group entry="${group}:*:${gid}:${user}" cp $file $file.bak && \ (grep -v '^+:' $file.bak; echo $entry; grep '^+:' $file.bak) >$file rm -f $file.bak >/dev/null 2>&1 test -z "$verbose" || echo " Added group: ${group} gid: ${gid} user: ${user}" fi exit 0 fi if test x"$act" = xboot || test x"$act" = xuboot then s=`uname -s 2>/dev/null` || s='Unknown' r=`uname -r 2>/dev/null` || r='0.0' platform="${s}/${r}" case "$platform" in Darwin/*) DVER="MACOSX" test -z "$verbose" || echo "MacOS X system detected" rc_main="/Library/StartupItems/${samhain}" ${mkinstalldirs} ${rc_main} rc_dirz= rc_inst="(cd /Library/StartupItems/${samhain} && echo '{' >StartupParameters.plist && echo ' Description = \"@install_name@\";' >>StartupParameters.plist && echo ' Provides = (\"@install_name@\");' >>StartupParameters.plist && echo ' Requires = (\"Network\");' >>StartupParameters.plist && echo ' OrderPreference = \"Last\";' >>StartupParameters.plist && echo '}' >>StartupParameters.plist && chmod 644 StartupParameters.plist; )" rc_uinst="rm -rf /Library/StartupItems/@install_name@" ;; IRIX*/*) DVER="IRIX" test -z "$verbose" || echo " IRIX system detected" rc_main=${DESTDIR}/etc/init.d rc_dirz= rc_inst="chmod 755 /etc/init.d/@install_name@; chown root /etc/init.d/@install_name@; chkconfig -f @install_name@ on; (cd /etc; ln -f -s init.d/@install_name@ rc2.d/S99@install_name@; ln -f -s init.d/@install_name@ rc0.d/K10@install_name@; )" rc_uinst="rm -f /etc/init.d/@install_name@; rm -f /etc/rc2.d/S99@install_name@; rm -f /etc/rc0.d/K10@install_name@; chkconfig @install_name@ off" ;; AIX/*) DVER="AIX" test -z "$verbose" || echo " AIX system detected" ln -f -s @sbindir@/@install_name@ samhain.startAIX rc_main=@sbindir@ rc_dirz= rc_inst="/usr/sbin/mkitab '@install_name@:2:wait:@sbindir@/@install_name@ start >/dev/console 2>&1'" rc_uinst="/usr/sbin/rmitab @install_name@" ;; HP-UX/*) DVER="HPUX" test -z "$verbose" || echo " HP-UX system detected" rc_main=${DESTDIR}/sbin/init.d rc_dirz= rc_inst="chmod 555 /sbin/init.d/@install_name@; chown bin:bin /sbin/init.d/@install_name@; (cd /sbin && ln -f -s /sbin/init.d/@install_name@ rc2.d/S900@install_name@ && ln -f -s /sbin/init.d/@install_name@ rc1.d/K100@install_name@; )" rc_uinst="rm -f /sbin/init.d/@install_name@; rm -f /sbin/rc2.d/S900@install_name@; rm -f /sbin/rc1.d/K100@install_name@" ;; OpenBSD/*) test -z "$verbose" || echo " OpenBSD system detected" grep '^## begin @install_name@' /etc/rc.local >/dev/null 2>&1 if [ $? -eq 0 ]; then RCLOCALTMP=`mktemp /etc/rc.local.XXXXXXXXXX` || exit 1 sed "/^## begin @install_name@/,/^## end @install_name@/d" /etc/rc.local >$RCLOCALTMP || exit 1 cat $RCLOCALTMP >/etc/rc.local || exit 1 rm -f $RCLOCALTMP || exit 1 if test x"$act" = xuboot; then echo " uninstalling from /etc/rc.local completed" fi fi if test x"$act" = xboot; then echo "## begin @install_name@" >>/etc/rc.local || exit 1 echo "if [ -x @sbindir@/@install_name@ ]; then" >>/etc/rc.local || exit 1 echo " @sbindir@/@install_name@ start" >>/etc/rc.local || exit 1 echo "fi" >>/etc/rc.local || exit 1 echo "## end @install_name@" >>/etc/rc.local || exit 1 echo " installing to /etc/rc.local completed" fi exit 0 ;; NetBSD/*) test -z "$verbose" || echo " NetBSD system detected" if test -f /etc/rc.subr; then DVER="FreeBSD" rc_main=${DESTDIR}/etc/rc.d rc_dirz= rc_inst="chmod 755 /etc/rc.d/@install_name@" rc_uinst="rm -f /etc/rc.d/@install_name@" else echo "${0}: unsupported platform ${platform} (too old)" exit 1 fi ;; FreeBSD/* ) test -z "$verbose" || echo " FreeBSD system detected" if test -f /etc/rc.subr; then DVER="FreeBSD" rc_main=${DESTDIR}/etc/rc.d rc_dirz= rc_inst="chmod 755 /etc/rc.d/@install_name@" rc_uinst="rm -f /etc/rc.d/@install_name@" else DVER="Solaris" rc_main=${DESTDIR}/usr/local/etc/rc.d rc_dirz= rc_inst="mv /usr/local/etc/rc.d/@install_name@ /usr/local/etc/rc.d/@install_name@.sh && chmod 755 /usr/local/etc/rc.d/@install_name@.sh" rc_uinst="rm -f /usr/local/etc/rc.d/@install_name@.sh" fi if test x"$act" = xboot then if [ ! -d ${rc_main} ]; then test x"$act" = xboot && mkdir ${rc_main} fi if test "x$DVER" = "xSolaris"; then ( . /etc/defaults/rc.conf . /etc/rc.conf found=0 for p in ${local_startup-x}; do if test "x$p" = "x${rc_main}"; then found=1 break fi done if test "x$found" = x0; then cp -p /etc/rc.conf /etc/rc.conf.bak ( grep -v local_startup /etc/rc.conf.bak echo "local_startup=\"${rc_main} $local_startup\"" ) >/etc/rc.conf fi ) fi fi ;; SunOS/5.* ) DVER="Solaris" DVER_REAL="Solaris" test -z "$verbose" || echo " Solaris system detected" rc_dirz= rc_main=${DESTDIR}/etc/init.d rc_inst="chmod 755 ${DESTDIR}/etc/init.d/@install_name@; chown root:sys ${DESTDIR}/etc/init.d/@install_name@; (cd ${DESTDIR}/etc; ln init.d/@install_name@ rc3.d/S99@install_name@; ln init.d/@install_name@ rc0.d/K10@install_name@; ln init.d/@install_name@ rc1.d/K10@install_name@; )" rc_uinst="rm -f ${DESTDIR}/etc/init.d/@install_name@; rm -f ${DESTDIR}/etc/rc0.d/K10@install_name@; rm -f ${DESTDIR}/etc/rc1.d/K10@install_name@; rm -f ${DESTDIR}/etc/rc3.d/S99@install_name@" ;; Linux/* | GNU/kFreeBSD* | GNU/* ) rlv="2 3 4 5" linkopt="-f -s" # find rc directories if test -f /usr/lib/lsb/install_initd && test -d /etc/init.d then test -z "$verbose" || echo " Linux Standard Base system detected" DVER=LSB if test x"$DESTDIR" = x then rc_main=/etc/init.d rc_dirz= rc_inst="/usr/lib/lsb/install_initd /etc/init.d/@install_name@" rc_uinst="/usr/lib/lsb/remove_initd /etc/init.d/@install_name@" else rc_inst= rc_uinst= rc_main=${DESTDIR}/etc/init.d rc_dirz= # test -d /etc/init.d/rc2.d && rc_dirz=${DESTDIR}/etc/init.d/rc # test -d /etc/rc.d/rc2.d && rc_dirz=${DESTDIR}/etc/rc.d/rc # test -d /etc/rc2.d && rc_dirz=${DESTDIR}/etc/rc fi elif test -f /etc/SuSE-release then test -z "$verbose" || echo " SuSE system detected" DVER="Linux" rc_inst= rc_uinst= if test -d /sbin/init.d && test -d /sbin/init.d/rc2.d then test -z "$verbose" || echo " SuSE 6.x system detected" rc_main=${DESTDIR}/sbin/init.d rc_dirz=${DESTDIR}/sbin/init.d/rc elif test -d /etc/init.d && test -d /etc/init.d/rc2.d then test -z "$verbose" || echo " SuSE 7.x or newer detected" rc_main=${DESTDIR}/etc/init.d rc_dirz=${DESTDIR}/etc/init.d/rc else echo "${0}: unknown system" exit 1 fi elif test -d /sbin/init.d && test -d /sbin/init.d/rc2.d then DVER="Linux" rc_inst= rc_uinst= test -z "$verbose" || echo " SuSE 5.x system detected" rc_main=${DESTDIR}/sbin/init.d rc_dirz=${DESTDIR}/sbin/init.d/rc elif test -f /etc/debian_version then DVER="Linux" test -z "$verbose" || echo " Debian based system detected" if test x"$DESTDIR" = x then rc_main=/etc/init.d rc_dirz= rc_uinst="/usr/sbin/update-rc.d -f @install_name@ remove" rc_inst="/usr/sbin/update-rc.d @install_name@ defaults 99 10" else rc_inst= rc_uinst= rc_main=${DESTDIR}/etc/init.d # rc_dirz=${DESTDIR}/etc/rc rc_dirz= fi elif test -f /etc/redhat-release then DVER="Linux" test -z "$verbose" || echo " Redhat based system detected" rc_uinst= rc_inst= rc_main=${DESTDIR}/etc/rc.d/init.d rc_dirz=${DESTDIR}/etc/rc.d/rc elif test -f /etc/mandrake-release then DVER="Linux" test -z "$verbose" || echo " Mandrake based system detected" rc_uinst= rc_inst= rc_main=${DESTDIR}/etc/rc.d/init.d rc_dirz=${DESTDIR}/etc/rc.d/rc elif test -f /etc/yellowdog-release then DVER="Linux" test -z "$verbose" || echo " Yellow Dog based system detected" rc_uinst= rc_inst= rc_main=${DESTDIR}/etc/rc.d/init.d rc_dirz=${DESTDIR}/etc/rc.d/rc elif test -f /etc/slackware-version && test -f /etc/rc.d/rc.sysvinit then DVER="Linux" test -z "$verbose" || echo " Slackware based system detected" rc_uinst= rc_inst= rc_main=${DESTDIR}/etc/rc.d rc_dirz=${DESTDIR}/etc/rc.d/rc elif test -f /etc/gentoo-release then DVER="Gentoo" test -z "$verbose" || echo " Gentoo based system detected" rc_uinst="/sbin/rc-update del @install_name@" rc_inst="/sbin/rc-update add @install_name@ default" rc_main=${DESTDIR}/etc/init.d rc_dirz= else echo "${0}: unknown Linux distribution" rc_uinst= rc_inst= rc_main= rc_dirz= for ff in /etc/rc.d/init.d /etc/init.d /sbin/init.d; do if test -d $ff; then rc_main="$ff" break fi done for fg in /etc/rc.d/rc2.d /etc/rc2.d /sbin/init.d/rc2.d; do if test -d $fg; then rc_dirz="`echo $fg | sed -e 's,2.*,,'`" break fi done if [ x"${rc_dirz}" = x ]; then echo "${0}: no install directory for runlevel scripts found" exit 1 fi if [ x"${rc_main}" = x ]; then echo "${0}: no install directory for runlevel scripts found" exit 1 fi DVER="Linux" rc_main="${DESTDIR}${rc_main}" rc_dirz="${DESTDIR}${rc_dirz}" fi ;; *) echo "${0}: unsupported platform ${platform}" exit 1 ;; esac if test x"${rc_main}" = x then echo "${0}: no install directory for runlevel scripts found" exit 1 fi if test x"${act}" = xboot then startscript=NONE if test -f init/samhain.start${DVER} then startscript=`eval echo init/samhain.start${DVER}` elif test -f samhain.start${DVER} then startscript=`eval echo samhain.start${DVER}` else echo "${0}: cannot find samhain.start${DVER} in ./ or ./init" exit 1 fi if test "x${startscript}" = xNONE; then echo "${0}: cannot find samhain.start${DVER} in ./ or ./init" exit 1 else if test -f ${rc_main}/${samhain} && test x"$force" != xyes then echo " ${rc_main}/${samhain} exists ... not overwritten (or use --force)" else if test x"$DESTDIR" = x then : else ${mkinstalldirs} ${rc_main} # if test x"${DVER_REAL}" = xSolaris; then ${mkinstalldirs} ${DESTDIR}/etc/rc0.d ${mkinstalldirs} ${DESTDIR}/etc/rc1.d ${mkinstalldirs} ${DESTDIR}/etc/rc3.d fi # fi test -z "$verbose" || echo " ${INSTALL_SHELL} ${startscript} ${rc_main}/${samhain}" if test -f "@INSTALL@"; then ${INSTALL_SHELL} ${startscript} ${rc_main}/${samhain} else cp ${startscript} ${rc_main}/${samhain} && chmod 0700 ${rc_main}/${samhain} fi fi fi if test x"${rc_dirz}" != x then for ff in $rlv do if test x"${DESTDIR}" = x then rldir="${rc_dirz}${ff}.d/" test -z "$verbose" || echo " cd ${rldir} && ln ${linkopt} ${rc_main}/${samhain} S99${samhain}" (cd ${rldir} && ln ${linkopt} ${rc_main}/${samhain} S99${samhain}) test -z "$verbose" || echo " cd ${rldir} && ln ${linkopt} ${rc_main}/${samhain} K10${samhain}" (cd ${rldir} && ln ${linkopt} ${rc_main}/${samhain} K10${samhain}) else : # ${mkinstalldirs} ${rc_dirz}${ff}.d fi done fi if test x"${rc_inst}" != x then if test x"${DESTDIR}" = x then test -z "$verbose" || echo " ${rc_inst}" eval ${rc_inst} fi fi echo "installing init scripts completed" fi if test x"${act}" = xuboot then if test x"${rc_uinst}" != x then test -z "$verbose" || echo " ${rc_uinst}" echo eval ${rc_uinst} fi if test x"${rc_dirz}" != x then for ff in $rlv do test -z "$verbose" || echo " rm -f ${rc_dirz}${ff}.d/S99${samhain}" rm -f ${rc_dirz}${ff}.d/S99${samhain} test -z "$verbose" || echo " rm -f ${rc_dirz}${ff}.d/S99${samhain}" rm -f ${rc_dirz}${ff}.d/K10${samhain} done fi test -z "$verbose" || echo " rm -f ${rc_main}/${samhain}" rm -f ${rc_main}/${samhain} echo " uninstalling init scripts completed" fi # boot_install|boot_uninstall completed exit 0 fi if test x"${act}" = xuprogram then PROGRAMS="@setpwd_prg@ @stegin_prg@ @yulectl_prg@ @sh_main_prg@ @samhainadmin_prg@" for p in $PROGRAMS; do test -z "$verbose" || echo " rm -f ${DESTDIR}${sbindir}/`echo $p|sed 's%samhain%@install_name@%'|sed 's%yule%@install_name@%'|sed 's%.*/%%'`" rm -f ${DESTDIR}${sbindir}/`echo $p|sed 's%samhain%@install_name@%'|sed 's%yule%@install_name@%'|sed 's%.*/%%'` done test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${sbindir} ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${sbindir} >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi exit 0 fi if test x"${act}" = xuman then test -z "$verbose" || echo " rm -f ${DESTDIR}${mandir}/man8/@install_name@.8" rm -f ${DESTDIR}${mandir}/man8/@install_name@.8 test -z "$verbose" || echo " rm -f ${DESTDIR}${mandir}/man5/@install_name@rc.5" rm -f ${DESTDIR}${mandir}/man5/@install_name@rc.5 OLD_IFS=${IFS} IFS=':'; export IFS for ff in ${MANPATH}; do if test x"$ff/man8" = x"${DESTDIR}${mandir}/man8"; then echo " man directory ${DESTDIR}${mandir} is in your MANPATH" echo " -- will not try to remove" IFS=${OLD_IFS}; export IFS exit 0 fi done IFS=${OLD_IFS}; export IFS test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${mandir}/man8 ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${mandir}/man8 >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${mandir}/man5 ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${mandir}/man5 >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${mandir} ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${mandir} >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi exit 0 fi if test x"${act}" = xudata then test -z "$verbose" || echo " rm -f ${DESTDIR}`echo ${mydatafile}|sed s%REQ_FROM_SERVER%%`" rm -f ${DESTDIR}`echo ${mydatafile}|sed s%REQ_FROM_SERVER%%` test -z "$verbose" || echo " rm -f ${DESTDIR}${pid_file}" rm -f ${DESTDIR}${pid_file} test -z "$verbose" || echo " rm -f ${DESTDIR}${mylogfile}" rm -f ${DESTDIR}${mylogfile} test -z "$verbose" || echo " rm -f ${DESTDIR}${myhtmlfile}" rm -f ${DESTDIR}${myhtmlfile} test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${pid_dir} ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${pid_dir} >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${mylogdir} ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${mylogdir} >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${data_root} ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${data_root} >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi if test -d /etc/logrotate.d; then if test -f /etc/logrotate.d/@install_name@; then test -z "$verbose" || echo $ECHO_N " rm -f /etc/logrotate.d/@install_name@ ... $ECHO_C" rm -f /etc/logrotate.d/@install_name@; if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed" fi fi fi if test x"$force" = "xyes" then test -z "$verbose" || echo " rm -f ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%`" rm -f ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%` elif test x"$purge" = "xyes" then test -z "$verbose" || echo " rm -f ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%`" rm -f ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%` elif test x"$express" = x; then echo " Do you want to remove the configuration file [y/n] ?" while [ "1" = "1" ]; do read ff case "$ff" in Y* | y* ) test -z "$verbose" || echo " rm -f ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%`" rm -f ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%` break ;; N* | n* ) test -z "$verbose" || echo " ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%` NOT removed" break ;; *) echo " Enter y[es] or n[o]" ;; esac done else test -z "$verbose" || echo " NOT REMOVED: config file ${DESTDIR}`echo ${configfile}|sed s%REQ_FROM_SERVER%%` (use --force to remove)" fi test -z "$verbose" || echo $ECHO_N " ${SH_RMDIR} ${DESTDIR}${sysconfdir} ... $ECHO_C" ${SH_RMDIR} ${DESTDIR}${sysconfdir} >/dev/null 2>&1 if test x$? = x0; then test -z "$verbose" || echo "${ECHO_T}done" else test -z "$verbose" || echo "${ECHO_T}failed (not empty ?)" fi exit 0 fi if test x"${act}" = xdata then STEGIN=@stegin_prg@ CONVERT= GPGPATH=@mygpg@ TARGETKEYID=@mykeyid@ KEYTAG=@mykeytag@ NTEST=@mytclient@ if test x"${NTEST}" = "x-DSH_WITH_SERVER" then RCFILE=yulerc if test -f $RCFILE then : else if test -f yulerc.template then cp yulerc.template $RCFILE fi fi else RCFILE=samhainrc IN_RCFILE=samhainrc.@selectconfig@ if test -f ${RCFILE} then : else if test -f ${IN_RCFILE} then test -z "$verbose" || echo " cp ${IN_RCFILE} ${RCFILE}" cp ${IN_RCFILE} ${RCFILE} fi fi fi if test -f $RCFILE then : else echo "${0}: cannot find configuration file $RCFILE" exit 1 fi if test x"${GPGPATH}" != x then echo echo "You need to sign the config file now" echo test -z "$verbose" || echo " ${GPGPATH} -a ${KEYTAG} ${TARGETKEYID} --clearsign $RCFILE" if test x"${NTEST}" = "x-DSH_WITH_SERVER" then myident_uid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${samhain}:" | awk -F: '{ print $3; }'` if test x"${myident_uid}" != x then DOT_GNUPG=`eval echo ~${samhain}/.gnupg` test -z "$verbose" || echo " using --homedir ${DOT_GNUPG}" ${GPGPATH} --homedir ${DOT_GNUPG} -a ${KEYTAG} ${TARGETKEYID} --clearsign $RCFILE else ${GPGPATH} -a ${KEYTAG} ${TARGETKEYID} --clearsign $RCFILE fi else ${GPGPATH} -a ${KEYTAG} ${TARGETKEYID} --clearsign $RCFILE fi if test -f ${RCFILE}.asc then test -z "$verbose" || echo " mv -f ${RCFILE}.asc samhainrc.pre" mv -f ${RCFILE}.asc samhainrc.pre else echo "**********************************************************" echo echo "${0}: ERROR: cannot find signed file ${RCFILE}.asc" echo echo " --- You need to sign the configuration file ---" echo echo "**********************************************************" cp ${RCFILE} samhainrc.pre fi else test -z "$verbose" || echo " cp $RCFILE samhainrc.pre" cp $RCFILE samhainrc.pre fi if test x"${STEGIN}" != x then test -z "$verbose" || echo " searching for ImageMagick convert utility" OPATH=${PATH} PATH="/usr/local/bin:/usr/X11R6/bin:"${PATH} OIFS=${IFS} IFS=":" for dd in ${PATH} do if test -f "${dd}/convert" then "${dd}/convert" --help | grep ImageMagick >/dev/null 2>&1 && \ CONVERT="${dd}/convert" test -z "$verbose" || echo " CONVERT=${dd}/convert" fi done IFS=${OIFS} if test -f stealth_template.ps then PATH=${OPATH} else if test x"${CONVERT}" = x then echo "${0}: cannot find ImageMagick convert utility in PATH=${PATH}" exit 1 fi PATH=${OPATH} if test -f stealth_template.jpg then test -z "$verbose" || echo " ${CONVERT} +compress stealth_template.jpg stealth_template.ps" "${CONVERT}" +compress stealth_template.jpg stealth_template.ps else echo "${0}: cannot find file stealth_template.jpg" exit 1 fi fi if test -f stealth_template.ps then : else echo "${0}: file stealth_template.ps not created" exit 1 fi if test -f samhainrc.pre then : else echo "${0}: cannot find configuration file samhainrc.pre" exit 1 fi if test -f ./samhain_stealth then : else echo "${0}: cannot find utility ./samhain_stealth" exit 1 fi ccount=`./samhain_stealth -o samhainrc.pre 2>&1 | awk '{ print $1 }'` mcount=`./samhain_stealth -i stealth_template.ps 2>&1 | awk '{ print $7 }'` if test ${mcount} -lt ${ccount} then echo "${0}: configuration file samhainrc too big," echo " need a larger image stealth_template.jpg to store" exit 1 fi test -z "$verbose" || echo " ./samhain_stealth -s stealth_template.ps samhainrc.pre" ./samhain_stealth -s stealth_template.ps samhainrc.pre test -z "$verbose" || echo " mv -f stealth_template.ps samhainrc.install" mv -f stealth_template.ps samhainrc.install else test -z "$verbose" || echo " mv -f samhainrc.pre samhainrc.install" mv -f samhainrc.pre samhainrc.install fi tmp_configfile=`echo ${configfile} | sed 's%^REQ_FROM_SERVER%%'` if test x"${tmp_configfile}" = x then echo " No local configfile to install." exit 0 fi if test -f ${DESTDIR}${tmp_configfile} && test x"$force" = x then echo " ${DESTDIR}${tmp_configfile} exists ... not overwritten (or use --force)" else test -z "$verbose" || echo " ${INSTALL_DATA} samhainrc.install ${DESTDIR}${tmp_configfile}" ${INSTALL_DATA} samhainrc.install ${DESTDIR}${tmp_configfile} fi if test x"${NTEST}" = "x-DSH_WITH_SERVER" then test -z "$verbose" || echo " chown @myident@ ${DESTDIR}${tmp_configfile}" chown @myident@ ${DESTDIR}${tmp_configfile} fi # # Changed: don't check if DESTDIR is set, as these are not # the true install locations anyway # if test -f trustfile && test x"${DESTDIR}" = x then test -z "$verbose" || echo " checking whether paths are trustworthy" RESULT=`./trustfile ${DESTDIR}${tmp_configfile} 2>&1` if test x$? != x0 then echo ./trustfile ${DESTDIR}${tmp_configfile} echo else test -z "$verbose" || echo " configuration file ${DESTDIR}${tmp_configfile} ... OK" fi RESULT=`./trustfile ${DESTDIR}${pid_dir} >/dev/null 2>&1` if test x$? != x0 then echo ./trustfile ${DESTDIR}${pid_dir} echo else test -z "$verbose" || echo " state directory ${DESTDIR}${pid_dir} ... OK" fi RESULT=`./trustfile ${DESTDIR}${mylogdir} >/dev/null 2>&1` if test x$? != x0 then echo ./trustfile ${DESTDIR}${mylogdir} echo else test -z "$verbose" || echo " state directory ${DESTDIR}${mylogdir} ... OK" fi RESULT=`./trustfile ${DESTDIR}${data_root} >/dev/null 2>&1` if test x$? != x0 then echo ./trustfile ${DESTDIR}${data_root} echo else test -z "$verbose" || echo " data directory ${DESTDIR}${data_root} ... OK" fi fi # install_data exit 0 fi samhain-4.1.4/README0000644000175000017500000003651312615253270010754 00000000000000 CONTENT OF THIS DOCUMENT ------------------------ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ +++ +++ NOTE: The distribution package contains a much more detailed MANUAL +++ +++ +++ +++ ---- See the docs/ subdirectory ---- +++ +++ +++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - INSTALL basic install procedure - PGP SIGNATURES signing database and config file - CLIENT/SERVER how to install and use with client/server mode for distributed host monitoring - STEALTH how to install and use with stealth mode enabled - USAGE some usage examples - CAVEATS what the name says - START AT BOOT TIME how to start the daemon during the boot sequence - CONFIGURE OPTIONS overview of supported options, and defaults - TESTING test suite (also useful to see EXAMPLES) INSTALL: ------- Unpack the source with: gunzip -c samhain-current.tar.gz | tar xvf - This will drop two files in your current directory: samhain-{version}.tar.gz samhain-{version}.tar.gz.asc To check authenticity and integrity of the source code, verify the PGP signature on samhain-{version}.tar.gz (public PGP key for Rainer Wichmann at http://wwwkeys.pgp.net/): gpg --verify samhain-{version}.tar.gz.asc samhain-{version}.tar.gz Then unpack samhain-{version}.tar.gz: gunzip -c samhain-{version}.tar.gz | tar xvf - cd samhain-{version} If you have an incarnation of 'dialog' (xdialog, dialog, lxdialog) installed, you can use the GUI install tool: ./Install.sh Otherwise use the commands: ./configure [options] make su root make install At least the following executable will be built: +++ samhain +++ the monitoring agent, without any client/server support (i.e. local use only) Additional executables will be built if you compile in client/server and/or stealth mode (see below). The 'make install' target will strip the executable(s), i.e. discard symbols. PATHS: ----- For configuring the install paths/locations, see the MANUAL. WARNING: ------- Some versions of gcc have a bug that generates incorrect code if strength reducing is enabled. If you modify the compiler flags, always use the -fno-strength-reduce option with gcc, unless you are sure that your compiler does not suffer from the problem (see README.gcc_bug). Also, some gcc versions generate incorrect code unless the -fno-omit-frame-pointer option is used. The -fno-strength-reduce and the -fno-omit-frame-pointer options are enabled by default by the 'configure' script. PGP SIGNATURES: -------------- By default, samhain will report on the checksums of the database and configuration files on startup. You can always (clear)sign the database (once initialized) with GnuPG, as well as the configuration file (recommended: gpg -a --clearsign --not-dash-escaped FILE). However, to have samhain check these signatures, rather than ignoring them, you need GnuPG and you must compile samhain with the option ./configure --with-gpg=PATH where PATH is the path to the gpg/pgp binary. Samhain will invoke gpg only after checking that only trusted users (by default: root and the effective user) have write access to any element in the path. The public key for verification must be in the keyring of the effective user (usually root) For more security, it is possible to compile in the checksum of the GnuPG executable, and/or the key fingerprint. See the MANUAL for more details. The public key will be searched in the gpg home directory (~/.gnupg/) of the effective user (usually root). The key identification and fingerprint will be reported. CLIENT/SERVER: ------------- samhain supports logging to a central server via TCP/IP. To enable this option, use the ./configure option ./configure --enable-network=client|server [more options] NOTE: client and server are __distict__ applications, and must be built seperately. By default, installation names and paths are different. Do not blame us if you abuse './configure' options to cause name clashes, if you install both on the same host. The following executables are built: +++ samhain (client) +++ the monitoring agent, with client code included if --enable-network=client +++ yule (server) +++ the log server (no monitoring, just report collecting !!!) if --enable-network=server +++ samhain_setpwd +++ a utility program to set the password of a monitoring agent (see man page samhain.8). Use it without options to get help. To set up a monitoring agent, do the following: -- select a (16-digit hexadecimal) password. To generate a random password, you can use: ./yule -G -- use 'samhain_setpwd samhain ' to generate an agent 'samhain.suffix' with the selected password (you can rename the agent afterwards, of course) -- use 'yule -P password' to compute an entry to register the agent -- in the servers's configuration file, insert the computed entry (replace HOSTNAME with the host, on which the agent will run) in the section called [Clients] By default, client/server authentication is done with the SRP (Secure Remote Password) protocol. It is also possible to store configuration and database files on the server. See the manual for details. STEALTH: ------- samhain supports a 'stealth' mode of operation, meaning that the program can be run without any obvious trace of its presence on disk. The supplied facilities are more sophisticated than just running the program under a different name, and might thwart efforts using 'standard' Unix commands, but they will not resist a search using dedicated utilities. To enable this mode, use the ./configure option ./configure --enable-stealth=XOR_VAL [more options] XOR_VAL must be a decimal number in the range 0, 128..255 (using 0 will have no effect). The runtime executable will contain no printable strings revealing its nature or purpose (strings are xor'ed with XOR_VAL at compile time, and decoded at runtime). The configuration file is expected to be a postscript file with _uncompressed_ image data, wherein the configuration data are hidden by steganography. To create a suitable image file from an existing image, you may use e.g. the ImageMagick program 'convert', such as: convert +compress ima.jpg ima.ps The following additional executable will be built: +++ samhain_stealth +++ steganography utility program to hide/extract the configuration file data in/from a postscript file with _uncompressed_ image data. Use it without options to get help. Database and log file entries are xor'ed with XOR_VAL to 'mask' printable strings as binary data. No steganography is supported for them, as this would require image files of unreasonable large size. However, if the database/log file is an existing image (say, a .jpg file), the data will be appended to the end of the image data. The image will display normally, and on examination of the file, the add-on data will look like binary (image) data at first sight. The built-in utility to verify and print log file entries will handle this situation transparently. To re-name samhain to something unsuspicious, use the configure option ./configure --enable-install-name=NAME 'make install' will then re-name samhain upon installation. Also, database, log file, and pid file will have 'samhain' replaced by NAME. USAGE EXAMPLES: -------------- Review the default configuration file that comes with the source distribution. Read the man page (samhain.8). initialize database: samhain -t init check files: samhain -t check run as daemon: samhain -t check -D report to log server: samhain -t check -D -e warn start the log server: yule -S CAVEATS: ------- Permissions: ----------- samhain needs root permissions to check some system files. The log server does not require root permissions, unless you use a privileged port (port number below 1024). If you use --enable-udp to listen on the syslog socket, you need to start the log server with root permissions (it will drop them after binding to the port). Trust: ----- samhain checks the path to critical files (database, configuration) for write access by untrusted users. By default, only root and the effective user are trusted. More UIDs can be added as a compile options (some systems habe 'bin' as owner of the root directory). Integrity: --------- On startup, samhain will report on signatures or checksums of database and configuration files. You better check these reports. Both startup and exit will be reported. If you are using samhain as daemon and start it at boot time, you may want to check that startup/exit corresponds with scheduled reboots. If the path to the samhain binary is defined in the configuration file, samhain will checksum the binary at startup and compare at program termination. This will minimize the time available for an intruder to modify the binary. Mail address: ------------ For offsite mail, you may have to set a mail relay host in the configuration file. START AT BOOT TIME: ------------------ the easy way (supported on Linux, FreeBSD, HP-UX, AIX): su root make install-boot CONFIGURE OPTIONS: ----------------- ------------------- -- basic options -- ------------------- --enable-network Compile with client/server support. --enable-udp Enable the server to listen on port 514/udp (syslog). --enable-srp Use SRP protocol to authenticate to log server. --with-gpg=PATH Use GnuPG to verify database/config. The public key of the effective user (in ~/.gnupg/pubring.gpg) will be used. --enable-login-watch Watch for login/logout events. --enable-stealth=XOR_VAL Enable stealth mode, and set XOR_VAL. XOR_VAL must be decimal in 0..32 or 127..255 and will be used to 'mask' literal strings as binary data. (0 has no effect). --enable-micro-stealth=XOR_VAL As --with-stealth, but without steganographic hidden configuration file. --enable-nocl=PW Enable command line parsing ONLY if PW is the first argument on the command line. If PW is "" (empty string), command line parsing is completely disabled. --enable-base=BASE Set base for one-time pads. Must be ONE string (no space) made of TWO comma-separated integers in the range -2147483648...2147483647. (The default is compile time.) Binaries compiled with different values cannot verify the audit trail(s) of each other. THIS IS IMPORTANT IF YOU COMPILE MULTIPLE TIMES, E.G. ON DIFFERENT HOSTS. ------------------- -- paths -- ------------------- ${install_name} is "samhain" by default (see --with-install-name=NAME ) configuration: /etc/${install_name}rc state data: /var/lib/${install_name} log file: /var/log/${install_name}_log lock/pid file: /var/run/${install_name}.pid mandir: /usr/local/man bindir: /usr/local/sbin/ --exec-prefix=EPREFIX Set sbindir prefix (default is /usr/local, ie. binaries go to /usr/local/sbin) --prefix=PREFIX install directory (default is NONE) IF PREFIX = USR; then configuration: /etc/${install_name}rc state data: /var/lib/${install_name} log file: /var/log/${install_name}_log lock/pid file: /var/run/${install_name}.pid mandir: /usr/share/man bindir: /usr/sbin/ IF PREFIX = OPT; then configuration: /etc/opt/${install_name}rc state data: /var/opt/${install_name}/${install_name} log file: /var/opt/${install_name}/${install_name}_log lock/pid file: /var/opt/${install_name}/${install_name}.pid mandir: /opt/${install_name}/man bindir: /opt/${install_name}/bin/ IF PREFIX = (something else); then If EPREFIX is not set, it will be set to PREFIX. configuration: PREFIX/etc/${install_name}rc state data: PREFIX/var/lib/${install_name} log file: PREFIX/var/log/${install_name}_log lock/pid file: PREFIX/var/run/${install_name}.pid mandir: PREFIX/share/man bindir: PREFIX/sbin/ --with-config-file=FILE Set path of configuration file (default is PREFIX/etc/samhainrc) --with-data-file=FILE Set path of data file (PREFIX/var/lib/samhain/samhain_file) --with-html-file=FILE Set path of server status html file (PREFIX/var/lib/samhain/samhain.html) --with-log-file=FILE Set path of log file (PREFIX/var/log/samhain_log) --with-pid-file=FILE Set path of lock file (PREFIX/var/run/samhain.pid) ------------------- -- other -- ------------------- --with-checksum=CHECKSUM Compile in TIGER checksum of the gpg/pgp binary. CHECKSUM must be the full line output by samhain or GnuPG when computing the checksum. --with-fp=FINGERPRINT Compile in public key fingerprint. FINGERPRINT must be without spaces. Only useful in combination with '--with-gpg'. If used, samhain will check the fingerprint, but still report on the used public key. --enable-identity=USER Set user when dropping root privileges (default is the user "nobody"). Only needed if there is no user 'nobody' on your system (check /etc/passwd) --with-port=PORT Set port number for TCP/IP (default is 49777). Only needed if this port is already used by some other application. --with-logserver=HOST Set host address for log server (default is NULL). You can set this in the configuration file as well. --with-timeserver=HOST Set host address for time server (default is NULL - use own clock). You can set this in the configuration file as well. --with-sender=SENDER Set sender for e-mail (default is daemon). --enable-xml-log Use XML format for log file. --enable-debug Enable extended debugging --enable-ptrace Use anti-debugging code. --with-trusted=UID Comma-separated list of UID's of users that are always trusted (default is 0 = root). You will need this only if the path to the config file has directories owned neither by 'root' nor by the (effective) user of the program. TESTING: ------- For testing compilation etc., you may use the test suite: ./test/test.sh n [hostname] The argument 'n' is the number of the test to run. Some tests require that the (fully qualified) hostname be given as second argument. Without options, you will get a short help/usage message, listing each test, its purpose, and the name of the configuration file used. You may want to review the respective configuration file before running a test. Also listed are the scripts used for each test. If you have problems getting samhain to run, you may use these scripts as examples. samhain-4.1.4/mkinstalldirs0000755000175000017500000000133412615253270012673 00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman 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" 1>&2 mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here samhain-4.1.4/acconfig.h0000644000175000017500000002720512615253270012014 00000000000000 #ifndef CONFIG_H #define CONFIG_H @TOP@ /* ---- compile options ------------ */ /* Define if you want database support */ #undef WITH_DATABASE /* Define if the database is unixODBC */ #undef WITH_ODBC /* Define if the database is oracle */ #undef WITH_ORACLE /* Define if the database is mysql */ #undef WITH_MYSQL /* Define if the database is postgresql */ #undef WITH_POSTGRES /* Define if the server may listen on 514/udp */ #undef INET_SYSLOG /* Define if you want logfile in XML format */ #undef SH_USE_XML /* Define if you want external programs. */ #undef WITH_EXTERNAL /* Define if you want to reload the database */ /* on SIGHUP. */ #undef RELOAD_DATABASE /* Define if you want SysV message queue. */ #undef WITH_MESSAGE_QUEUE /* Define the mode of the message queue. */ #undef MESSAGE_QUEUE_MODE /* Define which users are always trusted. */ /* default = 0 ( = root) */ #undef SL_ALWAYS_TRUSTED /* Define if you want network time. */ /* default = no */ #undef HAVE_NTIME /* The time server host address. */ /* default = "NULL" */ #undef DEFAULT_TIMESERVER #undef ALT_TIMESERVER /* Define if you want to use the mail code. */ /* default = yes */ #undef SH_WITH_MAIL /* Define if you want client/server encryption*/ #undef SH_ENCRYPT /* Define if you want version 2 encryption */ #undef SH_ENCRYPT_2 /* Define if you want to watch for login/-out.*/ /* default = no */ #undef SH_USE_UTMP /* Define if you want to check mount options on filesystems */ /* default = no */ #undef SH_USE_MOUNTS /* Define if you want to keep an eye on */ /* sensitive files that your users own */ #undef SH_USE_USERFILES /* Define if you want to watch for suid/sgid */ /* files */ #undef SH_USE_SUIDCHK /* Define if you want to check kernel syscall */ /* table to detect LKM rootkits. */ /* default = no */ #undef SH_USE_KERN /* Define if you want to use the Kernel */ /* module to hide samhain. */ #undef SH_USE_LKM /* Define if you have a vanilla Kernel */ /* (2.4 or 2.2) */ #undef SH_VANILLA_KERNEL /* Define to the name of the MAGIC_HIDE */ /* string if you use the Kernel module to */ /* hide samhain. */ #undef SH_MAGIC_HIDE /* Define if you want 'micro' stealth mode. */ /* default = no */ #undef SH_STEALTH_MICRO /* Define if you want to use stealth mode. */ /* default = no */ #undef SH_STEALTH /* Define if you want stealth w/o CL parsing. */ /* default = no */ #undef SH_STEALTH_NOCL /* The magic argv[1] to re-enable CL parsing. */ /* default = "yes" */ #undef NOCL_CODE /* XOR value to hide literal strings. */ /* default = 0 */ #undef XOR_CODE /* The port number for TCP/IP connection. */ /* default = 49777 */ #undef SH_DEFAULT_PORT /* The identity to assume when dropping root */ /* default = "nobody" */ #undef DEFAULT_IDENT /* Directory for tmp files */ #undef SH_TMPDIR /* The data root directory. */ /* default="/var/lib/samhain" */ #undef DEFAULT_DATAROOT /* The quarantine directory. */ /* default="/var/lib/samhain/.quarantine */ #undef DEFAULT_QDIR /* The location of the log file. */ /* default="/var/log/samhain_log" */ #undef DEFAULT_ERRFILE /* The directory of the log file. */ /* default="/var/log" */ #undef DEFAULT_LOGDIR /* The location of the pid file. */ /* default="/var/run/samhain.pid" */ #undef DEFAULT_ERRLOCK /* The location of the pid file directory. */ /* default="/var/run " */ #undef DEFAULT_PIDDIR /* The location of the configuration file. */ /* default="/etc/samhainrc" */ #undef DEFAULT_CONFIGFILE /* The location of the checksum data. */ /* default="/var/lib/samhain/samhain_file" */ #undef DEFAULT_DATA_FILE /* The location of the html report. */ /* default="/var/log/.samhain.html" */ #undef DEFAULT_HTML_FILE /* The install directory. */ /* default="/usr/local/sbin" */ #undef SH_INSTALL_DIR /* The install path. */ /* default="/usr/local/sbin/samhain" */ #undef SH_INSTALL_PATH #undef SH_INSTALL_YULE_PATH /* The install name. */ /* default="samhain" */ #undef SH_INSTALL_NAME /* The sender name to use. */ /* default = "daemon" */ #undef DEFAULT_SENDER /* The address to send mail to. */ /* default = "NULL" */ #undef DEFAULT_MAILADDRESS #undef ALT_MAILADDRESS /* The log server. */ /* default = "NULL" */ #undef DEFAULT_LOGSERVER #undef ALT_LOGSERVER /* The console. */ /* default = "NULL" */ #undef DEFAULT_CONSOLE #undef ALT_CONSOLE /* The default base for one-time pads. */ /* default = compile_time,compile_time */ #undef DEFKEY /* Define if you want more debug options. */ /* default = no */ #undef MEM_DEBUG /* Define if you want more debug output. */ /* default = no */ #undef WITH_TPT /* Define if you want tracing. */ /* default = no */ #undef WITH_TRACE /* Define if you want slib debug. */ /* default = no */ #undef SL_DEBUG /* Define if you want slib to abort on errors.*/ /* default = no */ #undef SL_FAIL_ON_ERROR /* Define if you want to use SRP authenticaton*/ #undef USE_SRP_PROTOCOL /* Define if you want to use GnuPG to */ /* verify database and configuation file. */ #undef WITH_GPG /* The full path to GnuPG */ #undef DEFAULT_GPG_PATH /* Define if using the gpg/pgp checksum. */ #undef HAVE_GPG_CHECKSUM /* The tiger checksum of the gpg/pgp binary. */ #undef GPG_HASH /* Define if you want to compile in the */ /* public key fingerprint. */ #undef USE_FINGERPRINT /* The public key fingerprint. */ #undef SH_GPG_FP /* Use ptrace - screw up signal handling. */ #undef SCREW_IT_UP /* ---- misc ------------ */ /* Define the package name. */ #undef PACKAGE /* Define the package version. */ #undef VERSION /* Define to the position of the key (1...8). */ #undef POS_TF /* Init key for exepack. */ #undef EXEPACK_STATE_0 #undef EXEPACK_STATE_1 #undef EXEPACK_STATE_2 /* ---- system-specific options ------------ */ /* Define to the address of sys_call_table */ #undef SH_SYSCALLTABLE /* Define to use SVR4 statvfs to get filesystem type. */ #undef FSTYPE_STATVFS /* Define to use SVR3.2 statfs to get filesystem type. */ #undef FSTYPE_USG_STATFS /* Define to use AIX3 statfs to get filesystem type. */ #undef FSTYPE_AIX_STATFS /* Define to use 4.3BSD getmntent to get filesystem type. */ #undef FSTYPE_MNTENT /* Define to use 4.4BSD and OSF1 statfs to get filesystem type. */ #undef FSTYPE_STATFS /* Define to use Ultrix getmnt to get filesystem type. */ #undef FSTYPE_GETMNT /* the basic type to which we can cast a uid */ #undef UID_CAST /* for ext2fs flags */ #undef HAVE_EXT2_IOCTLS #undef HAVE_STAT_FLAGS /* obvious */ #undef HOST_IS_LINUX #undef HOST_IS_I86LINUX /* obvious */ #undef HOST_IS_CYGWIN /* obvious */ #undef HOST_IS_DARWIN /* obvious */ #undef HOST_IS_FREEBSD /* obvious */ #undef HOST_IS_AIX /* obvious */ #undef HOST_IS_SOLARIS /* obvious */ #undef HOST_IS_I86SOLARIS /* obvious */ #undef HOST_IS_HPUX /* Define to the name of the random devices. */ #undef NAME_OF_DEV_RANDOM #undef NAME_OF_DEV_URANDOM /* Define if you have long long. */ #undef HAVE_LONG_LONG /* Define if short is 32 bits. */ #undef HAVE_SHORT_32 /* Define if int is 32 bits. */ #undef HAVE_INT_32 /* Define if long is 32 bits. */ #undef HAVE_LONG_32 /* Define if long is 64 bits. */ #undef HAVE_LONG_64 /* Define if UINT64 is 32 bits. */ #undef UINT64_IS_32 /* Define if you have uint64_t. */ #undef HAVE_UINT16_T /* Define if you have uint64_t. */ #undef HAVE_UINT64_T /* Define if you have utmpx.h. */ #undef HAVE_UTMPX_H /* Define if your struct utmpx has ut_xtime. */ #undef HAVE_UTXTIME /* Define if your struct utmp has ut_type. */ #undef HAVE_UTTYPE /* Define if your struct utmp has ut_host. */ #undef HAVE_UTHOST /* Define if your struct utmp has ut_addr. */ #undef HAVE_UTADDR /* Define if your struct utmp has ut_addr_v6 */ #undef HAVE_UTADDR_V6 /* Define if your includes are broken. */ #undef HAVE_BROKEN_INCLUDES /* Define if your getcwd uses 'popen'. */ #undef HAVE_BROKEN_GETCWD /* Define if your vsnprintf is broken. */ #undef HAVE_BROKEN_VSNPRINTF /* Define if you have va_copy. */ #undef VA_COPY /* Define if va_list may be copied as array. */ #undef VA_COPY_AS_ARRAY /* Define if you need unix entropy gatherer. */ #undef HAVE_UNIX_RANDOM /* Define if you have EGD. */ #undef HAVE_EGD_RANDOM /* Define if you have /dev/random. */ #undef HAVE_URANDOM /* Soket name for EGD. */ #undef EGD_SOCKET_NAME /* Define if your mlock() is broken. */ #undef HAVE_BROKEN_MLOCK /* Define the proc f_type. */ #undef SH_PROC_MAGIC /* Define if you have statfs. */ #undef HAVE_STATFS /* Define if statfs works. */ #undef STATFS_WORKS /* Define to long if not defined. */ #undef ptrdiff_t @BOTTOM@ /* dont modify this, unless you know what you do */ #define SRP_GENERATOR_1024 "2" #define SRP_MODULUS_1024_1 \ _("f488fd584e49dbcd20b49de49107366b336c380d451d0f7c88b31c7c5b2d8ef6") #define SRP_MODULUS_1024_2 \ _("f3c923c043f0a55b188d8ebb558cb85d38d334fd7c175743a31d186cde33212c") #define SRP_MODULUS_1024_3 \ _("b52aff3ce1b1294018118d7c84a70a72d686c40319c807297aca950cd9969fab") #define SRP_MODULUS_1024_4 \ _("d00a509b0246d3083d66a45d419f9c7cbd894b221926baaba25ec355e92f78c7") #define SDG_0RETU _("return.\n") #define SDG_TERRO _("ERROR: file=<%s>, line=<%d>, reason=<%s>\n") #define SDG_AERRO _("ERROR: file=<%s>, line=<%d>, failed_assertion=<%s>\n") #define SDG_AFAIL _("FAILED: file=<%s>, line=<%d>, assertion=<%s>\n") #define SDG_ENTER _("enter=<%s>\n") #define SDG_RETUR _("return=<%s>.\n") #define SDG_ERROR _("error=<%ld>.\n") #ifdef SH_STEALTH char * globber(const char * string); #define _(string) globber(string) #define N_(string) string #else #define _(string) string #define N_(string) string #endif #endif samhain-4.1.4/init/0000755000175000017500000000000012724114744011112 500000000000000samhain-4.1.4/init/samhain.startMACOSX.in0000644000175000017500000000055512615253277015062 00000000000000#!/bin/sh . /etc/rc.common StartService() { ConsoleMessage "Starting service @install_name@." @sbindir@/@install_name@ start } StopService() { ConsoleMessage "Stopping service @install_name@." @sbindir@/@install_name@ stop } RestartService() { ConsoleMessage "Restarting service @install_name@." @sbindir@/@install_name@ restart } RunService "$1" samhain-4.1.4/init/samhain.startHPUX.in0000644000175000017500000000334412615253277014653 00000000000000#!/sbin/sh # Allowed exit values # # 0 = success # 1 = failure # 2 = skip # 3 = reboot (now) # stdin is redirected from /dev/null # stderr, stdout are redirected to /etc/rc.log file (checklist mode) # or console (raw mode) # /usr, /var, /opt my not be available until run state 2 PATH=/usr/sbin:/usr/bin:/sbin export PATH rval=0 DAEMON=@sbindir@/@install_name@ NAME=@install_name@ run_the_command() { if test -f /etc/rc.config then . /etc/rc.config else echo "ERROR: /etc/rc.config defaults file MISSING" fi if test "x${CONTROL_@install_name@}" = x0 then rval=2 else ${DAEMON} $1 2>/dev/null ERRNUM=$? if test x"$ERRNUM" != x0 then echo "EXIT CODE: ${ERRNUM}" rval=1 fi fi } log_stat_msg () { case "$1" in 0) echo "Service $NAME: Running"; break; ;; 1) echo "Service $NAME: Stopped and /var/run pid file exists"; break; ;; 3) echo "Service $NAME: Stopped"; break; ;; *) echo "Service $NAME: Status unknown"; break; ;; esac } case "$1" in 'start_msg') echo "Starting the $NAME subsystem" ;; 'stop_msg') echo "Stopping the $NAME subsystem" ;; 'start') run_the_command start exit $rval ;; stop) run_the_command stop # # Remove a stale lockfile, if found # if test -f @mylockfile@; then /bin/rm -f @mylockfile@ fi /bin/rm -f @mylockdir@/${NAME}.sock exit $rval ;; restart) run_the_command restart exit $rval ;; reload|force-reload) run_the_command reload exit $rval ;; status) ${DAEMON} status ERRNUM=$? log_stat_msg ${ERRNUM} exit ${ERRNUM} ;; *) echo "Usage: @install_name@ {start_msg|stop_msg|start|stop|restart|reload|status}" exit 1 ;; esac exit $rval samhain-4.1.4/init/samhain.startIRIX.in0000644000175000017500000000221412615253277014635 00000000000000#! /bin/sh PATH=/usr/sbin:/usr/bin:/sbin export PATH rval=0 DAEMON=@sbindir@/@install_name@ NAME=@install_name@ if /sbin/chkconfig verbose; then verbose=1 else verbose=0 fi log_stat_msg () { case "$1" in 0) echo "Service $NAME: Running"; break; ;; 1) echo "Service $NAME: Stopped and /var/run pid file exists"; break; ;; 3) echo "Service $NAME: Stopped"; break; ;; *) echo "Service $NAME: Status unknown"; break; ;; esac } case "$1" in 'start') test $verbose = 1 && echo "Starting $NAME" $DAEMON start rval=$? exit $rval ;; stop) test $verbose = 1 && echo "Stopping $NAME" $DAEMON stop rval=$? # # Remove a stale lockfile, if found # if test -f @mylockfile@; then /bin/rm -f @mylockfile@ fi exit $rval ;; restart) test $verbose = 1 && echo "Restarting $NAME" $DAEMON restart rval=$? exit $rval ;; reload|force-reload) test $verbose = 1 && echo "Reloading $NAME" $DAEMON reload rval=$? exit $rval ;; status) ${DAEMON} status ERRNUM=$? log_stat_msg ${ERRNUM} exit ${ERRNUM} ;; *) echo "Usage: @install_name@ {start|stop|restart|reload}" exit 1 ;; esac exit $rval samhain-4.1.4/init/samhain.startLSB.in0000755000175000017500000000402212615253277014504 00000000000000#! /bin/sh ### BEGIN INIT INFO # Provides: @install_name@ # Required-Start: $syslog $network # Required-Stop: $syslog $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Keep an eye on stuff # Description: Keep an eye on stuff ### END INIT INFO # source function library if test -f /lib/lsb/init-functions; then . /lib/lsb/init-functions else echo "File /lib/lsb/init-functions not found" exit 5 fi prefix="@prefix@" exec_prefix="@exec_prefix@" DAEMON=@sbindir@/@install_name@ NAME=@install_name@ if test ! -f ${DAEMON}; then log_failure_msg "Service $NAME is not installed" exit 5 fi if test "x$2" != "x" && test "x$1" != "xstatus"; then log_failure_msg "Excess arguments $@" exit 2 fi log_sh_msg () { case "$1" in 0) log_success_msg "Service $NAME $2" break; ;; 1) log_failure_msg "Service $NAME: Error" break; ;; 4) log_failure_msg "Service $NAME: Permission denied" break; ;; 5) log_failure_msg "Service $NAME is not installed" break; ;; 7) log_failure_msg "Service $NAME is not running" break; ;; *) log_failure_msg "Service $NAME: Error" break; ;; esac } log_stat_msg () { case "$1" in 0) echo "Service $NAME: Running"; break; ;; 1) echo "Service $NAME: Stopped and /var/run pid file exists"; break; ;; 3) echo "Service $NAME: Stopped"; break; ;; *) echo "Service $NAME: Status unknown"; break; ;; esac } case "$1" in start) ${DAEMON} start ERRNUM=$? SH_ACT="started" ;; stop) ${DAEMON} stop ERRNUM=$? if test -f @mylockfile@; then /bin/rm -f @mylockfile@ fi if test -S @mylockdir@/${NAME}.sock; then /bin/rm -f @mylockdir@/${NAME}.sock fi SH_ACT="stopped" ;; restart) ${DAEMON} restart ERRNUM=$? SH_ACT="restarted" ;; reload|force-reload) ${DAEMON} reload ERRNUM=$? SH_ACT="reloaded" ;; status) ${DAEMON} status ERRNUM=$? log_stat_msg ${ERRNUM} exit ${ERRNUM} ;; *) log_warning_msg "Usage: @install_name@ {start|stop|restart|(force-)reload|status}" exit 2 ;; esac log_sh_msg ${ERRNUM} "${SH_ACT}" exit ${ERRNUM} samhain-4.1.4/init/samhain.startGentoo.in0000644000175000017500000000116612615253277015322 00000000000000#!/sbin/runscript opts="depend start stop reload" depend() { need clock hostname logger } start() { ebegin "Starting @install_name@" /sbin/start-stop-daemon --start --quiet --exec @sbindir@/@install_name@ eend $? } stop() { ebegin "Stopping @install_name@" /sbin/start-stop-daemon --stop --quiet --retry 15 --exec @sbindir@/@install_name@ rm -f @mylockfile@ eend $? } reload() { if [ ! -f @mylockfile@ ]; then eerror "@install_name@ isn't running" return 1 fi ebegin "Reloading configuration" kill -HUP `cat @mylockfile@` &>/dev/null eend $? } samhain-4.1.4/init/samhain.startSolaris.in0000644000175000017500000000210212615253277015472 00000000000000#!/bin/sh SBINDIR=@sbindir@ NAME=@install_name@ if [ ! -f ${SBINDIR}/${NAME} ]; then exit 0 fi log_stat_msg() { case "$1" in 0) echo "Service $NAME: Running"; break; ;; 1) echo "Service $NAME: Stopped and /var/run pid file exists"; break; ;; 3) echo "Service $NAME: Stopped"; break; ;; *) echo "Service $NAME: Status unknown"; break; ;; esac } case "$1" in start) echo "${NAME} starting." ;; stop) echo "${NAME} stopping." ;; restart) echo "${NAME} restarting." ;; reload|force-reload) echo "${NAME} reloading." ;; status) ${SBINDIR}/${NAME} $1 ERRNUM=$? log_stat_msg ${ERRNUM} exit ${ERRNUM} ;; *) echo "Usage: $0 {start|stop|restart|reload|status}" exit 1 ;; esac ${SBINDIR}/${NAME} $1 status=$? if [ $status != 0 ]; then echo $status exit 1 fi case "$1" in stop) if test -f @mylockfile@; then /bin/rm -f @mylockfile@ fi /bin/rm -f @mylockdir@/${NAME}.sock ;; *) exit 0 ;; esac exit 0 samhain-4.1.4/init/samhain.startFreeBSD.in0000644000175000017500000000123112615253277015272 00000000000000#!/bin/sh # PROVIDE: @install_name@ # REQUIRE: LOGIN # KEYWORD: shutdown . /etc/rc.subr name="@install_name@" rcvar=`set_rcvar` pidfile="@mylockfile@" # there are no required_files in general, # as they might be downloaded from the server # # required_files="@myconffile@ @mydatafile@" extra_commands="reload" stop_postcmd="remove_stale_files" command="@sbindir@/@install_name@" is_set() { eval "[ -n \"\${$1+X}\" ]" } remove_stale_files() { if test -f @mylockfile@; then /bin/rm -f @mylockfile@ fi /bin/rm -f @mylockdir@/${name}.sock } load_rc_config "$name" if ! is_set ${rcvar}; then eval "${rcvar}=YES" fi run_rc_command "$1" samhain-4.1.4/init/samhain.start.in0000644000175000017500000000327212615253277014146 00000000000000#!/bin/sh # This file is public domain and comes with NO WARRANTY of any kind # samhain deamon start/stop script. # This should be put in /etc/init.d (at least on machines SYSV R4 # based systems) and linked to /etc/rc3.d/S99samhain. When this is done # the samhain daemon will be started when the machine is started. PATH=/sbin:/usr/bin:/usr/sbin:/bin basedir=/ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ samhain_daemon_user=root # Run samhain as this user. # If you use this, uncomment one of # the su rows below. export PATH mode=$1 # The following test may be removed if this script isn't to be run as root. if test ! -w / then echo "$0: this script must be run as root ... fatal error" exit 1 fi # Safeguard (relative paths, core dumps..) cd $basedir case "$mode" in 'start') # Start deamon if test -x ${bindir}/samhain then if test -x /sbin/startproc then # use startproc if available startproc ${bindir}/samhain -t check -D else # For Linux su -c -- $samhain_daemon_user $bindir/samhain -t check -D # For sun # su $samhain_daemon_user $bindir/samhain -t check -D fi else echo "Can't execute ${bindir}/samhain" fi ;; 'stop') if test -x ${bindir}/samhain then if test -x /sbin/killproc then # alternatively use the command below, if you have 'killproc' killproc -TERM ${bindir}/samhain else # Stop deamon - no PID file available, so search for the pid SH_PID=`ps aux | grep samhain | grep -v grep | awk '{print $2}'` kill ${SH_PID} fi fi ;; *) # usage echo "usage: $0 start|stop" exit 1 ;; esac samhain-4.1.4/init/samhain.startLinux.in0000644000175000017500000001303312615253277015162 00000000000000#!/bin/bash # chkconfig: 2345 99 10 # description: File Integrity Checking Daemon # # processname: @install_name@ # config : @myconffile@ # logfile : @mylogfile@ # database: @mydatafile@ # ### BEGIN INIT INFO # Provides: @install_name@ # Required-Start: $syslog $network # Required-Stop: $syslog $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Keep an eye on stuff # Description: Keep an eye on stuff ### END INIT INFO # For Debian # FLAGS="defaults 99 10" NAME=@install_name@ DAEMON=@sbindir@/@install_name@ RETVAL=0 VERBOSE=yes PIDFILE=@mylockfile@ if [ -x $DAEMON ]; then : else echo "${0}: executable ${DAEMON} not found" exit 0 fi # Sort out sourcing in the distribution specific library functions # and the command to run them. if [ -f /etc/redhat-release ]; then . /etc/init.d/functions DISTRO=redhat elif [ -f /etc/mandrake-release ]; then . /etc/init.d/functions DISTRO=redhat elif [ -f /etc/yellowdog-release ]; then . /etc/init.d/functions DISTRO=redhat elif [ -f /etc/SuSE-release ]; then . /etc/rc.config . /etc/rc.status # Determine the base and follow a runlevel link name. base=${0##*/} link=${base#*[SK][0-9][0-9]} # Force execution if not called by a runlevel directory. test $link = $base && START_@INSTALL_NAME@=yes # Check whether START_@INSTALL_NAME@ is in /etc/rc.config # If yes, abort unless its value is 'yes' if test "x${START_@INSTALL_NAME@}" != "x"; then test "${START_@INSTALL_NAME@}" = yes || exit 0 fi return=$rc_done DISTRO=suse elif [ -f /etc/debian_version ]; then # . /etc/default/rcS set -e DISTRO=debian elif [ -f /etc/slackware-version ]; then # . /etc/rc.d/rc.sysvinit DISTRO=generic else DISTRO=generic fi debian_end() { if [ $RETVAL -eq 0 ]; then echo "." else echo " failed." fi } # Generic function "a la Red Hat" MOVE_TO_COL="echo -en \\033[60G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_NORMAL="echo -en \\033[0;39m" echo_success() { $MOVE_TO_COL echo -n "[ " $SETCOLOR_SUCCESS echo -n "OK" $SETCOLOR_NORMAL echo -n " ]" echo -ne "\r" echo "" } echo_failure() { $MOVE_TO_COL echo -n "[" $SETCOLOR_FAILURE echo -n "FAILED" $SETCOLOR_NORMAL echo -n "]" echo -ne "\r" echo "" } # echo OK in green if is success, FAILED in red is failed generic_end() { if [ $RETVAL -eq 0 ]; then echo_success else echo_failure fi } log_stat_msg () { case "$1" in 0) echo "Service $NAME: Running"; ;; 1) echo "Service $NAME: Stopped and /var/run pid file exists"; ;; 3) echo "Service $NAME: Stopped"; ;; *) echo "Service $NAME: Status unknown"; ;; esac } case "$1" in start) # # Remove a stale PID file, if found # if test -f ${PIDFILE}; then /bin/rm -f ${PIDFILE} fi # case "$DISTRO" in debian) echo -n "Starting ${NAME}" ( /sbin/start-stop-daemon --start --oknodo --quiet --exec $DAEMON ) RETVAL=$? debian_end ;; redhat) if [ -f /etc/sysconfig/${NAME} ]; then . /etc/sysconfig/${NAME} fi echo -n $"Starting ${NAME}: " if [ -n "$OPTIONS" ]; then daemon $DAEMON $OPTIONS else daemon $DAEMON fi RETVAL=$? [ $RETVAL -eq 0 ] && touch /var/lock/subsys/${NAME} echo ;; suse) echo -n "Starting service ${NAME}" /sbin/startproc $DAEMON RETVAL=$? if [ $RETVAL -eq 0 ]; then return=$rc_done else return=$rc_failed fi echo -e "$return" ;; *) echo -n "Starting ${NAME} ... " $DAEMON start RETVAL=$? generic_end ;; esac exit $RETVAL ;; stop) case "$DISTRO" in debian) echo -n "Stopping $NAME" ( /sbin/start-stop-daemon --stop --oknodo --quiet --exec $DAEMON ) RETVAL=$? debian_end ;; redhat) echo -n $"Stopping ${NAME}: " killproc ${NAME} RETVAL=$? rm -f /var/lock/subsys/${NAME} echo ;; suse) echo -n "Shutting down service ${NAME}" /sbin/killproc -TERM $DAEMON RETVAL=$? if [ $RETVAL -eq 0 ]; then return=$rc_done else return=$rc_failed fi echo -e "$return" ;; *) if test x"$VERBOSE" != xno; then echo -n "Stopping ${NAME} ... " fi $DAEMON stop RETVAL=$? generic_end ;; esac # # Remove a stale PID file, if found # if test -f ${PIDFILE}; then /bin/rm -f ${PIDFILE} fi if test -S @mylockdir@/${NAME}.sock; then /bin/rm -f @mylockdir@/${NAME}.sock fi ;; restart) $0 stop sleep 3 $0 start RETVAL=$? ;; reload|force-reload) case "$DISTRO" in debian) echo -n "Reloading $NAME configuration files" ( /sbin/start-stop-daemon --stop --signal 1 --quiet --exec $DAEMON ) RETVAL=$? debian_end ;; redhat) echo -n $"Reloading ${NAME} configuration: " killproc ${NAME} -HUP RETVAL=$? echo ;; suse) echo -n "Reload service ${NAME}" /sbin/killproc -HUP $DAEMON RETVAL=$? if [ $RETVAL -eq 0 ]; then return=$rc_done else return=$rc_failed fi echo -e "$return" ;; *) echo -n "Reloading ${NAME} ... " $DAEMON reload RETVAL=$? generic_end ;; esac ;; status) case "$DISTRO" in redhat) status ${NAME} exit $? ;; suse) echo -n "Checking for service ${NAME}: " /sbin/checkproc $DAEMON RETVAL=$? if [ $RETVAL -eq 0 ]; then return="OK" else return="No process" fi echo "$return" exit $RETVAL ;; *) $DAEMON status ERRNUM=$? log_stat_msg ${ERRNUM} exit ${ERRNUM} ;; esac ;; *) echo "$0 usage: {start|stop|status|restart|reload}" exit 1 ;; esac exit $RETVAL samhain-4.1.4/c_random.sh0000755000175000017500000001427612615253270012217 00000000000000#! /bin/sh # this program collects some entropy from the system # into the file "my_random_file" and outputs the 16-bit # Unix 'sum' checksum (seems to be the only portable way # to get true entropy with a shell script). # Apparently, on FreeBSD /dev/random does not block (???), must make sure # we really got something rather than nothing. rnd_tst=no /bin/rm -f ./my_random_file 2>/dev/null if test -r "/dev/urandom"; then if test -c "/dev/urandom"; then dd if=/dev/urandom ibs=1 count=4 > my_random_file 2>/dev/null nsum=`sum ./my_random_file | awk '{print $1 }' | sed 's%^0*%%g' 2>/dev/null` if test x$nsum != x; then rnd_tst=yes fi fi fi if test x$rnd_tst = xno; then if test -r "/dev/srandom"; then if test -c "/dev/srandom"; then dd if=/dev/srandom ibs=1 count=4 > my_random_file 2>/dev/null nsum=`sum ./my_random_file | awk '{print $1 }' | sed 's%^0*%%g' 2>/dev/null` if test x$nsum != x; then rnd_tst=yes fi fi fi fi if test x$rnd_tst = xno; then # touch ./my_random_file # if test -r "/usr/ucb/vmstat"; then /usr/ucb/vmstat >> my_random_file 2>/dev/null fi if test -r "/bin/vmstat"; then /bin/vmstat >> my_random_file 2>/dev/null fi if test -r "/sbin/vmstat"; then /sbin/vmstat >> my_random_file 2>/dev/null fi if test -r "/usr/bin/vmstat"; then /usr/bin/vmstat >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/vmstat"; then /usr/sbin/vmstat >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/vmstat"; then /usr/local/bin/vmstat >> my_random_file 2>/dev/null fi # if test -r "/usr/ucb/netstat"; then /usr/ucb/netstat -n >> my_random_file 2>/dev/null fi if test -r "/bin/netstat"; then /bin/netstat -n >> my_random_file 2>/dev/null fi if test -r "/sbin/netstat"; then /sbin/netstat -n >> my_random_file 2>/dev/null fi if test -r "/usr/bin/netstat"; then /usr/bin/netstat -n >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/netstat"; then /usr/sbin/netstat -n >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/netstat"; then /usr/local/bin/netstat -n >> my_random_file 2>/dev/null fi # # if test -r "/usr/ucb/ps"; then /usr/ucb/ps -ef >> my_random_file 2>/dev/null fi if test -r "/bin/ps"; then /bin/ps -ef >> my_random_file 2>/dev/null fi if test -r "/sbin/ps"; then /sbin/ps -ef >> my_random_file 2>/dev/null fi if test -r "/usr/bin/ps"; then /usr/bin/ps -ef >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/ps"; then /usr/sbin/ps -ef >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/ps"; then /usr/local/bin/ps -ef >> my_random_file 2>/dev/null fi # # if test -r "/usr/ucb/arp"; then /usr/ucb/arp -a >> my_random_file 2>/dev/null fi if test -r "/bin/arp"; then /bin/arp -a >> my_random_file 2>/dev/null fi if test -r "/sbin/arp"; then /sbin/arp -a >> my_random_file 2>/dev/null fi if test -r "/usr/bin/arp"; then /usr/bin/arp -a >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/arp"; then /usr/sbin/arp -a >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/arp"; then /usr/local/bin/arp -a >> my_random_file 2>/dev/null fi # # if test -r "/usr/ucb/w"; then /usr/ucb/w >> my_random_file 2>/dev/null fi if test -r "/bin/w"; then /bin/w >> my_random_file 2>/dev/null fi if test -r "/sbin/w"; then /sbin/w >> my_random_file 2>/dev/null fi if test -r "/usr/bin/w"; then /usr/bin/w >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/w"; then /usr/sbin/w >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/w"; then /usr/local/bin/w >> my_random_file 2>/dev/null fi # # Don't use (NFS problems ahead) # # if test -r "/usr/ucb/df"; then # /usr/ucb/df >> my_random_file 2>/dev/null # fi # if test -r "/bin/df"; then # /bin/df >> my_random_file 2>/dev/null # fi # if test -r "/sbin/df"; then # /sbin/df >> my_random_file 2>/dev/null # fi # if test -r "/usr/bin/df"; then # /usr/bin/df >> my_random_file 2>/dev/null # fi # if test -r "/usr/sbin/df"; then # /usr/sbin/df >> my_random_file 2>/dev/null # fi # if test -r "/usr/local/bin/df"; then # /usr/local/bin/df >> my_random_file 2>/dev/null # fi # # if test -r "/usr/ucb/free"; then /usr/ucb/free >> my_random_file 2>/dev/null fi if test -r "/bin/free"; then /bin/free >> my_random_file 2>/dev/null fi if test -r "/sbin/free"; then /sbin/free >> my_random_file 2>/dev/null fi if test -r "/usr/bin/free"; then /usr/bin/free >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/free"; then /usr/sbin/free >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/free"; then /usr/local/bin/free >> my_random_file 2>/dev/null fi # # if test -r "/usr/ucb/uptime"; then /usr/ucb/uptime >> my_random_file 2>/dev/null fi if test -r "/bin/uptime"; then /bin/uptime >> my_random_file 2>/dev/null fi if test -r "/sbin/uptime"; then /sbin/uptime >> my_random_file 2>/dev/null fi if test -r "/usr/bin/uptime"; then /usr/bin/uptime >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/uptime"; then /usr/sbin/uptime >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/uptime"; then /usr/local/bin/uptime >> my_random_file 2>/dev/null fi # # if test -r "/usr/ucb/procinfo"; then /usr/ucb/procinfo -a >> my_random_file 2>/dev/null fi if test -r "/bin/procinfo"; then /bin/procinfo -a >> my_random_file 2>/dev/null fi if test -r "/sbin/procinfo"; then /sbin/procinfo -a >> my_random_file 2>/dev/null fi if test -r "/usr/bin/procinfo"; then /usr/bin/procinfo -a >> my_random_file 2>/dev/null fi if test -r "/usr/sbin/procinfo"; then /usr/sbin/procinfo -a >> my_random_file 2>/dev/null fi if test -r "/usr/local/bin/procinfo"; then /usr/local/bin/procinfo -a >> my_random_file 2>/dev/null fi # nsum=`sum ./my_random_file | awk '{print $1 }' | sed 's%^0*%%g' 2>/dev/null` # fi # # 'sum' is portable, but only 16 bit # /bin/rm -f ./my_random_file 2>/dev/null echo $nsum samhain-4.1.4/docs/0000755000175000017500000000000012724114744011077 500000000000000samhain-4.1.4/docs/HOWTO-samhain-on-windows.html0000644000175000017500000003400712615253277016335 00000000000000 HOWTO Samhain on Windows

samhain file integrity scanner | online documentation


Using Samhain on Windows



This document aims to explain how to compile and run samhain on Windows with the Cygwin POSIX emulation layer, and how to install it as a service. These instructions have been written by Kris Dom, who has tested this on WinXP Professional, with additions by Geries Handal and Jorge Morgado.

Interix / Services For UNIX

Samhain can also be used with Interix/SFU 3.5. Note that in Interix, the Windows filesystem is referred as /dev/fs/C, while in Cygwin it is /cygdrive/c (both refers to the C: drive; other drives are analogous).

Older versions of samhain would need to be built with ./configure --disable-mail (i.e. without support for email logging) because Interix does not provide some of the required functionality to build the email module. This issue should be fixed as of samhain version 2.0.7 (not tested).
[Based on information kindly provided by Geries Handal].

Cygwin installation procedure to compile samhain

Cygwin download

  • Make a temporary directory to store cygwin installer (e.g. c:\temp\cygwin)
  • Surf to http://www.cygwin.com to download cygwin
  • Use the "install or update now (using setup.exe)" to download the installer in c:\temp\cygwin
  • Execute "setup.exe" in c:\temp\cygwin
  • Choose the "download from the Internet" option
  • Choose "c:\temp\cygwin" as 'Local Package Directory'
  • Choose an FTP site
  • Click on 'Default' just after 'All' to change the installation type from 'Default' to 'Install'. This will most likely install way too much stuff but I am not familiar with Cygwin, so this way I know that all libs and compilers are installed.
  • Let it download the stuff (there is a lot to download so be patient).

You don't need to download and install All packages. It is enough to keep the Default and then add the following additional packages:

Category Devel -> gcc: C compiler upgrade helper
Category Devel -> make: The GNU version of the 'make' utility
Category Libs -> minires: A simple synchronous non caching stub resolver

When selecting these packages, Cygwin installer will automatically add other packages based on their dependencies. The package minires is only necessary for a minimal Cygwin installation (below). [Kindly pointed out by Jorge Morgado].

Cygwin installation

  • When the download is complete you have the Cygwin software in the temporary directory, however, it still needs to be installed.
  • To install, execute the "setup.exe" in "c:\temp\cygwin"
  • Choose the "Install from local directory" option.
  • Choose "C:\Cygwin" as root directory (this will be the Unix '/')
  • Choose the Local Package Directory: "c:\temp\cygwin"
  • Click on 'Default' just after 'All' to change the installation type from 'Default' to 'Install'.
  • Let it install Cygwin (this will take some time so be patient).

Samhain install procedure (used 'samhain 1.8.7a' in this procedure)

(in the following procedure I use my personal preferences)

  • Start up Cygwin using the "Cygwin" icon on the desktop (a classic Unix environment will be started).
  • Download the 'samhain' gzip/tar (I always put in my home directory)
  • Make directories to install samhain (taking into account the configure options):
       $ mkdir /usr/local/sbin
       $ mkdir /usr/local/var
       $ mkdir /usr/local/log
       $ mkdir /usr/local/tmp
  • Go to the home directory:
       $ cd $HOME
  • Un-gzip and untar the samhain package:
       $ gunzip samhain-1.8.7a.tar.gz
       $ tar xvf samhain-1.8.7a.tar
  • Go to the samhain directory:
       $ cd samhain-1.8.7a
  • Configure:
       $ ./configure --enable-xml-log=yes --with-tmp-dir=/usr/local/tmp --with-config-file=/usr/local/etc/samhainrc --with-log-file=/usr/local/log/samhain.log --with-pid-file=/usr/local/var/samhain.pid --with-state-dir=/usr/local/var

    In my experience, the paths given in the 'configure' command should refer to the Cygwin filesystem view, i.e. /cygdrive/c/..., otherwise samhain may not work from a pure DOS shell, and may not run as a Windows service [Rainer Wichmann].

  • Make the binary:
       $ make
  • Install samhain:
       $ make install
  • Now configure the "/usr/local/etc/samhainrc" file.
    Remember: "C:\" -> "/cygdrive/c/"
  • Initialize the samhain local baseline database:
       $ /usr/local/sbin/samhain -t init
  • Start it up:
       $ /usr/local/sbin/samhain -t check

Cygwin minimal installation procedure to run samhain

  • Files needed to create a service (from NT/W2K Resource Kit):
    • instsrv.exe
    • srvany.exe
  • First copy these files to the "%winnt%\system32" directory.
  • Files needed to run the 'samhain.exe'. Copy the following .dll from the Cygwin setup (c:\Cygwin\bin) to the "%winnt%\system32" directory:
    • cygwin1.dll
    • cygminires.dll
  • Files needed from c:\Cygwin\bin to create the /etc/passwd and /etc/group files:
    • mkpasswd.exe
    • mkgroup.exe

    To generate these files on a minimal Cygwin installation execute - on a Windows Command Prompt:

       mkdir c:\etc
       path\to\mkpasswd.exe -l > c:\etc\passwd
       path\to\mkgroup.exe -l > c:\etc\group

    IMPORTANT NOTE: You should re-create these two files, each time the Windows users and groups accounts database changes. Failing to do this might generate critical log messages (depending on your configuration file).

  • Create a directory structure for samhain (following the compilation options you used)
       - in a DOS box (or via Windows Explorer)
       mkdir c:\usr
       mkdir c:\usr\local
       mkdir c:\usr\local\sbin
       mkdir c:\usr\local\var
       mkdir c:\usr\local\tmp
       mkdir c:\usr\local\log
       mkdir c:\usr\local\etc
  • Use the "instsrv.exe" binary to create a new service:
       instsrv.exe samhain c:\windows\system32\srvany.exe
       (this will create a service called "Samhain" that will start the "srvany.exe" process).
  • Now edit the registry to change the startup parameters for the newly created service:
    • regedit
    • HKEY_LOCAL_MACHINE->SYSTEM->CurrentControlSet->Services->Samhain
    • Add a String value (type: REG_SZ called: "Description") under the 'Samhain' key
    • Open the newly created "Description" value and fill in a description for the 'Samhain' service
    • Add a key to specify what file the "srvany.exe" process must start:
         Edit->New->Key called "Parameters"
    • Under the newly created "Parameters" key, add a new String value called "Application".
         The value for "Application" should be "c:\usr\local\sbin\samhain.exe".
  • Make sure that in the "samhainrc" file, you have used "/cygdrive/c" to refer to "c:"
  • Initialize the samhain baseline database first:
       c:\usr\local\sbin\samhain -t init
  • Reboot (it is Windows so ...)

It seems that start/stop/restart the service does not work if samhain is configured to run as a daemon, because the Windows service manager cannot track the forked daemon process.

Therefore, if you run Samhain as a Windows service, it might be better to configure it as a 'normal' process which does not fork a daemon:

  • Set 'Daemon = no' in the samhainrc configuration file.
  • Edit the key HKEY_LOCAL_MACHINE->SYSTEM->CurrentControlSet->Services->Samhain->Parameters to add a string value named 'AppParameters', with the value '--forever'.
[Rainer Wichmann].

Also see http://support.microsoft.com/kb/q137890/ for information regarding the creation of a user-defined service.

Note: the first time I tried to install samhain as an NT service, I first installed a default Cygwin on the system. This however made things much more complex. I think when there is no Cygwin installed, it is more easy to install Samhain as a service.

Troubleshooting samhain

[Rainer Wichmann] I had some problems at first getting it to run as a Windows service. Some tips:

  • Running samhain from a pure DOS shell (outside the Cygwin environment) helps to identify problems, in particular if it refuses to start as a Windows service.
  • I found it neccessary to put the cygwin1.dll DLL into the same directory as the samhain.exe executable. Also, you can use the command ldd ./samhain.exe to identify further Cygwin-specific DLL that may be required (if any).
  • Also, I found it neccessary to use Cygwin-style paths (/cygdrive/c/...) in the './configure ..' command when compiling samhain.

[Tip from Jorge Morgado] If you, like me, have a Windows server not part of any domain and (for security reasons) you even turn off DNS resolution, you might probably get the following error when initializing the baseline database:

  ---------   sh_unix.c  ---   1487 ---------
  According to uname, your nodename is yourcomputername, but your resolver
  library cannot resolve this nodename to a FQDN.
  Rather, it resolves this to yourcomputername.
  For more information, see the entry about self-resolving under
  'Most frequently' in the FAQ that you will find in the docs/ subdirectory
  ----------------------------------------------

To fix this problem open the Registry Editor and create the following entries under the key HKLM\System\CurrentControlSet\Services\Tcpip\Parameters

Name: Domain
Type: REG_SZ
Data: your.domain.name

Name: NV Domain
Type: REG_SZ
Data: your.domain.name

The NV Domain registry value contains the computer's primary DNS suffix while the Domain registry value contains the computer's primary DNS domain. This will make the warning message go away.

samhain-4.1.4/docs/MANUAL-2_4.pdf0000664000175000017500000206722712703400302013054 00000000000000%PDF-1.4 % 4 0 obj << /Creator (Apache FOP Version 1.1) /Producer (Apache FOP Version 1.1) /CreationDate (D:20160413101758+02'00') >> endobj 5 0 obj << /N 3 /Length 11 0 R /Filter /FlateDecode >> stream xgPTY{si249IЀ$Hn2-49AD$)8:EEyqpQQYU[[Ϗ:;羺UzȐ ɰ> 3(8p H 0D[oo+k?Q '/s,^IW8=%1{8cq?_e> ʄS+ԮfG[^N/?_zVCte?(.Or}]/t7Y9;Ꙁ嶖z RWN0t8@g ةo9(0-pGo:(H2O:4w7&CɛRTRӬҪ>e dje͜r:fg(fn;=b{y;&w:<+n\www̛||~=ߣ~pڽ{p n~.bE,6)>R)ᕌT4t灎2fYAٻ[(7*=D8zHPQURYR*jڮFfoa#6GZkj k?9ι^Xڱ  YǛ =d,\̜ =uGZuZm/ i޳?\Nk/:2;:;]]Cv[tˉ/_(!,]̺8)[z_ rϧoל]x7dercxA;wZ73l=|ýk]Y?24?`,tL`a7->gM`"00>|W%y2ETӴ/7|jq6wk^k?&,YVwFz矽OxPAɏ?M-~'K KKB. t ]@B. t ]V,r96_6@-Jh 7#edoMDEa&s|.7>s7  endstream endobj 6 0 obj [/ICCBased 5 0 R] endobj 7 0 obj << /Type /Metadata /Subtype /XML /Length 12 0 R >> stream en application/pdf 2016-04-13T10:17:58+02:00 1.4 Apache FOP Version 1.1 2016-04-13T10:17:58+02:00 Apache FOP Version 1.1 2016-04-13T10:17:58+02:00 endstream endobj 10 0 obj << /Length 13 0 R /Filter /FlateDecode >> stream x}; @[jynE :I$$&ދ|.2f1.;V,4#:&4JZ.&IrWlr#TjD{wU6ZR 99+0BY(28]Zְm:fyWa~ JnޑU)el41uHEb endstream endobj 8 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 10 0 R >> endobj 11 0 obj 2453 endobj 12 0 obj 858 endobj 13 0 obj 192 endobj 15 0 obj << /Length 16 0 R /Filter /FlateDecode >> stream xUK6 W zMi:M&td9 E{_HVd]?|eICF4 wz wG `!0VEpl|W٢| (~C-P{ mU𛇭3K#l Eopb$!U~qAxMv}@8jfkTtG̖Β׋ѷˋu 64opQw}R!waQJ9 a\U-|e/QWj=.o## tWP3 KcU5YZ 8 X)?׋Iwb`ab Bc4d"{#6G&(?8E;“Tq@Րy:I<$ CҔns~ K< ɑ㭧 u[U[6'+=e^mh)JU0:tS)+NV<X[=;&u%sŸ7c7c"Ujy!HFE+ѵad+8x"-ūՆpĕ2Jo%|>慄%N ױ1(g-O|Yw6Ds:K=t89o{Ӻ}V endstream endobj 14 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 15 0 R >> endobj 16 0 obj 892 endobj 18 0 obj << /Length 19 0 R /Filter /FlateDecode >> stream xW͎8 )tUv8b[v1 ZAXm4K8=OIȏ?R~."|IDی⧓G$jDkFx؊D פ&ע5̞ >WY0i;bܚz^<9ߒ+9h\I7~B4 3W4N6/Pt,]0e+ We7d fcx->||31M(,%3/&|}'JtS*kyEƍ*tF۔1`EK"JݪϵT 0^4Yemt.l;rhFdiɃD)UV+ڰW ,tN:{><`Y6pѸgQU+`a ڰ XobivW뻗y' /k>GG(pmy^MZ9V:ZI!d@幬2-,;俢*fŦLjV-Kodh#x⭖y8-GYsiu2˫2b${e0[Hz[>t%ZX@=K]mbě:( :bIԲ)/Y%1I!M*u$/]rMrUU"ct)H-!@ z\A;]ǮWwA(NmZUsǾ X Hz*tFќ\ٖtxPg ݛQ+?NV,!^g?3 emʸ'7G{VI.kJ[ЉF#Ss}umZbhk,oNYI&Iu4Z${ihF3sYe<z[Az; d|O/K!W1]7q:$g|ȲMSa̩4:TIjy>QFR ,iudAN >'!84T6UMAn^IBt9 ϲ6# yU2 iA/ ;fKC > endobj 19 0 obj 1353 endobj 21 0 obj << /Length 22 0 R /Filter /FlateDecode >> stream xZ[s:~ϯά3(u?)'lw:md眝MۚʒKܜ_ %v HEDB{-~$ $wŏHNI)V M0&QД9+%TSs6y\ŗ0fCBw_.E=\|rtS Nj7)B.i4 ))%eqU]5;š ~`_/^?aPjv*JC8y!٣s''/5TF<:a Q3/ZΌ ][Q(r4ȣ,GAqB1,T\NmN B ,BSe61A%⠛7Q4U G,;YՐ끬|\|kPi!h ,gр|Ǫ >xcYܬĹExTum#OBC:̼$BC8UumQe !*qE2KjAq*Ţ${QPa\ǘ# *aMe92*!m)hD1yۭvPێyw\N#ߧfE=[PϪٴu#e0AAܖ"pLE퇇w䎨fzCW3!mG< (Y4o4-%〦i*)wЪ"4rv"QCU Q-^^Oz?>/&dPt|DX.-/b4D/3]{0鉼84,ÐB|ũv82޴c9~fu y-&UR]gADﶆ|n΀'7 Ȩ3vv`]fr%߷ciMwՓj4=_YW9jwk7;v };[EĖ3'\`J'$LfֽAu͎=0҈ZJ2`i^NSS@`ŏm! V[>)t]QS(w?ܾJ6[dF'2:Ir칡j`p6j7v:4Ґl [ ?oQMwAAoU&[Ά+,nyIc?G&92Ƀ$g[7g:nN[]Ag-ŪQwaXۻ ^eB ]Kez䢘ˡݞYc<||o2U3pDӡV %MD[.$HzW GDl,5$6ɾRKxUǺ 5#l#K#Bj /c{.iʅCR;[&./Ӊ2[?=P:7Q/W|U1@QlA]O8fغA+R"og)4E/o6hMh E@HE0dȶ\zt_p&D: хԧ}N_.ؐ%A5<,Iжkz<9l; 5-B))tk6GAj[K+!P*RH L**lG%NyDCDH4\1?bIJ"X,Z.yW[,.a)U~#3ߍʇxC^ْ$8NTH*N" 4U3P%KD.Jd py+'(;9Ҏ)pI1$V+G\m'q4h+|I6IR,m4$?7iiRE+Qq@^nFJzٕdJӀfi%:#UIRK5EeeA7JMe^Y_6Juaã10%jt jv-tiX7J+; 8UFݴӉ^L*cvEu`ObnOwFrBL AX iѧݒVa1gE@ ?w(j*5Ğ-XXsB:qN&@5pf(y ($=6vSm+nY6SzEd#I+MXzvgW]Y4qx{O-~E9?҂iE8)$" :Z"#[D"N6q'yT5FYu+\ޫw9 ԉ!1%B-CuW~xX7A(džig$ƹgp/2\IR*cMۀМ꿜mJtaT+Q P_$0 oKW^Hcn'v1;)&fˁ De#% ߲eBvϒI^np^r1dowMęR>UٕpAN\%Cޢmi|6R'i?nE: }GO>φ>N;>St[ endstream endobj 20 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 21 0 R >> endobj 22 0 obj 2691 endobj 24 0 obj << /N 1 /Alternate /DeviceGray /Length 27 0 R /Filter /FlateDecode >> stream xc``I-f2``+)rrR` \\ 5F}Y<^qVJjq2]g\dg000q"!A@ Q 2JRs4ItadتJ̢̜T.43D73BeriQT$: endstream endobj 25 0 obj [/ICCBased 24 0 R] endobj 26 0 obj << /Name /Im1 /Type /XObject /Length 28 0 R /Filter /FlateDecode /Subtype /Image /Width 25 /Height 24 /BitsPerComponent 8 /ColorSpace [/ICCBased 24 0 R] >> stream xuR Ycd)]d[A#PRjZFP-q=;}wlZIYFXbEԕ/ zѿP![S/n݊*Gni8XKTEy&pd˲ٹ` y; nF'"E[:юi[ڀ Ҡ0@IiH(y| endstream endobj 27 0 obj 201 endobj 28 0 obj 202 endobj 30 0 obj << /Type /Annot /Subtype /Link /Rect [ 426.747 108.304 498.132 117.304 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 32 0 obj << /Length 33 0 R /Filter /FlateDecode >> stream xYKs6WЃݑa$"3=Mʴ($G];99 .v.̇EݘЧ8 %v")N8!>fP8֎ xx6ӂL(U/8YM[Z%h페q쇌G!4 ՏpL$ۡ(۠$+(5{mӪG6&֎;8BL@80r݁x4Ƙdc`oq %C~5MP0,(RH K8!PAq*5s-WQ5;D>TI6ȸynr}l;*eGOIQL>D)9\la}¤ I꓊2zHՄBo#l<*-۟9j৑G翋(~7ޘJ/??D ~n }P9p$aAߟVfL$"NFΉ Qtc zx xQ؄s`da?s{m7C& g.Q!*Ҫk ϼݘpzz8D,j@űwj0.8V3zPuI@Q3oD ZDQZ6&_NJ,1zc^0 #lXPK2?gχ3;NU4:h3a@ ]݁BvB^<0{X A BҖUrF'C GWg(lcj\>J{wknp$ۺXXm7>VÁ;OQvԞ{&WxP#(47hUN##UN*ryC!L ?PСvdy zq+4YpXA"\iྀz@Jxh7SRFm*-V`pw iƅɁ(=9a9Nxu%GK{ w=CT{{Q)3UM2.]6ŏ1z6yB 34n>5ǹƙ;7UGGƺJՍ6O9;߆ U/R[#[ $QA;{Ne.AC~ t:h/\ PJGjBx gja{'p/í U6#[z!2<{MS8o8I+oc[B^ԗ"$6nL.+)u'?7ͧ9KLWN0V9ekiH1|SSk+‡Eӻx=;b}uӺ}@5^36ǾJ-cyZ#NkӱͨU,â endstream endobj 31 0 obj [ 30 0 R ] endobj 23 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 31 0 R /Contents 32 0 R >> endobj 33 0 obj 1930 endobj 35 0 obj << /Name /Im2 /Type /XObject /Length 36 0 R /Filter /FlateDecode /Subtype /Image /Width 24 /Height 24 /BitsPerComponent 8 /ColorSpace [/ICCBased 24 0 R] >> stream x]Q!0ߗ+]2ve\# c#X$GȒnv- Oa}B GAUHO4O1e|o{}r X,em41 lEUDa`TGBa. zKUB^ .yl#DԤ9Q;C^%os3=6뵰 z% ϋ1X|_4%eSAɬ9d endstream endobj 36 0 obj 240 endobj 37 0 obj << /Length 38 0 R /Filter /FlateDecode >> stream x\[6~c2>Mn'$6f8;+q5YoD"9>],^ `KǥֻgYÀ8ʶ Ŷe(6؁v "FzEol-ㅩOo~]rXMblCb7 ? .w&}- ,#Q|/c8,"P'c Z%ZlL fv9NS_x@:^S:#nbK[5eh^k87@ƟB[m!YSX&=`xlWeNyry:oM?x2"Ҟ1{groArr~]>~&1]Ҽ95Dɬ0 x0[Fq(FyHL {-y$ k<{ ?g4l /,@tgXH˭yum]Ѐ;0?delW/  +[}rZ'<< <ܕ3Ү;.U, >\(`Ap]rx\ ]bQ%y;=cWTk5b4-gN:'Yg^5ˈ <)o)rW>.k3PXS(ƧI^0BXM q)'[[B!'Y0v60@!O 1Xe8:8\ `S?GucYMFTհa^sbs*w[?)vjȧj@>kGC)\B$@]A6NyُàQ;bzha2 D Yl1%Ie8e3X6}N׉2ow, 0 ˪,L`|] E -JKE%ӪxFQ]ؤɾ.Iׅ}~mUMNDi+F 4axAִʓRE,iw1{ś-H8dj)h dS*{2HS*v]im7$Vڔ۹l/r2e$$KUdPD,I\2IsY4u ,!ælNvewZSu<JEXO2x<&P NL}=l*W.W?DC4eEkK6:xSPBX+?`_e ߁ݰ8p$Ƀ\7o^|@nQ@%f<&"gE10l(nQׂhof2uix7kBWDx*(ĀpjݎxΈ3T} ]1e{&(QDTaM0g6)bBWM I1gjSap Elf|険3kyL/=S>CĚ#JQ› 詧G3'کo=Y5M>5s<9:`3Zķc\ 6 .|BtaGT;K )7ĥg&n'@T:P؉0gwp0yh# 0FRޤ8o:ȮxjA> endobj 38 0 obj 2155 endobj 40 0 obj << /Length 41 0 R /Filter /FlateDecode >> stream x[[oܸ~_q#Rԭm b@6!ΌP4%^;%z;l<7~BevE 'bGQխ'( ̔bF}a脆S>ހ6#3X W.GXC._3w=_~.:rZ#}bcQ6(E'tN4?$ߡ4UIGt_{KRQ*a] #zyr'ݼs06I`FZNuNQx10UqG+t_-vorhkE=I#q_o.+Y'LV#0eeF'h(He`T@`Apr['OztZ3pA0LGwiƭ@"p`F_ Y0|žgIQϷπiҝCHFG {&ܽig'1]#l/ꒊagEӤUt CrX_uzN b[]ZjXXemt (](`FxycbKHN$qX_@uWS/UF/TF89]/p/k(-G_b[̥rKZ }s. ՗B0ӟ zՌMY;[E~~AI|[,/`FA]\z+MXTyG]R/%5uiVz=/VGMŅp!vOm?؄JiA[|Q-iFN]myVǎJՑž2ݧۤJ|]CɅa@ڑYkS{RI .aK4Rr d(9V>H0|[C ,q&.pj%ز'qGs _y][Rl\d*ᬻ Xr[)_Xg]EpnFֳSU;:)Ȳ8]!-QQi/SX|NDƕvhV%%Bǁe&ߍj[%G->gi(~ӆZ4VÖr P HA tRQ!R&3i _pFqF:xtֿw~]縨_#d2)8Js()9,+8y1TH,U=]~r:լƐ B/_@?[}f5 碔%.E? DT@E=Xң35Ě?]6h޹ n 1_0a 'GM&Ai.'ddP,j|ĥ&e'j89/[U?t9JT"y¢1sue O;N^8ی'y}^V&dޔ_UH1A2 .tɟ U̧X2N k wf+:8='z8r ][BSSaꚫƦö֏4Yxn:{4㛫h\g9ʺ/E@sVd Xc˩哙wm$OħCJêc A=[J!~N^IM_5<*;k}Lr$0x>Fy2r|1ıZ.d@ fكbÑL_1h@]]?1TEVI֢r!GClM+ XJ<K}78rZb|*ȗLc龽F cQ1/j*:K5}R $tC㵟y ,=FYtbEBKҟE7>'eQ:i5s&YT{1yf7#Ikn cJ?0S{ӑ[o-(.%kw gi|gtnyOJ9電E4@cѱ;2Z@? )aR jSDd@{!>yyB%.9ļB8ZP&fՠSoF'uCLE7'fMġ>13>/~CM7d{Z񒋡Z㫮re#K)\jĘvUDgTVm)ѽ3ioiA=Kޓ7@zM WlmzSHk!2 \;X766Y%{0jLSIލ+]}9(IW:&p%E hj!+\°…CIl8=l JƻHgp/}> endobj 41 0 obj 2543 endobj 43 0 obj << /Name /Im3 /Type /XObject /Length 44 0 R /Filter /FlateDecode /Subtype /Image /Width 24 /Height 24 /BitsPerComponent 8 /ColorSpace [/Indexed /DeviceRGB 255 <0800001000001800002100002900003100004200004A00005200005A00006B00007300007B00008400008C0000940000947B7B9C52529C5A5A9C7B7BA50000A53939A54A4AA58484A59494A5A5A5AD0000AD3131AD9494B50000B52929B58C8CB59C9CB5A5A5B5B5B5BD0000BDADADBDB5B5C60000C61010C61818C6C6C6CE0000CE1010CE1818CE2929D60000D62929D6D6D6DE0000DEDEDEE70000E72121E7E7E7EF0000EF0808EFEFEFF70000F7F7F7FF0000FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>] >> stream xmQ0to4 F W1)5wYIg_63Ͷm;Ri5 F HРpmt NεHd'6L=su+C{¸=qˋ!jsjXQ:5lx2en Gc?CsMy`RmV/NwIvqwO'(e3HW*E}> stream xTMo0W19ݶ-==$[pwYafI# +wq!#A RFB1>(h`)]Opnxj1.7i  kr`w$aO x%~ [J֏ 8t?X(łaJw=@Pj. }&LdƷ{;P:h5eP ̄ d\j<gϫjمXjt͐n@U'NLx@.絛Q553Ajpoµhp- n nCp|J#ƙ=iY*`g6bSrͣ+[Nj8' hA6 ~6hE5}03YWf^-3 oiU[`PW];,^UGKn'l6 endstream endobj 42 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 45 0 R >> endobj 46 0 obj 471 endobj 48 0 obj << /Length 49 0 R /Filter /FlateDecode >> stream xrܸ]_7K) &;/){V*N<~ !Y4.^'tw[h~+D5)!Ct 1ɳ TkӑP/a{1^[C1 pj-pİKaxD@y].O!QNp'Eo;qBÑRNP͛Cp8$2#$+dkEOOGt3|@OcHMa`B!!\;xrZ1YEj Iq =1eӥ 4n|@#g} Ual0vg 3H҃lcig8,\`YB\=JOƐn6⼊!q@VioaY`'Qwp={o/1n6e9B_ 4`JmIfl&EG5ڶW\#A05Բ@JT HToӽٗ5e32T*f'oƯ]a{NUΒ:bP!,YBϻ+K75xo_}z7xgYy$kuN33Ѻy$Q1a CWc;aObܐuo7$J%h?peSFC<չZdw Kut}YKv I8Uݝk20rL4lw7e tA6wPɓL^ k A@/LT ɭzV zrAG"1Kfbs#hH94mџBF;Y+{~Ns'Z記pW0v@ zm n{ oꓶ%,:u6+O#Mz_yV?yԾe%?p6WbdQ͠\V^Kb0n -1ۗ.*u׎eQnlzoV:Bn gmic<ia$FԤ*騚 8GR0͂DB0a7Q^!`FU1쒑km-eM L+Y,}̵ R k Du :/Ĥ 6IoQ7? 4$ RDM*^-$C(HqPs !n!><9 tp_N5ƚ]1g:#d #}toe8qZ@i,S"~gD]Ks;"\ػbJ8m4&s)GWVueқ,m0U[}Ѕ>jDz~Pmiec0Zp6YL' | um SBKO lYf\ӗP^> endobj 49 0 obj 2776 endobj 51 0 obj << /Length 52 0 R /Filter /FlateDecode >> stream xYY7~ׯ`pȾۆ`cbcy GFCcƓ_ūIu5T:>V_+?YDqhW =1!!bTb#FU"?`" ʥ/ozߓ=~ܬn%hsΣ$ϳe8 r'@ 3yJ4t쁣yw{Y!!8""]! ?!e4DT8H鼓lΌj F3b,)Tbd,qcwrꥰ+@&#Xudde<[5}3'+GL} B(DDsoEօq9izRuZ}.ݰh|#e^}{q4zf/<$̠,'YSv5]f־"3^AYYSzD\KY(ldj-lJi5Nf:4="{_G#qXۚj^#PURHM,=ح8;$"BH,3;[I%]3ՐKQt)ِ%]cCtԅb@ki{ PȜB<uǮ/CWcgzaЉ*!;Wc؅-]Zj 8ODž-][_3-Z0FyN'\<B @VMY> endobj 52 0 obj 2062 endobj 54 0 obj << /Length 55 0 R /Filter /FlateDecode >> stream xYn8S谇r[`vgۃ`]}P٪*#.ڲ>]-I_F#,Q$E~$oJ\_I@$IIv|)=GT:Ohx!THJc aFk>?7%m|59qa]`.Yy0dG%͇O!.y|ibi Z@{oGwMK>IߛPYw$࣠@gy5APrZw8gk[ϜxIOv9mM.SQuc:ՓI yS"^euWw%5Н&[nHv-9|r`$X';f_X4umYzIMcI`ˠ11Dx.Dю6jb"E0=(i]& ||p !Ċ<ੑ f ΚJK=p0xx] {63V[Jn'M+Q9"μjj՗ r/qP#BV5FS_& 0o  +m=;,Dd;D99ĝa2o~ x{([]IkLq2'wWY\֞~!Bɺpnݟ(Z^7y{Du7oW#؅h.`N ee3RLx2m鲿CS6%ik+IaF :;';iW̷5ZA, t-Bbڲduu,N=/Glgt*I .EE`qfw>]&sR='흽}a޷jm3h0mh7Bj<@2oC' MD]\l~ߡ!d\mͦhDQ/lڷí1١Z}8fM0$ub#J>9sC`h5M1h& |old5}j| v+;HYYP$(gݎW֝')I$R!㫌TuC,aiy!Apۡb'SToGW\WyPj<}k;@@#EHoֶPCC?Zp r~o6) D !ՇT?GR|֕2^9kgUT9?tZzI!AD`ᨯwpG%|Hġ/:a!>g=0w~Ou4lg.ڥbX]/ɺ SDBNPOBU=lB;QaT$CO*7ӓAz2(Uf;#X{)vS}Zōci48V]h=JpҲl e'5*3.ymSxH*ŜxR9mx@>BZR) i:LdO&)ś[yKdZX{3PeC PXkx,uk]K_J"vƍ+ZU p^1E[xTkkMX6ׯj/Zr67.ڀ, hFe]Qֆ\~+ endstream endobj 53 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 54 0 R >> endobj 55 0 obj 2361 endobj 57 0 obj << /Length 58 0 R /Filter /FlateDecode >> stream xZO8޿b4H`;,rXRX&;%Mڸ+Dmϫ=Ny{>I|:l}D#;z8 QhVBT(N4-X GA9п>œ@ymPU n; '<44^pܦ8q@\<[n:b' (cd\ $ׯw׹Ҏk㌺z82b7zzXp6#1Yq%۰7BVa'pBT*NhMSL(Mik5pB;nT[{,),Ðӗ .줾特splA}vds ^YN[zYn a`Ȥ|Ie aXDb5꿌5G"ڃWAk[w_;>)Y3' ~'KWEU{>H8"_r@.֬?ým5K&/yNQƿh?B) GƞV&x5nZ%'9j A$ IS_\Iq%NriVlQL[ތ`y͟6 hv^E%u fUY,LKs0<2= 3 kӱsNkbWβ[e#,+GҢd钁 `<1d~#/r>$Zx3i~c4ԪzV *  T6GIkmwkb?=1zGIbAD o?kAgMg; )К8s_>HqL)Ԫpͺ"gѳP Þz;9f%C|.ڬl?z;)@4_Q;z[gPF&}-C'hUuy&Z^LG(T0R#[}L:yAojIyL%'qy}Ї+.RgEGSQ8&j^^s)-&֕;t8Di`3?``U '^KJRD25p~?<> endobj 58 0 obj 2310 endobj 61 0 obj << /Type /Annot /Subtype /Link /Rect [ 286.713 577.083 364.602 586.083 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 64 0 obj << /Type /Annot /Subtype /Link /Rect [ 445.369 577.083 523.258 586.083 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 63 0 R /H /I >> endobj 66 0 obj << /Type /Annot /Subtype /Link /Rect [ 328.85 520.335 395.51 529.335 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 67 0 obj << /Length 68 0 R /Filter /FlateDecode >> stream xk۶ ٩ IpNt:L'A)q}ou73X,MaBI򼈶OGD4Ӥ(NIS4%Q-x<~&c?Finpכ?1"\pM[Gn^IGw{g `(G?ݝ?60vPM=mUWCFwnb1ʿ5* =c+Ϛ|J Ey_]j@ (Ji9Pjb_=8. V g$䚯}3{"Z_t/=!Z7||ώy N8ͲoF&eڗcY5e[?sUG\ G_x>QmaїQaGs':(&8lMvh{ 3p"ǯV(A 5 3.ZұtZ )CXrł=i# ]{*`xlk'm|-|}_L&Mҙ)@kV,TՆc՛\rAx./ȉ1AE,NRDpyb"+!>ȀYfG;Q8Tq.DQ*7ҷ'n 4{*R?UU{W/Ib== x҆BV;Q Hr1Ji yPV'kY#De@wa2ĠQhS ̸(qu]L-=ұ|Zzjih珰[CE"MB 5 7pL bKB?c/gT@PҘ||~u E^@u*kvAF,0 i[*oe,/fެBT 'W/6+i,Fm"E(|,r=MYG'^6p_AiMs8$ӂt"HaX@Ɠ`!v7W6{NbؚF dZ6WC~fI|7qtF(4s6V[tPum)Е'G0_/ՠЩhg(!ZB_}M"8Ei*B%KfOIݐY#,Tm`g}O x47̃KaY*.`m8USFHo2hb2Ҙ٤P_e%J Ȉ"f9|= TqB,AI"kPru"Q8)Q`6vYVP*To`98$, J!;&celSym_n>~K ȃ,uo~7N죬z/(+ڃS zX_03+1\(T)M p:ZTCbhtu.AwaQ!ڳ%.:"`{ZV}hPL^#!C&w)vmcї@c c乒cՎ}}IXX>Ct9 a5|/ѣԿ"/%uIe/6gil9Հ(}*dz }LNYLfKBR]@i5 3hDYSfu&bG(k7SYkMd, hzKUf;{,-d"&]Hŕhւi&F\5PѦMtՂD3+s]zV(P&FC` ydkRL$#2AU`oy! rfBڦ8LߩX\1v;d9\8J$U&x}o^ZzÎb69mEAw|_W!kx;c~Uk}\*!hό&j_U(H\rqy.Ai&=(q S_O]%qt (jyWo"؉ЦJ!gZWjNRz.W.- {z4YTNsS^O7i؅5svvWÁĄ3=ٝ89f;:r]Ug&,a1 u'gmoK/O{'n+վS\ 8v<KPCh/Nۺ~1u+D᫧ *2RLIn5!-^H~IrX#=Rt֘#dw\?IXcDX^QP ̳\mjsdna)\,LOeUKA $Ҽwms;؉SV=۳赯~?K+ n\PĈ-X 7fr܄H煪xW?׃^8H`P8 1W^Q)`-hf[L#z \@#8kM(4 Z̕05T F~#U@\?@*+)wb1 ܚiFDYӭ)l!ޥ"/NSO*60{_'[ `v"Pɨ&j[])tg8d9v$PsǓV_|ډs'׌imVW'l\ZKHt6\vxpK`{  8:/_#7ƓHp{<"fy,j与ջ\v" A r#8t* < %-ruyF(SySrscL+_@q݇Bn#z߂W5J T]!/\#)3\t⾿TkTF:P[/pը @R  ?mw[QTHW67SY2$<[aKYD< ~h~WW R7}K|wӊEf3 !΅.$V5H;uXDcYjåA"-Օ& #Lp@»Aq$Ϸ2KmJ+|7=t"^4]9=avxz+<ȽL5XÄp\=C+|  O~TbD i=fsF0}HQ\@DT50͂b^2 endstream endobj 62 0 obj [ 61 0 R 64 0 R 66 0 R ] endobj 59 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 62 0 R /Contents 67 0 R >> endobj 68 0 obj 3366 endobj 63 0 obj << /Type /Action /S /GoTo /D [69 0 R /XYZ 72.0 421.889 null] >> endobj 70 0 obj << /Type /Action /S /GoTo /D [59 0 R /XYZ 72.0 654.845 null] >> endobj 71 0 obj << /Type /Annot /Subtype /Link /Rect [ 280.53 356.793 347.19 365.793 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 70 0 R /H /I >> endobj 73 0 obj << /Length 74 0 R /Filter /FlateDecode >> stream x\mo8_A$@P&޵5qhAVh,yE9YŢ$Zn]qSx=z86-p,!Wj|l;%FV+rQ"mo]h/&鄠7_@{=]L>* $ZL~N/]d4)PBlPhBO~9_lY9Jł 4b3qM5v2`tX } Y\jc)ߴrF~Չ߬HђADuGcۏD,+ 0p#%cX3&P. JH<!➥ g9/_Pjeӡ?4z+L0 p+kL]!`׸~͢i}CkhhboLeK0Qj 5hlPt!^>Dy:&1E*Kپ-K$yyRk9/c&bykhFQ]Dgd5fd3o}^4ZiL-m"<OߡOo_7nO MDEmַ(#n uMr0pmWQ.@R|QÄsx6Ze)/\N}X8CϟF9ӗiV҈1iI hEK]/&)%5 Q%T.>AYsAoc߲EH;4s80ԖN$lS)K FΒ`wخҔk*o:OLi Z6v|W] 6*јcŁKKfS2ޞ!jC(u&%jF:L95ӦQ ښ VȒ":!i n 7+ku|S k<0 ƔQӁpHGnO1LO"&V@?w%c[e[a C{Ь+GXv-ttAw*'hBF֗=.27r%QAk :V> endobj 74 0 obj 2008 endobj 76 0 obj << /Length 77 0 R /Filter /FlateDecode >> stream xXKo8WK,IQȡdE[4k{h{`,&*4ɿߡ$aҏS&3oL~("~%$h QG ,$$@c B[рF53+f9xRD@aF(oTg#l>V٫QǜB(JpahA^3EW)PnV+]P&:׵Vkvx ' b"(cLȚ,,,G7Z c&6O[Jk|}ZKƶl("p2 Fgcݭ+:l4O{W=Uڠ ЋզuǿX֪msywևn}4""ohV,+Ge 1IEz ZD llbwz76D$Q8j{X}ꇩ}^_&b"#{ۃ U8[jS YEa!2]^q""E6 * 0 ^YF q(7\ Pqd/iw T~ gIK$.b]jmeD/7RmS(t]/*)~I!8J?!]5<A{ܻ ?14t<-PeEqG4_'g8iY3E[{ظҩ s,tN"Ş{a8t|)U~`e@Ί::e'GgmL ˴3&F{*OcxVǭ)\§OM^95LOk,zUY*Ƨѓa].N)yI4w)#Je-d ~^n})=JJ漭*i6WԓI]M}mfD?u{1:!.0g@bwO8b ,R̺oMU;:(MyۍphMٍizUQFK«u9`ye/hWSzN% $s h˛\W`܃6HºhIcnK 8\̝i醱e J!U՝-qVNonvA;ok$)q XDF̜ J1xW3CD"tXGrnMCqDMl(!IúH_AJðnO\8Pp]v!zRy=e#'<EkO3gk],<*RX -Ok;U\/uV0nt!뱖N I$C;;D,` ]n*ݻ=20RFA0\`w{BoNzBYy2[d 2oTG九 ~$ endstream endobj 75 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 76 0 R >> endobj 77 0 obj 1435 endobj 79 0 obj << /Length 80 0 R /Filter /FlateDecode >> stream x]o8ݿاHTQHhmѱPYr-9i9IYSۇ̌4Ù|JSyAVwKD$qK(M8fQ-2RkH|Ch1Wx$1=-@7~1yXn}FhL<i1%yĒBKݖ|g۬^UېvMjZ+սJxw7(٨h,zB !#k(KXy{O70яF6ߓci82ʝDoQZ(Q1I/cI$ZF$>jۑ~#{RMGUWoF#9ɭUTwD^u6__j$q2UﲪodɄ]QŌЩ}#50HCeQP'WbHN$'EQjeKXU"85A 7EOHc"[J޶pƄ;#3Nr8rTڝ 9C'=:ժnUS-u 8aJ֎Zo z ͏ui^Rx}CD_QGJ_EУKCFI=?S)C֕<!px{gG)9+GٻnJ[]qdVfGxp8R L3:w|S?4)bۛ^2BLe2YA>c¥Wiʣ.a5/P8ET00Z6wcƕ &(rTn<~^\ ANTvP}L%1=21 QSjy=o!D?B=<i3ə;ֺs%G5X6M@z =D}gwNjԘ9}۶T ;Jo:m vø1e\ GqzMV=B϶77ňbFRgEM$g0RgEB̲\@@@}n"IbP<8gNs2aє 'i;J`ЙldI쉎ڟ<P0{831Ve#|b0l XCc$zgXݢdBC&•Y;(#[$Ddse)љs)(Lc:5x,eSa;4l0;<s5#Ҍ {L_FM!_ⶳ Ҩǹm 80i¢Ra7Owg.{gt*J?{~gIy$v۷lDO-A8SiY(Da[ W gjhG*UrBņpz8<Ғ3=i L,YvuvG`kᩈ頻/sP.0k5KtAs>;=r-i _26pg4b~Ų7- M4?6VaK@oaGXK)>ƄQ_exMi+U 4I;hl>8ltN׍'`VnvP a|yv`59hy?z[gޔ,3q7V`W;%iu}nMkՍ%3CyZF뛷/SQǼn3D6#{tn5EU/i9<]Ӿ1FA:ggRAB$TxAc̣"踝#a=G؞{32Z AQ%;7qb/zVXˢ6,vG*xtPqaMT|ʣ\ϱ)+졠#f2g^I \;vY,ogcvzמ 7Or~^J&'=%(uvMq>e%#4Dlp^ endstream endobj 78 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 79 0 R >> endobj 80 0 obj 2318 endobj 82 0 obj << /Length 83 0 R /Filter /FlateDecode >> stream xYo p@y?(P4)r^(·xFbK N5J~B9M`(;8o 򬔂b8~lQ6Sw,Y-z4O0a$T+֋l¾$sds8'=(B`xE P `]pݑk4Ƞ$[,˱]GȇSi#Ӕ\Lf4X;LA_nc 0sVs0hyl<忞H'24䲜z6^V$p@3հa(jft~6s8{.OAۙfZI@(wȡg" -1q2C0R dNC@ ̡ #D(r)Z)$ ?iB S5ꗺM_mpI*-יZmUp/ǼSBk. /bϏ5/fB<AV͑a#BfJ5c?I$_ɾ^uyOX"VȦGaTQtrŚEoN@ l4UW.3a9w)(o6Ef0,U9X!y:}`8Cy0AI _$ɢbcGǨmGG*~%KUV.O x1( e{&gSM89]Кg c,pe@@& HhCC&@v\7DJs++ϩ&eTxIRzNaV--l pszQJwd8.`@03,&y)0B>tյoG!t{K4:. nN }n :֑fE{0tǾ G2| QiUO}Z%m6bk4.p=n&S9CkscHi9 @4x/#C9Ǻ(ٮ+fmGY*C@ylڜ lhYH*e֧IC+Y+EMG,u3,O呈ԓw_H+E3ٳ{z&:Q{Srm Ȁ3kl,_X]j&§C=q6_ Zo>D5^$mZ,(O^l3񍦠5r mVYIw zhGHngPGs?V> endobj 83 0 obj 2544 endobj 85 0 obj << /Type /Action /S /GoTo /D [56 0 R /XYZ 72.0 303.373 null] >> endobj 86 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 95.495 188.501 104.495 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 85 0 R /H /I >> endobj 88 0 obj << /Length 89 0 R /Filter /FlateDecode >> stream xX[o~ׯ ЇȀNK&Pqp@IfoYr%wI-8%6lqùqqϋ{+>8@jY(J+8L|?BA %+AXc q@z>(T=.)M~u:ũšʽ(,O|{z;iSfp񖖔Sn>OE"-PAYy$0KF3?xIp3b"9)h}+Xߌ.ǯƹ땘TEV0Tk_MtZ _׃:x#ef-v8~#˲9YLC֒-ݟ47DM'btxZ#plo 3ol"ˠ G;T07MiI agwo'9϶@MN?:رԟ _!~4-foҽmZ+g3zZ=h%AXi.F$;2>5-9B Ћ~W/Vqڡ+!ٙ|ŧe3 n1#Kan!U̳}uw=#]+cøǚw׀[{a _~?y^ #|d!ۉxK1dg$"C'r&V+9x/ FґE+ D?)ax"H\t XZ> /+iEІ!5"CHy&y#H#hlũki 粯.Y0̪*k.Ocw,! ! hw -r͟d5YSۦLLsaZ*ft{4Vw=`N }6lGzblq'qr?j-RcjH8jN U(fGk(p;3N*E$j@}׊|f?#Ύ(2Jع6Vq/Xc+EKhrN9E<-wF1܍ܩ2JPG;>ޜfM)|qEBAϔ d=?6 *%kjWǚ@QIJU}'.I~?62n.2;2쎼 \5KZW Z_,uryu=jN-{hvԩ͢n^-9aiJ&8p:re$-pʌ%Eɛy"MiJ$Ck](`?> [Os\ jaVZ%Bi'B0i:F|t2`[\$IHIU$9-XR 82f !3ꈙ&D6iWMmf  %!9M|sV4-CcZ晘{n:=UGC԰g`Jb#,jJ< PB#^ fD յ=Bs>R0/.8yiJY)6fy5[QJ8\jhO5>;ץaiK6" gy=çeij-dwQdisn,K|/r /oV7k0Y璳91CF5Ld[(*ڞZl\i1Z-e9]DFzצrl^ϒ@EWN9py s0MLB B 3t> endobj 89 0 obj 1946 endobj 92 0 obj << /Type /Annot /Subtype /Link /Rect [ 471.109 717.012 523.274 726.012 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 91 0 R /H /I >> endobj 94 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 705.012 143.33 714.012 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 91 0 R /H /I >> endobj 95 0 obj << /Length 96 0 R /Filter /FlateDecode >> stream x]ߏ6~߿^HQЇ%isf-ZNIfDIMWH1IÙGʡ_K1(F{SNMQaFahEd+A|tB~~_x軋_:A oD⭥9__\ ]b`Q(>wgw4K(oP/$翡^{f[2T cOU@}LyނM[4uheWY`D?GzCFqr9!qQfcTԫ01` XCamfT!BcqPZո",PY0޲ڞUD0)͡* .U8<9 F<Ze[p!6?FZ,ksV6j`tFDvw˦a9zfViOjѥ 4ƛ:ٷNo]VEccȾ4*<+}4 #xhl)9BAyRtWy2D6 H|LvL<_!YPZҝX" A;"EbC*.:zF-nr~EjELFP_գ.4 o1xфaSVFi 4m;= } a&NkFx!GZ\&b4QCYlIGrQpiꨘ";ZEZV9]&s&l춉:_ǴmOzʖmDB}7Vȥ! POg]D̆O\ƈ:հ?%NBr(ݿ=](O6y56:y_CkjEqUމݭ&5nuҘKaoWA9u`x%+_idHˤsPhRV5:7:) `"APvPp{@xhnHI8G/HQ! qNj ʕL7ւml}@C{]'Y!cj "(p* X8zE]qq.7D }IЙoJS`9^Z!BY|"D= e2C ( ]@JT+%~\ qD!V+y4[&]. DGl2&Zx1{618YQ :NsU9$e~ &“Sއeu:svWIUHUN*zdp`/]ۙZKsib/N|3Ёep{cͷ?+mqe+Zdoo nVG~}. ?o:'Nb} -E3SD$lK(;t"7)mWMֺ$+sKgԶVdck -13.W<ͫ}#Vw,˕7f:J }MxQ~Z?qԳyG%Ed䃹 Œ7}D?e@OL_"Zc L?l_BKA+ȇc9޴[K9Ҍ5N[&#Z.n hTs.0$B#F@htz,29#?Oع0Q-:D?f Ʀ1$`W1*Ȗlg`g Nʴ`h6zJ<{Qhc-`$2.8˂w!KXx|{, XJLLL0Kܐi2E&OafKFZ̒qԲ`h>zJ't~Nid'N]|Ѹq B\ pndYR>}޲h60zzlB>oY @e-3҉Пja2Ksy˂`)y˂/7N2!_˓Pύ~>K r+?N,h f/ h7p_ODS1q87fBf,蜃Cry4Y%C[7 oy2Th:7.nԩ?Oc#>៶E0#?2SB@f U3וUe uUVDzyN9fr:FJ(vDŽE}:GB 0c . }:WE\O/]t{աvZH6N\LK؏|`0@CH7*?Jq endstream endobj 93 0 obj [ 92 0 R 94 0 R ] endobj 90 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 93 0 R /Contents 95 0 R >> endobj 96 0 obj 3117 endobj 99 0 obj << /Type /Annot /Subtype /Link /Rect [ 396.25 241.771 470.41 250.771 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 98 0 R /H /I >> endobj 101 0 obj << /Length 102 0 R /Filter /FlateDecode >> stream xr9_k%ca2g-QVWZJv߾ KnEI '?Y,zU$ HأQ{^H1ٓ㡘 ȿ+OX!н\y%'G6I><]Y^rkMF4<0ſ,w +I߲'N͟d#Cϣُ')TQ W&MSU:i|:\6gƎK BFLpG#<(빺#Kay0EGݧ] \JGVAwxe6nȶn|0яRQ>E>#nɺS߰+-JN+|S?.~@vIq3!ѐ/eAFJa|-i*Yegѯ׼mo(@$E ?M7f`k+:reeY?IIFcn6ݛ\g̾JwjV*/.YS f)nvaRȃxEyy_-_k;<$8!f43A}93cueAy׶YXo‡bc`6v峭jCW7f`\ 'O3>T큯mмi~_ v-I$=CgEk1+_Qv[ ^uóOxcxҔ*s/!xR<6S"AD@쎕%ߜw!t= ݩ$ӡ1҈/G{q~L}2AP?/Nd;>i,T?vu߳jc[)xCgfAςi2H$N8=!L](3G}f-haG0)D<{v-T.%"voxa=,LiO !G:#zAR/Ո!ʻ)3_:lٚGcϼ%5 D*7dщf#>]7uaPz@bC5QkJSib,B:L<4])-& |w j x(x÷/;]& فUJޜa M=rvNFvLȟR_NYJ~kfUCL6wˮn [e$CI^YfDZCkf]Ir nHpjN"pkD+o*xɚCE4?tʔ,AwRyC!vx<,Ƿڲ⎤vP,unb֨0UY9s.9wl^ x8"L"ʈQ!%vcL mtN^v?UpcATD$G $`zEM?oaL o%#  b2d8c2Hd49DS`ju1A !fI>"8D|` 91zWnI]kkQZK:V4A0#d0"t u]uM]yE4 Y!5MkXk=a٘2D\A$$ J+Gư[(uKC;+Вd T8 GIgv: JD:!H F\]o?c:4ID?(IFRc8&j ?]]&ppei GH Dm8vY̝1#ntENnBeO$Lb>(nURZ'n!;3>gYb+2dWZ iC x6#}w"?yٷL#v2\'-673xc\ߺXwgp 2MTӥXukC^$| ? )8qZ KE8G=ƹNӧO v@,Vpka*6ȡg~,]&k M9Ki祪ԺHNeBf.IU{iSbZ]/"/'r[ ܯo>O; ч-Hc_,NE,x4Y–ob2vߜ)L.XaI6 a)=W;oxsf Z Ѯa|J.(S?/uv ia >14TI!L*Nʢ(Qc(%  N!r<>aSO$q:BW7F*]'cEK Y_z>\RBNdŇm+;%b3".lV5¾ތ5 bx8(/Tm@!T[,ϼ8NchH-*TDiƙZPY7*GDYB憖1̱u ڥ1AS]!*-hΑA>#'<\huEOV> 0lc1|.nd.Yj rQ#oB?][̡mFL%EvՅ6,<ܹ G:( SG ʀ$zdC(wMf`jSL,Ct*A+2$MGiCz%qHZ{ff^>^F|$Y;QJ8 $dg&G[+ bLpw+1P@gQ; J>Us!K +ɂPrj "&ң΁N؎oauoG#;> Q;by1L_T= a‘ Y2Ѥ3BTJ 9YǏ]8ثfsMzbYu $GD&s#f.T_ szQɘM,W|kGa ll޴/?tI}%0ťoe?]I[_ endstream endobj 100 0 obj [ 99 0 R ] endobj 97 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 100 0 R /Contents 101 0 R >> endobj 102 0 obj 3384 endobj 104 0 obj << /Length 105 0 R /Filter /FlateDecode >> stream xYYs6 ~W1cۦI;}H2YmMu8 ;} | H( Lo!8(ų[$5ci#`E)\pjFY &uk6œP^_ܵl `3nj:4Ml[*E?6 []6$bV^>Nl[ ]mb12}lL-Ϸr5Gç:>Ia`#ޚgͶt|3MgԧpIFۜ˵7 W,n״Ĵ.`]S㔕ecX1V{Q^,} T*WcEx-BMӳ݁EU:7PF68h5HِL;z R.=|wOAQ *BKv@6G/BΥimPg hi7\d`m60JV[Rn 7LY'zW~!|yU3_)-vϫ?ެ'%^&L վN]vq.s֜=サT9?jb0MA,܍@W{STk|s#/- (Jߴ!_ Uz[secΘPz Oodui"XPzPV,dn䫆xޫ|X"Nw3%i%E, #~6l K˱P}*m>WgzB&&$.+P6Hj('beH(*- X) :,ȵLÁ,aqgb,cR:lͥOyB~ɩ\PȭD>Y<CU_?'o{x S7x r%R*WCggb,ၰTS3pn{x9\&>~Yhaf)Jh{Zׂ׼]I[ F2cpw,:&K nVN*t bE1?on?{фʷU_0@zL5 aA[a)FYs{RK@4FvI +NM|lnvި{z@ P֑K6@! (bx~fKIo\9x8^y9_ ϛ[H3Zm`Ek ּB[^鱬4no=՚Vo^x!\imRwCL<5p=D( *`Y#jm]?@{ermwƞEfaeYŊ0y 7Ԉn1^4ǛYubpuʑڮqnͮ2gޝz(VfScc u\2 *E/(YV*ȊVx()w7& b= pU)nmN endstream endobj 103 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 104 0 R >> endobj 105 0 obj 1911 endobj 107 0 obj << /Length 108 0 R /Filter /FlateDecode >> stream xnF]_1>pWo@%n." ̅7o|ΐ~>/Do0BIx (b=vGC 4>Phm!7z }\ ~Z| 龜aA0׬#h~CA>\JqPԏ},7bF v+-ĉE#x3!8A-VzBAɬ#2L Os3gpbQF6Fщ1?k-KNQ|&DQEddΥ\f0ꌆ 0 u mXηnxʮ(F+S򼀎1$_ pC8r3)]ᠷTԺJ8"asweʸ]%7"FL?Ďķ 3^!N&M׆yt:.XW;Y^tԪ_8]mxx#ò85f ɉqWwV# \GmE6u5p=cu6YQ12$m豐aQD(Zji떋C '/fN58D+3ylyxj þ J<%)> x2vF;J [%Q3x\`uLwpA9z=dl;4u+S/U48qfiO75hGVqZB"8Pm Dt[)O1 ] m/E3Yoq&Q2C8 ufR~~[-wH_a&;bڋض.z$ ,SU#[ؠ!&Ts {"]oOo߰NZΈ`3TNW9*K3٠]\(m`) }Iw?e<G|ۊ!Qas.#T5u0/{X| y!Sxl,<Y@b-]":FsJN!plx 7&ݾV[hf:;sg/rLrѣhjVl6~yBO9KY Qe#\yl*c,(ma샑PQ;8yDͳg"X^F\6`xu(DyO=V4!+_xrlUğ"d!GgTJfY(dK|asF&sTGrKQܜ1+Ůr̥rK3zхus ٣{UfW1x²h`7b?'舛[ vtbJ R;R(OOXxl C>daDiv=wFmykqZ׼Iֶ[*66Bp!]X0oD< mxw z;-fyvr6B.:s,Z [ܢOm`uR [c oF$_x55}@Ag?!*㥹1rߘYϪcJD{Aw 9HU {U7!I֣6`I}"wǁ,yF?|HwD#ʓ>r!}?diy.=ެ=@6򦃭4\>e!cg>OIe{"2wqi.n)9t&g#;lFg8fȏ1y.*(z+S\෇5l@ֹL|mwmM[so.qzD0; `Y R:5 4YoM2=n't _rZv`h x9=veܡ?٣>{bڋ75g`݆L*DWb֓}@d씶7W XlT}*UD6⫉1FJ U| #LCq+YxX 0XT‹G^Mp/޿v:Ǻ|G.ċ endstream endobj 106 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 107 0 R >> endobj 108 0 obj 2142 endobj 110 0 obj << /Length 111 0 R /Filter /FlateDecode >> stream x[mo6de@>$s8~h@66q!EW_'#?qÇ#aF߹E-'ȣZ`˦ ۢڡA1jXoodы w=ƕk7=SbvAźky6[~,MbsB J(N7l:D, ϳE# c˟Z^+Պ ,\"ȡ̢~n`xR˕tF>j-lHŗW;ZpsH`!A<dV*:.:h/sJ]\*R?r{ [ITG(\P(GqTh-b~b <]ҵyTQۅ*fCrIÜ} 3=gkS u?sS3փl0[<.ɤ ! -y7vZ oAjTf!vQ7顣~&ESI07TvaS=_z(z<\`T^q^˞z="> 8f\7zQ{ZgXۣ4r}+& k r|mlH>K (RféC@, Hǁ̪'ō]€,>M 1Ϸ\A諜 ]2'2ZdvXkg\I˨"Gu3׶N\(z=(<͌o>(ax̌Q9ME!=VJ^qXwpd@QJ`N3ҴN;rKI53z}p2|b#?0Xnwv-a*l/͈|Ө9$X}r9QUË:28h1 UoYu0M`xW0h3_A~>?݊=,=(_O{tL@$:rmü/E _*t= za{-t5j򄆶h&vY^`y&~uﵖV&ϪӬlyK^ȥ*ɋpa sCI3.yO8| Gwh 5~/\"}c yȖk ^vDpļ@떎X13CGQ/lt{VUbk\a/Zh5Ñ Οn./-#y=/)b5$ endstream endobj 109 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 110 0 R >> endobj 111 0 obj 2244 endobj 113 0 obj << /Length 114 0 R /Filter /FlateDecode >> stream xk6?dƻ36M\swyllM^3Sw:-ۚʒW?Hɦ|L"*#0oBעaa  l1c\j{@$d-?|ž a4b…sG7I?Fv7gX,> \1f:vdq \-mkʸN[]6^YZIu'Y:Y<0Fb'dPaf<ۡvwrBi@AeRφSQx˺p&˲("Xa/R0}>륌vhūk8l -tMy*e! Z6b} ۃM8,W{lgpexԗI䵼φp,`C>5"̕, ϊP\ǵBF1QȺ8,(SZ;2VYTYiVιiǫ,~;dSh&;!$H":(<* 푢<595uvH* IJk;,4< H<ngUA_Kd β:<&kҭ1#$(BE>qI"nyp@V)D2t1 )Ęg9N\t#/_^p7 sIZ6]^=R+:# ; ^MqqKzLXxϱ\~O2^g %f^^SǢ@[(Gf±0L@ pyN4YΒ_RF~!%44gFP:4w2&=o?*n@!+ኡ>GU f&4X e0r,nfL=h3Ԩ1Di "ĝ,$=3я{TH5aEYk4yӻ7o;GTKyZу1(M݂ym D+'Pqq71;満Ǣ%,Y:>L P-gSEFI !01XLͶ7;k/[T*TfW43?QTkc}bSi!ˠcOʱh8yfl:mW(7]b&v?7gEϥ s>Y1Đ,'@˸|j8X,DnX$̐0DPYSUϲK]iQFT.AD xymLmx?Dd0 ʻN(O]60rx<tG7~|؞M=fQ'B:q ,>l4#b0S}U ^S"'7&z!fgՃc\cވsVʶ1ivKrrkq9[ CqU5BBB+*؀wuAc㉫Cr~Ҹ8Ǘk(, (9hϣ\eKB$ZT [RdjE=k5-DiE7ˢQˁw2/$JCQe&?id&7~;܈l(ºȚC^M{VuBƖ4_gFfպL^kSb[HOWۻ%7rx(~| 7%7tG'FFT4نTIETW/KN^aNχǻkA=şjTe0 X3f \&ihxEOMn`+I{䉔E$16 &I㍜i=ys ԰\yLJnyC?6}: 5ˊ'w(6){ʡ(879f3ݴ!&?1 1{Ao9R x<z}T g⓪DUpN3Y4$&<0;c~m rۻ7so38x߅ w|~( '!^? > Yf̊d~:%\Q'>gDve%=*s1!+H pRm}#?oЈC? ;`!E~E zōBLމ=rp WA5ϋ| jm UQA ,2 "TQEٺh. Ny%AwΘ? 9DL1 Y`8 endstream endobj 112 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 113 0 R >> endobj 114 0 obj 2348 endobj 116 0 obj << /Type /Action /S /GoTo /D [17 0 R /XYZ 72.0 769.889 null] >> endobj 117 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 730.013 180.531 739.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 116 0 R /H /I >> endobj 119 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.455 730.013 525.455 739.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 116 0 R /H /I >> endobj 120 0 obj << /Type /Action /S /GoTo /D [17 0 R /XYZ 72.0 580.03 null] >> endobj 121 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 718.013 252.193 727.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 122 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.085 718.013 525.085 727.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 124 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 706.013 232.207 715.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 123 0 R /H /I >> endobj 125 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.101 706.013 525.101 715.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 123 0 R /H /I >> endobj 127 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 694.013 194.546 703.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 126 0 R /H /I >> endobj 128 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.505 694.013 525.505 703.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 126 0 R /H /I >> endobj 129 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 733.889 null] >> endobj 130 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 682.013 210.607 691.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 129 0 R /H /I >> endobj 131 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.387 682.013 525.387 691.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 129 0 R /H /I >> endobj 132 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 296.319 null] >> endobj 133 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 670.013 245.108 679.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 132 0 R /H /I >> endobj 134 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.135 670.013 525.135 679.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 132 0 R /H /I >> endobj 136 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 658.013 248.966 667.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 135 0 R /H /I >> endobj 137 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.107 658.013 525.107 667.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 135 0 R /H /I >> endobj 139 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 646.013 322.46 655.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 138 0 R /H /I >> endobj 140 0 obj << /Type /Annot /Subtype /Link /Rect [ 519.671 646.013 524.671 655.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 138 0 R /H /I >> endobj 142 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 634.013 177.408 643.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 141 0 R /H /I >> endobj 143 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.629 634.013 525.629 643.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 141 0 R /H /I >> endobj 145 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 622.013 180.168 631.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 146 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.609 622.013 525.609 631.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 148 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 610.013 280.848 619.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 147 0 R /H /I >> endobj 149 0 obj << /Type /Annot /Subtype /Link /Rect [ 519.997 610.013 524.997 619.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 147 0 R /H /I >> endobj 150 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 273.632 null] >> endobj 151 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 598.013 197.884 607.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 150 0 R /H /I >> endobj 152 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.481 598.013 525.481 607.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 150 0 R /H /I >> endobj 154 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 586.013 279.697 595.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 153 0 R /H /I >> endobj 155 0 obj << /Type /Annot /Subtype /Link /Rect [ 519.885 586.013 524.885 595.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 153 0 R /H /I >> endobj 157 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 574.013 208.63 583.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 156 0 R /H /I >> endobj 158 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.403 574.013 525.403 583.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 156 0 R /H /I >> endobj 159 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 562.013 264.932 571.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 160 0 obj << /Type /Annot /Subtype /Link /Rect [ 519.991 562.013 524.991 571.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 161 0 obj << /Type /Action /S /GoTo /D [90 0 R /XYZ 72.0 769.889 null] >> endobj 162 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 550.013 317.957 559.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 163 0 obj << /Type /Annot /Subtype /Link /Rect [ 519.706 550.013 524.706 559.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 164 0 obj << /Type /Action /S /GoTo /D [90 0 R /XYZ 72.0 506.507 null] >> endobj 165 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 538.013 258.222 547.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 164 0 R /H /I >> endobj 166 0 obj << /Type /Annot /Subtype /Link /Rect [ 520.175 538.013 525.175 547.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 164 0 R /H /I >> endobj 167 0 obj << /Type /Action /S /GoTo /D [34 0 R /XYZ 72.0 671.221 null] >> endobj 168 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 526.013 246.624 535.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 167 0 R /H /I >> endobj 169 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.225 526.013 525.225 535.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 167 0 R /H /I >> endobj 170 0 obj << /Type /Action /S /GoTo /D [34 0 R /XYZ 72.0 339.956 null] >> endobj 171 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 514.013 246.614 523.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 170 0 R /H /I >> endobj 172 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.225 514.013 525.225 523.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 170 0 R /H /I >> endobj 173 0 obj << /Type /Action /S /GoTo /D [39 0 R /XYZ 72.0 687.389 null] >> endobj 174 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 502.013 211.9 511.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 173 0 R /H /I >> endobj 175 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.343 502.013 525.343 511.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 173 0 R /H /I >> endobj 176 0 obj << /Type /Action /S /GoTo /D [47 0 R /XYZ 72.0 769.889 null] >> endobj 177 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 490.013 213.417 499.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 176 0 R /H /I >> endobj 178 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.197 490.013 525.197 499.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 176 0 R /H /I >> endobj 179 0 obj << /Type /Action /S /GoTo /D [47 0 R /XYZ 72.0 740.03 null] >> endobj 180 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 478.013 216.496 487.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 179 0 R /H /I >> endobj 181 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.307 478.013 525.307 487.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 179 0 R /H /I >> endobj 182 0 obj << /Type /Action /S /GoTo /D [47 0 R /XYZ 72.0 493.091 null] >> endobj 183 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 466.013 311.258 475.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 182 0 R /H /I >> endobj 184 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.619 466.013 524.619 475.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 182 0 R /H /I >> endobj 185 0 obj << /Type /Action /S /GoTo /D [47 0 R /XYZ 72.0 388.694 null] >> endobj 186 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 454.013 251.671 463.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 185 0 R /H /I >> endobj 187 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.051 454.013 525.051 463.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 185 0 R /H /I >> endobj 188 0 obj << /Type /Action /S /GoTo /D [97 0 R /XYZ 72.0 638.493 null] >> endobj 189 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 442.013 184.584 451.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 188 0 R /H /I >> endobj 190 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.541 442.013 525.541 451.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 188 0 R /H /I >> endobj 191 0 obj << /Type /Action /S /GoTo /D [97 0 R /XYZ 72.0 150.573 null] >> endobj 192 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 430.013 188.183 439.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 191 0 R /H /I >> endobj 193 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.515 430.013 525.515 439.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 191 0 R /H /I >> endobj 194 0 obj << /Type /Action /S /GoTo /D [50 0 R /XYZ 72.0 769.889 null] >> endobj 195 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 418.013 231.447 427.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 196 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.199 418.013 525.199 427.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 197 0 obj << /Type /Action /S /GoTo /D [50 0 R /XYZ 72.0 438.066 null] >> endobj 198 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 406.013 222.54 415.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 197 0 R /H /I >> endobj 199 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.263 406.013 525.263 415.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 197 0 R /H /I >> endobj 201 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 394.013 301.407 403.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 200 0 R /H /I >> endobj 202 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.689 394.013 524.689 403.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 200 0 R /H /I >> endobj 204 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 382.013 296.617 391.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 203 0 R /H /I >> endobj 205 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.725 382.013 524.725 391.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 203 0 R /H /I >> endobj 207 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 370.013 373.619 379.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 206 0 R /H /I >> endobj 208 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.165 370.013 524.165 379.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 206 0 R /H /I >> endobj 210 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 358.013 302.507 367.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 209 0 R /H /I >> endobj 211 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.681 358.013 524.681 367.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 209 0 R /H /I >> endobj 212 0 obj << /Type /Action /S /GoTo /D [53 0 R /XYZ 72.0 745.889 null] >> endobj 213 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 346.013 268.742 355.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 212 0 R /H /I >> endobj 214 0 obj << /Type /Annot /Subtype /Link /Rect [ 516.61 346.013 526.61 355.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 212 0 R /H /I >> endobj 215 0 obj << /Type /Action /S /GoTo /D [53 0 R /XYZ 72.0 297.006 null] >> endobj 216 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 334.013 350.288 343.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 215 0 R /H /I >> endobj 217 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.413 334.013 524.413 343.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 215 0 R /H /I >> endobj 219 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 322.013 270.019 331.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 218 0 R /H /I >> endobj 220 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.811 322.013 524.811 331.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 218 0 R /H /I >> endobj 221 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 310.013 186.776 319.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 222 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.525 310.013 525.525 319.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 223 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 298.013 246.614 307.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 224 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.225 298.013 525.225 307.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 225 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 286.013 216.593 295.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 63 0 R /H /I >> endobj 226 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.458 286.013 525.458 295.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 63 0 R /H /I >> endobj 227 0 obj << /Type /Action /S /GoTo /D [56 0 R /XYZ 72.0 670.889 null] >> endobj 228 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 274.013 303.849 283.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 227 0 R /H /I >> endobj 229 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.777 274.013 524.777 283.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 227 0 R /H /I >> endobj 230 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 262.013 265.401 271.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 85 0 R /H /I >> endobj 231 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.951 262.013 524.951 271.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 85 0 R /H /I >> endobj 232 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 250.013 361.102 259.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 70 0 R /H /I >> endobj 233 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.255 250.013 524.255 259.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 70 0 R /H /I >> endobj 234 0 obj << /Type /Action /S /GoTo /D [75 0 R /XYZ 72.0 247.637 null] >> endobj 235 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 238.013 182.362 247.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 234 0 R /H /I >> endobj 236 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.557 238.013 525.557 247.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 234 0 R /H /I >> endobj 237 0 obj << /Type /Action /S /GoTo /D [84 0 R /XYZ 72.0 283.503 null] >> endobj 238 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 226.013 320.589 235.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 237 0 R /H /I >> endobj 239 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.645 226.013 524.645 235.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 237 0 R /H /I >> endobj 240 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 214.013 188.183 223.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 91 0 R /H /I >> endobj 241 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.515 214.013 525.515 223.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 91 0 R /H /I >> endobj 242 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 202.013 302.002 211.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 98 0 R /H /I >> endobj 243 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.791 202.013 524.791 211.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 98 0 R /H /I >> endobj 245 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 190.013 199.202 199.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 244 0 R /H /I >> endobj 246 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.435 190.013 525.435 199.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 244 0 R /H /I >> endobj 248 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 178.013 214.93 187.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 247 0 R /H /I >> endobj 249 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.472 178.013 525.472 187.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 247 0 R /H /I >> endobj 251 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 166.013 226.782 175.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 250 0 R /H /I >> endobj 252 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.235 166.013 525.235 175.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 250 0 R /H /I >> endobj 254 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 154.013 187.902 163.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 253 0 R /H /I >> endobj 255 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.517 154.013 525.517 163.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 253 0 R /H /I >> endobj 256 0 obj << /Type /Action /S /GoTo /D [103 0 R /XYZ 72.0 745.889 null] >> endobj 257 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 142.013 185.68 151.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 256 0 R /H /I >> endobj 258 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.533 142.013 525.533 151.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 256 0 R /H /I >> endobj 259 0 obj << /Type /Action /S /GoTo /D [103 0 R /XYZ 72.0 255.406 null] >> endobj 260 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 130.013 344.482 139.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 261 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.459 130.013 524.459 139.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 262 0 obj << /Type /Action /S /GoTo /D [106 0 R /XYZ 72.0 769.889 null] >> endobj 263 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 118.013 322.217 127.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 262 0 R /H /I >> endobj 264 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.633 118.013 524.633 127.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 262 0 R /H /I >> endobj 265 0 obj << /Type /Action /S /GoTo /D [106 0 R /XYZ 72.0 306.499 null] >> endobj 266 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 106.013 270.892 115.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 265 0 R /H /I >> endobj 267 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.911 106.013 524.911 115.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 265 0 R /H /I >> endobj 268 0 obj << /Type /Action /S /GoTo /D [109 0 R /XYZ 72.0 419.563 null] >> endobj 269 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 94.013 187.354 103.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 268 0 R /H /I >> endobj 270 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.521 94.013 525.521 103.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 268 0 R /H /I >> endobj 271 0 obj << /Type /Action /S /GoTo /D [112 0 R /XYZ 72.0 769.889 null] >> endobj 272 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 82.013 219.058 91.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 271 0 R /H /I >> endobj 273 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.291 82.013 525.291 91.013 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 271 0 R /H /I >> endobj 274 0 obj << /Length 275 0 R /Filter /FlateDecode >> stream xr$qϷקl:jiCcOCI;?<~3x3/5 e ֧9 qZ[nƛ߹>|>7?~2[?3>\?_~s~w8iog_?|/wofvO=W4M'_O~x_AӘ_zt;f)p/.U~$I=pXF,%;X,Y dR"KE, Yr ˁ,Y:td2e @,Y&wJIM,e"2KiRF,KR:d)R KE,Y4dir ˁ,ґ#KG,YLd2eKNR'bXj#ڈvbXj'ڑ KA,YGq}MELMw8?m:юzOקNΏ/Cy;MC\_`syh#j6MfJnZ&3.벳ߟtȶ5W o7m+`c{f\翿AmRVT;|P !ˁ,ґ#KG,Y d2e˺ZIJu#ue]-N,j)R#KA,Y*TdR!KCuyv#+uic! q.l$&I&@ (6 @z܁`]b"(DPA!J*4"hDЈ "8A'N "D0`u`] @{1A!B*Wdli҈q;stM5w|O42uU޼f4tnulIˏ׊j'z:Iґ#@,Y&Ld2岝岝F,@M,@M,@,Y dR"KC, Yr ˁ,Y:td2e @,Y&\5\z݈岝岝N,@,Y dR"KE, Yr ˁ,Y:td2e @,Y&\5\5\5\z݉岝 KA,Y֌Vu[ 0_T3Z#SmVn9$>~LJ3_-|pLE̿9޶/=zs8HR6Tk P+ԽXXF,{#މeIJwd)R KA,Y*4diҐ@Yd9#KG,Y d2e"$2KLRF,KR:N,#KA,Y*TdҐ!KC,r KG,Y d2e"DI,u":K6bXj#ڈvbXjG,Y Td9k87``Yd7k>Tv6ai_,ڳ/]'/_<}yp3uc~Qѽp=z3u0fyl3 DʍAZOre!ZSrZHޑj+B9S*LU2UeTS5jLu0TSuLՙ3`T&SMH$#ZrZKHޑj-GB9S*LU0UeTS5jLu0TSLՙ3UgTSML5j"Z„rZ˘Hސj-eB9RL(G LU0UaTku EG;37y#6DyOo}x<9]Oק~Ƿr?4|8,2svl2X(]JIn,^$W;kR3`T&SM_Jra T}LITLAޑ겟)ə0UaT*SUL՘1Uc:3UgTS L5j2D$G.$GN$Gn HuLU0UaT籉z>쉼- |Znis֭ )^ R_~9?|93o)6Lw"[@DQ>k\X>XT*SUjL՘1TSLu0UgTS L5j2dTk?#ڑ ֞(G+ʑjˁr*LU0UeTS5jL՘`Lՙ3`TSML5jMִ)RiS#՚6%yG5mr*LU0UeT*S5jL՘`Lՙ3UgTSML5jMִ)ʑ%esK斔-)[R6lnIܒ%esK5m6e;k:|j{3;Ӧj7x6Yoý^<3›7s˰9p;,wC_ @2UeTS5jLu0TSuLՙj0`T&SMH¡Z87ZkPTk-;Rp(gT SULU2UcT:`T:SuL5j0dTZ8#Z rZkPTk-;Rp(gT SLU2UcT:`:SuL5j0`T&SMZkPTk-ܒ%esK斔-)[R6lnIܒ%esKĩiJۛeti ϽIћÙofNp1p?<=_NSO>?onV4C\ތ^qNʕdD2UeTS>efm|>B| X(OP,gT&SMZ־$oHvE9RqQTkw\3UaT*SUL՘1UcTSLu0UgTS L5j2dTk\#8 ֹ(Gy.;RsQT SL.ZZL7k:&׋~r=iϧw^+ḷLGQ^\X>XTSLu0UgTS L5j2dT#պx 3(Gu ;RgPT SLU2UeTSLu0T:SuL5j0`T&RgPT#պxH.!yGu ʙ0UaT*SUL՘1Uc:`T:S L5j2dT3(Gu RgPT#պxL-)[R6lniԴ 4)&vfD^:3G:<_Χ_{g>.zvgL=jrt7v2vڣDyCrcy\2UeT=SϜvmDyCrcy!Q^{\XT&SMHu٣Hu٣ .{.{#e3UaT*SULU1UcTSLu0UgT:S L5j2dT=zHT=zHT=zHT=z@ޑGə0UaTΣ\I u9Mprn4w~ͣOǛW!>!>!>!ZrZHޑj_C9S*LU0UeTS5jLu0TSLՙ3UgTSML5j"ZrZHސj_C9Rk(G~ LU0UaT*S5jL՘1TSLՙ3UgTS L5j"ZrZHސj_C9Rk$H֯ S*L--[m: S&59pg­h[&U/ׇǏ.O>pӗfhߏ9XL#t]7=k[ 3IOʍÀrGya@ra9RkpH.LU0UeTS5Z{a+O$7k+嵇ɅL5j2dT#պ 58(Gu ;RkpPT SLU2UeTSLu0T:SuL5j0`T&RkpPT#պH!yGu ʙ0UaT.[ڴ0!uK)eN X)uw>y>u`}p8]n>ǿ9.%w;:ˍ1:aGcQ^Wɐ\X>X(dHn,gT&RU(GjHV֪}wZQT S*LU2UeTSLu0TSuLՙj0`T&SMHV֪}7ZQTk>ʑjG9S*LU2eGȜ&t{\]@u)o\{G6qy>n2+ʍA;rG ra`9RQTk@ S*LU2UeTS5:`:SuLՙj0`T&SMZ(G5 rZ(G5 ATkLU0UaT*SUjL՘1TSLu0UgTS L5j2dTkHf!HސjB,ʑjB S*LUm:;;B `VY~r|}⻺^vwa}=K^7Sհ#iWP+5 jA@uH'X&5N,RtR jA,Y*TdҐ!KC,r KG,Y d2e"DI,sR˺ԍX&u9; I,Y dR"KE, Yr ˁ,Y:td2e @,Y&IM,jrR˺IJ$u'u9 KA,%GZKҦ]K^wGx3Ǘahv^?hѝ&#P,wra`y$Pn,G˝*HT;U#N$G˝*@.LU0UeTS5jL՘`Lՙ3`TSML5r #N oHuSɑr wܩLU0UaT*SUjL՘1TSLՙ3UgTS L5j"N$G˝*HT;U.wyG˝*HT S)Odcg&f'z ]rryrޅ͟oRr߼quwM7=uw{uw{+uw{3UgTS L5j"պʑjMH&rZw yGu7 3UaT SULU1UcTSLu0T:SuL5j0dT&RI$HސjMH&rZw@9S*LU2UeTS5jLu0TSuLՙj0`T&SMH&rZw yCu7 #պ;RI SZFSLMro"种jKgqZcy늢q쇻>=\rt}t^S?Oqz Ym簜)R (RO'R#KG,Y d2eڑIJu#eN,k'R#KA,Y*TdR!KC,r KG,Y: d2e"DI,kRnIJ6!5v@݉emCjd)R KA,Y*4diҐ@Yd9#KG,Y d2e"$emF,k+RHIJ!5d)Ȳ0As:5!rG|&7}]xv_Z?O~OO\Uo~䘦oǩN΁ire|ɂra`y|rc9S L5j2dT. IT oHuY8Hr,$9R] S*LU2UeTS5:`:SuL5j0`T&SM,$9R]!e ɑp. IT SLU2UeTSLu0T:SuL5j0`T&R]. IT$GAw,$9S*LUjM`\)Z.|F7Ug7?[E^Ώ???=^/r׿ 3mOM][7e㶃!cy|Y_re|Y_ra`yܙ3UgTSML5j"u} ȑ꺾yC#u} ȑ꺾LU0UaT*S5jL՘1TSLՙ3UgTS L5j"u} ȑ꺾yC#u}T% gTsSS%ȈiݡPke]]qݯh}n>XGG7ۖ[1in;zq5oEsW6Q,wϣM ˙2UcT:`T:SuL5j0dTv(G.ʑjmrZ풼#nLU0UaT*SUjL՘;#˅r,7ʣ\YT&SMH.B9RˡHސj]rZCP(gT SULU1UcT:`T:S L5j0dTP(Gu9RˡPT!UHU;RT SG9z*ݫG)Z9bӏw_yTޙPl1#;/ŘtYs"ʍrGymsIra`9S5jL՘`Lՙ3UgTSML5jM-"ʑjM-";RE3UaT SULU1Uc4ޙ"I Ԇ u jE5Ld2e˚K$5DP7bY&5HjbYsF,Y TdR!KC, Yd9@,Y: d2e D,XT!eM˚&$5F,KR;d)r2)ezt;=̌w?Η룧k5Ms=x3ҏs~ qicy|rG/0ʅdTS#Z}JTk)ʑj>%yGLU0UaT*SUjL՘1TSLՙ3UgTS L5j"Z}rZOQTk)ʑj>%yGLU0UaT*SUjL՘1TSLu0UgTS L5j2dTk)ʑj>%yCHVS3UaT[|OFֻ[4Y;ϸ6 ۹ӧtGO ˦T7q{ mیkSצ$'kS)əj0dT&R]n@Er܀ .7"9R]n@Er܀LU0UaT*S5jL՘1TSLՙ3UgTS L5j"T$G @ސr*#T Huə0UaT*SUL՘1Uc:3UgTS L5j2D HTP.7"9R]n@TP S*LFLc>Wvv#Xj~x>襶C|y~|ۅ5rk FVq{C8!ʕyras͜zwYn,{cQ˅L5j2dTkrZC87ZC8#‘#¡ S*LU2UeTS5:`:SuLՙj0`T&SMZC8#¡Hp$Hp(gT}bp32fYni2vkcgL:&_p?ɑ4HuYOr*LU0UeTS5jL՘`Lՙ3`TSML5jHuYT$G}w'9S*Ly9z2숨ymF9lwU2Ϋwwx9>C]?|x7x<~we=^+t!zgv=vgwT9ʅ ʍ ʙ0UeT*S5jL՘`Lՙ3UgTSML5jMT9ʑjMT9;Rr3UaT;(ejCu Ä|{U7UzPO|>^4?tyzޙ˶ɧIv&M7DyX(re|L,gLՙ3`T&SML5jMj֤6RIm#՚F9RIm3UaT*SUL՘1UcTSLu0UgTS L5j2dTkRH&IސjMj֤6;RIm3UaTkRGF1zaXkoD7N2"XOϗ{/|z|~痛V@ǽ{U+|MstVp|X(݁Hn,@$W3dT&R8ʑj Iސj QTk8rZq3UaT*SUL՘1UcTSLu0UgTS L5j2dTk8rZq7Zq## S*Luq { \wY9qy9wz7UoOǯO?pz~WߟօJΏ_vNfsL$9XLSs9-9-ʅI:E}|~yӇr߾4BFoqp{5nۜP(\X>X(X(*LU2UeTS5jLu0TSuLՙ3`T&SMHnRrZ7C9RԡMHޑjݤLU0UaT*SUjL՘1TSLu0UgTS L5j2dT&u(Gu:7Z7C9RԡMPT S5֦I=mNoϧہu- +9~s`ùxuh ʕAB3okA@uh@mR[CI=@Ydґ#@,Y&Ld2eݦIJnRF,&uBR˺=! KA,Y*TdiҐGwԻ壳X(re<& ˙j0dT~](GMRmPTk.wZt S*LU2UeTS5:`:SuLՙj0`T&SMZt6](GMʑ6jGڙ0UaT 97boꮄunsovNB}^w33wIfhy;Sd9no&rGy$|M]y^$7kEre^$3`T&R]^$G .c/#eTə0UaT*SUL՘1Uc:3UgTS L5j2D؋Hu{.c/#eTə0UaTko?dUunzn7`Nzy_:Nx>fgbge\_as\ro>4wZ UQn,םI,wםI.,G*Ʌ SLU2UcTNǒ${Dy@yrGyrL5j2D5G9R=R=ʑjIޑjQT SLU2UeTSLu0T:SuL5j0`T&R=ʑjQTklrZc{wZc{3UaTh04qnӦ};z`}&lO|}p}}:\>wz&8?\rt2mSs8m\\X(rcy<˕L5j2dTkrZ-7Z-#q֘ LU0UaT*S5jL՘1TSLՙ3UgTS L5j"p ր Hd$He(gTֆOSɘe<ce~xixlc}ri}4˽9ڧ-d΁_V|y6VJ?kPn,?nP,w?qP.,gTS L5j"ZrZrPTkUʑj!yG*LU0UaT*SUjL՘1TSLu0UgTS L5j2dT1#պp օc(Guʑj]8r*LU0UeTS5jL՘`Lՙ3`TSML5j]8rZ!պp H.#yGuʙ0Ua5M04;Z&ehM?m&t)/STL\Og7a;z}ٟ|&͝fP,wra`y<:ˍL5j2D5rZ?(G5rZ?$HfPT S*LU2UeTSLu0TSuLՙj0`T&SMHu]6r.|ސlHu]6r.9S*LU2UeTS5jLu0TSuLՙj0`T&SMHu]6r.|ސlHu]6#u ș0Uaˀ&sO%~~ó N*;́5ߧ|l/} 7ʗ>+:\X>XTS5:`:SuLՙj0`T&SM^Kr^Kr^Kr^K#Z23UaT SULU1Uc˵d)D ˵d 7ʗk@,gT&SM^Kr^K!Z2#Z2#Z23UaT*SUL՘1UcTSLu0UgTS L5j2dTk@Tkޟ7^Kr^K#Z23UaTݡ{uw=wܝO{|lGLI9ǣ7Q\cnM,'ʕL՘1UcTSLu0UgTS L5j2dTTTT{C!ސjoHw;R흩 S*LU2UeTS5:`:SuLՙj0`T&SM*R ʄT JCҐt*JgT SLU2UcT:`:SuL5j0`T&SMR T!UmHUܒ%esK斔-)[R6TS9Ԭ)[&em{L7yΟnȖ[դ̏Sx|xO?\OK\-v%:dC^gGsZm ok'Q^ﵓ\X>X$_k'9R]kyC{$G{$G{$gT SULU1UcT:`T:S L5j0dT.ﵓ.﵃!v#vwNr*LUjp nSȝvOyv{׃7GͣzWwΖ'V^+ɕzL5j0dTIPT$$oHnPrZ(!yGu3UaT*SULU1UcTSLu0UgT:S L5j2dT%(Gu#պ ʑjÄ]LPT S:5dzk1g%zVE|w?2և/ߟΏ'||}40O#sz]=G4gs攮Z"yZ"Q^{-\X>X(*LU2UeTS5jLu0TSuLՙj0`T&SMH(G5'yC5G9R18;R18ʙ0UaT*SUL՘1Uc:3UgTS L5j2D5G9R18ʑjQTk NTk r*LU0y'&#gkaQv~v\]S3 ot 9o+7ʅ S5jLu0TSLՙ3UgTSML5j"՚|D9RG7Z(G5rZ(gT SULU1UcT:`T:S L5j0dT#ʑjM>!՚|D9RGwZ(gT SULU2UcT:`T:SuL5j0dT#ʑjM>#ʑ%esK斔-)[R6 0],q9P|bܮmV߸> endobj 275 0 obj 16558 endobj 277 0 obj << /Length 278 0 R /Filter /FlateDecode >> stream x]8=BoUAc˟[j`Nح+(%VlgBԲ%JxnuZ|ă4ij7>I bM<⇔EdGXZI9'xwx+Qnz~L^,&#{d6.i2|Ҁ?F;˪\Cۼ*I&E冬*/6/dbh9RQY,JzYO (KVY_ ]i (4E4^ٶQr$&gd6O4c^_ƺXaRF5)yĔ'ǼA̵^YVy07H[ywhZ-/BdX 2Q8o6 (4p7c)n\vnj]?l'F_W<%Ր@IyA=^yOxA3 BFXf8Fltu0vJO쭐r:G4R}z$/Uh {r=b}{|~s˿77Fh'J闞RtVϘH5WHB{^7e)VjpU ى!F![Meƶ>ix]սL+zN7k @05Lͪ%EM9l<]^jeфFL'| <^e1^|,k͋+Z2W짠og MT:Ec7 _k)~|n"_D˃֟%6^/ Pď'B?zO"Ւd r}4w~`BMe:1+d3 ]&ǻ a=io6zβ]ًU~Q'";~\”L{q=E&1`+VߚPCTʺQvR2^zXh-6aH4"9 g4 #{~P.4#a 1t|ϣk洇hyiX>7s /C'ADwH Pi,20}-mĻM -Y%$Ya!z{=a[bf`:J^zЊlJ,OSQ%wG 5N|*]$4$,vҘ|6c ;Fzo#>°)T0t]WAu춃IA#a Ixx"P \qP4CCp3LRSS14(0B ˖.sćN.UN R@D%gԧ~SLHa'؇<O=-o9kBuAA aj|Dt0:!%TKxqsk'Kv䵣,:3[.hv{_D,Z{xyA]hOxcaGÍ+pCXpkԹG)H7L_bCr@C{ WPHP?=5ߋ,goK/^Ew/毺Hߓ?}GZAbgl[R endstream endobj 276 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 277 0 R >> endobj 278 0 obj 2350 endobj 280 0 obj << /Length 281 0 R /Filter /FlateDecode >> stream xWS8~_o\dɒsRP uJq'\bہm'J=p]>~]ٟTʁx($.U B,dU gsZVc 2Bڌ'lϡnoߒƱkQ%NmSrFL9]Ó(UAB4y4&(i'G,BL]# RȬ+,I{7>*t)^ubX ;"kd#XҎu3ߌs3Q#_ؕko&\a_uz\eu'Hmz?w~atԋxohA(ctkvV ]gC-ebQیGmg5+({w죍c;LmXuW\zOk?#? endstream endobj 279 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 280 0 R >> endobj 281 0 obj 1172 endobj 283 0 obj << /Length 284 0 R /Filter /FlateDecode >> stream xWKs8 W`zJfR؞ڎwIݩ;EmMdɑE,n$AӀdz< rTSlJ,nS*Y۰m i gk, k(||c@e@L^Lu7iV@5Ga>8a05;ĵ8Gx _ΓxשI d>9 bs"a/]vq6.rϱ"ʜfҋ"(:Db8g=s, )(;ǀӇOpݲ9.Ý. .lы^/6PF9XܐorQ.p0O49NZj̵ŜR㖼Za tqr-oEњc\ ?n,d,X e0Z1M]qmBm'HsCi*묱cmJmV^1N^j J,0FIUNUŹ6 c*T&i/BoQNH\7z endstream endobj 282 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 283 0 R >> endobj 284 0 obj 1418 endobj 286 0 obj << /Length 287 0 R /Filter /FlateDecode >> stream xYY6~c7V5@dI6\b %&Z=:)HAy hVcHPÿE˲;ͧ$ HhV{Q~H br&sVLjXc3?@7'm~Tćup%[6=Ɵ}>9ny6&'O)rVg$ L~Z4~ZIWOoHbN"By "h@!$gǖWr Ey.}/"Vv4|S^h/yAc䧙K qy{[o'cm0y a!}2޽]a%vN^M6]'.ǑG=#3s/%g(#a4iBv'd@&wp`m7{amQOK˶;U<1Mx뛢<٪1TNSa=7*Q" V+u),;yzK]襤 krJ4kC;MmZG-.r͋a]Wm6C GMbt /=1~7FĊ vhٛ :C+5+p,*~e1aKvIQH`О]DQgtTj%)&gVP>}V qawf^b/'4y?t*ڪs$ZT8dEJJ7H,lǑtCCę t&8 Z%/HE( FǦ臖9hYLQxy*)GY0Α# p~yIZ [X'5S1<32d8 &s#mv }nYF 8 !|DK'ZH>ޔ-+:V< E~B]x g8ęgq4ë<.CKV9/p1t.Fgh.Ӹksv.odC8# c39`'* ^#P2sj)݉Ovh'zwǼ7{VCgZ'TKԞ!CQt}kgG ? p|"u4ؤEcX4g`*?RjmEfmMj4d5v#5mdtȑrrdy5ZW+\.…ڰ>OŒC2F®FP{#u0;36IRD7@3ƪntƙdTar"N4S:rm!NslZL $j7e&jڞ,ωqO]ܢDm9n(#xYz]M3 z7 =}3QpV!qk&8-2;&c.R7U]g/ݭwɲ@p+u6zd22MW0q4v G*qgMnqgI:L&  %B+޲o]aPHYеDZvJOqT>T =l;CO=wx6lq/z%Å.@%bB*}O \>HyFYo"-*(-t4LY.u! ݤDHwIYٵ.U ?gwla?z)n<ĉe !gk}5$~+#ͥ60OSRK]jW3?Bm'M|R8Ԯg~Z3kXХv5cԋ2%ȥv5cԦG8OX e.ūצDݴ!kS2& dvmLU :B=KkJY_I :F:K$`vЦIP8tc> endobj 287 0 obj 2229 endobj 289 0 obj << /Type /Action /S /GoTo /D [285 0 R /XYZ 72.0 769.889 null] >> endobj 290 0 obj << /Type /Annot /Subtype /Link /Rect [ 178.32 165.643 252.48 174.643 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 292 0 obj << /Length 293 0 R /Filter /FlateDecode >> stream xَ6}c`&)2gm'E&l5]vxHZjM''HU*źș("p$EYqS3DYHH,DBÞ +1sW/w#7V>Nts#x!=5g0A Xa@*7AxQ'kUf @w#f !)8PUdc~eiCFtqԹ3$:nͣRމ]*꾓/GDx,)y gBZNS+gQyǐ Bfol|%n\t(sDv%i1%pF4MiFQ8W.P2eyApӔ(عyh@$ #:r'*!&)#hM5 qև-bF}IcG)N[9N`F 4 WmT.֭1 o+yڹ] 9gK~{BHyuFsA%]AtӇV܉Ϊ;m'ӄ[iVPj(Zdax~'Q( 1w #Ǒ)ȅ@,ط?Vq)ƕk,0l,toJOC;3҉QѲ@h(ʣ}w{ " j.mlMeWGJDQAer#2QDeթLhZ?ʞU+ !G:n}SW팯^{D="Oa≀]yb7,{]m=˦nw\y{uUIMD.5~pz *+>'f9k`nTQ粐e'G_gǝ 4Bd'U'Jȓ|@ev܊ate)(~zuN0j$Zو̙PQ\]Ab|.eg`}",JSZ.?CY[b=>; sޅxخ?4 W-0^3]VRz1תݪUݬIyNz;0voo0r, ,͹vyS}4lFZz3vSJ٥u]gqMq)K~x)`UuӏQYSvn+do'3e[7Vfy2ٔ!m 6=qH(奨 *]OlW'Fp@4&C5K@ }5&{րFL˱A(/|(5$\8^M*/'Ν1Kv[~IA@je\]xcQ_)SFn>''(˄QlOf\5#d;Ye)19%^tb'Z9"lܐzÑ~~`\j228OKv^m;bu.:;D[Z4SgJ#xFxPG<.++bdnZYu,҆ttm!!}^ROfn\28J4IXyH@eyoVEB2^хkt!#34i/;L#>ZGDZ[&]ө\̄x| +E/#4 NnjiP,]xje I lyqATe7^$]%?6%,4R$31-K AG,:6U_4$~rNd C-Bkڙ$Un?UAU_ޠC.'c65 =C_#+L_&,DBp캍w 8Gp@gDon3 n#$b'[btSGrfQ-H7+ВNs.bʟDG*[ 8c+ ;mtFnM Op3Q8&]iDQɫsd+dzŮaЭZz`Cw5=>/r|Uu9_F0;U¬#Ne}.G`Yee_gSZS!Ά ѮHO3L4G"WOε/G1ܽ.v5yE<,P`^s^p?d=JpV1!Wl(\zrɃ*uhg8}*ȄC&N:i_tdO=nt' _C_\vx+Zfp5r315D vW0/jJОﮟS;R~C :8>+玹{/>= endstream endobj 291 0 obj [ 290 0 R ] endobj 288 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 291 0 R /Contents 292 0 R >> endobj 293 0 obj 2696 endobj 295 0 obj << /Length 296 0 R /Filter /FlateDecode >> stream x]۸}gl{G'}i!th4DGu}")v޲  >ćO^*z@D"%G$0!Yg,^?>ç0"><7 V>X Oח`L$'#Cs<M$#jOdExI $Qq"M?LW 90]^YQreY%CIya-F ~c/4Haph.(RyFYuߍp]8YAPYQ//w݇(VX+뚠i*U%Ѷn;4#tg{F"R5f'^N/p wOÕ?| +0>TWZh{[NeG|g>вet(ʻe[&YI6-q+vhzV6ȾY_2i'?ny_L̄05 }_88 tqoYZPVBm(s\ ,+?]ffr5$woAK޶A4 6 ~i滿!x풷Źfsjq:0a(765PĠMo`HÚm_i Rۃ %RHbKcKF:^5)tIubI"E /S6,$WU)8FCazqx ;ªCO5+ fNmʫD,GӸTL;a4˚HÕu 2m癗E- _Ke,CgiVeqiD_& 3\ ۅE9Y9Yl[wuY+5wosފNȸ-PU )]<$+f &4|ݞ fXiUӡjS>)aDƔ$˚ Ơ?;ft`sOב?\Pg:z3,ʓpM"goRxAG9 u繽S!`)'^䃔YVYeݷ'e/O3fiD+n7^Q>Bz͵wЛ =paEsO{pXƄ C#5Af;B:BҤ1Q$3f1*PUm0lKC RtdF{[G^\ XX/]&ic%^JDP04D-Ú[Yg=iz_ ! N M礨E $I2 KxN ;QT\k@fj-F|4D9LTbP;KCi|XT2O9lsM{bTC:#GJ5}uSHlh_jK~4łNem0[Q/8tzr{ u7qP>.褑G p{ %%15B5d#5l$25*FwLc={5Fx8V.xPIrܴͬ,Ǒ9Y="W-5^0Ir'@!#DI^d~,%W7vYq֊i4C-%pr/j¿Svߖ*xT}-A<| tFL;MSD*7mXQej}'Β`e]#bC.Q^1_`.WSx4#,_NoNwsOf5ݭ! snyZ<Ӝ l|ꂹN8+B-07Ty6zQ ǡôp$i%7lЋXle,o(E!8֘H@`LbUwl҄D@ZH|o#sT<"Xi*8jJRD#A Zd^FK\VCc5%-'tMljR!|? ZU0M'^PG&+ӈ;-lp4)՜H l JIh0g%ziܒe"7ج?"C,@HQ{).ia>" ]-~*pMb%wPvq[-X?º"OXi^X?3֏<47@/FjV Z=sj0:ʐ8^J)x,?/s"| l q}I'xckbb:5(πI+Ы#ۦi9$WM̑m^PA!bFExg Ō}n~è kA c;z]𕖔0P{>sf ?XZR>V_ ["?5#9 /`٣w) z翾 ~yNJ]b?<  A]>l'B{";W%7O><_k endstream endobj 294 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 295 0 R >> endobj 296 0 obj 2853 endobj 298 0 obj << /Length 299 0 R /Filter /FlateDecode >> stream xYYo8~_Q&uN2bgv=6%X;:x~T:`wAHEV}Ud,\`~bu8Z|]8x00cpT?@<>g[sߢ^0uɀ!E.nvl>db!zb猱 xB8U?U.6}ShE^BpY:Ag2rvPԝ4EN5FsmnOC/"[ (8\ ڝygpCK{>=-;rz?qC8¯\7I$%'ދ?ƻXdtr\ 1X_|C?urqGV4V=sWi)WII2v,J7jUYZe]ՆMwuO.w7veu5\$?gx8>ԗXwqG0w Z\*<C)ۭH%:j$"Y7\-!WĽ^oQ?˟ZUeZOd PZ)HUegQZ.: BPTeT-jLCj AkQq ezLJoo߲o~w4$&:YP~kQ-m (m"8!:xXg#pTFʂQiNE )u,bBKVB @qΏBww.hX^TϢhzF#/Kc {Jɺ&؆Ct6]꺦@d?GpP$UU\U_zKķ3jkcBa$.nPhŷwY3P KY; z'D;HAb4IXXH`1FZL)v+BM5Ŏ#D7Dڙ ` hf!ԓl7<7GDhbT;LADp܈dqB,\o5) mLL+4,>f9h1%]AqQ5\9p+K>ɋGR4N7鼩\nDh%MطhnH=[Ae,bЂ:*F-֤TaLJ҅RfJeź8%B`H\v$`G oXt@fCB'd8aXs9SsBӄuD1/eOq&Q6jKgzi*txsH』ynvǝlՒ€'EY&$p|t{Y`Ze]"ܪJ~nF~lJ(9 Fo5a!='h[;xO>&rV<:n |4t$&4ܖاgiW{z?-V!4mr+YtX|C))E.t:M Đ=gDt(p_5 P:,O(26m;J5NVnjM?1r՞wE7pӷxҸeM;L6LZ˽/NQ-V}8fOfL-"Ғ$fI/N[|Y`yZeHząu/jqc^:o IpfL 4'Х'ancK@1'mW&X̄N3]гAtE"a2amc:ܧ[?9ìƧA 졮蛶yhm۱կ;>U猫v>LJ3F]z{#Q.5rS^L%3Q'Y> endobj 299 0 obj 2066 endobj 301 0 obj << /Type /Annot /Subtype /Link /Rect [ 218.31 251.801 292.47 260.801 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 303 0 obj << /Type /Annot /Subtype /Link /Rect [ 329.39 205.358 403.55 214.358 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 304 0 obj << /Type /Action /S /GoTo /D [288 0 R /XYZ 72.0 164.143 null] >> endobj 305 0 obj << /Type /Annot /Subtype /Link /Rect [ 386.422 82.85 457.81 91.85 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 304 0 R /H /I >> endobj 306 0 obj << /Length 307 0 R /Filter /FlateDecode >> stream xZo_Ab6-RLM-1ЇC@i%C EgtH,b4>qFRNx!19PLJXQc2Uu99 `U"\ꝧפ_@W?>\=&, 8+AhH_v՞txEuK@9E "'<8]OW_ȱn=L\;6Ͻ*j;QO4Mi`Br)!i<e#11৉ s(81ƛgq()bLTDIEXj{w+sYhj[ -KG=k2i76H=\l6 CpߪismQuܫssV}>5<|fCw|M#NfB4i 2ܐ8\=ǑM܎K}FF/WO#gѷݎCxHv'O[ث}@'`@};%idDwΩx y΁sUo\&ګWګaaz&iX$R@B+!ّG*ҴS:<G"{"f^|mzr#QWI,m푑jڦ0*f1P1⛲Wm%I]4 3u% Ů@Ee_vt(o #}gw 1~]nG97UXרm!ˉhO%l[Sl1٨Xt]QW}\; u_nHIV=0.C?~֪c$aV5Ù".N쨅d(.C}draA 37'cDE-|VQ<8W;UARNG,Q Yt}+A*\=!=É׾թ-)Փ* 薫^%]6IiA9~ksx&UV%,Cy .HZLtW!A-;,o`FOe۟C;r ;8̺yydMhgD)\n@sĨV`{= *_ǘw/PH[ AxK˅N *L;aqaL%j,NA1ڑ=M3о͈vct V; bl9h1#^}q; 1q cÌqjлyt1MoD~Iow =rnsYҝ}wousid(Ǯ_u;sL]Nw 7fȿ6Jv%mԅsXOQg:e ;: l243_X+%܆j+6NӵT˫zKsz.NxG Q{MFZ?](ZXZoiw@GQ endstream endobj 302 0 obj [ 301 0 R 303 0 R 305 0 R ] endobj 300 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 302 0 R /Contents 306 0 R >> endobj 307 0 obj 2935 endobj 200 0 obj << /Type /Action /S /GoTo /D [308 0 R /XYZ 72.0 481.889 null] >> endobj 203 0 obj << /Type /Action /S /GoTo /D [308 0 R /XYZ 72.0 173.41 null] >> endobj 309 0 obj << /Type /Action /S /GoTo /D [300 0 R /XYZ 72.0 475.988 null] >> endobj 310 0 obj << /Type /Annot /Subtype /Link /Rect [ 447.028 427.974 523.272 436.974 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 309 0 R /H /I >> endobj 312 0 obj << /Type /Annot /Subtype /Link /Rect [ 505.505 86.229 523.275 95.229 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 313 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 74.229 179.72 83.229 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 314 0 obj << /Length 315 0 R /Filter /FlateDecode >> stream x]۸ݿ .%AҢnrIAQ9ZmuC %or8}OxN$;~W)#5N@C84$Gr=B1AsE sV\~˯@!. -'C6E$Kv?/gBd&' 4M"8>M%#=/y rَR4~,>JeuGS+b\&cEW 8fV`SW: QjImݑ~]/*K8MaIϋnݧP)Wt:T:Hu?r/PW8բ+/LBE͎{_&&h OL.o Va ϷPѐYŁ~L%Cc^y dw&׵8J1t̷VCۡysٙ97V||5a;K:!u^.yQr􁼆=&##R7"Yw޺fhdJB.hW__{-@u_!a8~u#a0!yb1qq`ptk%=g'!Z)T=|鶹:i#J><C*r`l鐎:ScN!/~e拡s3K|/t\k$2qӆ5Hx|u+Ys8f5 L~A =y:W^6RmLVpq/5 V5Xݳ7V`:^Xg5Y16:9?Ѓе3MՃހ EM'6Ճ%ɘAzͥbZG0MQwnx^k{ G1[pV7Sp˻_6R[7{4Ҧd]>wq%"^A3tQKc @}j)d4o4H.!SM&uS o4BGv0U4*=2F@VM UX6d5|<Fr$ϚAD~ R8\}>DM?9@(EZ#+5azr[]L.\ ئ|kO+s3x4VnX:\Nuۃw;!6w=*144¦qD44Ј+CЈL&]i3K}oGftjp>\\javbK#t,+&T|zI}Z*p:,4}`ZE+Nd""l]#RX0h-&Pjٰw>cmՄDxuE+"RIHх5aԌAt^G"eyBtGѼ&=zVbBM~;DEq ~vhp@օ9wEhAu[7A.[MTqu'Ǯj( t|#p~ªCG셁cCXF kOc2\m0Y`GsOF5/6PwsPͣ!>eE!.:W%d#9Bg;uY&VTG2\z-ܼ7BC9Bm=sږ4 ㆁ|MO-*)r4#6lE6֚!j#D ̑oL™Byfcy2=xxNOr:--D3QdPEQbO+3x>Xti{ /Rr"^D'2QfgH񭌊 gR a!DV*#v;HTVS%8x9¡wE-{ OF:[lۀNhC}6LIiT'-)ZN+!p]C( pLCWwS IDD#ns' az\QSk]sg,7Rm&6|wX]0QM,7ޕ٣J>͏Ks@DG6:W wXD~+MAU*WJ?,=* vј2b]ak5Ϙpȳ k5Xj&J!Б872 v6>XVt++n;Od `K:ҽIżR G^ WlI!xӁؓKxn'- +V"'MI5i_%t(EϪoSA%oi۲[F@lϳ\v%Zz 8H;JS \ -.MMvÎ'rd8mţ4NucGΑ"@'٣ֈ4WTF* ۡ ?v ? ~TyZ50Y ʯ_i$> endobj 315 0 obj 2625 endobj 317 0 obj << /Length 318 0 R /Filter /FlateDecode >> stream xr8_ʋ*[}dL=vyPnUbGl~/cJ5 88 O^ڟPd!REJ|/ߏH{aBdLJHk\ #=k|򷳯`Ά?\;͑MMg'g?{)!ObV$Br'_/>v[? ]>^we^~G/[Q%E,ǎmO?=kut{fߤRO!'^e.9J d:83b/"C#( 8{R[:F. ((`G/Oo3_ \Nu$p r%.Z>׼mvuimPnѧխ;-;Z+K[WN<ҩ~QzyFL@%/(R?2Gzk#ZHT$¡ h0]@F8'qA- ru8[LQ)Cec ݖC[=tf;,5XR*"~Q8g]fa-}6sc$J!`f))' Ћ b_5NYs| "%m,?"ɢ;G?#mn #HSxBxΩkڝSR\-tp;]֩/]]]hhWqni~k^;b7Bڈ:n_9|+W5u%,Xq )&qXXFix D̳s^ʂA@+%͂9NEBd6*Jo7q $+]BPEgc1",e:z`]/.qy""UZgf7(PUQnH}`<(R$Xt5SRwfl~xq@!KM @aYh3a˓ Cn_?8D_s{PAyy_qaccC&PqQQ̲rG8bUzx_ɢP^2xԑdp0΄y@+pƪ厎pG9$G?@:|rR< nk^C!NgѦpy Unn )B&g$/˒Gd3t$VpZ-wNjg?T~  ["v*y*-kdq$ 30+nkX$2Ȓm1FC4\&˧&fJ9{00*#AQhR,ێ֜v[qƓSN4Fvټ2rfA4k*{YP0@6u; CS+EQաn؏5 Qk8!^ #|{~"\7l 9ʒ|NYA3P>Y-0=)m+vu])( oyC[ֹVŅFۅ±&Hy~دP^ YUWT 'gɰ0nHᲯ*0uF.fFs/-|Ha.Nr xJ~b|ѯ 7S0MkavgQ\Hp)#dr.#w[i>6[R6>ML,ʙ^b?EĆ*gU9Rk`kn28%hжܯڰT(> ʈ#0ZyXiEQFF`{,LwÈU`"[)DV)UaaLlIjjix_ɖ VN@BCW_"Bwհ^쳺(&~kiF#>|̞ƒX)Γ֠=+MQȦ{Gd,'Zшd /UzqagZ![\"{ZJ8@cۖ5޲ $Ie+p)XAX8p,V/sawt`פF<ޏXV|P#Ҋ 9sMu7{+Nf2dsZ.g/woG˪g zYLuy@M= !E' ,{W%:bUoZ͝ ~0 g\- ͱaÑ=?ʥT?"g0@z@X} l.D3̘͹+( 6Bo܂ͷO7B4E`͗| \9I6Jh -y!sbI52$f JOWL; I Dn |ؚ.Z^?N:f a= ÉUB>R~:vu vT|[5ڑ tYc8}> endobj 318 0 obj 3082 endobj 320 0 obj << /Type /Action /S /GoTo /D [276 0 R /XYZ 72.0 207.319 null] >> endobj 321 0 obj << /Type /Annot /Subtype /Link /Rect [ 303.7 153.617 382.86 162.617 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 320 0 R /H /I >> endobj 323 0 obj << /Length 324 0 R /Filter /FlateDecode >> stream xr]_G}jq*- $ϵsH> 4%?z][BF ş<IO0,<Mr) #/̒wh/^8 3L% 0(<(&zn? sM8YAPYQ'/_~VE˜e( s" #d^KpCJ868VG"t׋< F(3aMAm[(&-mn]{Lx8 ##pG?4|9V'߳rڱFڏS~2ՁjG3ݴ{(K :@:<~7q٢#4*Bh{c)"BJL+O "!G6;jX$vi"hĶbn8ShSZ`b\mO{Άʼnb![|륅cX0[ M 4 j98Urcqdw`|7U8W*@ѝ0vaǠq`cBgޙ;u%%埏V2Q("\92SM` _~d&F 5=N@Cۖ5t8޿VBNY0" + L9kfCX\"D4@Ø [k< !+g$a GqB$JۗCqm̊kt/5(m ?f)OêX̢Y.!eNFű~X10HȂ)LT1"ɋPUH`Űq} *4"&9 I%NW[ll!2 "0uvllʱJ$Rki? 6՞l]r% "r(Y>Dɿ\,w"(#G3`qi3vqdYvT,6@)A@(y]J".JC @Ǔ 0Z~he(V *ȰV(H܂Z@o #.=pbtQ0=_tnQ хEge(7Poj` \uQ&bC prq\v'E/ bEk옖%EƢTo-Q2[Yc(g2A7@ {P z8<žklx; ],/ xj/E?|e@/Iω?iA Ylqp9cjNk-ҁ#jQ>:![)Isg=7躠'{*41rMI \TP92b@Qy,In ?2E7o-߿|ڦ+B bX@\^ xٴRK!i g(n2HEʵCJhE#su Jәѭ:cS:8NHIjH"~H~tR3G};J-^qߘ$p׳XU!䳲\HBXTJG E̢~ECy)F"YXkf? V;vOfq%|5@ntX,(ݽ$j4^JU.`L>B0YMgjREBp?UU.ǂ 2p00 n Ż0Юϱn/a۫yw/ٞg( 6ᄹ ,d biX\2,EޓMP&{毕sC7hCQzvs}g ܽTu HW;A vZ9"_J0Lib."K++=(9^H*#kQϖNʣ8\vw!~Ptx1"1l!i`q$tBtoXno&q^Te@ !L a ٺYɩx-s&M\q͸YG>" Ru'G>0%>e/$ l,8Dz?0"Dx}Ht{RvȫuePEh]d`!X{TGx-̽^rW| |`Ȕ\_!X՝0W!^/G;6k6X[О7RǭyJ` >Ó$uuF蹨AU%%uˠI!<NFH?y񟜯R'RJ6{K{Td5YEy"a6(*Ktk!m ծfZsh z7Ē4b Clk"-OՃ]Y>"JL"-jFrٵc{:acz6^< h3j(xq*@QxEJu\,FgB6Z@dK _ݩ%{j8Y#gٞ+*И@:QJ?~ xe[Ց< + A^bWIؽ??] endstream endobj 322 0 obj [ 321 0 R ] endobj 319 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 322 0 R /Contents 323 0 R >> endobj 324 0 obj 3135 endobj 326 0 obj << /Type /Action /S /GoTo /D [319 0 R /XYZ 72.0 719.149 null] >> endobj 327 0 obj << /Type /Annot /Subtype /Link /Rect [ 463.736 759.389 523.274 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 326 0 R /H /I >> endobj 329 0 obj << /Type /Annot /Subtype /Link /Rect [ 220.0 747.389 233.33 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 326 0 R /H /I >> endobj 330 0 obj << /Type /Action /S /GoTo /D [300 0 R /XYZ 72.0 169.415 null] >> endobj 331 0 obj << /Type /Annot /Subtype /Link /Rect [ 399.426 429.463 477.595 438.463 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 330 0 R /H /I >> endobj 332 0 obj << /Length 333 0 R /Filter /FlateDecode >> stream xYsܸ |XN'I/K/q.p%zF$$;Oq&c@ aw.~ma|( [-x;P,eFnF@ˢX`nqs 2 °G%⳦[+I?_/Vo=dct}7XHc(stsSY4O)/P[t±-/ & FZ EöoQ^)+z:c+oe=ݦE@h1jІnhth"?fLKIx=L:%|~>׬g]¥OM GدFt:h:N_6]ŬDqGF&^~OڡR**ڬ}Z_ҥ|EZƯot?u*&KV#w Y\J}ͲpH\W~z*+:-b :u?%u Хy]wpn1\q6NqnC akOnVS!du[B1 0A-|#Boa*T޲zDPcهM5.ƾ6mqJ5J)$9RU>r>8^'8 Us$@p剆2 LnemUS@|ҶȵlхEؙ9&:V$ԁ&qWE 5x2qBx-z~qٛ鑡e1" Vd&uA߁'5h^;GFC/!( x`0L{ 7}g=]spיCyJ~Xr -=!y]SkR#!{x72'Q$r̦bMH cS"@>D,PP͟@CpG¶ ϒTߊ ӦazJdYO.7[A&8tXؾFİNY6+7qaED;٠ѝzwڥ/q=\-Ur*tUׄ5ڪѓ+^/SI޳&I 4oq=B3r"Zۦ{ũ=iT z)YGW"D=93.'2}!>ׅtzUi䁪aX=@t{xKLtnÉ=Ǡ|)BX*ʳ6dɯO$p-ww\P؋CŔ/M7bqzU):Ys`;[E-A<8)N HոVE TQTƗJvڊ!9Ix{FȌփ|!СaLWAM j4Gkŕoa(dc]GmQS'rˁqD}<zGc6Ӆ\c,Htps.ʐ]w+Nz7}UH\fS7)iJA;S^5q*t,DdhcgtFxt,\^o oZ0\r~P){ 4y/%"wϺ߅%Mv|s+OS;ֆeOeP,Kcގ4' a3 S!0AG 1`<ώG,j @4uĂl><' ~5=搾N0|̨۪#2R - endstream endobj 328 0 obj [ 327 0 R 329 0 R 331 0 R ] endobj 325 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 328 0 R /Contents 332 0 R >> endobj 333 0 obj 2545 endobj 335 0 obj << /Type /Annot /Subtype /Link /Rect [ 363.453 215.508 440.16 224.508 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 337 0 obj << /Length 338 0 R /Filter /FlateDecode >> stream xn]_Ald!##v6QW2eT7GM{܇קb7ɓXLbUNā.O4IRξq#=:4BP/$2 I {l  :OaMN|lWn>XO9۳B:voT,W8aB{m]C߈ꁴP0QHW0ϙ(#C#r+ RDu{ŢS 1u$'SS/Z3fc0ȩ s)ֱe]wܶ ǰu4NS}7}X؊':XmM.eHx#/ 7HV}i*Xk"ct;3ҷVEIS$QFCjE] :)Xs!bm7 qEd>v +pMN= V=jh_ ) cFn wNyWA)]#AD^y_wD_,DFz!oMABTu.$&J*,G p)…ocD%FijJjQׅݔ&,bPNm)Dɦl_^rfHR׉?FRDωt{+>S7 /* l@ 0 (y Iu\  T6W݅IiD^]--Ug#]m!}==xa,}kH''sSTCxaPDm7gj{v4g|ֶXH qߵlkr+fFqR1hϦi[ޮh"Lf02N\p;3ZB=|зJz̀qoVq@tT?z| x@(t3A DK u@ݎb)O n[g6`^[tgBjB6#^3N#2HcWF-{i v~k|gFsk-.y5V/ZgzI4*sbY'#oFSh {e93b*쾮U$ cz˫a d)u(\_*+3 kN>t+ 9x e3cIȦԇ _6 Q^|JB@wUCj #> Qml4>C_"wٕW(ux<6H>7U! ԡq%k^ԕ,0SNVqR-Q<@3C~no Rh@Dv† ex8tI6DsQ e9xZ!ێW~ M|IH(Yѩ}?Κ%|or-F+f\@D>X.cG5t bK9p4[[5cn«ȇɩ23b k 6fXl̶t;\8P{KF"$H͈3~0@#Kzí-14:slKI醼;nCR@Y$AD}9EemQ}&-5Iδ蜠AmR/Lq~DvOQQJ{]4n!ICAS,p[3Vpl[3Нܫ x ^ͭM}wJN澉!~Co"hbk9X ѻO< ULSg*8Q:'XnU#jamjjef@> endobj 338 0 obj 3193 endobj 340 0 obj << /Length 341 0 R /Filter /FlateDecode >> stream xَܸ}'E f LcQ#_")jg=UTU/WIixŬ3pf) Q #r$ӥT@|gU}]}{$`fuwl[/ _9", ;kbK 4#懦ޕs[{C^'re2e ``t=)^۲%Ǧ.E?OLM5}"j=zI]r(!I48Į+(z4aTW K?f[wv1eI#NO|WkT:+-tFJ8FU !FTD ”3 M{dA08+yU~/st3^d0AJ&*f"KJ꠯լ8ⳃC;~]d.ZErB-,A%ӂXۅ'ozkd/->(1yUڕ 52с?[k: qxjɩ-rΣfB`)Yd]KE39Ց횖-ђVd+Bҥ$)ȓ1cyb}c'ٖW!wwE׮7hϝEOmsmYiJH;w[04 (sK#o僮fD $,lڵH`g"hYm y/k=dUHŘ4#Hy!:u'[k:V/W?k)`4@!o9KRLe'A+tdDM]9@ ӌY&qKF2\w1fsaSo粪 X7ݦlF Ě^+_ʞPb ⤵Q8STY$l%DveekAGeu--VvezD/-}Zg|EޕMʀO8 ipZ@~w勖 15)OyՍ+CJ$gȿLJK A(Nqa,a3wLZ^D80 L3V>(x|sX4T_(<(CxJy |02~}.OD=xT*0\PkKA 鄇\,NgXj;{PV5Az1/e-7ڥ,]ʮ9ʉ鎇O +-^#c0p!f&1܊f:Y9 A 1v+?46o,4<;P,LC  u5eeq$R}"Xnu!U`М+raOrK 5$y&MaLTqYG:ocXJe`Pm۾Ђ>%26Ub_>A!y{b\ tirE:4T)KeIU|vV]1f3PϬڨy6&EXf͉_r6Oxτ׻'ƴ/xoU02ӕ`Bmf}|AF%LGLKܼ۳] .Ûk F4H,MiXj1+b1dǹ̪ Y wѧ1+IgWo6BHi-vKu)?}.#k!33 hHXZC$/-y"tO9V6%\\JFY*:o/<@C"Z йL(>2xv ',hx<+5F IxI± ʡ- 1ߡ* funuDlڬ 01=mT0nN;NZ|y1fp*ZVqTiYuB"՝{qoׇ&RGi ZV݀/ 6+f_Ģh3."3}F7@}mc|#fVǿ]tP<|rè&^99^i'U8 Muܓ!{?y(k\#PCvܐSא\*?yno6I 5eP =6,md53\NSXy5cJzfēHble Rr8 OR_=uC 'Df iغL!Y)R޶4Eu= h:KDg8Sv}͉#n6gmf~2`17YK1Ff#4rq؃pY kI{z1 y쓊}OM%)ιlEAbC-]LR 2 uB .Dh6 7We4@D|`R}( }0~GK ej^_%g(&kywjQ'M~E)M .c򐆇47 ye3ClIh=*ɬY@ YrCp2s%"!9+sB'0EL3Ʋ4 \F?:n!IWxӈE9L">B>[O L*'B"H vl:c@;cw?leWiK]#Es<-_\T Z|(3> endobj 341 0 obj 2984 endobj 343 0 obj << /Type /Annot /Subtype /Link /Rect [ 222.19 216.777 296.35 225.777 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 330 0 R /H /I >> endobj 345 0 obj << /Length 346 0 R /Filter /FlateDecode >> stream xY[o:~ >:H dl)zvuq K-TI;.. pf8P/lfB[ad?y9ll%m;u< -:cп&FoaLlwsVϓ/lrп|6NyrMFĶm/D合ܣodc[T]sw|Y8X`+eECU֜Ѿ,etm[f/\D'\/.cNkvZh! ЇBNP^=P6uo#e`QDtYaWhe+uYiwx\;Bh((*76|fxċGxt=],i ;steNlM39\z|{8@W?BdeF PcFj4d9k1.6YQȱr-`ֻX4,©hMƨ?TthS3hvh}n؞q̴,|ߗ  -PVÀMYݡv16hqu̢lFyJʢ_υC X4}3"`{1{!F[ }-;Rk;&>/>}Ӹ3G%qZrH$* (cBYXUhj9ǚqi%-ܕuq""׹D7檑Oݎ(=e}DžN$c3é&n2AƊꍁݒ,!nZdz T43Кޒa] fƒ-S }h <"˱lhz}4尺RI kNGN V/9pkK8ˍ5θZgMAHܟR-CՉtU9\sMH6.x \09,wvFΐQPmCћ2˓!H}*l5eG_&pmg97mZJ.HՂ9kU 3eh~|y:ԮYKfLol{:WE:"!}9̇:ێ88!AWpq@CX|z㼝lč,23e:+)TC؆p1Vµ%VzsQA@荬% 7CF0_ڐ"/l f,v}Fk7`VT#+gݐ H:4\v+ XѤ΂19kvI@]O f?$4(V#8=+LujYfmj3oIwvX82(!*8U9[ BV^nQU61'yQleV'i( 2V *ߐXArr[&W}_nal 򘦬2h]n=,k.iYV/qB7QFK"E!+gt;RO-rQV\^C$c#GNT~_GL1qG}pe(Ɂ؇C<2|P+Edۀ_ $T$`kK 3]7pXᐮ(PT9HAm~GHAW? p}@tgn=վ;ې3T"ǁmp\-n$1$K'M>`cU.^/jG06pU+bD=Yܑٗ)W>le.TٮN~5|,s|G#"/?B(٣7O{ޖ/+Tnj6{[AòrbGa几@|5OyNjǚemt8DMM*Kr4xX^ SV(#,)l Ht;/$}/1ؗV龀1O\%XI&7dRkE3ipb> endobj 346 0 obj 2863 endobj 348 0 obj << /Length 349 0 R /Filter /FlateDecode >> stream xXm6 _bv7IRl e|r1Wiz~%r,gݷ/i" _18- ,A0g1@4f T` F@џrAЏ@fdxkv k@nH"b%_]~Or?&E #g6jP^6ΛGtʼjczm{׺ƩEQ`f8y2ǁ8b8'# |FK&7)!I% <\Wݻ V:9UPĊtVZReJBꈾ4u~wl O˻~B*j`?IPyvU; ̠!'/$%o~/adTbo~oR޿/Z>/ o&)ɏO΄*?gq+uޔ4Jm\*9M7>QMCȪ38Jmog7,iSyF4@#>!-$ABAGF'h3Yt#E!h$f7%F7, ]iHDg&4,I@sos: ak+DZj7dft,訤S3cY8|ʭ\;ٜteY&3-gv|0 1( a4oe[]|I]Q. c >ʋ#8(Luw,HZgX=,=euU6M#'G7a$<Ð&v' 5[y9T!plAyr)fCljp&8(H>=8T dm6W pe8:^j ʪ^+D=ba,<gUs!0.Xy) g`@ +ˎì6Wwm z=e Q: 괼aP|ݲMzQ;VO- *o^y$D= [Vʳ8&0Zг8m_~[,͆@-]d&4=V6i^ѿA=@#A$V!-1v<4^Kp?\az ''Da E7^V0(Of(ip 6_QF7&3ٞ1E)ضJ):69iH]R,]G%]s|Pݣc|beQO߁M7ZSq%W̾Clj/ysm.3Wqzi3̂[;Xutگl&ݠ1ciwc8bYXzȣ`"?yCҲ\12GԢⴀ3tkdtv煣tH=CU;r3уԬWUY<}l`Ri =IP *<:5 4abDWaL ܫ2+*SNդ=jt깶,e Kui(O'Ҧt;oo_{o_#zxe,бtk'ڌqs)]F<;Gdj6ՃWc!f OkׄOtϥR ^[H.f*RqWmúj:sK1ڙTj+"f=93N ^s7\qOA[ & gn SuH&Ss#l~V/"awߵO/B4-g G94H9(-NBwVZ3 %I endstream endobj 347 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 348 0 R >> endobj 349 0 obj 1837 endobj 351 0 obj << /Length 352 0 R /Filter /FlateDecode >> stream xَ8_:} 0If`,m"XR"E{f"뮢|ߍ"fYN$ HhT(=/$ADgcլ<Ͽ`MEC_ۡ*-(u  UJH#vcm"2QtKFA,Aa)+Y'%ݔ(yQ+XW$=O<|RIf}džH2+g̶5.s&D;?GClhux |2笔xB7sFn-\[*aABbIM|1H9P{*IrȋiΔeނ }^7@.GLltmWmhIh1W.;Q~X2 )b@f_[5CÆ],`X#kh_;VƐς$_`h/F@19MaǬ)v˳="ъ[j1y4hr.#D45T(xfRE_uPOdnmO!4@¨hM2 Ve`t tB_%^a`摒T,Q90Į?Af?'DOn, u+,YU 㿡b;ou0 !'mwzog=+L[W)̟H&ʤ):#f#UȍeeܜͧN|2^#Z#H˟!C#3/ʼQmM1\Z0æ8*Cd4rupO "o.{l}z@`.J댄!̤si@!1j8+dR+(kARY<+x6Q=a, ] :"0<*vSc 0w(svM7R -u(;]GNjLIgQ+;N[{޶o dIF Mun"& ẁ0/&ІX+xhdG9jis_",tS{YQlYȾA-pש&Ro綳8(bCwr$Hpf\/7,& LZ`{[w;xqED\'Ѷ\z82}wQ.r0~E,NMVR唼>Q}yׇwdǧ.<^sѓxȌr1wU$Ν:_/=H=sL 0OH77lm6mϫW8tX|#jm1G/ub'L *Q8nƏ .Q; T8tll'Y027$u>&}Դ__ōR)@@ "Gj+as.&P > endobj 352 0 obj 2706 endobj 354 0 obj << /Length 355 0 R /Filter /FlateDecode >> stream xَ7}o34=}^kǁzX`AIԨ׭(_Eo쁡fXWVqyAǫ,$QHa c/Lȑ I ` ȿ+tΎ0_`.Y}Ȧ^{'W__ݽMHޚX'9ɽ(,Ŀ䷛׼ޗ}S-d" ȀE8#eݱ rq=0]^YQ)˲%0,?wyb?":Qp@AwQ[:Fe ((/ /wljBev #/Hz! o-vlwyh3p"M}߼~sˇ/ i_Vvv谦XUXIy TvQ3LBD(r]/wׄ-vkHْwO'ވxM(7}GhG*F!t˺MC/IP9jePhkh #mH#;d KShpXCޜ /"rk鶴7edlwpz'Hoh k[n)jeeu C^L]jP9[ {VYdW6l {Pyc*tob}}vĮ\j9ԣMg$lM=5Fqü% 1f,'d6d^h#u@@5Lj MFefvlùٵzܲɊr=zxhBQ#v+`hhr1e|me(m;3]}y6ٌy ͳd yS^A,^B!wǐxd 2L$ѢJ;? prfľ%Jܵt‹O?{mhDt+ A|bu[>2OS>$r]]kH Z:̄{ uV<艖4ZjT!@-ەGF#kNRf"Nw&{^A<\%rv/-R/gUDQSL:YX@tx k Er-4gHٗϰ-)HMFa<dK>)~0̋Q(4X0Ƚ8I"JAVJ!la6 .]z>eoO%{9PAΰٟE"4T(ـK rV˶M+1BPl^ɸP~`A _M;%q>8.VI03keC@, <h%^Bd7HŅH?k;#%v?LNK瞳Ǚ-!KC ת+--UZde5E0or 14RvfV4BXjIA§=khq6Iy%3 nl ] =(~W\O*~q]yETҊ/JYS//r0q , D>܁ 纣 m818;Y {7lڊŞT[3.סzhNRDSbX4*B*[^a,]0cRp0lh,G ISʪǹ=KZE@$ H}/hhFP!މV"/S?dEm.VA-o( G:=m?JX,mDUvZQi9 ^=*ǃB>0B@*T]xG>t:O?A!圓(K=(݋<2dH~`IZeS$E7QHlr'0Qw9P8$i8P'X9Bt:X-u9[X]xvԅ1n<ɦcpA< Ad_6jVGOTCBK8'y*dxo~pS"XWaRfr@kז*;X}f8NVG,[zD$a }sF Ne 9?xH; IW;p!'>E Bh6s_N3~^NXjC"5{4|yz:@i2[hN,4M" ͝#7d)eYY/D RYdrUB-G; vx=7wr/`3g}ӀT!r1p[>2q} lsXB~} \Uk r5/ =i$ĚcٶQӔ`GX83oYa<1и"G07(a.,VHd6Bkk/,@q\yBO$J7?}޼ZÇ Z^GPΪh:B@Tb v3+?D^JX#)p+ER!ZlFlՄTEZ֖qYysYZͰ}猷]S{{+V}j+LfDl 6_I.%-״ԔMj)ʢ`UjR2-q Ȁsq3.[.`o=\L$G܀%8WN5ߴł<">߹:{U]sqr5t" ˁ.wD0ǚDnLE+?Z)Y8+$?J8__+ ~ƥ%mѥ Ć4ϠUџݫ& D/Q}w,wr|VxITqߛ6KHCila}\I1FIbC fÅ݅\a kqTR#[ e'F؈&}( CUԕ M6<y楾CAI,FгSZOŽKD( 3o P_H5і[!eͰ!j^0cZPC]>aRlm>t!8_]JH|)#+>ADŃ؆c{KkNBIJwJFllʮX\"iPoNE2i&\8hkcS>+5|&Ncމ ,Ig,~-`XZCB}]#~!A@#}"ƙjΨq1#BX# bIoBT^(1C:†A5* DzY\:`zr mEkٶ_KRKF=p@R\ =ŇRj9E!}5'5!RGuX>SDEjG{> i-EmԆ] z}U|`/5wg+;G : '[ ]V` endstream endobj 353 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 354 0 R >> endobj 355 0 obj 3628 endobj 357 0 obj << /Type /Annot /Subtype /Link /Rect [ 318.0 568.406 432.0 576.266 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 359 0 obj << /Length 360 0 R /Filter /FlateDecode >> stream xXmo6_A  CQ!kۺ"ahhK$;ETڏuZ;u!+ <$)ZUb hHhi*4 Q {ݷk9{Vm3}O32gwlhL]݆#h(VJ `CѢB^tMQodUΊ9?4"J0r![T-4ECV4bDON~6ZO%'^ǘM4-fq`ߌFMt8G#Fy=-9QغO#ܴ ǰ4NSB9_i;V#%9́j)zc ۢVw~*.Dmw=-NӍ΋n* W۩s]ų8#tdƮ]g,^ OEù O <> sϵ5\[;<-yyV IT`+ Lԙ@_l!Dp|7A9$$C7Ѣ!{*Gu[Z?K}:UE9PR'g>O\':/%(40'z؃m[|c/ Dzq.sh ^U"~:;ѡA6ꎕVeqh\/18󫚷WXRgˢX!і7Dž9. Y Wfóx`Y[0m.NܰP(;ɏ{08op?ԁO쭂9u 'H\'$joH-@7uPu#*?tp}x4pU!%D9[= Sl-4' }츿d“g.$Vo^s+D헢儡8JԷBӇ*[ 9*k3*ZHz:ɭ}}9R Ž-rguT;hN䈠 ^Rl+% R1@-aweRlÍZw̕8 !k HHvۭhZ)&T3bi0cpQOհlYK9#kҗ/>oKղk.{#͐ahSC:@H#q߹=AI,1[rGUD][m'c.%[XU<5*1j L[vUf;UkkQC{!MbS߆W97|@slÂiK"m"p~q9-u\\7qi edv?=G<5Ϩju}2{ŀA4 l{ozZ}rhoKca3b~VgyVu׀00WaMj·x65\Zb,+Ӈe$8"JdR(K_ Xhۈ"+7B endstream endobj 358 0 obj [ 357 0 R ] endobj 356 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 358 0 R /Contents 359 0 R >> endobj 360 0 obj 1828 endobj 362 0 obj << /Type /Annot /Subtype /Link /Rect [ 305.359 385.898 374.551 394.898 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 304 0 R /H /I >> endobj 364 0 obj << /Type /Annot /Subtype /Link /Rect [ 383.721 385.898 452.913 394.898 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 365 0 obj << /Type /Action /S /GoTo /D [356 0 R /XYZ 72.0 235.575 null] >> endobj 366 0 obj << /Type /Annot /Subtype /Link /Rect [ 479.885 385.898 523.22 394.898 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 365 0 R /H /I >> endobj 367 0 obj << /Type /Annot /Subtype /Link /Rect [ 132.0 373.898 158.66 382.898 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 365 0 R /H /I >> endobj 368 0 obj << /Length 369 0 R /Filter /FlateDecode >> stream xY͓81]&Gv+{M0=65[OH SC=!لae9ٟ7_ >$<",5qPHQBJqѸŸOM~ǞP{ϛOof. T,FW|œj|J"D<w|bL̨O72A F JKR1Fwnio F]a<)Ȣ\ә?6|Hi+k(FQNIQ)i%$.lIPmYI''Q[ҟVC$ 0NBMt=)^۲#.<&3 MRX!4$1I ;sEl[$t]b nI;Gwζ}sA.峅\BtBb':~LJδҕZVv[u %uaÛv_z]ޗ '@%_dP5ǣQ!޸Ur[Q-R6SxA˪0$y) Y>eQSi`QNNK٥=X'? U=v]'"9i^[ing>oʞy~a ~6WNPE<+xB"SjN,GKqi%Yֈ<wV {inNi&@5-(hnQ}@+ Ocƪa6D}4Tcӵf;ĪM~(ЎdȗUe!mRqhA<䭹ײ?A#H2k* C"랷~a?bv_($ F\d9Ywr AS( lӿJާ*( ʰز~i/^m bD*l}s r=zT>VEwמEօzSnZ1p@{]/zQHM`ŞD=Ch fyZYmf5&wn6f5#>-T"LMT7/b6x*H_Qb!E-Iso6M1O,,w}[6% ;uG)an  A={/OozZ }(g롭4aK#F5:#s>/h&W4Czߥ4`4Bۖ'٥4D]0)z C 3y/^J'FG%GGO endstream endobj 363 0 obj [ 362 0 R 364 0 R 366 0 R 367 0 R ] endobj 361 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 363 0 R /Contents 368 0 R >> endobj 369 0 obj 2467 endobj 371 0 obj << /Length 372 0 R /Filter /FlateDecode >> stream xYoܺCm`P"9iӾCq.wVr$ ;k%E{HpfHoՏeiUpZ')9!4Y䐜xš-?N'HOa&!劜E}f&#G޼IFwrB*y!trwdKodJE,u "6|R<2jĆ9DO8h<Keu]5 Iqv)~>,b%Wz7-{9Ykf'4~i\{bѡ?xxR|/}N&ƓS{9FZdi`_biRWXOYܡ7˹kTFӌu]1R~/淉]YoS:eC^ MB(8>FH^Ը--SH+XW+R0(tVQ)r+ٶq< G 6͚"\?]b$< j< nV(5kE`>XrD.QlAwиun˪,Y]ziw kWDQ&lk9]8:'x:2i@uu~ ƾ}/02_S &q&:3U3EA~2\qj&9NrݴIZ)w\q<66"A*9`2d}B/B &獛V6$*kչ;MђhM(ŠP 'Lc3 m /W i}9*I9\L%z!`#i_DVG:cg"ፘ6wAfzU[UpQN94a H帍C::tiu#M~'%l!d迾m15e>*s큇Vyh&zoYX0" FWLJ3S08*6ShrRB|bbP@"_ 3 S34]/7[{AY#f 5TUsh2U`i n&呥P3.XL m`qЮmpkquu@MC͞X"uru(LșOd}tjN.BJ 2Qa Blԧw-x}|y_,~GuFUЍ)2vM_3UKB 7&=!?)E/TQF#Ku6ڏ|lđ"-=Z lo,rڑvp=9\z]|vÅ ":,rI.yڦ}i^(ZД,W# J]c2: W:˴fY]H|/уPf:@}5$^*4mN6QČ@Uؼ<*%]VTyĊ(*.=B7)פ`ryt>-&5qsU9v4Qi9o6LP z e. nj^.>zz"! ӷ%?pLTl}{yqRL4 DBO?4ST0DcYJsHHᑲ'|ҷ\V/|úg8!ýVid QOЍә[[[RsgNiYHqfk%x$`-@y;H"伄•Do5޸Na#l;ߦ'*ʒ˥(x\R[#UG~]wyYר%$*F8/vjRN^-D12tZyqsٺ…U ړیDU ӽM?otY ]Yo|?\6 endstream endobj 370 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 371 0 R >> endobj 372 0 obj 2420 endobj 374 0 obj << /Type /Annot /Subtype /Link /Rect [ 366.0 759.959 480.0 767.819 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 376 0 obj << /Length 377 0 R /Filter /FlateDecode >> stream xXo7 _AKDtv֡C4}XνGIw^(,Q$EH~[0R>#q@]| "^ؑJ|P ` SR9ʌ_τ(~Y|<+(GkUwۑm_}0 94!&O-|9{_kVx:nRY\@_a۠c$H"T8p:ӱ)dшJ6{ؖlhy9Σį [mSىE&%'G(iG'34cć8Qo,j1x GXDIG$_ʵWݭ+\up:;(Oи oP+œW'E gPeRvױ2PxG2^B-̘|-sv|~jKe9םa|ŵ,֥COmsL.mlalmۼ\@ aCE"ߨ;3ۢZ?ꃧ"a!qQ}c[XWu#+saRzl bB1(Xglnwj`]V첆rB?뺗N"uQL|CEA_GKQԗrILx'F]>.$p̓'W)Ga+ף#Q5+끨jabt\i-A|UmBIB8rWɴMj2P*ԇݶ\?kJMH]>ɢ~1ܟ_ .fOd, dfghjzO.úhAҬWe1>)>gzP$C~9Gߌ?t#:€gSmS+yj ؤe\vu &+w5aMMTq\2QURa/̑Q|\j}=ԴI,Y}MtD/>߳PgYsZB]K9`3[!g-N(sZy8ЖU!6P]{`-xl]p'/I׀Zi+SEIrxH[D|HaEvQu+WOA;Nٔ88;hg2ƹ APFэ~Hb+8X~fr)ZR}|!HyyE-uυBpr}F|T}#u23q]ړǜpbjx>OcF8mz0mz6oqOУYJ6 fFNNdr-GȬJ23qu +N& T';{Y@ n 4k b>>:MQb]O>J]\@wP۩4~dI<쭲lTf:}6b endstream endobj 375 0 obj [ 374 0 R ] endobj 373 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 375 0 R /Contents 376 0 R >> endobj 377 0 obj 1584 endobj 379 0 obj << /Length 380 0 R /Filter /FlateDecode >> stream xXKo8W l E!mm4 Em"z4w(J-AqxHG>sB~žqY1Q~+ OB{Lđ(4ĝ]]yaäK"'a҃K1P /vӰJW+CBoIl,* lKڦR2獘kS"Xל&= k4g0g?X 2ԉ"cۆoZ4Ȏ%I!LQh0y&j;uL8. tZ WEʥS) `1g[=-Wf[=~}/W.p7Kx}o,+ gIDyW+2־C~EoDL8nP,ZXOEpJ&MU찝pYf|;|aͮ*K:ݾ=~;I#^{naW|z;+xqҡaAgiiQ߃2BD(#v۲)35cc %,h1%xhShJf7+v9xlY`?0--S_'NRhVCWÊlXZg[Y Î"WĸQf\aw]9߳Ya!Xs-i=qȂ>}as{$qP Tj;N7xtCT8=uU RS~֡)$I>nèl;~?JJMnX40=ӤnkB(Z^ܝۍ*UϹ^_8tB ^JUg|跪׳ endstream endobj 378 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 379 0 R >> endobj 380 0 obj 1584 endobj 382 0 obj << /Length 383 0 R /Filter /FlateDecode >> stream xXYo6~_1@lԭ~hs.Ɓ^qd-wW )![aCqÙ(ХVF<olXa!>OE7#-ˎp *J>@IamɻpCPj=#g.. N:bM95]M|=Q+B.k ,j- aL/Vh[^&L{|bOO'9\&yR8Xj@D6Vèa9OjS+@ow0K@/{od_aga`ůw:`LcM-{FhHԠ¼#]C Bs_d/ߖ8X;MD4]4wyeJ7묮Ok(,.!NhD6V*J}baKUTeV~JyUn ^(T{㠟Љ!Xw&nj`~PE-ȟ{){2Ȋf uc^ݸ_tt^q?d W[,SN!U^1_]x3y+^rp\26C)*}bj;e6҂!l#&e8?` V+-'$xHte $$Nz~ư lq;m\gxP _(rfˆ.( ȦIěqVQ s`OLݙ-KXi-E1/֌uqfJ- R݄ +Ǜcux0 ђ W,u{x\&@p΅\\2`Ǵꯁx h^e~ .Ÿ ЦD"aMPOvZv-9rU7pw`I2nx1?(tWg1rLp2b+ P4ve]Jܑ.+'x3uoO6U9ĉl^G Ǥ JeYVLáX?J}\DbȰt4dc\|h\Y,DarcTȭ֙V:٥xUr T͙lU2r1 aXAQz֖_v爜7s>1)1D]L=z6*x b @Ş0 S3L;L}Dҁ%psLV=ySlTrD].JC> endobj 383 0 obj 1940 endobj 385 0 obj << /Length 386 0 R /Filter /FlateDecode >> stream x]s6ݿ3 gFGf&5}ԝ %A/T|HB-d WG( 9^}1tF2NԐ.( O".ȑI`W%oX%=] 5lfߓ|<^xu 3ZpJIżP8?6zED}7} WrY҉W4MST/r6uor!if),Mٍkn~շ w8-\\o`""vMKɩin`5*88+ș9!xO Z[2t<yHE9$8gT^MR1P6e AX~z+!L氝(%O{ 1Z-pxv_: bA oKyfXV:k9-&275f|QfP#!ަ$b<0?vw@CL0 iH%H* x]79gy ج{p9'`D_β}V~ {C]LXA OX!ɺunenݧBNečfYgAS/7-zZLDy=m.'+A۴Q[+j0ҡxfcDB9 Dzd \Y4 ])":!wYY;}C2UQicqHOᠻrp($ w@ۦ9^u%k({ҕǜG%,m9o3~ bHYn:uЕ|藖/Hw̋}mMӶ;5/ݮTCe6;-,xM?- YE*rYm 0 M Er;K\>r}b_(=8Xa|&9o.-d|H!1cTËGAWZM!/z[''t> х> 愅`n^b/u8ﺃ1Xo·Jϥ  n8Ctd<X`#QwjL'1A@x%iH%&70ٷ/W0k'Ȑ@|Slw|MF &F &yRkEo%S]/fƅJ UWv<5]We: x:e85?[eUo2ťw;zSkI61.OMYx |3$3JsjŝyAP^ʁ`p=7!N+1nisb/ |՞SG$KGSQ30&VOʗE=.lDb.BDyiMo,i jE`^nC w5%C:іy{sJ<$o\_[Z+i ` 2,<ʽ@[BŞD9NܚT= FYR֡[#E?RHJY'BL`+3NVj!jwY%8J9/{(?/t+j%X ${m- ׊jP} +~Ȟt,d+媓-qxS1~Ȫ7~z3ȑ~2[{ktȾ,܇<8>b dޣLt^Ad$YoA|Aq n F 뽶&z7 Ⱦ /&& D0 iGؖGл8i#n!> rOZ;cۮUCp%ZZ1?DM3&랪CwE?_7:jwer;K~5KZ95+Q{`l lFRC>WBo0^ ѳ4D`ۺi/fucD?phַ;vu@ՠn3LLDyowo 54SüE.+ePT\0;P+MdUUB7VP|kʫ:J1.tԅcQ-߽zl(CE0ަE-[dZ Oevsko)XrsޞQA-TpnW% endstream endobj 384 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 385 0 R >> endobj 386 0 obj 2715 endobj 388 0 obj << /Length 389 0 R /Filter /FlateDecode >> stream xXKo8W %Q6mbƋŢA)K%:l~D859p߼H?N\.wIȈt[ܡ>SII8YWq tNT6xāssFu7=cK!ɇd!lXqqz,VՍbjI̓6?AR e9'2rٴZvOJYO#<ǡKCVTvBaHG_qQa3{cQ_pJvYqΧp\aW4:??k/ƻQ0eyq!Dĕ\zj_Y&jQFV˲_fSenSPXWY7Hd-QJ{An]F6Hd%mO_=U*YXZɝź_j6@yѴ7%*9|OKdo_oH$"-'[q |W< SK% dPu0 KCZ>Šh/7crӐH`,4ƻAd%QK?vUd{钏FC"lށp2؇̶jl= 7&F92$nO{'•&UTqH]H]7P ٘<+ Γfz]4؋|0#p)7~^xGzu.8ܼ4>梨> D3W_yXL]O"/nХ^PAօꢺʂkJiEq̽.]N%r$^J^\co<.nqdx,I+`tFɪG"L1Akً9 l!5C5b+JfIYΊ*3pӘ풺(8}|qsYu88r< ᮿyj{o 7(4E5NMSct0,ֈjxxqQNz G!Wg^X &†}~(:jYAD]qN[עٔƈ|`>ZfYDU%x #ykY-#wuF#ybBԔI yl1$n=Zs!+&+e8[MtPC_  ؄B2c#jw$5bD6~%C:,&/cA66l4!cMTT C>29Vذ as.WЅƦ†MW5=ǯļ_ToB< xc@20F,6묳ʄKQve endstream endobj 387 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 388 0 R >> endobj 389 0 obj 1727 endobj 391 0 obj << /Length 392 0 R /Filter /FlateDecode >> stream xَ8_t:fL$i`@[͍,::|YHn̾%Y%.IוO<٨_i4j>I<BD4`L(FJ.~F|"GOx''컮;5ϫlXOyzz5z+ qQI{*^IiI>eY$ބI6-U[kYV5Rx42]y4,QTr%IB=t#4H F=0Qwfzs?n YdOx*j:OrX"r.Y|n:'L`K]S,I&}LER8ޞnlJlSamY [@͏B5'"Ӯ{ '4R>ݧ7R_;Q]$ŒF V\bOtP6uiwpG8v%- Wl_[QZ̿xuVc~UMm b\4m-vҫRւ ąc(-V^v-%)fI8k|)6!y(U-H CVy\rv[I(-<.m|MS:oH~ݲuH71=p!Ԋ"anQAEnMcK}5lb t5!){~l~ -*0ھ^`z4^"{yU{5E+ϛ \jZRC8Ьl$DNKʅOpFQ2J,XUiyZP˳LC"EyVb2G*?D#C;Stlck]T ִCZfLf u c^DԲ}G xg k%|rΞR,>1;]L YY0Cf$<rH{m`i5*}(zɌ,=@BݼД0 t,[Ph }jכX kPi)K'ʴo&Y2NV&6`ݩn `/z\Ob S4Y4fA 6({17fQQk"[ܙO{Me1FhZN >&?C3@;(c5eJ&Z`=F9_vΛac)6WܰEn mg wJs#ϟ(~t ho t7$a]-PGד,-ds d' |@S\؋F村NjXʐ%vyNШN̍n2#/@lmԁvm -);@o8ۥ]wV3: .QCW/*`sGPXfl!8ƲIPbN3zi< K5X lLS}hy f(YBd%3ed *RFh:cu!c]8rltE9~TY[t?"ʴ`hMjO}+ɇlWo-$zSm8|d:f>y3:&ozmPww`/ހap sU1ryXpg$F]KÉЀi-_Mo*{GFwp\-r0G}CC+)"ԉ@4D+g}mAl1ۡC8CnyeSߤ ^lK%(%&PM0ڬqOҮۮܱ" nĄz$;'BYNImsV F/Py(^yʆ=,-Lc(( jUb,p` U03ϒVCf佪P䝬|[䩾gqF!Y }O3ӣ@|^4e=|4xɜ߷#@2c3]!N>X;Y=%H8]pF39{gHɛ@ (ǺګyH?8?/ endstream endobj 390 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 391 0 R >> endobj 392 0 obj 2813 endobj 394 0 obj << /Length 395 0 R /Filter /FlateDecode >> stream xْ6]_7li<D%Aw$rLR3v~6иxSR F_h"$8yC1z( h̒ )Kȉr5> zs?/E@/%{^3;7=௉o0 ;b9+fA$9iĸm])=iӡ(%/r#4aơn;RV7e)TͿ6)O0,h&,~F8#Ȍԓa"J |Yv07o C3{lnd+Le$qOlhrp0Ȇ{rgS`DKk]eo \7cȓV!' $uD hjAۉ&TL":^ħxvigKlU7GeDP5ij|.h xHI k%"L?<%B5IDcj>0Z5k$ . W1JIz@FXz]T&Px~QfGl-U\p$9*Bו< 7Եlb @2A\r`ȇs" P) 3\ ܥIetuk(f Eń󖑩 *Tuu85G bc͍qw(ukk+Sݚ(_^tDXڼx*n9%%yEcU3%5'[letބ8E_"9כԉ'XMvX"JeGN69oޝ^aGK!og)!sNC oBJ ">ʼ3V9d W{#6 Jj"%ܹ<xi3t7FWݔ8eU&PjJqRV?Gc,+)?b+lŎKoGij'nյOJ]' 8J0 Ȥ&!S"Xqv*Vz#ހXk bv~JT`¦S]a)5p@6N4dPgA>J~g%Wr T44R PK R"C, h|9^<رt;Q;| "ʕ[;gcx n;(Z*-s]dewuM'+bm0(>v5:": s"k7a0CN%[V#=*.puK f!.Âm^{]="tQl/&Ȅ1i2SٌYVE 2a4t/gLSVe]'YxAn!!Z=(BGؤovy2DQK@YoV]8K%i4y<%i䗤kH#my*!e-eZ/lL8m?qTMh.=CsWC.7}U[ι5}[¼>Wc - P.rGf/ '';A  lr&d;!Ƕ#+P;0=;|r&OqD\|QgiAd)ɷ0HP!nB`e!lBae}w8ʢw B{"n̻M’R.*)x]+!kTVʜfxfg0u[vBה@O;GG4Xmh0=1;6(((eSG䣩B@&xp ِ0'`^Ye]+?:g4/:< Sv.>pdh)yW|mhAY|h7Y9/B>\HeAG4a׀~yFF;\p˳ ؘBvq^|P5[*.à17=?#q&65Qd g9Z5Ic»3 endstream endobj 393 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 394 0 R >> endobj 395 0 obj 3210 endobj 397 0 obj << /Length 398 0 R /Filter /FlateDecode >> stream xkoC2`S- IT8p?Ƚ;|HT>x nmؚgvClDcEQLbRjȷ-Y'$=&@5?kߑOreWذie!.Hݮn %l]}'M6qGm#Y.%w|~Ul{rKVXV&펿BܓpˏC PB]մ$+[UU-)εm+4w#Xr"zaZtO]xpZc1@1*HϣamS֩3wV9Nq SV4.7#W(u\ho%yEy4ڬx pkn0ꑢ2}nY 1NJA햋 c,yZg4FI1=塸5r,hMöSRcAqgM59Y|y{IjRX u fkj 70u3ptn4pUhp}XǢC近Z9 {_w?da2%A>y:tm(_ݓ/>NHmU+iϹwݳdV=% $=!HJf EUdk;^&4cOx%G9җ2l|qpfvåB ]vg_W;V%a"K 힇$)uAɻju#!νcދ]ΑGCTpಈ~B{#TL<*yzH֞52(?ZćO6CYdi?,Dauu(M3)jB[ ]o$+TV5ߨQؼ6 ۃ1'(o8Z@ H:!C[B]̹;CǷW?xdt!ł/Er27wf^xY _׼W؋eo]K=sJJ  bw^QB,+1hȽ9r(uH!!SDLdNG; <=|]GG5͟~?j\ye.|̋Z텪.8Z{s+[HìQg/됦}AaύtHT< Z3ZW^ef&!$*ݗzIUәĻjצijOdE①w4XV5j+)spZ5>ݥ~?S( X7rL z3,`Ȓ: jwCW̊)[񐆳PD}/  endstream endobj 396 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 397 0 R >> endobj 398 0 obj 2556 endobj 400 0 obj << /Type /Annot /Subtype /Link /Rect [ 309.25 199.258 375.91 208.258 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 234 0 R /H /I >> endobj 402 0 obj << /Length 403 0 R /Filter /FlateDecode >> stream xks6CΜ#Kt:n4餽&L.].Ï$Hzm1A әxOnfΦ<输)0<8AS:CRc`,緳s~<lϼR;K75/I?ٟ}wv*r|ϹQay^:KL p=vlլ;M^rV]:큾dDߍDx#޴ZY씼b-QuK;S $aH>Eq$b%H *#> lEkm4C8QeI'7_LNcݻIBev׷͙q|s O1oٺH o6i4RmzfZ=\}*=Աn]$p4|/juw nEYFh«&f ah(<'yn\ZZ)Pi&nBjә kVQ~` %Y /5??K~9Yx#hFԒ0Zي9^;ov4V]^.zP+ A=kQD-Ma擪N⑽Zk;nyBFj-S(-`scR2 hKAFiDU-OdM@LL-XKk\OS}W!ЧyC1v"A"j}G g2M &o9BPi/iy_'{;1suKmثm>-Q5O#L`:./2 Xl H;.ʮhڲ6m^ YeG8MmjXJl¸ŸcuΘ)^A&SDNYtF>`8fY Ր\~:w¨"g"_j/9 6'R E'zɔF/kFћMՆ,madD7]^ѪĽP>/>qEQﻒVl+4QF ІQHPњRQ(nm<ʊluip]W̘#ӕPwb\ʁ?B`[A]V¹(ye]Aaؓ!t lZX*o 姮g ґ "7˖ҭEPg "(j Q$U+C 2!zJKpc+H,Wrǭ~_ ύ=A3ȹBo9@m|*r <8awfkj`U(5^2gA77r[1qK|qYsh &Ny̪3 BP j xɈ,MM\)~_ԡ '73ԅ0uy,ېH$̻3wP=$"F.{T1*)yܒfF m<ړw=BI/ j\l_K&?r䌿Y>:~8AD©+E1ćejqL 8qyAL51W/ i PU83fgVAETïBm,!!@SUw:#1IOYC-k!t:Gw–A:N2p;9~b2\yxG-q8֏CN[P8A̛V[=lAC%a#ZC)5xviSBz5Q<u]_o5pcd@\5YxZ0AT9$-8xIio . [> endobj 403 0 obj 3584 endobj 405 0 obj << /Length 406 0 R /Filter /FlateDecode >> stream xYn8}W QxӅE^vX,ꢐe*K$'P,>A"fΜÈ ?W$E$C;Hȉ!z ¥}"C>`] ~̅3G} sfº=@}9+Gb0J=fR?"'28_/g|.6e/Hq_zϿ?{<_8tcYT5IZ/ʴ~&"O뢴; JWc1 УV;|.<:Oq/=a`cߵXҁu_ƸacJJ#/_ inn:;-X@z7eY[W^ ] 4Ik=*u=3E'Q{ݛ06BiH/"gz(2]hPa7[Ouv=9[2z>,_)A% dwXLw]v$ ղk1Y /*)&Ş1,.͒z)uUEmηm{SC?iGV0 K`?.ԳLK",߾L{p\zʼn>oo߾{|8d¿kHK4UCn iGbiI:O;6FmQ<ץwԱ`̇9q0N",!כ/;N!j@9QΗ 1g"g޶;~ZF g9bsSd^dY}6ǿ]'n0T@@bqtj^Ft=Hd0bH~HyO75J6^Y|j3=*<wO\r-AhJbYQ_fgTBmjjmMG}LXY$.f 9aGk6'qP ep}.#xK .&MY;f8뚲|("mo)L]bZ ,uK[ ~קOoo}_2]Da oIp7lSUݖtRBqpc26uf]lrRB8 [/̝40gNJ]Ic (osBW':zmڎsjG:x[)^7_:^}8KyX$ɦtcZcnHOi u`qF&~'\z<2XRGCne :XxGZI/v@!CQ(8svUBx4 "g*Y’*fP'Ŝh=i>YWByǜ%dnC, 1yum'! ;ق"Bj﷯+2/+c<cw)?Ku:wrD]J d84$&nR12_ǰmc PzP1Rmlohc {AF<{ AQ=]3zm=6 (̰))|>mǙLaG!:)w> endobj 406 0 obj 1985 endobj 408 0 obj << /Length 409 0 R /Filter /FlateDecode >> stream xXn8}WLuDbͺiwKyh$*5Џߡ$˲M}L"5sxfHggǷMƽf6S1lb @ SDMg %=oh=ryKﺓ[c)?߷[L ʦ߰hP!H搳xDr ł|7.,p](y")< bBfu!ܘRp..>܌oG;n"Fjf6SmWC(j>]dr lVӈ* "Xh*JCUrIĦkW*qWضdE-QxH2 bcSU6Я9 ca%"J #Ai!訪B\4έ?렎w]@"RкOm<|<pPǃncҥl"koB୥n Xm_az\S'wP2՞#٪<] 3w|?0x[[Hu$\5<%&:E''kWO/5{Z3 RBMA)8sk/rQÝjV zΫ9/opO ;9*8)bt 9nh!2P*+(mG(fV")po(9Ir> endobj 409 0 obj 1559 endobj 411 0 obj << /Length 412 0 R /Filter /FlateDecode >> stream xZݏ۸߿@6?^z- ڴ%DQ;$G$%KN ! 7$3Ù x"fYNVHI0AR(=/$ADȐ 渍o`,yQ_xo?5`›aX-.:hHyd{_c{acM,GEyqF2yyԛr{hzKHWoE8O(ё-'kkZa`hYQ)KӔz%]q :="jP0kj;Qsu=FyNayE%9_a{{+k^4\RafߕMmþb7c`ЌzY6l nݾyen hzU:"El׸kLT)7Om3TOi6NR2OI\ٱiJ=+Y]˹xYe ~ Cve}j0a(sljHbRt5NH5~4I^M9V 10p, HQ_Q$z_8Yo9#Ó0lT>ᡒQPߓf*\JWvPN-LsUSw /K5r{fO=VcQImh#*kZф\Y,:Ueіw8%U ֚6:. ӋJmcr/P.Gg@qKF3x]oSw pBzao:^w%LX5GIqlɴti2|(q5g#{=_uluXKԗOi X| SFܫ.fOh [15l>Y(ڻf}S` J==)ÈNxb0?@I~Lp tvmX'Pɩ |6IRʣ$N nMSqV,;78JWx`O0yِ%׆'  j&(&tª7f>1gԆN[^{'D 0 JRSȻ#r4dd#Y@`{8%}$q .K62=ș7^LExM |\1飒aF4i тwrEvzKe*`͠3XRiJm0F (acyysr+n(eC<z `rX-B^\Eqt^@(̠̙<,>Rӆ%ǷX`ipZ_\ L.}d(_L;}*;V%i55I lC'JwVojCKn/P9Aj!ȽhʞuR[JE#)߳!l|Q >a, } Wx]˿`3gJTa ܍/C5~-+KzR]?R73]p`80r's J6S2^4 xD f$i|l`79N#:b(D& Oኯ}J7R6M@_X&}UKNY}+Kʹ^Qx:,.7 7m3@Pʓ(Ҍf~yA.d'ȇt.?&J'N ;٨ҘIv}NGGC9eP cOO'BF5M3*Ȑqy3!vس':s> endobj 412 0 obj 2647 endobj 414 0 obj << /Length 415 0 R /Filter /FlateDecode >> stream xY[o۸~ ЇmGriζMS(֋h$e:czfDfsX8Ȇ?'+ZE^Emn`r} PE*`ϔp{ ~/ja,dȆ} rjئ;gzq6@ֻ1bڶ(<7h]^ްjG]C=1hQXA E=ӑ3"ZdJVі5JÛQ<۶-rD駰R/"V)y(p=ˍINr߷<%2F<:a*$y{[Y{i6ƝOV9NDI(\m?W58̝e0T"^JV 8}&{pun|t $#@ mIʪts6. _8r ]yn q8]is2p`j:;Jܤy盯\7g>дaZf.2ϴ22_8wXC$dղ\!0jȞD^컒TJFո!j`,Tv0udh{@붅A$tbCXG/6=ɡ 2ǵn(4TJbU'6yIzX 1X}]|\h6X o6o_o6 KlF~':]p%aG LeDj[˺ow"I]8B/sH[M➨KfZ$O)macQAe=Y*K{PTKQ{OX= sò,4Ip<#_[aSb9?I@Ҷk'lS}XyX lspJW|*Ϟ$ޝ([ȎV$Y#kOF ps$`oM'T Vv,ɡ|XQ3=sNb-82l'TzJ츶DEO agph&j&+k"Qh n.'(Ή MX$F QT(3IQL-H+2.z8T_SZSHc@\ʷJ\BY$q(Z%f8t§,p@[tI[5r Ȟ/ر8δTCis"+ ێlS&Q1V6' jM5rg}MB+tGcPߵemҪF=a[H Ƞl94YZkH@g? ͺ6@U'X1@;ߎfF Ypݗ8BVEZtʺnf‘τP ._߃Nе<  }Y-*0(j j)pO|誣2hg%ck)rAr{uwY@wjIwX=%sC1rht(l%*ffZ~e!n I) WHG4MU ݛi'"h#UF~s1eV*+RJVDFC}M8k. AY*x/$(QhP5@;H *E `N@ד~*B}LXw/nr L˰Xx>@ٺUGU:z0A*IނoiU+~݀NgOt2_axZ3j@.oSV#QO㏴ Bfͅ5JWP uϪ.'OO>F{l*NRa$"҃8w/n 1zt(s䲌@@fWW]ݖ.z3-|RBǵ"0MDor q=js" n8axpPv܈3$ިj9H Q$Q`mWf>Ihן`/ղ޿XUYӖYfgSa"u ]-6 _ TH=L`eH\0hpTrXCW(v(3CoZkZ طș&RMS8"p 000IIjnr\퉾 $ !V?D>a` 1L>[- endstream endobj 413 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 414 0 R >> endobj 415 0 obj 2460 endobj 417 0 obj << /Length 418 0 R /Filter /FlateDecode >> stream xk6  hE=,Ep%vn|%,9{_3|H[[R;Cq3y߯('ɏW:%I@µY}/ bIyALdh\ @|o >=]+VwW_$|͇P(}?NIAr$_NFT{"D"큿F9g  C-["ўɱD[7?G }K4}Q"*=QNp$I<_S^:_u?B+Z4ajG+ZyLYu?p]8]fYeKGNF/3_ PJGpA< ͅݑWu{f#oraO^9[<Ч HZGOtr.# \w& -Ј\3XWYWZ 9|H@cpunrBe0O༐sqj rkފq0K*rg^=,Y#^ϭ^bbOC-ۖ\z`?Mp+28Ƥ(Įj)! xJYGrI>sT6gsE!rV9;Y_>X+B5Xh2ѩ*kɁ%2GHdU"]4L:''W+NrS7Gbu'7 I-Cl|72ךR:q?R}|Y%q8݈>=g%w #/l((ye=NpmLixo 4q6Q.Ҥ[>^(mX4 10{E|:4Lsx0XW`0'.KT41';5X M}\0iÑ( XHt3*ΊP`z H#]֕VHRX厕 H0M""&{_e jQLw oitpJGiU*0dMy^0JwݾJz :ɐTFCpgSLHS_[ux ejJœM%Q0П$@˶@oB42 ~> S!(4;0<:*|XS:sDDf$\ۼW DBInny_C?QE4/QyC:*0G!h34t˅ ٮ/mfP)jWwbr8f;0]yvQ9k;ΒOa[QbrRphYb$Ux=r=htAk/dĽd5xp(CC2&1n(co V z7c-MU\ŸYkeȼ>9  5f񹢶Y-D2o. [4I?;Z3;ڥT0+ *L>0/"a_ D!vI^`I_nWOؼvG ТA)xt@@=c?5mȳ&EUoVgBdhE^t'&T{Uj5ͰlQ-2ɧ#RRXf b-C╳8ҨJ質k&X } =KgɂQ_P 3$bWz|9P ҠP|՝];_)Kyu,NĐݵwC`!SiÅ)jXKDR#fGVvrJ((lb4l_N!D|Hv&`$t)  LKF rAbzPQ(F&Ap밎 Tz0 b$Ix~dƘy Z'D맃W8,{T?(m:囏C&!0O|IaOi B=ƕE:=d ~|고ƟԕIy;cw7EËzo0 y |[O,̢s GVwzI?jش@9nVcӍљ8ڛ5V^K&(rbsF` Lmx 29FN2xtz@Qܳ|g0Qzc`tЖۭ~4~Ұz^Рc]?R ɬlvA0(j'n% h_H w:b5 O뫹FýGy_"̀2W(&eg e`(Xk >2$pХ Gs(]1}fA6 qk/iӰ9 jŰĚVr5l?|jiXOZ._PTS_/Oe1$ t7uxZy& ez.AJ'DPҀEv560hۣ'zdӗ m5Ay6v)VFzzbp],X 8P@az/U#b_)P5NT=/Ws endstream endobj 416 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 417 0 R >> endobj 418 0 obj 2643 endobj 420 0 obj << /Type /Action /S /GoTo /D [416 0 R /XYZ 72.0 411.347 null] >> endobj 421 0 obj << /Type /Annot /Subtype /Link /Rect [ 200.56 387.229 272.22 396.229 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 420 0 R /H /I >> endobj 423 0 obj << /Length 424 0 R /Filter /FlateDecode >> stream xr8MvYg3Vf2v*8$IBÊ뷁4]7fy^%YCN:0~~}_u᥻-#u2r󉶅>Ҿܖ8;fвPhk eGn(ѡ-5+w}W6M1#E PEaSzMNB$W R-uo/=G!77Cք]\09ȲOɟ;˟ɯ,t{.I=l˥;_O/qTɡƼ VhGqw=/@!5:nГyÍ^:*0p 9#/!;Z1k^Rj(;,6@@(qJ0ɪy[nYIE3QN2?CJpcˏKv 3ؖ"t `ΥFlV+WH."~6Κ F¼`0kYc/}*|B>cT\A׃ I\vG9{Қ02kj>E4!(đD,]3@r3oD BQyAm/rXXBU%8:w"I-\7ͼ6X.S{n8[z[1-Ǐd-[Y*%[Z(RK~};n ,*7򂅵fw4S!%;Q[sk6]Y9G0dǠ3Ł'Bܗ x6FcTҔ.ݑ EVyF1uDQE#tPfqz~2Fn!Ij7iAMȣG* bxB sJ|BCSx~D0xŃR߅\NcX?A:NW?Cbt|_>4 uf&Y}O/Nj *i9 ,X5eɰ `,Qtbbb[Aj@-CC, kA)= rax`M:yhׅiŞAO+CPDв/#d;¤r Ġ]Jk0餪H'!lݓj ^<uAQ25`.9!HKtteK-Br."A. lo|([a+6ΚUSo}Sx3kV,ƙtE9^ÜYB7=I?䑨"=ԈVC.P#͙) \vQUj,j/~&R-QT:qin2hu]?T^ 'ZVDl+PW3M[bs‘Rpٳ >^Y(C,(gJ9ē\&U:&;K2P !⵿_i@ Uoܞɢ,$lHBlL f0yEpw'uY\0/z^BǻW8^}=%6*xH{P8v$ D;gvj(r Yz5%2n$Lz+aSB즳.c㑠35ba$Rfe5{q7p fkѓ51(]c)R&d 9վ, %A"nA;S(n ӝՀ8!g{xSO}xj׆^\Qረr@ h XVJaHS- 2JU"~@/vf~N!ubX-Lϔ2@Nh$"$"+ | /a&DՄg֛1 ?Qam|X2@I,?jRr;Ubp]"xpftmKڼ!&=ߠl`#N#?pp endstream endobj 422 0 obj [ 421 0 R ] endobj 419 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 422 0 R /Contents 423 0 R >> endobj 424 0 obj 2827 endobj 426 0 obj << /Length 427 0 R /Filter /FlateDecode >> stream xk7{~E.ɞ.Bz-UiKB]'_߱Ϭ| x^n"  JŻ /lQv|`!;$@Ùt+|D,F?-^ a8w^+5F~ v?XQc(v<z*Լ< A##[A_I,\qDPs䲪 y;WZEmB/"lsH\v3xښp 'cj-ǶQzG@I% l9$SXj+Duh;BԴ$ m|{FeSECK?%Y6 x9XRݔ#D*y5:~$f*Dv7OnoFڤ8Iq>U`"FU,'N@AFVJ~$_zPQT? WB=?/Ӽ7#-INӱ&:c(̓Mnk:d!'p=˫neq$E7!#BsE WbqΪ BHV֨LS$L|kD%q] IF,j.LB 8> s]ƳSu/up 16}m69rcҡAD\ZdQI`ohuwCnX`\@?Iaߜ,vcT*I!TA/H`wN,toL9Q&*d4 =߾D%MS&RRm!,bH`SNnuv/hRnv+p.e>-IHl-,%x.Z559BGk=Cp`9[i!K,xX6XDt+.|:RGq.oM*|Wؔ[o~P{+>`v?~b9sSg>'g؏bϞDz8P$e[>V\n[}On=ڭZ,PdcGQ*)Wؐ6MمBmt/ yar ] 񢬤Es:U5̕%K%ˮ `Zj8@zq;+u}^7B8SǏqhADh٭tJ͸"u S uZIGƠ\?nu&eq`9=V4I9FG½4ŘwC/*-h̏}T_w iku~snfYӨ,nqEg*#ޠ qi Ɔ|h*ø q[2[ἴ!>c&m>[]-7{ |=@Ӟ=qK@${ 0,6]"qđg9=Hp۱z4{*Ձս[n>(XƩjn`&v#DSU{F, !WF endstream endobj 425 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 426 0 R >> endobj 427 0 obj 1953 endobj 429 0 obj << /Length 430 0 R /Filter /FlateDecode >> stream xXݏ۸_A lh> Hz n-Sk!HnwM, Ù3m"D)E曑G((Ό(%8)!1 ):(E- j)D6݆m>"0uCnW~| |3 @HfڧXj%1-?N_nNGtHwo"pZ`"c? t?S5_f ŏE9&Ƙr<m0?D;#f1,YL׿7%W0k0݆pZQTyY.f[XaxB„ߤ@qƪ~8Q>LKgeHSu0x%rb(Gzi@Pwq(ɱ'vq;2G0Gwtۿ:k6u}:89Mޡkj+Ց%LEg>iF1XFeC6yZG95Y@W[ܶ-8\폙7fՑus'a{]9FS' |bw_EbA^{J4EeIQ;J#L@[(@#r+V[ybD{ 9ѺosB&ц[.Mxe\ڮ3tJX۩͊;a #^׼)cwp!=]/m Hh, >tL4/< GT} ͨccdG.c0Sjh#ok`^ñM$^N#$snl 4^VH³,PkNj-c4jsT!Fh =C82ꓽ6U>-PmkcOL+_ e jdy"wwR`ȦDP j-?ؙa) ʘ,{>? ZUKنvUTa(F0hIziUcǪɋ}iu1vir614{X_ olYFLk$%m&8D97VJmJ3؟~f*'84d)B$kq˚ql`!x"eP]MàVb{}v i/8VV84p,E?4o\)MqZ&+& WXK, GP wn4xTE2-ˆmP9S, 9ٶp&zf@%MHG/u+(-#an{nZØ.ty.Dun1&KaB y +l\0/a?lcWqZ8A?oGiiЯ"~r+PRхDIb> endobj 430 0 obj 1920 endobj 432 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 759.389 289.28 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 320 0 R /H /I >> endobj 434 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.892 759.389 524.892 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 320 0 R /H /I >> endobj 435 0 obj << /Type /Action /S /GoTo /D [279 0 R /XYZ 72.0 570.045 null] >> endobj 436 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 747.389 296.664 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 435 0 R /H /I >> endobj 437 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.834 747.389 524.834 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 435 0 R /H /I >> endobj 438 0 obj << /Type /Action /S /GoTo /D [279 0 R /XYZ 72.0 348.426 null] >> endobj 439 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 735.389 302.217 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 440 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.79 735.389 524.79 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 441 0 obj << /Type /Action /S /GoTo /D [282 0 R /XYZ 72.0 769.889 null] >> endobj 442 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 723.389 289.28 732.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 441 0 R /H /I >> endobj 443 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.892 723.389 524.892 732.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 441 0 R /H /I >> endobj 444 0 obj << /Type /Action /S /GoTo /D [282 0 R /XYZ 72.0 463.153 null] >> endobj 445 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 711.389 310.452 720.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 444 0 R /H /I >> endobj 446 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.727 711.389 524.727 720.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 444 0 R /H /I >> endobj 447 0 obj << /Type /Action /S /GoTo /D [361 0 R /XYZ 72.0 769.889 null] >> endobj 448 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 699.389 325.163 708.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 447 0 R /H /I >> endobj 449 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.435 699.389 524.435 708.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 447 0 R /H /I >> endobj 450 0 obj << /Type /Action /S /GoTo /D [361 0 R /XYZ 72.0 468.108 null] >> endobj 451 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 687.389 220.706 696.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 450 0 R /H /I >> endobj 452 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.279 687.389 525.279 696.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 450 0 R /H /I >> endobj 453 0 obj << /Type /Action /S /GoTo /D [288 0 R /XYZ 72.0 769.889 null] >> endobj 454 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 675.389 277.48 684.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 453 0 R /H /I >> endobj 455 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.863 675.389 524.863 684.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 453 0 R /H /I >> endobj 456 0 obj << /Type /Action /S /GoTo /D [288 0 R /XYZ 72.0 531.011 null] >> endobj 457 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 663.389 214.66 672.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 456 0 R /H /I >> endobj 458 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.323 663.389 525.323 672.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 456 0 R /H /I >> endobj 459 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 651.389 379.467 660.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 304 0 R /H /I >> endobj 460 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.12 651.389 524.12 660.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 304 0 R /H /I >> endobj 461 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 639.389 266.468 648.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 462 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.069 639.389 525.069 648.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 463 0 obj << /Type /Action /S /GoTo /D [325 0 R /XYZ 72.0 568.933 null] >> endobj 464 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 627.389 295.114 636.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 463 0 R /H /I >> endobj 465 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.845 627.389 524.845 636.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 463 0 R /H /I >> endobj 466 0 obj << /Type /Action /S /GoTo /D [297 0 R /XYZ 72.0 336.124 null] >> endobj 467 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 615.389 397.953 624.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 466 0 R /H /I >> endobj 468 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.038 615.389 524.038 624.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 466 0 R /H /I >> endobj 469 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 603.389 424.621 612.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 309 0 R /H /I >> endobj 470 0 obj << /Type /Annot /Subtype /Link /Rect [ 513.83 603.389 523.83 612.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 309 0 R /H /I >> endobj 471 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 591.389 263.144 600.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 330 0 R /H /I >> endobj 472 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.095 591.389 525.095 600.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 330 0 R /H /I >> endobj 473 0 obj << /Type /Action /S /GoTo /D [316 0 R /XYZ 72.0 688.545 null] >> endobj 474 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 579.389 248.807 588.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 473 0 R /H /I >> endobj 475 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.209 579.389 525.209 588.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 473 0 R /H /I >> endobj 476 0 obj << /Type /Action /S /GoTo /D [316 0 R /XYZ 72.0 280.881 null] >> endobj 477 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 567.389 295.01 576.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 476 0 R /H /I >> endobj 478 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.846 567.389 524.846 576.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 476 0 R /H /I >> endobj 479 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 555.389 264.877 564.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 326 0 R /H /I >> endobj 480 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.083 555.389 525.083 564.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 326 0 R /H /I >> endobj 481 0 obj << /Type /Action /S /GoTo /D [319 0 R /XYZ 72.0 243.473 null] >> endobj 482 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 543.389 332.053 552.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 483 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.554 543.389 524.554 552.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 484 0 obj << /Type /Action /S /GoTo /D [419 0 R /XYZ 72.0 675.645 null] >> endobj 485 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 531.389 349.751 540.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 486 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.417 531.389 524.417 540.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 487 0 obj << /Type /Action /S /GoTo /D [419 0 R /XYZ 72.0 540.177 null] >> endobj 488 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 519.389 294.509 528.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 487 0 R /H /I >> endobj 489 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.851 519.389 524.851 528.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 487 0 R /H /I >> endobj 490 0 obj << /Type /Action /S /GoTo /D [419 0 R /XYZ 72.0 438.953 null] >> endobj 491 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 507.389 321.392 516.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 490 0 R /H /I >> endobj 492 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.641 507.389 524.641 516.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 490 0 R /H /I >> endobj 493 0 obj << /Type /Action /S /GoTo /D [419 0 R /XYZ 72.0 385.729 null] >> endobj 494 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 495.389 310.659 504.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 493 0 R /H /I >> endobj 495 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.723 495.389 524.723 504.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 493 0 R /H /I >> endobj 496 0 obj << /Type /Action /S /GoTo /D [339 0 R /XYZ 72.0 588.605 null] >> endobj 497 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 483.389 349.462 492.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 496 0 R /H /I >> endobj 498 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.418 483.389 524.418 492.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 496 0 R /H /I >> endobj 499 0 obj << /Type /Action /S /GoTo /D [342 0 R /XYZ 72.0 492.599 null] >> endobj 500 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 471.389 326.032 480.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 499 0 R /H /I >> endobj 501 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.603 471.389 524.603 480.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 499 0 R /H /I >> endobj 502 0 obj << /Type /Action /S /GoTo /D [342 0 R /XYZ 72.0 344.453 null] >> endobj 503 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 459.389 362.443 468.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 502 0 R /H /I >> endobj 504 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.245 459.389 524.245 468.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 502 0 R /H /I >> endobj 505 0 obj << /Type /Action /S /GoTo /D [347 0 R /XYZ 72.0 589.889 null] >> endobj 506 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 447.389 231.878 456.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 505 0 R /H /I >> endobj 507 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.195 447.389 525.195 456.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 505 0 R /H /I >> endobj 508 0 obj << /Type /Action /S /GoTo /D [347 0 R /XYZ 72.0 338.99 null] >> endobj 509 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 435.389 287.36 444.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 508 0 R /H /I >> endobj 510 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.906 435.389 524.906 444.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 508 0 R /H /I >> endobj 511 0 obj << /Type /Action /S /GoTo /D [350 0 R /XYZ 72.0 591.785 null] >> endobj 512 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 423.389 292.783 432.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 511 0 R /H /I >> endobj 513 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.753 423.389 524.753 432.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 511 0 R /H /I >> endobj 514 0 obj << /Type /Action /S /GoTo /D [350 0 R /XYZ 72.0 384.946 null] >> endobj 515 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 411.389 264.84 420.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 514 0 R /H /I >> endobj 516 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.955 411.389 524.955 420.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 514 0 R /H /I >> endobj 517 0 obj << /Type /Action /S /GoTo /D [350 0 R /XYZ 72.0 222.759 null] >> endobj 518 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 399.389 356.97 408.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 517 0 R /H /I >> endobj 519 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.287 399.389 524.287 408.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 517 0 R /H /I >> endobj 520 0 obj << /Type /Action /S /GoTo /D [353 0 R /XYZ 72.0 443.321 null] >> endobj 521 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 387.389 303.849 396.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 520 0 R /H /I >> endobj 522 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.777 387.389 524.777 396.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 520 0 R /H /I >> endobj 523 0 obj << /Type /Action /S /GoTo /D [356 0 R /XYZ 72.0 733.889 null] >> endobj 524 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 375.389 242.603 384.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 523 0 R /H /I >> endobj 525 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.259 375.389 525.259 384.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 523 0 R /H /I >> endobj 526 0 obj << /Type /Action /S /GoTo /D [356 0 R /XYZ 72.0 302.336 null] >> endobj 527 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 363.389 263.196 372.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 526 0 R /H /I >> endobj 528 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.967 363.389 524.967 372.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 526 0 R /H /I >> endobj 529 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 351.389 286.303 360.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 365 0 R /H /I >> endobj 530 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.799 351.389 524.799 360.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 365 0 R /H /I >> endobj 531 0 obj << /Type /Action /S /GoTo /D [373 0 R /XYZ 72.0 661.889 null] >> endobj 532 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 339.389 314.694 348.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 531 0 R /H /I >> endobj 533 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.593 339.389 524.593 348.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 531 0 R /H /I >> endobj 534 0 obj << /Type /Action /S /GoTo /D [373 0 R /XYZ 72.0 178.528 null] >> endobj 535 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 327.389 323.044 336.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 534 0 R /H /I >> endobj 536 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.533 327.389 524.533 336.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 534 0 R /H /I >> endobj 537 0 obj << /Type /Action /S /GoTo /D [378 0 R /XYZ 72.0 297.063 null] >> endobj 538 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 315.389 338.221 324.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 537 0 R /H /I >> endobj 539 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.421 315.389 524.421 324.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 537 0 R /H /I >> endobj 540 0 obj << /Type /Action /S /GoTo /D [381 0 R /XYZ 72.0 582.217 null] >> endobj 541 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 303.389 284.09 312.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 540 0 R /H /I >> endobj 542 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 303.389 524.931 312.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 540 0 R /H /I >> endobj 543 0 obj << /Type /Action /S /GoTo /D [384 0 R /XYZ 72.0 745.889 null] >> endobj 544 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 291.389 259.38 300.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 543 0 R /H /I >> endobj 545 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.995 291.389 524.995 300.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 543 0 R /H /I >> endobj 546 0 obj << /Type /Action /S /GoTo /D [384 0 R /XYZ 72.0 473.218 null] >> endobj 547 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 279.389 223.237 288.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 546 0 R /H /I >> endobj 548 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.406 279.389 525.406 288.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 546 0 R /H /I >> endobj 549 0 obj << /Type /Action /S /GoTo /D [387 0 R /XYZ 72.0 628.322 null] >> endobj 550 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 267.389 284.09 276.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 549 0 R /H /I >> endobj 551 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 267.389 524.931 276.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 549 0 R /H /I >> endobj 552 0 obj << /Type /Action /S /GoTo /D [390 0 R /XYZ 72.0 757.889 null] >> endobj 553 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 255.389 272.022 264.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 552 0 R /H /I >> endobj 554 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.905 255.389 524.905 264.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 552 0 R /H /I >> endobj 555 0 obj << /Type /Action /S /GoTo /D [390 0 R /XYZ 72.0 138.442 null] >> endobj 556 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 243.389 263.7 252.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 555 0 R /H /I >> endobj 557 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.091 243.389 525.091 252.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 555 0 R /H /I >> endobj 558 0 obj << /Type /Action /S /GoTo /D [393 0 R /XYZ 72.0 438.439 null] >> endobj 559 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 231.389 341.812 240.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 558 0 R /H /I >> endobj 560 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.478 231.389 524.478 240.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 558 0 R /H /I >> endobj 561 0 obj << /Type /Action /S /GoTo /D [393 0 R /XYZ 72.0 231.353 null] >> endobj 562 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 219.389 367.934 228.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 561 0 R /H /I >> endobj 563 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.275 219.389 524.275 228.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 561 0 R /H /I >> endobj 564 0 obj << /Type /Action /S /GoTo /D [396 0 R /XYZ 72.0 662.345 null] >> endobj 565 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 207.389 223.237 216.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 564 0 R /H /I >> endobj 566 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.406 207.389 525.406 216.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 564 0 R /H /I >> endobj 567 0 obj << /Type /Action /S /GoTo /D [404 0 R /XYZ 72.0 558.457 null] >> endobj 568 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 195.389 284.09 204.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 567 0 R /H /I >> endobj 569 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 195.389 524.931 204.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 567 0 R /H /I >> endobj 570 0 obj << /Type /Action /S /GoTo /D [407 0 R /XYZ 72.0 181.889 null] >> endobj 571 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 183.389 288.949 192.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 570 0 R /H /I >> endobj 572 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.781 183.389 524.781 192.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 570 0 R /H /I >> endobj 573 0 obj << /Type /Action /S /GoTo /D [410 0 R /XYZ 72.0 648.117 null] >> endobj 574 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 171.389 223.237 180.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 573 0 R /H /I >> endobj 575 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.406 171.389 525.406 180.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 573 0 R /H /I >> endobj 576 0 obj << /Type /Action /S /GoTo /D [410 0 R /XYZ 72.0 172.749 null] >> endobj 577 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 159.389 284.09 168.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 578 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 159.389 524.931 168.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 579 0 obj << /Type /Action /S /GoTo /D [413 0 R /XYZ 72.0 517.889 null] >> endobj 580 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 147.389 195.096 156.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 579 0 R /H /I >> endobj 581 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.465 147.389 525.465 156.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 579 0 R /H /I >> endobj 582 0 obj << /Type /Action /S /GoTo /D [413 0 R /XYZ 72.0 358.874 null] >> endobj 583 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 135.389 240.015 144.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 582 0 R /H /I >> endobj 584 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.137 135.389 525.137 144.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 582 0 R /H /I >> endobj 585 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 123.389 403.226 132.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 420 0 R /H /I >> endobj 586 0 obj << /Type /Annot /Subtype /Link /Rect [ 513.948 123.389 523.948 132.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 420 0 R /H /I >> endobj 587 0 obj << /Type /Action /S /GoTo /D [425 0 R /XYZ 72.0 642.623 null] >> endobj 588 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 111.389 284.09 120.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 589 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 111.389 524.931 120.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 590 0 obj << /Type /Action /S /GoTo /D [425 0 R /XYZ 72.0 373.043 null] >> endobj 591 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 99.389 284.1 108.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 590 0 R /H /I >> endobj 592 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 99.389 524.931 108.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 590 0 R /H /I >> endobj 593 0 obj << /Type /Action /S /GoTo /D [425 0 R /XYZ 72.0 225.041 null] >> endobj 594 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 87.389 405.019 96.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 593 0 R /H /I >> endobj 595 0 obj << /Type /Annot /Subtype /Link /Rect [ 513.934 87.389 523.934 96.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 593 0 R /H /I >> endobj 596 0 obj << /Type /Action /S /GoTo /D [428 0 R /XYZ 72.0 340.289 null] >> endobj 597 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 75.389 284.09 84.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 596 0 R /H /I >> endobj 598 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.931 75.389 524.931 84.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 596 0 R /H /I >> endobj 599 0 obj << /Length 600 0 R /Filter /FlateDecode >> stream x]u{lJEdơd[R2ЅLLzgoU(j^T<=SH ?_W?ig7o>~Nϧo*Nsɺrs߷ ~gn_ۛoϼR_Nj/roޝ2op7yJlW??x8ǧE~''ð/qVy0FdVwOםLg/&h=\?37?~.?-_nf֯?7ůJg_eMo7tsO_>?~t|zwr:k_֚->fwi=mvXH\I LBbqB ,DJ+lDF4"hDЉA2A @P%AI@P2 %A!B*T"DP`!"X`%6"؈`#4"hDЉA:A@P jf j&BJъ&[6ygmD>.[y5͇flbx6=w$kIW>yfmZ͖Ղj'u"uA$T+eEYVdYeC Y6diҐ!KG,Y:X@,e $b)XJ&dbԂ,Y TdReAYdYeEYVdِeC Y4diҐ#KGN,u :K&bXj"fbXjF,Yƈ0rg2L//7w,fH&?d|T6>q_'g ceĔSu/YI[qo_l6t"TI]PmC'R+[$نH-vRj#%T+#KG,XЉ2NN2N&1t"5 KA,Y*TdYeAYdYeEY6dِeC, Y4dґ:X ԉXЉ2N2NF,YI0[p#N{jee6t/Ngn i$[.6Zg]5PWT;/n ԗ37ԊF, ,Ȳ ˊ,+Ȳ!ˆ,4diҐ!KG,Xf!nlD,g37r6u&وjd)R KE,Y*,Ȳ ˂,+Ȳ"ˆ,lȲ!KC, Y:tdr6MqCM,g7r6UqCM,g?_gb9F,Y^NY:HY\l$u9{ˋ1^N~??|p|wxx|x8~;? OXY~+z.7[SH-66LQ -XI@lDЈA'c`b Òq1(1!8 "(DPA%J ,DJ+DFlDЈA#N:q`:@ cb #q11"(D0`}< 81F}uT21?=y:3bU+i陕}Tuzeg=٠AwI]Pm{VT7RvR !KG,Xƾ;e콃:'5=xPgbF,Y TdR"˂, ,Ȳ"ˊ,+lȲ!ˆ,4diҐ#KGN,c2vIM,c2vAeY d)Ȳ ߭vct>8ͤ]-y4go^'Pܥ+^l]7 yv? 6R{ՍjAuEڐ!KC,Y:̉XD,s"9XR KA,Y*TdYeA%,}8uP-vRj#%T+#KG,X&q! IM,CR˸R KA,Y*,Ȳ ˂, Ȳ"ˊ,lȲ!KC, Ytd҉e\`Hjb:˸2.0u&q! KA}߾7r$Ex{˩-7[;W!ˌѷpԛ7yzx~MLE]L=BӜ_lf;WwVAd"﯀XH\I * .$&J*,DB DJlDA#Ft"DЁ`LT1i c`LQg @L "DPA%"X`%V"؈`#6"hDЈA'N<b s@ c8b"(DP`L2}LlO"Uaqi:Aq=LK+y .irKo$o(/,77+ʅL1UcT:SuH5/#՘€rHjLc@9S*LU0UeTZjaVZje6ژ1UcT:SuH5&8'PTcʑjLt@9S*LU2UeT S-L0T+SL2TSmL՘1UcT:Su3 PTcRY(G1L3UaTc60h*8PLwXlXpU~Zo9xH~zXhq~S?|{.hZyxR8 )}z2v˽aye֣PQ,o(WLU2T S-L2T+SmL1TS5jL՘3UgT$ʑjC9Ru(GqŽI;3UaT!78yRLLk;7] ;dᾷ6twvsig4=sjqbBks˒W^b +)P>\YT S*LU2UeZjeVZjc6jL՘1UgT:R3(Gq  #8Crg(PT SLU2T S-L0T+SL1TS5jL՘1UgT #8CAT ʑj yFqLU0U5uJ87NP 5nXue;ѹ^_שE/oOoo,fKIM'8b8f៓:n j#&T+ˀjA5,Ȳ"ˊ,+lȲ!ˆ, Y4diґ#K'q"eZu" 5Nn3Nn KA,Y*TdȲ ˂, Ȳ"ˊ,lȲ!ˆ, Y4dґXNgLr:_&u&ӹ5d)Re\g&RKOs^ +r}d~♻^|?~mߞ4]p/.+_yws>+ۭ\YPyP.,,wL2T+SmL1TS5jL՘3UgT]H5QTH5Ijۣ S3yODWrMonww=ϼ|]<˷Ow~nwoPsy ;o~oCnmNˡ߆Ytd҉l跡&߆XΆ~jb9}r6P#KA,P5/쌸JTV2醚r߼<>?=vGڽ%_y+,3r:11rGyrCyrsjI.LU0UaT*S-L0T+SL2TSmL1UcT:SuLՑj̩E9R9$OH5ԢƜZ#՘Sr*LU0UeTZjaVZje6ژ1UcT:SuH5ԢƜZ'sjQTcN-3R9(gTƜZөqN]FNv3B8g4a+/yzi fa|V N긭 9njEu#u"9˜eN2gb3Y d)R"KE, ,Ȳ ˊ,+Ȳ!ˆ,lҐ!KC,Y:X@,e 2KIRD,%KR2d)R KE,YdYeAYVdYeE Y6dِ!KC,Y:tdRbԁXj"&bXj&fd)Re,)cq]9l˃ q"B{`~fۋ?;wݡ3%| ,z^Oah+-r#yaC_lֿ>&]yfgdlw3Jq f{H q08Cra9R *LU2UeT S-L5]7ӓPcz+cLOra9S5Lՙ#qLOr:A8'9R Huӓ S*LU2UeT S-L0T+SL1TSmL՘1UcT:R$G㘞Huӓczg:IT S:la8z, ʠ>/qPiL}P/=?qxyZt+<<._9:Xk_yvKŒ;; qw+$gT|'9RoT[|'9RoNr*LU0UeTZjaVZje6ژ1UcT:SuHu;ɑxw':Hu;3RoNr*LUjyim>w1r%;!f~vM/蝞i>NMNϬ-Ǥ[I}1sxഽ~iW;% ˍqpT4ʑj&yFqpLU0UaT*SUZjaVZje6ژjcTSuLՑ5ɑ5ɑ5ɑ53R&9S*L !>\Q{N/ZWXuZIJW7%ݦX]f^}Ӝ_lWv봲b﬿\YPQ.,,wq3T+SL2TSmL1UcT:SuH!ˑj,rEr$H5@9S*LU0UeTZjaVZje6ژ1UcT:SuH5@9R$Hj,'r Jƒ(gTuD5)LPuD% 1FLyi(p|~݇|}w~ћ|~㻋1x_H/`1i`fm`>AQnLՙ3UG1A9Rʑj FPTc0BTc0r*LU0UaT*S-L0T+SL2TSmL1UcT:SuLՑj FPTc0BTc0r# SsJ{16^im6,#㟣?x8?xv~4jz";cXqx1hI;3=Zl<Ϣ,o(/˅Y^Xn(oL1TS5jLՙ3UG<#qrR'@89LU0UaT*SUZjaVZje6ژjcTSuLՑ89HuGr:N#9R'<#qrə0Ua1VL0!FB-&_nu$d $rs_ΏƉxO/?LϞ||{|>yx"њԼe7^Q-RAڗrGyFQEtIsvAmeGrGLj ݛ3qgNӄƏ.p\] .">x[nyx`Q>.rC$ȕLՙ3UgT%@T% NK"NK"NK" S*LU2UeZjaVZjc6jL՘1UcT:RD9RDڞ':-r:-=HuZ LU08Gf;yV~['40P՛8`zj<}~ _NO/߽^~쾽tp7Oϻ_]R]/堖A;.6R?R+eY d)R"KEYdYeAYVdYeC Y6diҐ!KC,Y:;Rػu"oGjb{v2H,Y t5OUKZ[[ݧttsu8vΏY Wbp_V^vUv"{ֲU]R,wǤ-\YP˙3UGqA#ո R{ƽQTރ(gT SULUjaPoiQ^3 -\YPn˅L՘3UgTcbʑjL#yB11H5&<#՘r*LU0UeT*S-L0T+SL2TSmL1UcT:SuHUPTcbRy(G11H5&\0Ua,dO996L^=2\^ǓuŠc!?=L>#yvulXNdeYL"yL"Fya=?^i-o_Sw*bWQw.P_yvoWݼ;˅N8rCyJ,W#8rgPT SLU2T S-L0T+SL1TS5jL՘1UgTY$#8DT,ʑjE"yFq LU0X(fd/k\ib3.StZ+|sǗǻ??7[ZQJPC^<׎}wvAI,o(c$q#68OrCy'<\XT:SuHu3R퓜 S*LU2UeT S-L0T+SL1TSmL՘1UcT:RITc$G}g:'9S*LUjL.N,6̆!U+/_=$R[,_"t7xݠ+]0R;y;&QI^Xn$1H5H5'R TsF9#՜0UaT*SUL0TKO? ՊF6ZP]QjdґK Rb)D,%˾FL,%KR KA,Y*TdYeAYVdYeEY6dِeC, YtdґKRbXj"fbXj& KAi)'r :=f]q¼c4vsjS{xߟ?><<𼸕M}]wOe峜_l%ۮ/[s;CQP^Xn(;i(GɅ S*LU2UeZjeVZjc6jL՘1UgT:R(G1; p#՘rQT SLU2T S-L0T+SL1TS5jL՘1UgTp#՘NTcv8ʑj'yF1;LU0D2  iXMU49ơ?</gxK͘YT8l,W;cد ZjW: ^,sGyWP$W7~ɅL՘3UgTc<ʑjL'yB1uH5Γ<#՘:r*LU0UeT*S-L0T+SL2TSmL1UcT:SuH5Σy#՘:rSIjLG9S*L5NBIŦdx6NwRʲ83__Η^KZ&pxtM܀߄!g|zUY[+[-G1X,o(˅YTS5jL՘3UgT2#8YFTdʑj,C9Re(gT SULUjaZjeVژjcS5jL՘3UgTdʑj,#yBq H5N<#8Yr*LUjϐonm+[2~r5鏟ǧ(?׏^AM\?P| #RmeqDjz}> +}rCyG\YT:SuH5(G1 yB1@9Rqʑj#PT SLU2T S-L0T+SL1TS5jL՘1UgT8H5$OH5(G1 yF1@9S*L5CGwqD/W?.vzBo/eӬf<1sNㅅO~e:{#+]nmgreyCy߳Fƞ5ʑjYy`ӸbI }Tc #XT SULUjaZjeVژjcS5jL՘3UgTc #X (G3R/PT SLU2UeZjeVژjc6jL՘1UgT(Gʑjr_<#XLU08 F]q^_y[7)N@/%q)ȕ~l0lB $H.,,wB$/,7B$gT:SuH5!'GPTʑjB9S*LU2UeT S-L5ĭuu,#j#u!jEu#u, jA54dґ8Djb@e "5A2Y d)R"KE, ,Ȳ ˊ,+Ȳ!ˆ,lҐ!KC,Y:=&q2XqPgbGyH,Y d)RZ[▚fmv@ ń.].TX -G  rG [rL0T SL2T+SmL1TS5Lՙ3UG Huv† /,7a4ʕ }r*LU2UeT S-L )%\EZP]QnFjKVT#KG,Y:q3eAeIM,cLjbeR#KA,Y*TdȲ ˂, ,Ȳ"ˊ,+lȲ!ˆ, Y4diґ#K'1,&5A1!1e Ae I,Y [T,MCAvu8n OS.U~|>?qv66y |K^˕ m`QnLՙ3UGYTe@2 UIHURT%#UHU2S*LU0UeTZjaVZje6ژ1UcT:SuHURjB&jFf*LUjֶ< Ք cvivc[9tCTZjaVZje6ژ1UcT:SuHurW|| 9R!GC7LU0UaT*S-L0T SL2TSmL1UcTSuLՑ| 9R>t~qbXw/IV>yo塷}oePX^Y({ (/,7=+ S-L0T+SL2TSmL՘1UcT:Sug2QT\&R(Gq>M3UaT*SULUjaZje6ژjcS5jLՙ3UGqH5NvN#8IT'ʙ0UaTcy܆Jg1lN=riO_,Nsy:~b>l\X^Y(̓ߐg7L՘3UgToȑ|T7Hu>~CT7LU0UaT*S-L0yj'< uArZQH}9~C-F,Y:tb9&y̓P<יXo KA,Y*TdȲ ˂, Ȳ"ˊ,lȲ!ˆ, Y4dґ< 5̓P< 5̓|lY d)r6lσ_lXPV/mrP~9~K,o(%W;/oə2T S-L2T+SL1TS5jL՘3UgToɑl'[O]luxoorO_s~|;߿oxLwt~vj ]l|n(c< +}rCy㡜Vژjc6jL՘1UgTU(Gq.ʑj\r<#ոLU0UaM= Vb7)մsm}amjW}\[osE7^nylP>"wC,o(]!W;gWnș2T S-L2T+SL1TS5jL՘3UgTίݐ#R_!G+r7Hu~E S*LU2UeZjaVZjc6jL՘1UcT:R_!G+r?':"wCTW~>Hu~E S:"whn~Eb+z}n b~a1MC\V^oCN߸^ra(cJreyCy CI.,,w0LUja04۸ۆ:FTWT;c j#u ?AF,Y:tb9;AM,Q:q jb98AM,& KA,Y*TdYeAYdYeEY6dِeC, Y4dґqX jb9*׉XCJPq@rNY d9Jn͇Cɘd׃:M)O/>=<>ǿ?_z~|GOHu>hCT S>]l׆7_z endstream endobj 433 0 obj [ 432 0 R 434 0 R 436 0 R 437 0 R 439 0 R 440 0 R 442 0 R 443 0 R 445 0 R 446 0 R 448 0 R 449 0 R 451 0 R 452 0 R 454 0 R 455 0 R 457 0 R 458 0 R 459 0 R 460 0 R 461 0 R 462 0 R 464 0 R 465 0 R 467 0 R 468 0 R 469 0 R 470 0 R 471 0 R 472 0 R 474 0 R 475 0 R 477 0 R 478 0 R 479 0 R 480 0 R 482 0 R 483 0 R 485 0 R 486 0 R 488 0 R 489 0 R 491 0 R 492 0 R 494 0 R 495 0 R 497 0 R 498 0 R 500 0 R 501 0 R 503 0 R 504 0 R 506 0 R 507 0 R 509 0 R 510 0 R 512 0 R 513 0 R 515 0 R 516 0 R 518 0 R 519 0 R 521 0 R 522 0 R 524 0 R 525 0 R 527 0 R 528 0 R 529 0 R 530 0 R 532 0 R 533 0 R 535 0 R 536 0 R 538 0 R 539 0 R 541 0 R 542 0 R 544 0 R 545 0 R 547 0 R 548 0 R 550 0 R 551 0 R 553 0 R 554 0 R 556 0 R 557 0 R 559 0 R 560 0 R 562 0 R 563 0 R 565 0 R 566 0 R 568 0 R 569 0 R 571 0 R 572 0 R 574 0 R 575 0 R 577 0 R 578 0 R 580 0 R 581 0 R 583 0 R 584 0 R 585 0 R 586 0 R 588 0 R 589 0 R 591 0 R 592 0 R 594 0 R 595 0 R 597 0 R 598 0 R ] endobj 431 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 433 0 R /Contents 599 0 R >> endobj 600 0 obj 15345 endobj 602 0 obj << /Type /Annot /Subtype /Link /Rect [ 436.929 456.406 505.647 465.406 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 450 0 R /H /I >> endobj 604 0 obj << /Length 605 0 R /Filter /FlateDecode >> stream xɒ۸_ 2U9xfejJ4E\,k>;}}m<({'OB*/_4=D$BqIi(  RtAsR"Z?C~}OXS];%{HAOA=ocX^E aE!rA)>nd=04u{Ba;4jI㒆8LRPqXj݆ϓ = (!GY X2 -DXZ5˙zߎ/٩Ǜ\x[\Zm9܆]~?njSׇiyp$%nhJO $67Գ/Sݳ Gt69&lj֎JC#A)ݸD_Bu)gO/ Gq.ɗhb lgF!><]b xIDy## "B)Ŗ%~x7$iA0Z៥I z$џzfa#$[ SLrKg}#(/Q ۣYjY­|4 2Y%ꣁ q,͊ `d/,IG3#i)٠ϐ&:a[zty)YXc/]:U4AdDј"&<*<q kU<а}+_jE8؁on81 9[STMɣn(1 5O+'(A@B" 8#l6 @]t8q1Nt 1[ 7JSէY4{5H-vUBESG-Qheq1fW w=/0,hyv*>?Ӄ ."ݺEY_ C}EL[V䀹2w5mɅMWP4|Q 9Rg'q09.kNs 3A{VW ̵h6|;])\DyنjBoMDI"ς-d>~sg L7] F x=ߠf=h}aGy׻ S8̛z18U=Ԁy59Q1xm+NꘒA2!^ '(/_X%[XJe"þKU%&}tPJs;r(&da*E 6?_X<[9(_yk1%T\krƉz/A:ZfXT i-FBp_=î_=w] -z0 {eV&x 8luҸʜy;ByrCE2mo'y(eFٮeT*(ڊ2Mh1hx;c2D-u,؊yV>;rTEhN6tQ.򪝂"d Q8fqQW2,EfJR$lkc}q+/ ^b ?^5w5kU~@oߍ0(Ao0On?vkxqC2Bpʧ<|i+o6߬Sװ:pVۀ=lq%0"z_`/G6:s6ofq 3;,44hŚ3QǏDTN@M}Q Qm}*rt9(Szhc?Z}Dܰ*n؈#7B\a[}.uZ[ɛzEBbCC2> [L?#d lh}HM۹|S Kk] %$zt+TrFeط.>^SQcwDJjK>z.Rk 7_F9 AÙ;o1Y lDS(:Ʊa#1ۛE]S V~Ϟk(׺i!%p.'`* 6Vg[>w|:N=4A:>-Ug'|H䊡|EC@C4碂^|ꡄ0J&#I01K{iAt-XܱZetr<"a$t$[rVˏa,@j' ŝn'Y~2!JB˽kͲ. \\Rz*$ roW=fIx&&ɼm7aO, tD1i CLpe ߡ24Q0k}U"E ImFbdA=#ԣ+JVY~U NnkT%|B"`8K/ SReT^2Gm?W|XDz5_2 [ *JQ-G#,'h6|CZbP>ЅϩH" endstream endobj 603 0 obj [ 602 0 R ] endobj 601 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 603 0 R /Contents 604 0 R >> endobj 605 0 obj 2815 endobj 123 0 obj << /Type /Action /S /GoTo /D [606 0 R /XYZ 72.0 769.889 null] >> endobj 126 0 obj << /Type /Action /S /GoTo /D [606 0 R /XYZ 72.0 632.465 null] >> endobj 607 0 obj << /Type /Annot /Subtype /Link /Rect [ 322.57 668.22 384.23 677.22 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 135 0 R /H /I >> endobj 609 0 obj << /Type /Action /S /GoTo /D [601 0 R /XYZ 72.0 769.889 null] >> endobj 610 0 obj << /Type /Annot /Subtype /Link /Rect [ 288.157 645.965 361.161 654.965 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 609 0 R /H /I >> endobj 611 0 obj << /Length 612 0 R /Filter /FlateDecode >> stream xXKs6W3g"̱yMzhgzs`(JT"L|")Qh@rw߇ł S0c,d^@sHT.)M %lT%a|F>qb  &߾(=NPz&t)+&[W'ky~T7G>ӡKƽ:p.v h:"Zꁥ$Ga9n29Q[7D3f_ípowc.Tj/WT9.8d')pFєR:VkUm.%iӵ`ڇ§0XDZ 3ۧ>(M1tߦUZ6B.5y 56m %b8)pw*K4zhŢvM>ǮX&=r2)vmccU#P`3 [A"G-AIa\Wfn| Uf9rlC ymӀ2oaն۷:N[d;<ٮviMHD#KKmᩭumq]ſh%V686!V0k5W l/ǼBܕ-L33 agm1|v i\?QL?g{ R_1g/#^Ǽs槨b{7<86|?D7hbȫ= W{dvfoM0SO"`VL@'! TOm@8O&'JP*v }&tE r{|Qmb A.~"Lj/VSѸkjSגďkjJR^ʏy*ᡀYfF0(:0R\N;Ɔ*"]#a;xn(DiTk[$m@8=ybmAQ )sN_txƵ{iʷvNG. endstream endobj 608 0 obj [ 607 0 R 610 0 R ] endobj 606 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 608 0 R /Contents 611 0 R >> endobj 612 0 obj 1324 endobj 614 0 obj << /Length 615 0 R /Filter /FlateDecode >> stream xZ[ۺ~_A/Rw)NAt]E6(2m+K.븿CERo9y(^fsϷ+Pu$%wI?C!u/'nx!ٓPHJ ?wW%o|9kBa\lu{MNW⏒됸6ZŮ븩GaAJRGV{E]mmՖ-Hce#k|%?^F )u_MςEցqP4ѧ/ 3qc0O#t&,5e[/yCaiIF{l헑Vc8D{v<2^肂!o7(ԀǢ_}V)$MhΓrɪdKZZJ]ѝ~Dכ] ( B.:,!H.,Ug;Z E!^!fUi#1c^PV6,[gXjљK m2M?TpW5H:;qɊk] K}Qn{~rac 'dKnkE o?-{.ĝ 4٦C@9kM_ffZ'Fx"o kĝ(AW:=;iǾM=$gȼM,`CJ8>F"(O H$Dnĝ DuUn6Ppuy"#%ԧe~a^xAw-#K(=Y۟a˜Anc?s9)O9arYdn6SE« H`sCdnݾ^Q]:o O-B*ܨ*yMb꺱mW9dHmYNibK!cB 'R"K/qP˵&<z.{dPYŠyC<*b Of0&<͵cr; ծ@1)µQA@}B̘ 0wl ̉.dtkL &q!ZﳓX9eiC' 9cχ^THL\x՗Ƽ.ר3f*姝lHNa[vF`]ߎw^N0&ܜ /v1|CS7-M& ޛ`1XżA5[ *R^^OHއD 'Tp]gȹ..'|^cNxA [o=Pf A=#ΌРt /NIE: bc܀\\APE6s?B8zeeD 61d.ZKL7#7P*+Ǻ) +[kt"\WA8zFӪH@\Y m_tϷsM.j((~7,F303Mz/uhGK4TVFI!B~pʓY]ZO qlcٚC*.%*KseM^4^?ꕲutI|t?lrDHBXZ3s޺ )TfySސr?2hr9f{`dolYbp,}/ @91*[0 [\Ы@uU؞aﺔQ`RWxZ vP/ta(ȁ4ߗE;5C괬6=!bowC(שKVGH;*+Ee!Pi~$/H Vj*Mv BcTкIÉ R8=iTM_)-u[~ /NtI~cm!:P ?`oъqQC5,;r7 y?qH.(LSBIuH;ol[ '#yYȧ'x!tRHhuga͋c*FH*e[F :zOX 1OoQ3Y^Q%SQӞ+.NƇ mKgu=ǍxCE}772(O]XRCK==[$?&GCSFt?oW}x߽ros9`k, n=3U⑊-I% endstream endobj 613 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 614 0 R >> endobj 615 0 obj 2740 endobj 617 0 obj << /Type /Action /S /GoTo /D [613 0 R /XYZ 72.0 258.889 null] >> endobj 618 0 obj << /Type /Annot /Subtype /Link /Rect [ 188.35 279.389 259.9 288.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 617 0 R /H /I >> endobj 620 0 obj << /Length 621 0 R /Filter /FlateDecode >> stream x]o6}K`ERiSܥNE[ACkBFfm~ II䊔SόfFጜ/39ož8Av(" [R`!$@[tL Pe4t:|32xQ.Ti O9h=i1x A b7!$(IA-pzYlb9;G͆\U_Yu-~]-97  Evda= I k=Qta'i@GG> QiE:/z:f5~7ƍb\$Q#UbMw;Vw::0}^t!5T$b3xzl5~ݡB3և8z+ rL?!:gMa\WtQ: " &znͷtYO͚aÞ;;Sng!4f܉6 7ooT)<A閝+H}Ê:+5F˺۱bif}#;(Dsq[NV7Y+bty l P{z.92sY\;ƴzZPء])m#wxfKr;:ŒtT%t실Aak22? ,vjf}`S$oR@׬"J!m%F5+@nKFWt˧g :bo1LaQ==cX(kx~Fq˟^O: 'fb e0+[~8a/F} _ Rh'p(:JO,ߖEϛrКESĞE,rR~R>ͺvs-};n\uj+t)WV05G6Y1 'hnЬeUniG:p19 d)>Z B٪4?d齢E;slVmYp(;#ݏy%|Ȧ[=FpC>pm߶1w~ӾC}EF =Q Y>ibdEdn y&lb%yfzf*~3CNw;SeR/.uu0M_wYq M QMŏm\]+.0eC~wsK(Oq?i}iS#N,ݔpk *t(~Z1G2?!is>K~J_|+i8XCĻyz endstream endobj 619 0 obj [ 618 0 R ] endobj 616 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 619 0 R /Contents 620 0 R >> endobj 621 0 obj 2420 endobj 623 0 obj << /Length 624 0 R /Filter /FlateDecode >> stream x]8=B=t L\˶q@pb׉Ĩm3DɖmNIQDR%>Y_iD4Ȯ^}tJ&1ߋ!0R)J@k jV>')^VJM3#ꟛ՛_>GS,aCFR/ 2MM>޼;<۲9˹ⷤ?rRxן?{fR }@Ix>&d$ln2ҕ!Ҁȥ sPx}ZaoۺF뉘Yd,y$[Xwȕ@5]1wPyɷxpw/oËQJ"4i~O^Nȍ]U7XԊo[~(0?:bͫʀq6`G9` c\f I*ږyG]ZEUsld撽ha[zJ /DkFF.y_q˾e`yS |N74!})GFyqY'? O?;Q@k|ؓ8:wsד-YeRLg2O =_4qJk.Ӟ޿[0f7kJ~0a;OS`SPO MyZ' c箺`Rs+Nh܅iOj</Ƭ-VYL4ucfϡUM#FEČY*"NjA1gUC[`ԡ0rZra `8cZRΝ˴*_ aB=|h8{3SKz-'+>!I/kz'Q9p!8cƘ4Kآ~TOg*\# fuRl#0Ue"p\9rW+90w.8r̉7L rt:AԊHmhT>g8q$$bc<,[^F&3Py_1yzE@SGBx'lx1RW҈oϒH㬙KcfXcS>[7>M'[xCVw%>49.?|㗇xëW*-}"{X¼8_}8/, FA;m*!brXnۊkw}1EcPx?-W]41 endstream endobj 622 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 623 0 R >> endobj 624 0 obj 2147 endobj 626 0 obj << /Length 627 0 R /Filter /FlateDecode >> stream x]s۸ݿoqf$qq:M@dHAѿ.$ RAX'.7ǁ眭v|EA%G,0a;vJX{A؏h-[g^|k̇}/ 'G6?|>{C-6VAw <} _ħ0J6 i-^#`Ϣt)(PDz X-Tao& =0ui::АO&$ G oB[{|=6!$Eh8O ^3lJLm%4N[?--9",zЌ|$'ʲW[)v +jvek$K ch-> @\b؋B0͐ o:&5h}:]]۱C-ņ.{Q3mrPD-6rl<^mG]? i3'J2pqj@߆ZФakXoj]ic~619?֦ʶ^{uhޛB?LjR>REY ( Z`RFWEa 1umVwp3pid/ ]|XT@ z9s' °:/sب$u\+¢o6ҙhF&8o2u i%q  \;yLCN Y@"z^}wv]2e8 '*$'<4x͜\VuWQmi@T,Sd}_ϻsLXWNw曮on@ AEUBj{?o38OyVywP#o%Z+,V\IVH<.>?7g2ݡ_o"B<^JɳP M#`iz -l=F0<@j@ء7s L`8TvWWu}QO T֙o P^@ 5sXNAgsv4#CҊYr!n)?0v@՘,{3t0*Gڊg3. /4 0"C/ SY-C+'=t_одv _€1ǩ,ƹ6or֕KR>%B,DVs{4֏jY"ATv۩OPg~s]4. endstream endobj 625 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 626 0 R >> endobj 627 0 obj 2874 endobj 629 0 obj << /Length 630 0 R /Filter /FlateDecode >> stream xێ۶_di &AРI(}%fIޭ /آ[҇8Ù\~[+''@~ͭS"0"Rvf?g{ߢ?"@ {r"`nX}^|6#mH&&A ( =WU~)UQ>q'JSՓnF]?3 h4"Z(cX:Ri^~Kn$`v V0әl*oNj ncE 'g'shq+T)-.t4UVGr_;:J2H\6In-!MZv YésTdvt PIILq UWv]~Rnf9,_S Ƌd`" |VU]?ܼ0TRwv]*Wc7|q^p{ʾf!` : ޘ'f_K$!&%U6s>i@rX^!C,pݠJ3.&hs;YbMN- ~!:H YL[D}Ǯ;X'>xe\k-uCIvi5V1w9w)-RzXxrUUŻ#SZ+RuAZ]'-vLD=d&Vn~WTɇ[̽݇? 8b0+*l3尿7f,&JUuSO?M_% TOK0ogLJ N0c32q%Jj4/+јp9] #Z=C᝾8x?2)Rn,GhVBdbmiJpz>wE_1$j(z|ReW' ^?_c}QpI7px!$'ZnJѢbR ?j`jHˣLeí-`RB[y2K!%0ַa&u~idգ?bЖjK-Kf;mZ wMQm;MpO8C, 둪 vBYu98Wr4HUag?X8Ph)$CrnƦxNǝ.|z|m88 @1h/S}E{%rY?bdCcdwؕ#R9ߏD.~Pt$aQDmlLT%ÂG2P +->>Ô2JEah[)gYsIGlW@~?/ IW:@nF݁_Tn=ظnYցm!llt.ͣ/\+Y{%ucߠr+escj nÉ}M ݛ~X}4/jcQ,&||J"gq?4 endstream endobj 628 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 629 0 R >> endobj 630 0 obj 2682 endobj 632 0 obj << /Length 633 0 R /Filter /FlateDecode >> stream xَ}oY@6XRv Ao7g樏]O>E>f,I2eYEVXW׍OH H .cY Jfhj-/-G|TFPўё;^O-Za;()b~bT!9kh5dMݮ(Jf q1LT{H罹.끁SXAL3xQ=>^lB ׸Ys~xk/Y VVy_D+T?NDv)NB_ Rrh,o pc'bo0GWOb^ZU ꀓ4;gkW*U##EY"W7pp9, E9\ Y Xs!H 1IC@n5ߖ3yB{?@";ѡ sΥUsvGakh8Rx:(Ȳlvmo4jDoqFNEߣK<fE+̱I+r~xԾRfP'V¾ ڱb;6?+jhB=RUZuͤW:Z$`әz"KCם Ј1+ 6v6ZJP]c)6fdcKB8^w|G+"E!M;b2&&7>}v#==.;.n| mn|k&O]׵K ЏS 2H(F<$\J&O0QLJMW(. i쥰)1 6SB ,NiEyĪq ̛ܡ)& ⺏XkJ&+KlTͨ" Up:SɄѮ2y0lwcFlUZ$"(.a]j`}oWl#Sw[%_;`{B&3c; 3 t֡*c  ˡn+qAYjc0Cgs]\hTJd&Rm•J@t0h@C/zލjk e_lh5M:nDA6H@ŞHz1jœ;s($fN/Bp4^!/~Yb*U 1 D̟"rABHއbKP r}棳Z!Jd řH» TEǗ#'n.6˕ /ʩ( YGrzޜ!5#B5]MCѭTIQN> ̓@1;a| GW~EWID-fP i 0Ƞp6 ^;-InD z :yiv;e~s˧ZkC:6UKϷج iBYOiO=iP|ZrJw9ckL ( QPM- 7u?`qߔ29 :oL8|4Y) -=M_]W E|XA8Ig",WW|^Hsq¿,yȖh,:Oa2G(=d;Sf*PQuȴvB(lܟ{Z'# Bfyf^H,Z`~(9j4Q9"؎K*dPGod:O P3sEU˵D_j=pYyqV4i/)X~m%WU-ޕzO2l'- "2}hx '{fBGIj'> endobj 633 0 obj 3319 endobj 635 0 obj << /Type /Annot /Subtype /Link /Rect [ 426.31 655.204 492.97 664.204 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 617 0 R /H /I >> endobj 637 0 obj << /Length 638 0 R /Filter /FlateDecode >> stream xY[ۺ ~`/3^E]6ٓs6M>t<2msVGq}A"%[1A(qId$u/t]BRPHr3 ?w߳r?`Κw+QO%\}1{[HKbJz.0$q|/<(wUۮI$ o?f|u_JE4 8v\ ѧ/OBoŎ+ |TF~p Q/Zm=_Fˁ,J4NS$HLkX,VR[VG">9><&>z]8?+z.|OCQ|wȓIR/<0` ^*6Y ă9@[MZ}4 (!3ײ-*!oNY혁nؐ,9/ݝo 8v8p`, )HƐY.v̇,y֊HsÝɵe9acz}%_57wҥ%ݞ3xi4$1 ӵ+Sy~$K/p\F?InH)sB: TQ8{p&X[ϛOyw"MU8i6QD2 Ru`\bZAյ^Az߬&=T  WT)隉8>pi}"xBJ  Xa8' \cre`usqdT\a^Y @JJ]h&|w(\+:}>ps#q{hnG. mkŪfqnGDyaKwWVdވo!(}ք^&cr7Y;QnNPjR 5gG!}:.jD}ݡᛞХuhɌ U{Vhf`ՙp 9\hgB <~)^ O|3EϾ҂EVA'!2`˂T]^ &EE_u\!pAmB$4 $ c])A{2/'ʦy PW͖zRs2@sFD}[Q>ZΊ\ıIu8=/rmh׾+ė CsaޓgJ&/DTʃO &BQ`ee țV+zR"[H":;]Aj"?u'yP'vzrMV}ka_Ohջ*L*pt[aNDA/'zG( /iDn&q^Mg0#HEĬl3?;,Z|x` 4p;4"aaT;kNlLZNkP$Ӣu``oc#ms{^["X!֗8Xd49X^(s"sbzqͧ'W|'M $_k,9@VH(2=B! ?èM˛VS&KO :TFcE8}͐48)MG 7}[҇0%C y/0Uբ3P|s#zykxҫ\KO|ZV;|Aךlq,^De|tqd_ϵ >ҍ h l XK>My@FU0H|H="Lt |zEfm|Fu.(?.:i{-ME2sR/Ao,WTFPQo1p{{f9>kh,{E,#{a"gR#Q OͨfnFDi=anڲu,˅,JN,9Bd*'gy~/uu/I٪lC-J^sJBOCc=i.v5S{"(? bZOB, J=SϪk ^pgk=UQQfEnǶA!=M>@_ G?17 endstream endobj 636 0 obj [ 635 0 R ] endobj 634 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 636 0 R /Contents 637 0 R >> endobj 638 0 obj 2681 endobj 640 0 obj << /Length 641 0 R /Filter /FlateDecode >> stream xT0sL]m`6jV[U+EjUYC__0zLryof =0V8'@@}F1vxP!oz# juwt0<;of X| t|K0Χy@0ě~Ą Q"KG!.m2F;%Aqe W{q>ǃ/ZF acO]Dr߲-`1d FY#:v͐n@WEA-yf-F^ 뢽ptVFlW叫X)o#V\Au5xE!~s(␤U%NP+b"{ˏ;$W2Uh4vIZ|#CJwLOC6IUL}|bQO(w9xyCZw=z ^/]23uX܊4<ա6zaL_Xk#Q>q+ĶLr^Hdeic6R^ez> endobj 641 0 obj 578 endobj 643 0 obj << /Type /Annot /Subtype /Link /Rect [ 332.602 470.85 408.289 479.85 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 645 0 obj << /Length 646 0 R /Filter /FlateDecode >> stream xْ6}oa$x3NnxR(H2f<@xy0& }tň?qh'dW\}2xF"NРG.<',\ Qj3 |"\W꯿aΞx[ Izf&[#ǫ^y`UBD̨O 28wQZo":uoe`cI% | c׾M|+yfUِ<kuz=I ZD>zqCVfj+v:x3aYނt{cǓ~uU½NyZkDDPL[ qY{rfY@7$>M8<6:*w$&&傃Cț=jȈa44#F#wnJ*2մpϩ﫜gHt+!cu!'D^.y✶E 3PݔѦTBi$;drW]Jp}t&Ց)"Sx[pC'WH%70 tGJ$!!eK:Ks, $b1`,Dߣ34ԇ1b:k@:Hcr˹s sԘ;M x@#dmrFtD8+iqJ] 5SkZL4p,ޥy"nBKfF~ zD=쐁?P,< bd?RF8%/u |O=y'\C*!PTEA06 ܊:.r q-I-dc҈]@"K,6mmt=ם_Ij dMB &T%`*s銦~Xsr1K;9[Pgd+^hd scFSti~X8]AxpȦΚ}@{rxΩ*03kU}GI.蠹F9s&T e:+8‹GP*IStHw}X*t%!0'q쭇ɼ[*bKZ=NaLfj4m[GCO"1{BH/ge.3]$C5cA̐N}6}{3R'pf$dT%]CΚWcRS^<ѥlr~AdRQOwp bg)K#8iicro!>s »}l.E:&60n7yV,w%lGb/ Xm>̽*~$XvO Cxmd] <ԇA鴵e9‰ )+rFۑx0v:x{mDC*mJPQ`R?(G&H @Dž'Lm5M [#D"!h궻ј1GC[h,TӦv8ri\; |*"(cD,&WkB}vD8C˗APP@x-LPe4/Z 4oHsR%rWA1|%RD@մ<[*۬uaHf ŶZ&pU/y[PwpÇ4EŞ!]-nhP$\q0|9S DF9j*"*+$b̆7Z3Z\ 7{J/Ϛvׁs'yͬS}`Z/yZ[|AGF\挟)YH[HEc7 hvrA:5y(dmj,n<gX[,yuPj,h.if}XZ}vcc,c!bh,[co.mE7cd>;fx#p$%p6F 6ٯ5,qWHI)/X @{ӥvsc .UΗNepM֔Ccǖv Ŧ-$C)Gy5.}h#Os&il,FIe!?A v8tU]zΝ.;r)c"޺4Mesj-:Hk.b󹻐PP}vo7O2JcsAZ\{V-۔?vPg8U5^*BD4RH_똃Jz 0r)3v6(>Iz3}Ǯ#"vl/ӽrg"CkJ $tJ۹%w1˳{ppnmvj ^Ä t?تIUAQFj{vEȘ2$3*qC FBwE\ endstream endobj 644 0 obj [ 643 0 R ] endobj 642 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 644 0 R /Contents 645 0 R >> endobj 646 0 obj 3265 endobj 648 0 obj << /Length 649 0 R /Filter /FlateDecode >> stream xV]o8}WXmn'IvCKVmUժTW&ĩw bv_>0c{f9| ,do#p-#B%jBQ䙆k{ 5l%xCvmYA:0ά qy&ymV;3fp; gL4_[#m4-cF_>0)Кq4''<1zlq">t~1M#n_K+Ao<1l;t]g]/8j VuUVyy#kvۀ;߃>0 z۰{-q5)}C;^v_QV2$ $/ fxCӍC# '4*U+劊eSkKsLSQ&WnFx\"4˛ >U"=j6"ސ&|QфY|(vy :F$"W롊Ɏ5PAN?qE(;zbquolu9n.8mq99JESuhN:`p[`+{'ʴs֘+Kwrō% e*?4KM܁ؚE%{&Kjxf_?aS"0JPeqAWlN JaNX\kXy\*߭H3e,!S亲D3P(qx*o)/^: 8Kr^xGWFpK6Eɢmv4G89e I)fr"qDcziny骂؇\ A+HhM[\UII',g 1K{hRV?%Bo$224A."!iѯ,T+#EW:F`;Y*%?Nօ:: /UN쇸:E]3v`S5x Wad՛! Ot~񀿄 endstream endobj 647 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 648 0 R >> endobj 649 0 obj 1210 endobj 651 0 obj << /Length 652 0 R /Filter /FlateDecode >> stream xMۺ_A=lBQAQ/h@Co߁h[XIt;"-9gs̐ S [a)7CIHRB%F$ܒҨ3,?7{?n %n~T¹ˆ>`Y}|d3%( O@%~t%'peŗYJX,Y{8 BPPtEo(<>Ԗ)KúO#%/L.3E,9+#' n[F/w”\a1ڍ0`yF)MSGѓ< vGA>neCR cA'h!xFqX7X=I,A =#6M<uH&Ѹ1:D܉CSǮig*戗z;J0@2NÌQѝb1 W^"p%iȵMEkm)0lmre+.yn͈ɷ7x%|gF~KW1,RJä@ Zن4 %K1`{]'&OPF(:ң[}c}s՗c]N /sg 0g 0^xfkFF ;3Y,ZU Q3R@d1hύP~!gCB_ealYn:!ewj c %1L:BS7]~:m i}mXy D+:yG)i$̓,IW8(1WhiӄG4(/^3ݮF XME)☰ |j"{>nJ\pL;:r'bw '5tT\k(黓52),f:+U⍣vVϢh1}XR{ ;pA̓xEIa&<]9&v#VK@ck:Ӊ"+6+VΓťnxP- zYH-/Oϖ8Lɝե A|T4%'QYDW[ciD?=D4Ȣt1E*gPlI~~%D8EcAB^wP4/NL pPY TRHIg>[@g2aj+ғ7OF ]楫C h^lk;E!둙ˌ/C4[h<6,28 VeDksp2?^487Q C'>[+[ n0mcf !וCu}v4!ފ ;%vvel1[b zkDkh5uA&W%ĿXT8 #1)4y<evocubU`Q7GЭApt4 *HC1dmpݟUV&8Mfz"Z| X&48 g@c!ݢN"oJ H>#䎏Upwp/4Vu &YMzM 7E, m"h ]x=n!LKk9VYmOl[!QwP5\K|FGEe8]J<*x> endobj 652 0 obj 2227 endobj 654 0 obj << /Length 655 0 R /Filter /FlateDecode >> stream xnܶ}hB'@7n\wWVr$m\r(m3#r8rlRICiF拦3$5)^G#"R=@7XS 6tbasȦ#G~nMD%w;k3?FR/%H~ o6:rSbln~Y K4*RN$I<5'{KWH #?t(UmLY:FHL`PL >y(\0bŗr+ =TլlA@'xȖw*ksYoyDۊ!62DUu?xY[BűqVt=o{GWy~f[?VJ=H18,,q_`q+ @b NbvM ~ -]@׶PH |fsyu rU/S7W5 Ǫj3/4Ѥ`7͠6]h𯼬Gar A|״vV ?r^6#b<+#19EmQ4u[] @t%9ry&3cyQRʒ9grd)x%Kbα|#țXc-#C-lA蕉ԁm*q8m=Zjps4 -Ɖ{HH Ȳ8J Qh!Yۊ:,> VMFU D F(@?ݷrWC!v9rb: E. elb^]5 rHT5Amk \7x &^GYɂ0S=~K0d?d &H(%RlQꂔ=Q9Ga]Y߲l z.xcE .KG}=e^X 'ч~+V=@w~UiwXhq@%hhll-+9q}YZW%6c㞇5wA:f 9›50S[1BD1/+Bڮ쎖з~/7\`#ƒPlK`;vR'7 6[a`"O*H`YSo}tbFוF¡*}#3VX6)Ji9]jDAwT}`4N/U&^ #:`*iX vKGԃNY,1[  H*yʁ8e ;Mz2tov•Kv2t[g 9'La L}g?NͩW)t%}ҌuWr'i L)beĸ I4Tug7G\7pT7D xH}/`8 )f}(!{~y+C͏#"Nw8C=[Z li~˯8dulH]PWr7>Zq1R X.|*>Ni._" |fHpӅtZt( ݑ$9^U˹T#SUt|UxsXrjs0D0/2M> endobj 655 0 obj 2392 endobj 657 0 obj << /Length 658 0 R /Filter /FlateDecode >> stream xn8_A`. `+ 2 $f;8`BfĎŗHIgq*Uz26aw-ʔDeIQ}|3x%Ae8J 43tBST-b -GM=+•/[O7CI?66>d`twp&N Q X t}껚 ڶ=]t&H0JEub'xPQ֞5I{W$49 N0wxqXu?rXW,(OQ9Ųx~.|%zWnW -C/ӨD/$ÉOqıN>;Rx|k_jv*l`w]>LM놳V?#MϾ]ؠtQ^} Ό8RI$Rom[ޅUUݪ7RY5bz12UuSypϝRY(o+kĪOG͇KlgCJRDĝ-r(PgТj^AvrҪa k2KZ>TkoޙDM@g!p{P%n?2@Aeuo pyJ*HAr-ۓ6S֗%cI%@Gfj: ~o,A!KLˎ,~՞AE_!T#*\MpAPei`N1#p8`PHRI* N~^"&{V'Lm$^uw:7L0du}6&P{]p 溮PțѸkCKH࿒H~񶂖zX%Ar^$)RMrN$¥40 T^  iؤ44O,@鸜y=^ :;,eB@s#_ Z=*9{O3=Q!։=x9ZOO.fLū.kT˓.-(F YTo28Z#PybC|$uBJ$O\=NN=1#<8NӀMeIQ9d4 z%,pQsBPU#b|]Iǧ4Mea]ۀ 6-Ht~[;FJ`Ӂ(r{|PdzB_i40ՕNY@Wl;{c֪_uKmrf'[qu"C,|TóZꔿr^ƆLi#gLoFm( 5it4:N)(\=QT;h8tIބs8lcۺ]K9C9|vӪmy)Y-*IDR,=bgeZzğ򉭗΄fQCϚ|'ęK;4`r&Mg>N!ڀ7>7vU ;@[zmB\yJT_w8nե'1ZB%- 5A Ж .Ӭ$iTL5¤aT ꑋ/ʫE (;^QZF$+0iP3B^͠5"iy+_h:僽 >8/s`#-r<,CCye`OۼE endstream endobj 656 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 657 0 R >> endobj 658 0 obj 2403 endobj 660 0 obj << /Length 661 0 R /Filter /FlateDecode >> stream xTr0{LfbE`ĵgz`ak*P"+vζ[ޮj?,""x wE48!CSW zgkeGlcmG/J>! b v8SBZ)]O7#/64Vҙkx,8TH]>g}7@1b6mGi$ NY&|Ӟ2;Y#.MzCGpqͻnYՐF+$Mb-2֮B+uiޙ[0"p3p5Wd9˘ڛzM%3#߅q|0͑7 ggpD{7L=Y܍Հ GV/$VwQsR{8YBD0Ø$dYgQ#mԹVХצ!R56#q4()J.syh{ ndg]?G"zEдϥr]].ȍćՎʝWLG(> endobj 661 0 obj 634 endobj 663 0 obj << /Length 664 0 R /Filter /FlateDecode >> stream x]8}~8-(,[v>W[lsC88ةL;~Xg:}HI)EO)jxq|t@(@f?gsޣOA/>9DaY}ГI>vW(AfqEQ{,R חMR%yh)T=0&d͛/ j#FlNE-n*^ťD$s{fGlfE4g|a&tx38aԧ3 c7KYvFq0?(O8<ˆLOWU:0+x2ں*yE a^?8O7lC&EYZp%yk!$vN֛:9)jWܷ,q>LF`+ fhwܡI,бȏH>6DJ[FAWX! B. :JHӞ:TíJ-[Փ@8r{JyIcOnPо[q1t؋HQFmU1#\!lveCOf:y|d䑣q`Q( u+{}>оB̲!d1*?)ghd# O[{ɼGMH*o2>$sq dZ*` Yy1C*T$ pIC]D8Ln%W61ł17x2 A nćc*ߎki@5p9ahO}yXLz-*졖"#QWKz=$WXW@no%xt@n(/mR_ fP0$CŎwP{!XCtwHaL.[x2R'^;4No65@хs;)M:R bTSɜ7m "u̮5L"pMaF٫kOOʞ|Pُ'0DոDG*^C* m=z`S:AJ?%dd8WIfȔwIS2zS]Pu)A,TEy,FwYYilCqL=սs {QUC1´UgR=;'ijV0O:o>`{& ㌺fvU'u\8P헠~Fv|ϩNc{|w o>^U\.G//oXp/(̙4ZhQ<1ElRlH/ۚ9*-4)tThk6g\Ɨ=sL|im渝WDRMj@!9 ,1:qS1.iZ5PqRExgh|FE8˵3 r+￀BP9ɷ/ѻg1@!yQ̸l0_S;οgՐ$qSl;c@J& =̡ Op+H۵q;jS}: %Os!wrjEt\TE6^'iRŕpe~AU\~-;ՙ|qkRlIYud& ꥺIc4S|x-Aȹ!X_-օp 9zB!fHlԱыG}p?{U6[4qŜ`B6N:8 ~2Q ĉjN{ 8)k!-ѿUMft)?G (_;bH[ X]%2HXCyl@Y9E֎1o)l!. Z endstream endobj 662 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 663 0 R >> endobj 664 0 obj 2660 endobj 666 0 obj << /Length 667 0 R /Filter /FlateDecode >> stream xV]o6}omJᆳkl|x EBdIKR%NS% Ix%&I k?AL . a J\3|' |U3-~u3r\A].5#>.f<Qb 4M#ק(,|S]QW3κ-PuW<{w _HD&!P2EL?ݱYQV|^t q&㥢u8]9 8<9MFNrj̖ɒa_ ~+)Nȅ^MvWuH:&$2(ҩ^:6Vkuy(-nXQl[TnSlX4aW`Y7D{ K\5 UQ/!r aE yEg‡U+K\1a2I2%I#wdQ=5n vh#65+\m']jQchԆ *PU xJ4&/SJ;>)Q5ÃQp]b%/0w JªLt[kQo1f3y޼saJ[B ޔl3{RTuSĦ1|V(u~L܋RǢI*d"*•"A>4\C`v-E,`Q9 Y|+.dռOQ1-15{ܲ @B,PiAN :K? Yjvۚ|Vv\T2zSNjtx?X`© X}C@ڶhJm}u7-Λ܅O5ە{9;k-<>ZMZ Ǿޡ,Y &5 bWQapO+9J }\f/2_i7s>x,@>6b{ɡt]q[beRzeH,.*U_wjJfTWKo1Øwa`sɟs4؇m1-U^o$ endstream endobj 665 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 666 0 R >> endobj 667 0 obj 1103 endobj 669 0 obj << /Length 670 0 R /Filter /FlateDecode >> stream xZK6ϯvTulǕ$J-2Iy<~h(RNFwC?|" /?EHQѪlY(PJISJ%Qh3 .MsC7?uDa =#\zw6L{/0ߟJE}JO8< œ}JyLx~|Z`QF6hZK'ðpn7w?N4˘,2/KD ^xt_GŇWsXn{; Wz9'oi#iEN)2;qN"z^AG?Ub8vU=pO))#,IJy7Tb?pӓ"3 a9y^7Jh<-;A%7nA5OMa'owB)ݱid *=sTCU]c\~g~Uu{\TQx=*@_4yrmz7`#΋oխ=m1  @ײ_Zm>줟W+X )!AXAJeFZ)V YF~dER$цYV^AEfQj?-:l3"|o{N{҇=J4xe^ +XwmxدL_>9śX#vcf =gz/N2$IϘt1/fs]  BuƿIp/):lաvYY"S،kr)tAi0]Af p3X࠸|Jn/rFr^l1dpzfn0#18C;Mjyhh 51*%Tͬ&~G:ʲWeJ Tk-3FƸj{ldYIR A/3Q%Ѵů;aw7wF^ `/<;D 3U3쟈 Œlh2{Z|izUb,ޝYFt wR{x^-K[?h =^{Np]^Lǝ\fMA mláj ו}P/WN9!^ >({S-4IUO?B$1ena|U+cB`2{aղ] MB32 ,>o-Cbt'Pn=GxS_d(Fwءᴝ@cny' hBk1q=gt;W,Rm^ DB}0KiIϜ$=fbw=璋'AMtƴمAÓdf9h~zVv.()=f'AzD/\ؽ4 j['s8gNz#Gܨ9zdj$,8[Ѩ'i'0'm?Npmsf'6v,mcQ%*t Ю? }$!X1#'&8̭F:Ӹ\R"+wa#1 r S$s!Zbm~(DU P 5 Gob+WuOƿ<C0lNcWq+`UZ͝ FAsPrx E/b3F4;1kWĞTsT)Ⱦ+ȗU,43"$t:il ɯA2)1hFpKRNb$7|H\l18fdW3r&ر!}g -xԫ8bk+6pКNYƤ$AB\t9MԎHӇG*rۀLK:W0Nl{ݺiZq Q7+N0Pdh-R4RSU1o3>^Ҫ6rK`} d$9Eu8x.A䳦jG&7Jue~˃QΔӂ 02¥*.j/|IaU<)f$)SZI{rk٫ z?UJ-l*A~ #~ļ!A[;n{+lqD O>U},дSgRF_{ &Ȕ8`]X#q!5wIitV$SUviuUO;m=Jʮ8?"7? 764x*@&88PwY'L/ʙ4_!C^?ro+c#Pu :#ac}5TPDn)~{g럫*PI)>*]4TZ(—e13b۫q$ͩh^yQ\!z$jNyC=N1C5]иH"T_);^4#.¦N?;󵞉RŬ0/A]f-mSݭp7C87=*G9T">`M$FqN gr6cF0J ֦q~%QhZlDi Tc7w" endstream endobj 668 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 669 0 R >> endobj 670 0 obj 3013 endobj 138 0 obj << /Type /Action /S /GoTo /D [671 0 R /XYZ 72.0 599.093 null] >> endobj 141 0 obj << /Type /Action /S /GoTo /D [671 0 R /XYZ 72.0 149.969 null] >> endobj 672 0 obj << /Type /Annot /Subtype /Link /Rect [ 366.876 502.76 438.073 511.76 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 517 0 R /H /I >> endobj 674 0 obj << /Type /Annot /Subtype /Link /Rect [ 387.329 469.061 461.685 478.061 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 365 0 R /H /I >> endobj 675 0 obj << /Type /Annot /Subtype /Link /Rect [ 465.079 435.362 523.275 444.362 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 531 0 R /H /I >> endobj 676 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 423.362 143.33 432.362 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 531 0 R /H /I >> endobj 677 0 obj << /Type /Annot /Subtype /Link /Rect [ 450.83 401.663 523.274 410.663 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 534 0 R /H /I >> endobj 678 0 obj << /Type /Annot /Subtype /Link /Rect [ 347.701 367.964 424.258 376.964 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 271 0 R /H /I >> endobj 679 0 obj << /Type /Annot /Subtype /Link /Rect [ 368.714 334.265 439.119 343.265 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 256 0 R /H /I >> endobj 681 0 obj << /Type /Annot /Subtype /Link /Rect [ 314.113 300.566 386.029 309.566 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 680 0 R /H /I >> endobj 682 0 obj << /Type /Annot /Subtype /Link /Rect [ 263.94 288.566 334.27 297.566 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 680 0 R /H /I >> endobj 683 0 obj << /Type /Action /S /GoTo /D [668 0 R /XYZ 72.0 769.889 null] >> endobj 684 0 obj << /Type /Annot /Subtype /Link /Rect [ 478.732 254.867 523.274 263.867 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 683 0 R /H /I >> endobj 685 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 242.867 156.66 251.867 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 683 0 R /H /I >> endobj 686 0 obj << /Type /Annot /Subtype /Link /Rect [ 346.35 175.469 417.59 184.469 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 609 0 R /H /I >> endobj 687 0 obj << /Type /Action /S /GoTo /D [622 0 R /XYZ 72.0 433.141 null] >> endobj 688 0 obj << /Type /Annot /Subtype /Link /Rect [ 315.81 151.469 382.47 160.469 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 687 0 R /H /I >> endobj 689 0 obj << /Length 690 0 R /Filter /FlateDecode >> stream xZQ6~_ j,Y}"H.{&Όf͌==)Yq )$% MR NIQti"Y%R™H,09K$G=k0ۂ,Ї7Mv'%){I(U}yf=ٗ&O7?=l~ Mǽs1,")HJǒS\)]R7P5y)yͿg Ҕۺߏ& vp$E@ͺbAqт yActl K qp{ui_kƸHJR%tb@fq0m5Ӕ۳mݻv_UyInc;XfQj稡umt<e M% .fՠ`/H@a|9SϪ[3Tκ9g>ef\rF)Ym۶ON9V{`zǨN}ԝt{~m/xQlQThP5$ {_]d#7E斬~u]5T5$Wna:,"OfFc8U +jHUX|L L]H"E3S'oaeK'A 5) MdQ=4jxi/?Wqjᩊ-CC(x$s)~/TUmƱ};B Ti*[;Ʒ$s}Ob72H; IXPP:@*GrBI=d~Xcv (䂢Ʒ&xQƏ1.$^fռڦusjwaV6E,yҸSr>*D&13u)RU2ZХ|*,I*X)R]ͯ2(123ݏNC'2_5qԻqkWXY\H0Cq)X,JϠ D" p84"fqճrfJuNGC^#zD^-ŋ5yz΂ÉK䡸gkFPiNOBЈ?,"(7q^a{X[KayP΄>Z` BrLC†>ggg/ 6 GOS$ /35())?/ډ/ԈTFI%O#AW3%mh8zf# Yx O,_dRd mLP1FiD޷#li+ xThei4"yS>Q'MK=Џ͂vٺLѪPmv6qsnS\82¡ C9p51;)|6#e/H:#Fr"iE #!˙nLdDB-exLuUaDH<"yÈ )h_"#gܸU,;p:b1pw{Vg"ry;r57TFĝwQ?^ T̻%h.O?ÈDDy8G&D\\ n`ʫ]!ov:]ܐA߰c!p37 }/'}>敫N)I]}0i$wdKm/bot(#p2mL(1.6KȰ&5$HMlNq8z/pgġydЫf=X!+J!cd t}!-|=>qϾሒ-ċU1+;z꣆U ̉4e"[UM^"6*4/l&{ DvC}M>:}#61t1}XsERECeG@Z+D1~w53i}&wKN{%;%}ƛf|Ulp:o|G\%Z| cQvWOQiH p0U6]t\ 1'u \_py9.wM['DD#L g|_ ^+a5 UzyvU& ¶| @&"qrWyʧIp7.&|oLBx6J;1Kzpn׾!n' ^81|yX8xը ~N0'L9-όi/(|i{I,jx|ldp.uel&|#BŐ/> 9BRf.0Iӥ>u.0 {t KZ~HճYaڞNoo}9 endstream endobj 673 0 obj [ 672 0 R 674 0 R 675 0 R 676 0 R 677 0 R 678 0 R 679 0 R 681 0 R 682 0 R 684 0 R 685 0 R 686 0 R 688 0 R ] endobj 671 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 673 0 R /Contents 689 0 R >> endobj 690 0 obj 2880 endobj 692 0 obj << /Type /Annot /Subtype /Link /Rect [ 315.97 730.589 391.691 739.589 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 683 0 R /H /I >> endobj 694 0 obj << /Type /Annot /Subtype /Link /Rect [ 138.666 562.589 213.026 571.589 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 695 0 obj << /Length 696 0 R /Filter /FlateDecode >> stream xZYs8~@͋*}jNSSqj kPHʊoK$}M@~8 H(Ca b/LȖ%k,"T9 xC:k|7$>;3/lr?|>Yy8y'+c^_Hů]}W5k [u&zi<{f/BD1<(2G:f{3.$p FPH1DFPy;?QַuO#ܼ'f0+"+ G|WB P92`Vm6$ommIxi5  0$_;k?w+rIs\"73UtŶKWSd?в6 >^( Eq5tH T3571S/J}p8r,~8]^9Lw` Dj/hU{:ږO\v|rp X `<* y޲n[6viC dmMcy.q?{A`dnʺ% ,MR/!"ٕf`7R 20\"DqxORY(a=5- 5Yu[|ZrQeQÕxjbx9ޓWqLSZZG`0j:Ru 3c>Fæ6mJ`Y~F~zXE6YA7`/WeG >`Úe-wo5V)U-aLM A[Vl{SG DIlx$> LG qˈ r #V( w3Q aOU2nvWcP kr^4HH] ͬ{+~<%>SlPԴzOI=O\:ƆzӳP^kE av?5St =ݏ"/̃%=Mxˠt$0F_i"ve(͘Hnarm}[ulq/!}dCzK;ԺqY eg-RSG)8Llj}=)ndeD;ܖжJvrx r)-}]+Q3 6sXI딳rßV:^ӖvRPi Z3{--ZսZJ[>K%^Х@ 7͐uf[!HݾMci8"%'jD*N5EYlj$##)AaYD? `W,sHv|j)Zd̼u1_ENL ݔ™!<]95 uGuQ|-Q| R(K+D q"*ˣi' endstream endobj 693 0 obj [ 692 0 R 694 0 R ] endobj 691 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 693 0 R /Contents 695 0 R >> endobj 696 0 obj 2929 endobj 698 0 obj << /Length 699 0 R /Filter /FlateDecode >> stream xr8_]aSoinٚVvIS[S9%[kITDɝG{H!y' =7CP 6Џ b?B5"TIG~f{?A')ˎD}}qt3#e!BAO'b+,?=菻EQ%oh퇎 3Z?ӿv</JEm0A%IROzΊ+ MVF.lXZEoZKVu40vyINgcݗURF]άACQw/R jՋ&1Wkʬ=Q:9D)7DY1wuo[ 2{&h3FO~cNdI?<AY >lo.؟zؓF&C4k3-}11Nr[!?OhY^|"͉wz5XewCܣ\Y™-.@Z K[h'XK;OٝO` { ϴyfi%>T4Bەy3B$[sOo(&8Cٖm(#JBD{Z<:8‡ظOD 2ѓʪր*yy$p*€| t9>%, u̡o{w>uT6"bZB-/z`xaQp 8£Q‹KUrmh#C ߄|kXj^ `h,mw. Ap'~>3dQ؎cCs8' ?SvdHjƝ}*shgC["txޑAس~ άۅ ^͵A]pVϜ/Cb`&XJ]sIg[s.*cj~>.AEc+_˦}gH޻+?p#W= pMw3L0!:-m,EW [1ݵuha4}["bUABBW7b꺡mTi|c{K;S;&=YIpœ%S59GapGgEWeg܊a鷙cjF7<+̅U79s#xX#SMڐ 5;[4|j skh7tJP&v/Gyc [֟n{T"ҾaX0Va|^Eyw mcCPŋyJA@m-aTLO %G@jxd9LTVq,Vd8N6T=*ȤM#Z$3/*bC OufRF\{ Xd0 vYXxlA|%$HCwrrr-}:uX['W(;H¼7.'^1}7|xYk€=qw&χMp[փlv)C2`kM`"UW4؁Ѽ%BdZe s|x=Q6W,Sj + 6살h2]%h}WB~{RKA^$ODĄ;3D'`hwtlS~H&i*;Գn!H')M)*CѠBV 느,Sn9X(_e3lHP5T~Y F`K^mqg"btO[A*͔йHc.ۜTy 7AM։uL*`?q6oH)JVQlܦF]VV7ݳH&{:y5r?YG#);Y{(NSqx|410~!g?q1ߏ8Bݑ|Qv YOK~y`LiI`aYQ/2؇;nlu1Y`8;ȎmHS7rP9$~2OY0ϖ'3+` 25iLv,UN3o`@U>糟Β endstream endobj 697 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 698 0 R >> endobj 699 0 obj 2413 endobj 701 0 obj << /Length 702 0 R /Filter /FlateDecode >> stream xZ[~`ly(f6E`)"6 #K^I~)(4Ol˲D{1WCKZ|6ՏoS_&=j}{p NnQdR ׷5d*U8 )^x֗:+s֑x;eQ0e$'z^+Y5 Bqx9GjAGqߤ*!`Eo`i1UPzHD d+KI<7YYԻuROz ՇP \GNyRV&:&>nr3n }0Y1h8 پA$cښH/lsco?Kjf.,ҩG7񺄨ȫT=40)Ui"mԣP 묭p fJyJOg 9R{  5 y5ӓDq,XĎBj6KNv}Sʨ@**9fM4*59f5ϊtmMͣ]Wx3橨ш0vJ &GnuL_0PM|f drBj:𐾤yyi=NSyMvw_4Vk"ۆ5x,4 @],{4HJ IIOIK#[S̉ԗi@ѳdw26ɷa{A?R*j[BZzf},/ѽVCSf$jC4|CغϑX0Vj/D\`ɐĐ` TF (mēV" j~Br Y?hi t\LDߞyWb`j'P7E7{Px/BZJɝh`F,M 2(FV|CVqi*kY$Wz ߑGxbRtHMizbLoL~ Zʍ1Ȃ. ,{w0VE3J^N"pG엢0h}6N =nM4k͡N4"$@ѧty:ͭIq _goрG抎>yrx(UQQ݈e|n_zhVىFci A-XAei&fr`V)OH39q8,KuNyՉUn5ECEsAl/-Yyc_SO"+=d(JO:I> ];*)۹ݸRwV ؍3wݝy DwSx1%=t9|~p{KmlH\dc|"ֻ)."gw[]iMn8nyc+wk=ިu0(O"ިaUSY$ȣkr&n֪ިpjόo7Xhm3 endstream endobj 700 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 701 0 R >> endobj 702 0 obj 2440 endobj 704 0 obj << /Type /Action /S /GoTo /D [700 0 R /XYZ 72.0 275.297 null] >> endobj 705 0 obj << /Type /Annot /Subtype /Link /Rect [ 255.985 571.324 332.968 580.324 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 704 0 R /H /I >> endobj 707 0 obj << /Length 708 0 R /Filter /FlateDecode >> stream xˎ8aضZGn}dY  92FIn{o"/tgIU$Ūb8VTYVU4AiPyfIEiga}DA'8Dg6u3l5 }Mt$#ZI>W4P(] '\e/$ 2_;X E`P1a *wn. ^7_6hUq\e]TX%/}C=s}7}DeN$|#T[I&UEQQiica#=uaf3E{88\,F - IQXBZ[ʰ2SԸ D>/- tfk7U lQXTHo"}K< Mw>ID@K5:ul&3G G5˚9K,AB l D28W_vmSX؟Yw `Hl '|!n sx#PDG2!U, LΑ3ߌ-"ذv>a\@f" 2,PAD><9KAy\@Ǜn@PKk#zf#=xTꕪk Hi7 ZxGC2 GHE 3H,iDМG -Ńp3 tܖMd A渕 -ڻd"`pd[ta ]G@H]]kMݞC*}=_ϝ a<āk@OTCrva|7{ ߵ]"G+[i fLtEɎ_">֙#v+NqP{41vu]ҧ.$V@9=|>wqº(k( zGGGH4!`ݕ*?PPC#흉no7“g!HG ]C 򲓀r"3{XuTZ'CAF9PB4햊BEJ 3lˍ-؜ǮP-YR'I<(KKq KY? og8/Q` # dz [Ulf;zj6ڕXhӉ6xRWRd}pқDxhZ(%$ G941 ?I#B xJtݿL;˨d!|Q]8@+tV|2(bWj H䭨pÌMfy/b C >KPbQGr4x`Cu瓁d8PvVzbpwWIP[dȅ3k:= uQ.QCx Zv IYD ?q?LvqWE_~hFJӋH¥zJ0%"i9Қ^t 瞎 z 1"~Ϣ\ J9f ;}س Zxv,i 36Wd|t\V׳RY[urqh=2?uER^bycČéAh _O˓) %ED²WlڮgHg&q GW|SPn՝LlxM>s;\W!"B2eK`oQr@hHx> endobj 708 0 obj 2672 endobj 710 0 obj << /Length 711 0 R /Filter /FlateDecode >> stream xYKo8l l b`sPn"zE;,o!=NNqU"UůXE_iHqfv_ $@,60a8Pr3Z~;sDֽJԧGG73?~={!Jɺ8NBH ?z7l^+^hhPǫfCz !8,TԦ:N$hH->EA;sXҀip2†5\pEkXںe&0,K >t,ƺRlmtpqMEޟUyѽy7M;Koy!N@ESV;1 $WܮdV8jE'ڡ߫VYj=O3߫VF?ZCngo9Tr H 4S`4GbhI&ao2r+=iqÔ)J8E7FS zS0#bk<7屟ScȻ,X;v֮|%{K /)Jn7yՖQ3q2/q{4gmS#QC^ wԜ|BG[~'$ARi`;>Mǿ&x$i`@f.Y>?ZLJ*E|fd"P6E5VȠn}Eda썄>ιBE½GBBWv;.1$5?c9XF7փ=LS* ;K!+[FSt8ab?ZF*_;vMߋVWsƎgu~]l6RNJ1Q.FGȖ#C5:k 'P$HA oGmǍ΅ϋ(8y:R],F-8p#hcФyjax|mE ^}@/4(Ҍq86/~vwHzt9 )NtES@,/c [utDC{,g%_!Ɔ5><%J%m64 JdnAdD6DO*چ\bLCC8ed,٘\p24D!sdKgFnDۙ{U&TyU4V 3Ǚ<^t |P0(t@ λWCJqʇ0^oeX[ ^UY ZC94E`q+ ;61MkdS?Qv+\O-&k9B 㕲N氽C+8SȘOٺmIn+ _d,ƄA';L'~~zs',2ieSyƉleˆS}uDzZs ȢUMONVN6.zn[( أ1a~x"m}ח%ŤUϋj!F&M0T6/>Osփ dN?;s٣yEysciԌ詋sp1tv-z?\EYF,c4ϗoQ)*vq@ endstream endobj 709 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 710 0 R >> endobj 711 0 obj 2212 endobj 713 0 obj << /Type /Annot /Subtype /Link /Rect [ 327.25 709.201 401.41 718.201 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 704 0 R /H /I >> endobj 715 0 obj << /Length 716 0 R /Filter /FlateDecode >> stream xn8_nLR/2;` f8` nHjwz[|H$Jܒ"YŪbX0X@<8JW3OPL{ 1 <BKk@ؔ>l>=; 6of$0zas "ciS.QPWB-j+Tj:TM\Aa$~4ZTӉڤFK!=u謕a^q9ȥ SP38뿋♰ؖun? s&.B89%lkHw?*VFĆ ha&_v|Fx%%J"mO:q2`" cFCa GMv;y6BY1X ?S95#i-vGy>EӉD\̈́V>{^ 9G64cmVu?~GI,r$!:]҇AYȜَ֧͊Dl4ѐM$E9]VTU{$x7dҴ@F젵0n5#P( )O"CaQϱy8N׶?^϶s/ ~9}&Ph]+yAqyM乺atՏch@fH8ƫZPX )Ϣu~#dB lX7X%kCU\j*2+N2C&J v`0Ba8Źc-nPnI.0L@@&51Mȣtǝ'f QkVcV::{?v6:)J/Otș4Y&IӜZghU6M;0&I뢪F77]&OIcciYRҼɰ2X3cUCnq`9pqٓ&sűs /}6W' J[Uuc *콏*XNخaL+_2ؠ#msiaYU3R:P(o!D(Z<,ӹNJ؇< +CDX[tVΥ\rʛ#->*(nVRyȬ$ߨFm-рzL䯪̠ @D^N٭lh(FY5]beOC#xE!wbnklamvya0A>v7$ Pn!d͍5amR`Al",8Qx1Dx0 PZ_ W{uelJL) >%I"Lpl2(XW! dD?U ^P6bxP|pA 3؋S̗J ϘyF ItBX@eL2zEg 'tEryB*pa-^3qft{OB=U *t  D5`F J$2ͲyZtEmm6(WEo<+Ō_GD\l"\}C 90=3|IU,J(\ɧ^yKGZ;ڠ;J?uʛu*/GWZP-R0PU5O).HGjyTU1|$ I@^ JKn6YB2&:c/LI];TF<R4no"? qU;իCIT}>f{1>fS}t75'/:vV۳ 81Ť]w*ER^ݠ+ٲɫd'A/Mx~Hgstr 4W 4 [7߻t7Gﳉ_ Cʦ'W(k+C @/cG]s)K[aOG+q~i_ıQh^V~Nj:j;ZO~01HyLֽjOVdWy^!k3!Xl'@VgYJƏ $1"钋1rD8l'I'OktLҗYn9Pa)X.f;?+(QTbۤ~*y_=)<\H uJ- ^ g1NOw~Vp0BW-aⓘ >hA@5NQd tOj@qS-1gHUCT/Ϧ߰w`NjKžRpϼKc47wXw=RóK1.f'GkXz0a.H=L1le*o5G8?,21_h)$!}*〞h֒zi@+1˞<5gD>o d4֓<^mPmsdeON$復JVC>yjֽ9Y+1JϏuZs-zDC2џ=V~ XFJ:*Sc˨>qE]z,T 2^sDZ$lx9ϕ쥣HUӁ5ضhKM5.'N*_ endstream endobj 714 0 obj [ 713 0 R ] endobj 712 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 714 0 R /Contents 715 0 R >> endobj 716 0 obj 2815 endobj 718 0 obj << /Length 719 0 R /Filter /FlateDecode >> stream xk۸O`ňԓE=z+6{٢n֦m"H:.;|^;̈3!I^¿9C곥Q8IFĘ&耆hZ߫j?5y.ע>='B[zKHy!P#?=7?cY_H֨Zr[پ=mׇQ{^hL>p,ph\j)Y29k "CQF}0F1]6NQn3XEcc d5_n Uz-p[S۬}:YZ^41{{bW֑BSsY,,{fQnj4~ [%9fqK<1IBYE,9)VF4|-2s41vyIϡǛqéyepn|;?R/^%=pr~#"8G䑱<ǃCg9&1N:YZ$ڃ2hB2#Wa`ZoGṶ {=;(m. T!RTUdAm0XQ]_[6)$_`oyljIPmɜq22|=w /1;Q )/_zvOEΖK~d{I62~B51 IJNVҟ9*ȺA>BzKdBq)#hh:,ٲsdь ;N=x: Bh3@p FyśDnE;x)&s|VLjr=P@A`拄ez)zsÑ%'yB9JE zuk)yy-qF0*X$ yߝC:(wfE$00f"&{9|-wfdh6-4 #X?66lvU@/Msߋ Ț[oK>dTA ' @R̀`υ ݀^v7+;G$za?~Q1:+uhpfCvژIrfY.>ڏ{ķ7c.~?l endstream endobj 717 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 718 0 R >> endobj 719 0 obj 2620 endobj 721 0 obj << /Length 722 0 R /Filter /FlateDecode >> stream xY[۸~_A̓]vm' >mcK.ȏ!ER7Oҧ~GѹK#ľK8!꣢$b )pSr{Wg.rȻwr+gduޒMI>~z9 CvnL8rE$K<﫷|xْ"5?U-'iW_0Psh"B'"`H ̣, ϭCPPh *u&:8a[r$xIr)~Ob .&V yE6O]zWvw l}]ͩ\eӦcUiS!s5jX4ĉNd]D:=RMDig(źm^HGKꆢNȜp~7šP'q<4.%g"#Y8DcT^<"V-,z% `@q5jgMz: y\4 sKckEcYWp^_m==̕#%WQ ώ28E#m1% hs فgOM-p!?ͪI$s!,0J*K (|F|a_v/fsԻQUc {p!u|7>s~QBClnl'oYwݝ=ҲZB7 y3,֩1c~)`X {7*1Ȫk\TZ~:WuZ=MmTnxmIv6! :kgn, YZG@Z^2|Z]UVYdžom$j$x8ӽ`(M*VgbˇW Y-*x wuv8?oވEт's<2lCV"@M! #4z4E|U{UɊ"tg `W`A` 3dQW+K}=&\1xhm_l[q(+,f#w{za},qm ڢ9=DYU}W4U-J`kߢ@Ʉ'c6##~yp<_8n0y|% +4(MP!yŹ5xK^")/նìݗT-tƄ^81w&)4"BG\?YsN\!̳MHE#:;3湪 Q,f # ѓD܇$I3L|JX"WT_|BA_\$bj r9}Gi<}{hcsYƳͲnНpju0t" -\G:n ~REtOEc'ūcc`3/UgsZU¥,'#[`ho\ǵB`lblQqUPPo'snߪ)@:̔O{C@dȘ(YuM٠h/ ƢWwU5f{*[,њ^0R3b-5](BOmDhCؖ"W2;vbkֵ0gT8vG cC&S1̵4孢?[e7d9y D!$4mZ.\8|7cw$/׷2=]k\ϡj!"e Vڃ)@P_.H M&̫nCqk}!P)"{[ =o0F׆l(C], UF#aMvЧؗ0w ܠ/m ㄱ?om$R't[U 3{0/Xw3#MՐw3=X77/1龋):2(ЉMOYq[g)hPy#EYUWoFƠ&? X@.k!.ڡv(~zNLns%+4_1* 4Ƙ5c#2Cg?Q}~J;w3HRH EJ3VC@:l`չq eYΦ mI7(dH֚r 6h}b!\JEBgdݬC >((A4kh/r |b %ΪX!</ڠ$rF% ՜«׷ŅZ3xI6)Q%/lŕHu5D|'0 os ~$p endstream endobj 720 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 721 0 R >> endobj 722 0 obj 2580 endobj 724 0 obj << /Length 725 0 R /Filter /FlateDecode >> stream x]۸ݿo6C[rM͡ n> Lճ%EpH%g1g(3d$w?Y$y<diĠb "d2A̎ٷٿWJ2Wb&Ǜ?=~_5fRSxB eCrTu ~[}?=g?5$*IӔ r8yy 1Sg2LAb CBXz? s.<2<)⚳0}pNRGEm6^uwo]$\ԆN 6OU͊9ٰWT:zVau\7۽ r!cinb8\H%mUeDAVkUA]X$`<v[ue4<L1CݫctE€*F. [-814 f|/fzt'ȅ9OSc&8=~(E@R< n|~_-$l <"Tgn8 QN# t?؜U#VY\ 4{(㯪+fwsOb4:\ LO3D957.~-I8P< X EpSFEt%%q#fڠƱA;A4x\zl1CC !mI;ILtpff`渝=CqA{ȱr.'`\ y&I"RLv~)Wšd쇛cN> 1+"0'8t{KBWk2 s]AE؍#D*4GqEa0~F` SEʯ *rD׌#9 [P*>s՗UiE9vwѹ L_!NP1ce9EbYγ0NB"I7]2u#hnn Yꒊ|w?nMyܕ6"ˠIg5ݫ8 0ϒlN^i~B$jB߯-8f>:wAI0+ܬAf.9<46UMp"9XzQ2CFFq5dc;<*A$xPK#վ^S6Y EGrpGi“ gIa`ۢgjӡ̅XbW=JC'pTIrFQ)AC!l6ƻ TaqMWާU{|q{+9r9)T|񜥲x"MD:ֽ'ULMY18Yۨ#hgRNrhͭl) ZV^-K$>''r"hn*/}⊯Ksb9aak؛͚AX՛A}fi{2Ii'g.KG"` l7uSLջ<Oσ<:514rR  4Eӈ:L]U4=0QO 0nJK E$‰x*Z|PdxIvb1&qG;2.%gvU9MP?ޱ/X ܹ f\wS0> endobj 725 0 obj 2682 endobj 727 0 obj << /Length 728 0 R /Filter /FlateDecode >> stream xYY8~ %݀[MQwY`l2`,hnsю[<$R֑KfbUǕ0bu8Ai.B cC!+@Xc H7?@Яb9;aigKQwnz%0zZެfo\NGcH"o1+9+Ԕby0t(릾mf`k**Sa@'"+H >sH\~@g}1|xQʈO.IWg#cmߌr #'r$>9.v͘n"ꭎ.Q*ͫ->Wm?7? e.3Zo+$+P$珶@7 gכ3ތ{:uCUuùs_(kX )A״˪یxcf {zKk멲9j= |Sa[N,| "Zcx؍=$xg׆s 2\z۟Ht}޾͐ si;߿@=eNP 'bbҹؿ'?00;FA8bQDHl%&UCHe?(-WiDGFr h{\; Y;lG5ƪ h+6eu^V$`4X U2^&O IMiEB42$ U6meexd&\at (f[H}v^[Kt ) riU2*ĉ\B&J܋nI$B"kV=jA 7]BƬ vP% 8n90 7@ǡ;!J sb -W@]aG s,󄔁ڣtEq}Zm1#8pp'vY}Z9{)Yx & _Wqy:p>08RlQ-j]T '2[҉CR^ѺhlTZ=%VMQS=慦:s_3kMW>B2,;;XǪt X&dDHʩ"X3(i@ZeFceߺKpHX 7뎡KZ1VEEHG7f:xYfN oh RE/< 3C x.T>*Q"E*h;c^'=ҹ[l.tk4afu |al78% 4+ .v RSāL0uʣY]yDHd*JHƩvkdҠ'f:pߗf][`$2Xi@"k=9tTXU'^/_}A%qзM~X⍑ )hcYgwZA_"S:ɮN|j㥵79D܈݁|* PWe]]A8m^ pYő~$2ͱuۢdz #C"5ĉݎ{e[V[Z8[5//c{.wT4˱Oчxq1txă$Zpi'@e[@a'^2!mT6籘/4`/:)n1pqWqIz^xs[63}\A?-W_* w^},O7ջ!g(aƯ}?Xbcڴ3kշzGd3´ ,fE_ C!Yr9m˳UuQԤmh:Es7|nڿ~H R!ortǚNn_x-F;߃qE˾*s|y,^u*[$9u;yA) ԇ8ЉH] ̚CC_\RP񮀺Sj8":>93V1h}\ґ0PR~ :tT&b> endobj 728 0 obj 2423 endobj 144 0 obj << /Type /Action /S /GoTo /D [729 0 R /XYZ 72.0 436.825 null] >> endobj 147 0 obj << /Type /Action /S /GoTo /D [729 0 R /XYZ 72.0 149.011 null] >> endobj 730 0 obj << /Type /Action /S /GoTo /D [726 0 R /XYZ 72.0 140.129 null] >> endobj 731 0 obj << /Type /Annot /Subtype /Link /Rect [ 326.62 586.857 398.28 595.857 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 730 0 R /H /I >> endobj 733 0 obj << /Length 734 0 R /Filter /FlateDecode >> stream x˒6a+Ih|dNa{ƵيrHHb"i> t7o 'E1Jϛj"7P[>v3?չ΋қjiRekTGoms_tvfx ߛEɪ-.գBM_/.H`ХK~΋*ods2w%'Բ:it( ?a{N JS" Ps\-4*.dI!9ؠಎU*uΏ'C0Pd.ϋLqh8L q#'qvlqJZ㴯VMSwwzϓ~ LnSuR{y>͇HEJAH,Pu@95[wyq58QjfQ -C#AZB$.ߏ1A\_sz_'@__;}ioUZ'AF!*CϹBq 2>ۮ:/ѯҴj2*jGħZ4bU gI725L|bLm'fqޡ2PݰO9$}ȯ)jw{s);c]3RbK- J%sEY#<{VCc/|Zs=PCn ^x+WF˝UتZӐ8#(p]IsAX^HDcW%ֿD(2jF28ቍ2,.I<$ z.[7bL , ҝȝ޲;0-=t>%%CoXB l=bYMvA?A{ G=Lus%m-6RU}OSֶ@S$`k?vf'7n u, ]cYwUA P8b껼Tǥ Ƭ&Z/Jl7 DEh@&sb@b%ď(同XAMڮZdHb=um<9/#.xڰæX7|ĺ|jSA/JC4EV>sH*7%"f_ $09-Sެ CeM<;z:} IV5Y\C+) UGw9 P}$0vw~ÄܸdA~,E{C0pI%/-Rbh0Ԓuu\P8tE!f+ApϠ+?/# e^O<=gh9PJ;x2M>媁j}FZEV{E{3-<4} 0$d05^0s}7ZxKoxUl:ƞ#>wޞ@w V!#U" "@Ah-/Iەtvv z@ endstream endobj 732 0 obj [ 731 0 R ] endobj 729 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 732 0 R /Contents 733 0 R >> endobj 734 0 obj 2222 endobj 736 0 obj << /Length 737 0 R /Filter /FlateDecode >> stream x]s۸ݿogb7ns^.i;q(HBRq| AúNb?hwI,v UAgOOIOs*a( t@C@{&h]wWA?\}luOWdyջH6ߒ|=^}uFmoDc!*1Qt@_g}|Ȋ5%CdhWM}/!XkkEt:p&Υe*qt}wZ=\oթ*oH.gZv(6Z"#ckq8I4s+ /r&ˑLbAd2U U>-U!Kfff̤dHMڤA)iAg 0v` H+_*|)}mZ|1]JVDXɫK3{թ:g97|.mxL'unV66ZByZmJ_SP cd!˚f`@27 hH:[We=7`qC<7my x~|`@$tB:=ҼF L^1]kN)M9OTl8ɓg<Db Zha<bZllO}RPq N&66+0FOY ϼ̪DUJ7p 3ZV[lgP]AvKWPbAH-٥.p3b9\9iPNZ,.'"-I %D"lזeeKrB5W/x{OKŞr>&/ @LCB~.Sٌ"ϘwI~I&`Ƴl,i*Jݥ >H?@%1/N_/釨Q4I`-?#.,0r1P]ʓS}7&Ә+ѶM{>y}x=dMV}OuvI1FVLr;3b+/v1wj ]#B?>$q%cCM[//C/H-CPljǴ7F>8M=L_֓ (J0>~otV/fRL |Gѽ0ӴV@)VĈnt |,6BwZh(󜳽mh{Ne2ʧi2#s|JIƆ"<էz:C:pDh3`$KU: *3Z<VF 0%`9~x$ ` T+Y$vB; +ӱ,"Ia j",b<spx{i!Yt]|Hp?2a BN sEAqL:C]ԠaLL)VA땗N*pR '{0Kn[6B#!WSZDXSϞ}XEOG34W=F] C}z0d= nfwH6pC۶w9<܄ ՖZ70IT=W[$;dBlI8I'x|mk mL+le/gdLP7WF HKbFgPnN2poԗ&! Ti7A:[p"R+thwe \fϏ`  /AX09"8upO2ͅ Q^u^j32 QjIWr DڋWŝRԊC'Ϲ{6 nMr{v>9$ <% <k=8ru3V ,vȌEqv DvLǡn9%l;6k:xf`Y0mpXRRrLC*1oZ/wǺa艛vU%y]O7~:!>|P$=[U#!E澀~6'wn6m~uPá]/y6ma;l7yw2&$n/r鱹}̚ )~RGU.|#MFs5BBzvA^kPw (H]?f DPlݩ`li/ʏo&JiZ(mN_gYr4h4<HgGIkEeE-<ȨfDWEw il],}J|(G. :yn DHKr^MBՠX/RB,^ YV㽏i dޮA;&1ÞU5a={C}*טS<$iζ6O =hnH؟>p endstream endobj 735 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 736 0 R >> endobj 737 0 obj 2786 endobj 739 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 759.389 262.025 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 609 0 R /H /I >> endobj 741 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.865 759.389 524.865 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 609 0 R /H /I >> endobj 742 0 obj << /Type /Action /S /GoTo /D [601 0 R /XYZ 72.0 564.467 null] >> endobj 743 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 747.389 186.776 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 742 0 R /H /I >> endobj 744 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.525 747.389 525.525 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 742 0 R /H /I >> endobj 745 0 obj << /Type /Action /S /GoTo /D [601 0 R /XYZ 72.0 152.872 null] >> endobj 746 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 735.389 266.509 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 745 0 R /H /I >> endobj 747 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.943 735.389 524.943 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 745 0 R /H /I >> endobj 748 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 723.389 234.628 732.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 617 0 R /H /I >> endobj 749 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.175 723.389 525.175 732.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 617 0 R /H /I >> endobj 750 0 obj << /Type /Action /S /GoTo /D [622 0 R /XYZ 72.0 769.889 null] >> endobj 751 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 711.389 279.054 720.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 752 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.853 711.389 524.853 720.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 753 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 699.389 447.125 708.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 687 0 R /H /I >> endobj 754 0 obj << /Type /Annot /Subtype /Link /Rect [ 513.808 699.389 523.808 708.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 687 0 R /H /I >> endobj 755 0 obj << /Type /Action /S /GoTo /D [622 0 R /XYZ 72.0 150.71 null] >> endobj 756 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 687.389 259.295 696.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 755 0 R /H /I >> endobj 757 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.127 687.389 525.127 696.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 755 0 R /H /I >> endobj 759 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 675.389 239.986 684.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 758 0 R /H /I >> endobj 760 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.277 675.389 525.277 684.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 758 0 R /H /I >> endobj 762 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 663.389 304.02 672.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 761 0 R /H /I >> endobj 763 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.671 663.389 524.671 672.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 761 0 R /H /I >> endobj 764 0 obj << /Type /Action /S /GoTo /D [625 0 R /XYZ 72.0 622.052 null] >> endobj 765 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 651.389 249.169 660.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 764 0 R /H /I >> endobj 766 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.069 651.389 525.069 660.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 764 0 R /H /I >> endobj 767 0 obj << /Type /Action /S /GoTo /D [625 0 R /XYZ 72.0 497.332 null] >> endobj 768 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 639.389 277.945 648.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 767 0 R /H /I >> endobj 769 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.861 639.389 524.861 648.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 767 0 R /H /I >> endobj 771 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 627.389 182.92 636.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 770 0 R /H /I >> endobj 772 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.553 627.389 525.553 636.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 770 0 R /H /I >> endobj 773 0 obj << /Type /Action /S /GoTo /D [628 0 R /XYZ 72.0 341.441 null] >> endobj 774 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 615.389 335.521 624.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 773 0 R /H /I >> endobj 775 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.441 615.389 524.441 624.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 773 0 R /H /I >> endobj 776 0 obj << /Type /Action /S /GoTo /D [628 0 R /XYZ 72.0 146.355 null] >> endobj 777 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 603.389 279.654 612.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 776 0 R /H /I >> endobj 778 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.847 603.389 524.847 612.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 776 0 R /H /I >> endobj 779 0 obj << /Type /Action /S /GoTo /D [631 0 R /XYZ 72.0 676.322 null] >> endobj 780 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 591.389 319.646 600.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 779 0 R /H /I >> endobj 781 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.655 591.389 524.655 600.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 779 0 R /H /I >> endobj 782 0 obj << /Type /Action /S /GoTo /D [631 0 R /XYZ 72.0 521.318 null] >> endobj 783 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 579.389 304.866 588.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 782 0 R /H /I >> endobj 784 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.77 579.389 524.77 588.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 782 0 R /H /I >> endobj 785 0 obj << /Type /Action /S /GoTo /D [631 0 R /XYZ 72.0 198.446 null] >> endobj 786 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 567.389 221.292 576.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 785 0 R /H /I >> endobj 787 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.275 567.389 525.275 576.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 785 0 R /H /I >> endobj 788 0 obj << /Type /Action /S /GoTo /D [634 0 R /XYZ 72.0 733.889 null] >> endobj 789 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 555.389 248.265 564.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 790 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.077 555.389 525.077 564.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 791 0 obj << /Type /Action /S /GoTo /D [634 0 R /XYZ 72.0 653.704 null] >> endobj 792 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 543.389 240.015 552.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 791 0 R /H /I >> endobj 793 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.137 543.389 525.137 552.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 791 0 R /H /I >> endobj 795 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 531.389 250.82 540.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 794 0 R /H /I >> endobj 796 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.941 531.389 524.941 540.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 794 0 R /H /I >> endobj 798 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 519.389 176.832 528.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 797 0 R /H /I >> endobj 799 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.597 519.389 525.597 528.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 797 0 R /H /I >> endobj 801 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 507.389 259.38 516.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 800 0 R /H /I >> endobj 802 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.995 507.389 524.995 516.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 800 0 R /H /I >> endobj 804 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 495.389 261.0 504.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 803 0 R /H /I >> endobj 805 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.983 495.389 524.983 504.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 803 0 R /H /I >> endobj 806 0 obj << /Type /Action /S /GoTo /D [647 0 R /XYZ 72.0 769.889 null] >> endobj 807 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 483.389 291.743 492.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 806 0 R /H /I >> endobj 808 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.873 483.389 524.873 492.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 806 0 R /H /I >> endobj 809 0 obj << /Type /Action /S /GoTo /D [650 0 R /XYZ 72.0 769.889 null] >> endobj 810 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 471.389 276.037 480.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 809 0 R /H /I >> endobj 811 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.769 471.389 524.769 480.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 809 0 R /H /I >> endobj 812 0 obj << /Type /Action /S /GoTo /D [650 0 R /XYZ 72.0 480.995 null] >> endobj 813 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 459.389 195.341 468.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 812 0 R /H /I >> endobj 814 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.463 459.389 525.463 468.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 812 0 R /H /I >> endobj 815 0 obj << /Type /Action /S /GoTo /D [650 0 R /XYZ 72.0 423.72 null] >> endobj 816 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 447.389 376.335 456.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 815 0 R /H /I >> endobj 817 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.209 447.389 524.209 456.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 815 0 R /H /I >> endobj 818 0 obj << /Type /Action /S /GoTo /D [653 0 R /XYZ 72.0 640.655 null] >> endobj 819 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 435.389 340.829 444.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 818 0 R /H /I >> endobj 820 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.489 435.389 524.489 444.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 818 0 R /H /I >> endobj 821 0 obj << /Type /Action /S /GoTo /D [656 0 R /XYZ 72.0 629.849 null] >> endobj 822 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 423.389 388.417 432.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 821 0 R /H /I >> endobj 823 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.543 423.389 524.543 432.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 821 0 R /H /I >> endobj 824 0 obj << /Type /Action /S /GoTo /D [656 0 R /XYZ 72.0 280.913 null] >> endobj 825 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 411.389 201.194 420.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 824 0 R /H /I >> endobj 826 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.421 411.389 525.421 420.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 824 0 R /H /I >> endobj 827 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 399.389 374.417 408.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 680 0 R /H /I >> endobj 828 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.101 399.389 524.101 408.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 680 0 R /H /I >> endobj 830 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 387.389 310.168 396.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 829 0 R /H /I >> endobj 831 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.627 387.389 524.627 396.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 829 0 R /H /I >> endobj 832 0 obj << /Type /Action /S /GoTo /D [662 0 R /XYZ 72.0 515.453 null] >> endobj 833 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 375.389 200.078 384.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 832 0 R /H /I >> endobj 834 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.429 375.389 525.429 384.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 832 0 R /H /I >> endobj 835 0 obj << /Type /Action /S /GoTo /D [662 0 R /XYZ 72.0 246.778 null] >> endobj 836 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 363.389 257.706 372.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 835 0 R /H /I >> endobj 837 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.007 363.389 525.007 372.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 835 0 R /H /I >> endobj 838 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 351.389 260.153 360.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 683 0 R /H /I >> endobj 839 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.877 351.389 524.877 360.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 683 0 R /H /I >> endobj 840 0 obj << /Type /Action /S /GoTo /D [668 0 R /XYZ 72.0 677.447 null] >> endobj 841 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 339.389 244.51 348.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 840 0 R /H /I >> endobj 842 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.103 339.389 525.103 348.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 840 0 R /H /I >> endobj 843 0 obj << /Type /Action /S /GoTo /D [697 0 R /XYZ 72.0 649.089 null] >> endobj 844 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 327.389 415.519 336.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 843 0 R /H /I >> endobj 845 0 obj << /Type /Annot /Subtype /Link /Rect [ 513.903 327.389 523.903 336.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 843 0 R /H /I >> endobj 846 0 obj << /Type /Action /S /GoTo /D [697 0 R /XYZ 72.0 563.617 null] >> endobj 847 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 315.389 248.902 324.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 846 0 R /H /I >> endobj 848 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.071 315.389 525.071 324.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 846 0 R /H /I >> endobj 849 0 obj << /Type /Action /S /GoTo /D [703 0 R /XYZ 72.0 769.889 null] >> endobj 850 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 303.389 251.382 312.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 849 0 R /H /I >> endobj 851 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.937 303.389 524.937 312.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 849 0 R /H /I >> endobj 852 0 obj << /Type /Action /S /GoTo /D [703 0 R /XYZ 72.0 710.171 null] >> endobj 853 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 291.389 299.247 300.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 852 0 R /H /I >> endobj 854 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.705 291.389 524.705 300.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 852 0 R /H /I >> endobj 855 0 obj << /Type /Action /S /GoTo /D [700 0 R /XYZ 72.0 769.889 null] >> endobj 856 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 279.389 242.044 288.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 855 0 R /H /I >> endobj 857 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.26 279.389 525.26 288.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 855 0 R /H /I >> endobj 858 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 267.389 322.776 276.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 704 0 R /H /I >> endobj 859 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.629 267.389 524.629 276.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 704 0 R /H /I >> endobj 860 0 obj << /Type /Action /S /GoTo /D [709 0 R /XYZ 72.0 163.149 null] >> endobj 861 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 255.389 284.111 264.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 860 0 R /H /I >> endobj 862 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.933 255.389 524.933 264.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 860 0 R /H /I >> endobj 863 0 obj << /Type /Action /S /GoTo /D [712 0 R /XYZ 72.0 499.693 null] >> endobj 864 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 243.389 293.12 252.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 863 0 R /H /I >> endobj 865 0 obj << /Type /Annot /Subtype /Link /Rect [ 514.862 243.389 524.862 252.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 863 0 R /H /I >> endobj 866 0 obj << /Type /Action /S /GoTo /D [717 0 R /XYZ 72.0 422.732 null] >> endobj 867 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 231.389 244.689 240.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 866 0 R /H /I >> endobj 868 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.241 231.389 525.241 240.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 866 0 R /H /I >> endobj 869 0 obj << /Type /Action /S /GoTo /D [717 0 R /XYZ 72.0 314.104 null] >> endobj 870 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 219.389 249.64 228.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 871 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.201 219.389 525.201 228.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 872 0 obj << /Type /Action /S /GoTo /D [717 0 R /XYZ 72.0 205.476 null] >> endobj 873 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 207.389 267.838 216.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 872 0 R /H /I >> endobj 874 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.059 207.389 525.059 216.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 872 0 R /H /I >> endobj 875 0 obj << /Type /Action /S /GoTo /D [720 0 R /XYZ 72.0 671.137 null] >> endobj 876 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 195.389 263.412 204.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 875 0 R /H /I >> endobj 877 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.093 195.389 525.093 204.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 875 0 R /H /I >> endobj 878 0 obj << /Type /Action /S /GoTo /D [720 0 R /XYZ 72.0 566.177 null] >> endobj 879 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 183.389 249.104 192.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 878 0 R /H /I >> endobj 880 0 obj << /Type /Annot /Subtype /Link /Rect [ 515.205 183.389 525.205 192.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 878 0 R /H /I >> endobj 881 0 obj << /Type /Action /S /GoTo /D [723 0 R /XYZ 72.0 714.561 null] >> endobj 882 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 171.389 257.886 180.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 881 0 R /H /I >> endobj 883 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.099 171.389 525.099 180.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 881 0 R /H /I >> endobj 884 0 obj << /Type /Action /S /GoTo /D [726 0 R /XYZ 72.0 361.665 null] >> endobj 885 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 159.389 267.809 168.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 884 0 R /H /I >> endobj 886 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.021 159.389 525.021 168.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 884 0 R /H /I >> endobj 887 0 obj << /Type /Action /S /GoTo /D [726 0 R /XYZ 72.0 241.409 null] >> endobj 888 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 147.389 241.058 156.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 887 0 R /H /I >> endobj 889 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.231 147.389 525.231 156.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 887 0 R /H /I >> endobj 890 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 135.389 318.024 144.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 730 0 R /H /I >> endobj 891 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.533 135.389 524.533 144.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 730 0 R /H /I >> endobj 893 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 123.389 258.8 132.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 892 0 R /H /I >> endobj 894 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.093 123.389 525.093 132.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 892 0 R /H /I >> endobj 895 0 obj << /Type /Action /S /GoTo /D [735 0 R /XYZ 72.0 723.889 null] >> endobj 896 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 111.389 303.696 120.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 895 0 R /H /I >> endobj 897 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.739 111.389 524.739 120.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 895 0 R /H /I >> endobj 898 0 obj << /Type /Action /S /GoTo /D [735 0 R /XYZ 72.0 647.153 null] >> endobj 899 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 99.389 296.046 108.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 898 0 R /H /I >> endobj 900 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.799 99.389 524.799 108.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 898 0 R /H /I >> endobj 901 0 obj << /Type /Action /S /GoTo /D [735 0 R /XYZ 72.0 521.617 null] >> endobj 902 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 87.389 324.308 96.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 901 0 R /H /I >> endobj 903 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.577 87.389 524.577 96.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 901 0 R /H /I >> endobj 904 0 obj << /Type /Action /S /GoTo /D [735 0 R /XYZ 72.0 314.081 null] >> endobj 905 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 75.389 297.129 84.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 904 0 R /H /I >> endobj 906 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.791 75.389 524.791 84.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 904 0 R /H /I >> endobj 907 0 obj << /Length 908 0 R /Filter /FlateDecode >> stream xQsK)&bi2yμ3<@$J-wAnKά|SO\=~/׫Ѯ??eJfW|ʮn1h/o?\o)Wl]y_)_y˻߿ܞ?W/}Z%rJ)_AZwwW^p}swǧ_'y:ڡZ㟎n~ox|:~\/+' S\y1ơߑ_59a{՟ӃgO&苿/We-oOF#b[/ͷJg?~OG՛}/'|{On_LJ:>CQiC$3-9갉;Fb#V+@5 "(DPA%J^mo5UЎ[/7nnR.wrݤ^&r7IMn.w pM7n ppm9ps-[\r7-iMnZ/wzݴ]r7mM7nQf^>Tms\Zl,U]u~'oǻhsS ߾Wo󃖯MmƴԊAe_w ;FbU+;DNDpA'N "D0`NDq9b m 9b"(DPA%J4"h}}_R{CI=*Ճ^P-F,Y bp&9J,s:2@݈eNˑY d)R"KE, Y4dّeGYd9@Y:td2e 9Gjby&9GjbXj#ڈ6d)R KoϣoϋO6Mr)T5j$|YgWo~驛ǧ맛ӳwOxXVcaNnЪö݂jAuGuzPHF,Y dR"KC, YvdّeGYd9@,Y: d2eK)R B,KR*F,Kir4! KA,Y*TdiҐ!KCYvdّ@Ydґ#KG,YB,K-R+J,KRF,!KA,k>᥎ z&tڷ퍬sQ,#O^库ӛooowOC[ݟe vɅImvRˤVTR@T# &2W%\@jb+HM,sm KA,Y*TdiҐe:K uo6T;GEz ґe @A,seRu%J2W)\@jd)R KE,Y*4diҐeGYvd9@Ydґ#@,X*R\@jbHM,sU F,Y 8& \PFΥ_D՛_]; :޿zt[/x|eߎ/ZlC)nrf4Y29h;TwTgPy3ՃԊ,Y*TdiҐ!ˎ,;r ˁ,ґ#KG,YB,K)R J,KRF,!KA,Y TdR!KC,;Ȳ#ˎ,r KG,Y d2bXj!ZVbXj#ڈ6b Y dl½Ńe k}nǩ[f9R]q>s<=:==ӛo7q7_n߽G@8fۿ2(=lZPQεN6T;NVTe rYjbud)rԫY;笹ĵx;~{^ܬ޺Y'3Nk}:p\i3ǒ^=?l|-7m{%ܐ:@KnHmvRϗ/VTR7bKnHM,s Y dR"KC,--km Նj'VTR{AY: d2e.!5%72ܐXP7bKnH,Y dR"KE, YȲ#ˎ,r ˁ,Y:td2e\rCjbKnHM,s e.u#R \Dm yE4mu %;}ڮ}@ }=?.ws/[l s;PRwTwTs;PԭVe.u%2_\Ejd)R KE,Y*4diҐeGYvd9@Ydґ#@,XJ!2_\EjbHM,sY d)R"KE, YȲ#ˎ,;r ˁ,Y:td2e 2_\EjbHM,s KA91}IANr1MS7 ;Gzv'T\.Z͞˶ ˽TNoC.fW9ʵ\Y>Pn@yo,g:`T:SuL5j VREw;Br'yF|"<'rgIސjF9S*LU2UeTS5j{K^Y,(@7˙j0`T)c#>=ܼ}:=s7ONnoׇO'[%v>{X%۾ϟ(7;Od+Od ˙j \Hr H^j.$@9Rͅ(GLU0UaT*S5jL՘1T;SLu0TSuLՙ3`TB#\H@Ts!ʑj.$ yCLU0ռ1 y tw^]z۸q\xy;?^߽{<=tOw7SRݴ}??.,qi݊rc|~\Y>PLU2UeTZy,WraygyˍL5j0@YTʑjB9RsS$oH5M S*LU2UeTS5ڙjgv:`:SuL5j0`Tʑj"yEyn H5M)3UaTXpXqYCy qoD[lU^?~y{tڔI1=||ћ@9R㶣aygy7売\Y>PLՙ3UgTRmQTsnWt6$oH5F9S*LU2UeTS5jL3T;SLu0TSuLՙj0`Tsn#ܦH5F9RmIސjnӍr*LUj%H(w#,PTs ʙ0UaT*SUL՘1UK>׽~{3(wsS/幩ɕL5j0`TMHTM@^격ɑ격ɑ격ə0UaT*SUjL՘1Ucvڙ`Lՙ3UgTR]6"9R]6yE˦^$G˦^ oHuԋLU0>Xnb^j{ٙhMt;>|绝u1]/z:z3kQsxЛϟz((?P.,,GcI7.B9R]H^jnrÑ!LU0UaT*SUjL՘j@qI+˕声\XY(rc9S L5C#H57C9RHސjnr*LU0UaT*S5jL՘jgvڙ`Lՙ3`TRPTss8Wáp(G9ʙ0Uahx9RO;mPԗS_VcAɁ7?\<Ο<v>B;ԗԷmgA\raygy"\rkxxz/8Aw>8㶃yaygyΉ$7;sD+Rm T[cT SULU1UcTvڙjg:3UgTS H5}r%yEy[#ռ-R{ߢ S*LU2UeTS5ڙjg:`:SuL5j0@y[#ռ-ʑjH5}KT޷(gT2Cd,s 7ߝZѝ@ϯoox>q|}̧\@Om3ͻZ.˝y @yCLU0UaT*SUjL՘:Z^re@(,wʽXTS PTs=ʑj@9R$oH5 S*LU2UeTS5ڙjgv:`:SuL5j0`Ts=ʑj yEH5z3UaTs?_Eu}^l^%K˃U曟wܖ{k;͠N%Zn99j;,OeZY,(rjL՘jgv:`:SuLՙj0`T0ʑj&yEyH5!<r*LU0UeT*S5jL՘jgv:`Lՙ3`T9`#<rQT0Rs(gT SCF|FGzY  SzwwO'~pxzwOO7w篹UXZ|ӻ7ͭ{m^͗G(w#ʕLU2UeTS5ڙjg:`:SuL5j0@yH5O V#ޝ|9W٧맷6zQuS>9nRq3@yd@rc={ӛwǿ|~XU|g_:!-,||9eraygy|9erc\ RT UHU*RT"UiHURT SLU2UeTSL3TSLu0T:SuL5j U-HU RՂT UHU+RՊT!UmHUS*L5w:_}A/+RO,`ett\u}Ï/קxYg7~>=w/uj|$"qt$7;s#S5jL3T;SLu0TSuLՙj0`Ty:#eHu#9R]@ސ2OGr*LU0bƺU<}Ge[q>|qdI+ Azc{CjH4y/yϿymy.+]$w;SL3TSLՙ3UgTS & $H5M@9R]vyCymʙ0UaT*SUL՘1Ucvڙ`:3UgTS & (Gymʑj^@T3UaT SULU1UcT;SL3TSLu0UgTS L5j^r&"ռ6H5M@9RkPTܒMy-&;nKb=KXw79)q}_Og8=g?{\fjN' 7q9\"qWSq ɕ幚@y&9SLU2UcTSL3TSLu0UgT:S L5jAZVjEڐ6 S:_MUYuk?PH.,,/>僩:3UgTS H5/>A9R]yE5$GP7 %9S*LU2UeTS5jL3T;SLu0TSuLՙj0`T$GP#em(ɑ6 .kCIT S:Mu%66[ss)ίh9 =n^J y77o^/FyQ>P>\XY(yQn,wwڙjg:`T:S L5j+H RmT[E"kH5*LU0UaT*S5jL՘jgvڙ`Lՙ3`TRu (Gr#\΀rPT SLU2UcTSL3TSLu0UgT:S L5j.g@9R $H53r7PTܒeq,KS^Pe;/,ZwKA|xzx7w}pig`[ol?qq(/77˝yI)ʕ:ʅH5/)E9Rm S*LU2UeTS5ڙjg:`:SuL5j0@yI)ʑj^Rr%$oH5/)E9S*LU0UeTS5jL3T;SLu0TSuLՙj0`T%(GyI)+RKJQTR#ռLU0@9KJ^_R>rIۧrAgQOoK\v乞@|)rc!\Or*LU0UaT*S5jLRU₼ ;壱X(re9S L5j e#\O@Ts=ʑj'@9R(gT SULU1UcTvڙjg:3UgTS H5zW PTs=R(gTс [u>㢝on0vW7FX? ǿ~~-e|]k%"8qv6G '6.ʕ.ʅA6_T[E"VjkH5Rm S*LU2UeTZ_ cEy7y^+$3UgTR]Kr܃.%9R] T{𒜩 S*LU2UeTS5ڙjg:`:SuL5j0@=xIT{.%9R] T{𒜩 S+!|{s2a+!jmS6! Y>¿?>Ox||;ޞv]>tzͻ'77wy?={wjv>;Rc總_e$_ rc|+ȕ^A.,g:SuL5j0@^AT׻w{9R]zyސzW3UaTs=n 2Vu縐{ߡ+ֻ?&[x_7SUxN`3=?R"qraygy<$I%\Y>P^j^r%!ռ(LU0UaT*SUjL՘1T;SLu0TSLՙ3UgTR͋QTD#ռ(H5/J$yCyQ"ʙ0UaT*SUL՘1Ucvڙjg:3UgTS H5/JD9R͋I^j^r%E(gTT_X.JT՝6yMb?r.O?|<=['׷”;,ROw:x3j)osvX(\Y>HF\XY(H5/D9RK#QTH S*LU2UeTSW /$w$7;$W3`TRK#QTHWF楑(Gyi$ʙ0UaT*SUjL՘1Ucvڙ`Lՙ3UgTRK#QTHWF楑$oH5/D9S*L5'Z"Ȑ>/ yг>4im߯?mリX{qgִGhৣwFog;res ؆rGynlCre+~ڀZPQ=m@mvR6VT#@,Y\v5\rrrR KA,Y*4diҐ!ˎ,;r ˁ,tdґ#@,X.ՀX.\^WblRjblQsy݈A KA ߣT{W)9eqX^i՛?cr(tsz`2 L|/FGyˍA<rQT<4ʑj&yCyLU0UaT*SUjL՘1T;SL3TSLՙ3UgTS (G9ATsrH57PTsLU0UaT*S5jL՘1T;SLu0TSuLՙ3`Tʑj}"՜@9R73 (gT*n5|~!ĥ;DžmgAlY/=sOo?_>L\4w>qr5svg>R/%ɍrL5j0@֗$G֗ HuHu .[_ S*LU2UeTS5ڙjg:`:SuL5j0@֗$G֗$G֗$G֗ oHuLU0FuxgS|c0bn~V0B/zϏOo˞ar1L6J:ܦ_eռ}NWdyI'I,(υ$wsa.ə2UcTsaaPrL5j0@98G9R9+R9ʑjIސjQT SLU2UeTSL3TSLu0T:SuL5j H5(G98'yC98G9S*LUj^@-+쯎ssp^#q|9|??> 6._CқuU@\XY(NQn,w(GyYɅ S*LU2UeTZ(%y/,wGcQrL5j0@yYʑj^@T#ռ,H5/ @9S*LU2UeTS5jL3T;SLu0T:SuL5j0@yYʑj^@T#ռ, e(gT(_6tPᣅ7vx(o/ O?7tqyQJv q$,Hn,wuɕT[E"֐jkH5*LU0UeT*S5jL՘jgv:`Lՙ3`T?d9RT UHU*RT!UiHUS*LU0UeTS5jL3T;SLu0TSuLՙj0`TjAZjEZ6 jCژ0UaEQAf֋tg9n8G檀ǧ͈}+w{:|gEn9f Pn,wLʕ$r3(G9S@raT*SULU1Uc$5OɚK!~KRI,(%$wsI*ɍL5j0@9Sr3(G9Sr3$oH5g PT S*LU2UeTSL3T;SLu0T:SuL5j0@9Sr3$H5g PTsH5g PTXaJFllw%u c-绯 sORl;>qqܸ~ڎqˍ܀܀r*LU0UeTS5,u$|$7;s>+s> ˙3`T.."e>#e>7lGr*LU0UeT*S5jL՘jgv:`Lՙ3`T....!e>3Ua9QAF>ӝq;##o:.q|0Gϯ7tqg[.we\Cre@y!Pސr{1#b *LU2UeTSۋ? u6Hn,wH,(ۋ\XTS Huɑr{1W^HuR]n/Fr*LU0UeT*S5jL՘jgv:`Lՙ3`T.#9R]n/Fr^HuR]n/Fr*Luxe÷Gvv~$\Dž|9_YۿO>ی]ꡇ_v>qz9C;@rcmc;VTRjAuGu 2e QM,%e$5n2OXY d)R"KE, Y4dّeGYvd9@Y:td2e @A,%eu%y’2OXX KR#\^zuw,ձAqqP_uf\Y ;v\XY(;X(re9S L5j ռ .ʑj]pQT.(Gy\3UaT*SUL՘1UcT;SL3TSLՙ3UgTS wE9Rͻ"ռ .ʑj ]pQTZv_u ^?dAKо\on>+8KMt6t8;o]9nre@(,wʽXTS :H5ϹY#> endobj 908 0 obj 16347 endobj 910 0 obj << /Length 911 0 R /Filter /FlateDecode >> stream x˒6)W0|?R'J9vl!JA$$q"d>F$ j/nݍ~kE>ͲI0ѨأQ{^H19KTLjIc-q?'^5+|XSN+oblɦ_$-ay4"Cr iJ=_9K 嚴IA‘](Az$/{vyK^ m՟{UMy4\u*hfyũ%؎tW2 0 6E`cVRN:U@t5<]AU%-kfB܆I `f/U;}ƃQ'XX ]d3Ş)Tp \{ KDl(+.9d :4Rq-}M ;AU<`<{1 p.ct k#_% ,yAjNm%%t#b,ZIn05 *[gu' ~ ر/U 1˩O@e ȡRQC(!4}ZɌ$%3'} Rdlai`*[w" %K Y4K4iIc{y<46`ppyzp"4o=u`x\B<[zu*>g5v1/;4I !p:8TMhp3q:MAF3Akv:a_xkJ-!rه*AR@,۲F*r%Y d^T8kV[rp0'ϲ*^Hs^AG4 Id|BEd_-XOC;cdMcck֤+B Vm+^N1BKALƘD3/u!L~ 1R(䝜I*ؔm!~<-ӧ}4 'i[If:tPX 36^-LjTk<f($j*T]1 @녾`@梅/Nk.EUSS Vڜ6NxiҘ6xV.~8 T%d A (/@]Vz,rfrDoǼ-0I_.xaYo\. RN_ 6/[&Wj̓ * M١#D&V#Qeos;t^E{(?qp% e2} 8c hF[ ISD =/̨T .o\7Q@D!n|S*[OY&܅B!<^p0'ae.7j6Q;XRAbTtB~rب!?8Z(l7y2 q)a= U%UJ: 9:mR\yE9[!unu+:Lot=֯P ϝY SnƗYi|bc&/kF݊`9[䵄Uwr꠳9lJ^@? -sËU <Wo#Z'`6hu*xYmԨfg-G^Bf"[O 28,3˰grqDȗѲ̯I ]o i0vȏ%{تj[:X_v3w:N9k۬eͯxd&~k݃YG)POG]V+-08|Vk:>i9v0 b]Iq-v#f2`/+кA)M2> L'D>Dπc2]U~z6WV)5'i&4~>}_`Mf=R@Ϸ0&!~E)xcQd1PjK>$g6UJD޳BW 4ԻY|ˆͲh^:q_qZt] *hPYx#?JҠ6֫Svu% 0ML3]l.:T5r/b:\u*%Yk7"0}ͬ A>6CU ARj=4՗[cQxiV' mǬwAɿL[hݡ t[ނ* i;i`bx/  NύJu }B1crv ^nT`RAY*cϫi7 endstream endobj 909 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 910 0 R >> endobj 911 0 obj 2964 endobj 91 0 obj << /Type /Action /S /GoTo /D [912 0 R /XYZ 72.0 331.619 null] >> endobj 98 0 obj << /Type /Action /S /GoTo /D [912 0 R /XYZ 72.0 140.401 null] >> endobj 913 0 obj << /Type /Action /S /GoTo /D [909 0 R /XYZ 72.0 187.877 null] >> endobj 914 0 obj << /Type /Annot /Subtype /Link /Rect [ 486.316 747.389 523.276 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 916 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 735.389 151.66 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 917 0 obj << /Type /Annot /Subtype /Link /Rect [ 344.78 368.786 416.44 377.786 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 918 0 obj << /Type /Annot /Subtype /Link /Rect [ 174.0 333.119 245.66 342.119 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 919 0 obj << /Length 920 0 R /Filter /FlateDecode >> stream xYYo9~ׯ X&Y{/,2Vf DIDZJNx4})جbXȇ++ $)ڝ_8F1A42C$}pQ(DqR7"_Ͽ` m(W^&|t\Y й8QQ6gE~Ǧd(rTPV"?ۉLԂWwͿO{ODci'dPǞ3)$#q8WP=#! ߳Gݽ1n>cqi $k?>rH7$s9qt(Z,_o%KY%kGAUm9~fS]]ohzoEc{օ%_y&jqlز#LiqDX{ky |Vd:iǩvB^ԆKWgQʃZ{3ڴR<ߕK'M'C2gn knnSf2|? x/|j%c(lz[V☳)B<YV|i^djrq2gbnj/Bu ͳɤњM嬧UP -̚;}"ˣxK.o&^wfH--{QiOhTK&#ni咱E_;ލp>,KUli0Ąq{*; ǒ9iwś7,GҺv' )Nd7)DKoUSS* I:$0M=P 0!?>{><<{R#/C<̫HD"2q8Qx8Ͽo'y)΁G~D˩\eXlzs'_p3Qm^LcXAXB[7؇Fp땟KQ_/m-J #D40Wh+M*gN/IL#ӽuS'$υ*&׽ ƥ,Mxv18bd\Jb2vF鄎4>/>ox5cBF^FNZ)jqq&CZe Q.y۲SLМnʺjf/hy7ըAwllLu!l/g}pit?Jw $h!N~>y$Rh ѐ6R̲2-'4@Yѻ|`Wbi1}twM^nt#e@NE rrYH#U3۫Smv 1hU|TH i W`řMGJ"CI3N$ -Amϟ@EUYo$гB i.- C_Jj ŰUqvWg`/$ƄޝJU궬,)9Om28zG1nhJ~h{N u=> {FqAkC#Ev(@ KpOL.J zY"]9'Dq(|8PIZa-!Ayĩz&fxϦh(^)Ejhݺ䜬8Zڴ/7@-ajD߳aay`7ZS;:JXnY> endobj 920 0 obj 2427 endobj 244 0 obj << /Type /Action /S /GoTo /D [921 0 R /XYZ 72.0 688.737 null] >> endobj 247 0 obj << /Type /Action /S /GoTo /D [921 0 R /XYZ 72.0 469.822 null] >> endobj 250 0 obj << /Type /Action /S /GoTo /D [921 0 R /XYZ 72.0 328.558 null] >> endobj 253 0 obj << /Type /Action /S /GoTo /D [921 0 R /XYZ 72.0 263.323 null] >> endobj 922 0 obj << /Type /Annot /Subtype /Link /Rect [ 344.78 722.413 416.44 731.413 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 924 0 obj << /Type /Annot /Subtype /Link /Rect [ 174.0 690.237 245.66 699.237 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 925 0 obj << /Type /Annot /Subtype /Link /Rect [ 236.11 264.823 304.43 273.823 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 794 0 R /H /I >> endobj 926 0 obj << /Length 927 0 R /Filter /FlateDecode >> stream xɲ8Ǥ=>}HgT3xzj*Iu2̊GKEҒ1 P1EfYN3r&4qEǤ&T\?w]@v ّNwZǻnf~y}s&&, 3qBӈAHFC8ӳmOcW mH'U$'/JYAͅ ٯfZEc'ܠ4Mi7b(!i<7Zi@Ae(*xA^QMLacy9 2]evaqW8Jo~)+kɫ7KopM7_#dŖ) i&^Iќ<;ɪȾսނAXl룬A:)_:wYŏ"~rm&ނ;ߋN4Ӯkk>xOj2$??_LhAQN>?+Ibe97ުy`,yvnG{a;0G8CG)G~vTv'\zH'!H_nٱ DK1W/Ύ!M&r:)NǪ:ɥCBJ'Ia0BބwEv5 @a!dEbMQ<:7],Ze`]sC0"!t2)=@Z0EW8VóC]XD_(![(qo cSnQ98QJB+[vdDqo j۾eH{C mvj6jD8!& u@Dp ж(>m.ff4s%ZA4ِc6\τ06=4fHprvbʒW@+z3DaԆ EAJ>`R"PtCoѓanv"#Y'S#MfBQNcY@۽"YŤس T}bͬ+wbs[b l ,R;a}YT6j89liÃ1Q#ڱ9T4BKY"gPc/I: qKP<"ܽza9Q QXY4sybz< +I?bx+Tʇs֐WSjT r%H>I:qYiq,+wfŒ&ZNƱe[N7 +Z)S3",bpkII8-|2I=[pNdK06pfﳓ@s-nBR?ñ$Lg61O^$*%l)%K7Eh (W8ϓ 7Kth+ p$k(LlK0q⦱Je#GrJl9cDZ;rt%yS^a/QtYNf|>ߚsK:An.N`ջշNxS4vGSuiEyN]!Ie$Y&g5&"@'狔4ONuV 5I 8 ѝr?@6Pw|'bs|f<γ,MW_/6?>̂64\dP/l4ʇ{"D* ArbJ+ϸZDT8ݣlj܉c1zznߐI! 0jE~;qݧb-NGX|flv" >*8_̧ʾrDӜrY߻Jb|UEfK[LՇqu]Q & LbAH Vt" c6ĩ,0--NiaS"#|/ K%H0d)WKz'yK=&v2….*@YEi\m,~_0 îxMr̈́dAB08,^I3VU #ڬG#{@bJOqx -{f uGbᦛ!6\#[GoA?6p)5AN»qs[AwwT endstream endobj 923 0 obj [ 922 0 R 924 0 R 925 0 R ] endobj 921 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 923 0 R /Contents 926 0 R >> endobj 927 0 obj 2833 endobj 892 0 obj << /Type /Action /S /GoTo /D [928 0 R /XYZ 72.0 366.191 null] >> endobj 929 0 obj << /Type /Annot /Subtype /Link /Rect [ 216.895 477.935 282.077 486.935 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 617 0 R /H /I >> endobj 931 0 obj << /Type /Annot /Subtype /Link /Rect [ 275.023 391.691 347.045 400.691 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 932 0 obj << /Length 933 0 R /Filter /FlateDecode >> stream xrۺ]_{ƂpoMN\38[l$R!8 /v+/ N[_Ii$?,X<' 2@I*Br 稐5 ~xGX F~]|{07֋lv&yX]^3r{L%1cL$RGxRA-i+RC*Dnxu{d&?*ЁqLGTsOH FtD0<Ֆec?iw(1i)|D3L\rF#gZ^tu XQYbP~knf>.&6Zfלb_~ʫx8Պ||N59^յڒU|XN)%ųmSjR"}67c~o}VNA0SG2h f`!kL#*USeV?9埳oc{}Son搼:ԮJ +p\m:S#SDK 22l:P搕[cPр\OcU=3#"Cd: *Cs2cYfe2q)hL鎾RWo)w7]$W 0a2/K) MusՑ9# ``vϼX Hqb3ؾ3ts>8ţR1=h'O5ɩqPǬiz0Qۭ0>#ah~ V!O.aiKMҁr[o034J!誓:@֐PHgB;x~PYaW4dv"V2Zu .+Sl߷Qb$Cm!Kux}sm#q9%{+֢q;)6{GqwȘC/5Rz_z:)I.&xv{0;q?Z[z릺qS&q1[m퇗kQW~ROB+(ɨ6>Tdv00 f>4M)NL}usgK.hsKٳ/O3.g%N=Y5";Cx[.ďʅ 9Mb&aj[CG`ل[ט9qgC1s Eҫ!&I~!J1Y0$%qrqȉX7Qu+ =w8pڥU[wmͩ9`& $-c?)TCmoVy{@!wQp} dn -IBܬ=`nlYy_3!w+TUX\XR?.P$m/0X%SYI {| Y V!M!8S~=*HHل}ù$n.Brf4 '? lPJ O— BD BDf> hGӡi:eS3!ugH\ϕn|sȰmOQ~y˚F<9EMOupge}y`zZsNC^맫bvL.Vm|h45( endstream endobj 930 0 obj [ 929 0 R 931 0 R ] endobj 928 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 930 0 R /Contents 932 0 R >> endobj 933 0 obj 2771 endobj 935 0 obj << /Length 936 0 R /Filter /FlateDecode >> stream x˒mgF7]*^g}p|R PN> 4^IUNk 4ˆxy^xiEщ^*RqAI׈=j^{oMOXSyl%_7%}L<xk8ID /r? TWVN=_ϛgFAߚR?!'Ke~~4fiKDH #>tX(ߛWw]VgG-gf|,h]E[~d?N=[}ö{:xhG. +ÇP܋B†8r7Tޞyx;#f^O#~H,Σ4|<=!I4 y#콇{f>tdGÕI ndg{޴R0Oz9<VJ0GG5{2=?,nӸv^tbm9Ԯ}kCP CUXcatV40ޡԃ콷xS +X?!Hy5\ l |Wv`Pn%K"t f0aMw7kǞfV[y]·Bu`JO )H-l@w{wpf%?;CAWt(R"Y[gt9\Xkv'L7rӪd'6 hq>9X$ KI<[iӽoz6L`p~0 -(R!},3uJ΀!u])sqJ:_Wf +Dҫ4~Bf RѕX񒎼k›FPfB IgP<[]!nxP`׿WSA:ݨW#F<+vBK(L˚ΧU& ~﮴00|Z aL2*B 2F=:WL,y(ʎsd(d Y$,Q5MC*Sr smf2]! j%~ -س/a7~Z+>a`'xW1är`ڼhg ͅW>*j5}I!ܼz=;75Yz瞙;ߴ]1{'c(I,])!_TOL1oY9pAphK)t(%G_c͕Dbp@&|&1gvfZ0\) }#a6(o^-G/yv,R8V."rtvV/-o)"官%fQeKHѰ+Cx' X!5qHtPjQ/hIg D4v,3G^N uנ'Nq}p-3h n(Lbg փu2*Es7 \]Rs´,[a?{NG3;F(օ}K{y\Akk927HA#<-ޜa,ĠkD~w /y)$=/kMCQT!P-ѧZD>A@2rhjc zw*`SQv\A#QQ$^9x0Jc?5^j^ὕHz{fIsHjnIRX?XZhq0Q+Z]s|;<%}!5Vyȩ3N`GAFvJIeIDLOqk]%AAD.3tH.q&Õ]Mg+Ehx= l Ѫ@s2b7,/pJdR&OqGgd:7_6Q/I'Q!)O)~6Cg]A"(G Sow?Ʌi4Pe.;p@$tC:F\@#IsY;l{ ICb+܏N>)L{D):H (<`RSqs* jVC+nNS;FINSυ,̔:kBuj,[CQ7Dd:'!ӽۡq8Ow/?IPN *D"]9s %H] |]FNliϕumMS|dK!>/+FԨ6}j6 Ern b+}cp'/Kh{G>ExYzd׃ O`ӃuEk RRR ௶q:?T-c*5Ʌ=b](œ}wy.N7`!J_8 ) CwAXy,f[E戻O>%F,<'lt"#n]j凢 \XF-IDS'c9b.4EU% j_%CS~;);P%} ?HGJ?. H]e^M^`F"vy+!!QaoTd9venHag6zŏ-F9ǫ5Kp9\пD)~jkv"?&a4I"NFHΣRLR[;w#m^1jO"%c}C.8G!f׌' 8;u A2#@i%D? `J!ajdDQ/jL- ]+H6ΊkY oaE"[Ҫk9;ECad`;(9 &"M endstream endobj 934 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 935 0 R >> endobj 936 0 obj 2945 endobj 938 0 obj << /Length 939 0 R /Filter /FlateDecode >> stream xZKϯ-U\-qWrީr PC\,z7x&905F/@}v,lZ~F9Ym,Hu^d$/HK4zND䎂?䗧)%?H OFԗϑnvߒ~)9=ӿ &^l-%\S/%nLS7NJdmQO nhWI-#O`<2ds N8ypfx(6dm{&;gɵ^~+rUs {_SfNIRtX!L=3vL9'-E_xNL%%d/kOܯ* ʇ+K;G[(3kH\Jv%=67ǢF80Gx*rpqu0KC#sYǪL#uM\~3y]qZ6 #/vXaЇ6e>H)cdrn?[.X0,EKd:  1cX:|3pd!Yk)؈wa~EN WX_KцA4z_v*]q'1!BoDPa1%*.!p):Ғ % ['4d xCVdXՠCoANdCNm.=sItmt_jŨցnH*h}veL-hߓ~6OVh%Aܘ给!|,K2=;6"jmb<9#h{|XtdYOGR$mc#K!痳KS Ng)!$LN:TJ3 j4x;|xFAvCZ .La[g pH:IV;6U &(o@Ӌv5L٤n3u^BF`}!kE0mGwx/ tX0m&y]Ho,h9a Xfjul Ti)A>MP]IxNoا Jwӥ_M%[HD:um[^ [CZǫ:ۻk`8Hޝ<<41;_= %(2 ? ڊ lvФ. vөFPU5M,Q`Фxu i_ز5XQSaz= JÂ̱ʧ0WV/YhSs{X>_#-Ct1X[2!{C}<\5Y,9]!I1UӒ:jLlź &1yALv Q kV9-UoT oc#Xϫƶ95"<f@k% oVTEY+:̅ S=ΘF(%zzg^ Ɉ__\[v~f-6|fS76ﴕ[_u:KF^< \+pl.y": ȝ9JqƷK`H˷dۤY]o zJMZHԉ6m[jk 华pvo+->e>ěvg5T:dL'sF iufM*!ö#Ѥ1=DQ0zHitz&*VӱY7)4SxzdzK`駭^w"&BJXm-PX/mRmg`*lh>\4ݽ-]"w~l|e1 qFYxGA%[_vHZ.a*-$XRR’gqX:!]lugj8fٌ;r,)'־yp>Y`}"s\HcxmU*Ҥ_"]zF Eּ!ővϭzzB=Eikh:"18BEsl2V-$%;әE[DLjVIi ծ`3-ؾ{tzDZ~:G @ё`|f@#< `E0,3ПM׫[s#L ۶ 8:"ƅ^w"E:<Aq?~/$6^fEv ǿX1-݋ݍtC?ď,;bCh$⼞BiY `H_01H 6yRT ZCU4X abg1Js FhӏzҤXokj7HX2kw֨F a[œ`>75 O.<MnC/.\p{q%%$]Jr>.dN} Y6.ilA0}}Y??@O?3Y N]Y乙s\C] Q= ^_ +g^ϼ>&3 {|\j/C?re~&^#Tt\*WpA/I]&6N|!m('l endstream endobj 937 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 938 0 R >> endobj 939 0 obj 2892 endobj 135 0 obj << /Type /Action /S /GoTo /D [940 0 R /XYZ 72.0 453.181 null] >> endobj 941 0 obj << /Type /Annot /Subtype /Link /Rect [ 416.18 292.022 482.84 301.022 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 943 0 obj << /Type /Annot /Subtype /Link /Rect [ 310.91 246.778 385.07 255.778 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 945 0 obj << /Type /Annot /Subtype /Link /Rect [ 171.66 201.534 254.98 210.534 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 944 0 R /H /I >> endobj 946 0 obj << /Type /Annot /Subtype /Link /Rect [ 223.775 87.758 295.128 96.758 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 609 0 R /H /I >> endobj 947 0 obj << /Length 948 0 R /Filter /FlateDecode >> stream x]o8}~(lv{HMw@\sX>(eǞ#,aYck&}lS4$%Q$ERY_i4P[}7%̐b# 4F;tLQ%8!u4W_} s69\ud3#hz{Q@db((!vuۗUYo7W}cݑ!!8U"*E8I`h(!I<w\JPӀCG:Q-E+Ԗ,%K/e; IdYe0#ι/UuRkT1)Rv^-ufB˛ ۡܣu:+xYmE㞷xOh=r)E Wun/]$a$^h0 Y7qlE ~4[2"/IOf}0 ,qSǚ1p]m;s7$>`]y?y~e Mw˧;fUp`ܹE$6/r}*KFP$Xxwͦ|,DKueS[y9Bl WU5x+*;M Ξe_XDM7zr|/2/v_@ M2#\̢ݷeݣa?'PB+Dnޡ)B75\WWe)I8X-$C\8ѲWd,=<,J< -Zҝh~ǻb3I cP1f?b <_Pq@hr>b3%"YeYU\F,C"o\g$>5ڷM. . }h蚡ͅ;r|sҧ4|sy 7k䟾ȫ98I pW2)P)L#y+JųaSBTM{ēR܇1YABmtqd$)dg1 1ŭ.ؒ-k-,LMY d>盳gĒ|Ⱦ >ԑ82~,C+{)PHHLTa^ \xx|.U!*kd=huibAʴ]{-xBz4pSxlݞ5eRah{bF2T,^[B9MSZ:D+2ɡΠ# ND,=YO*;%3fEUSZ}A(vRMj&5ijaekyr#nK'v&T!ȷ ({fYʍ/)O8t*޿`aery)=MI;gtY{1' 1C8*X;dPv()o\7#{VŠl b;J[яo|پx?ԞD3]Ȑ GvvSM>̶ƍja( {.ؠ{ hm5|;tYhyKn=o~qWHfG`~9]H1R+x [ zLB٢nӗ>{J67pkR. .Wa&}wLWr+mC$߈]5[(M2H.9t5LJ,Hcs\_Ѹʊ::rMr\S#\G\u%WőaxxW `};R3 NL/!<<:|CXzk/:!P=cDz}d{<_l$bzrn|Ə9أW'n/x}PnBBž*ѪIo]{:haʠfkGa:^,k#2ˌ %JGAshd\%DLҙ2j[1% <HPuF.-sVsHi="Md^4>!F'aHދ>4f[4` [ ᖗfb7$ɋT=Jb|I7eyj {o+J¢6**M9Y QGx~ΞD" b +ez&BO-ErF.UYOmNâ~*ۦ~7fʠή/<@,\ Q/:6xׅmʀK$/qb7 t޺ E!K+Q.hSb7P;,nYmcfdA\&3D|j.F{.$O3AYi# ! ۓptcq1óO;L>{:{s9yig /;RbYeBUW3 2Dr zݾi{YboW%$Kq2r%@7qs{oV=pD̮ om9S2`>?8; 80?R|G0]@'^Ԯyo t0D5]B5MeL;G Ѡp CVրwU"磒2Gcprv`}j6"nWFǗ5 endstream endobj 942 0 obj [ 941 0 R 943 0 R 945 0 R 946 0 R ] endobj 940 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 942 0 R /Contents 947 0 R >> endobj 948 0 obj 2659 endobj 950 0 obj << /Length 951 0 R /Filter /FlateDecode >> stream xY[o:~ϯ[R ~yڴfӦ)[3#cO}I:~)Qd[y))")J#.[?i9ibS=$%+rЏ\7 ~ٓ)+"Ș?Rg2|=O\ru) r' ʅφmr}.ٞ?% uw]/%'{u=i69;iW? vΝ;JްR-;(~uOgaX%B.IP|hV 8h 4Y.ZwX\2~^8q˲$Nsϋ`]/:\&jE|]U^jr/_\xO^U:9?4|/Tj5  3Gy4ﮯbࢀ<5PCgsՑBĔϬȚe6g+ggHPo_jU5[5 oB{GX 9cIlc84]ZJ'LzR>iM.,/a ̉ػeVQd(R,c_p͹b:FγX'N=. ɡf>{{ ۩xy].돭X77Ca4..R%JKBqOƓ=Z/E${X$wTѷ8C Ǫbk0qjڼ=)o2k6l3.܊`9{j@ju>*9źEZ:Z* dGءyUG~cXFEUZ)ТZQ>[q.dokV_h@ſUPB}cy6dƝ/Y'*,;<Ŷ^Cr}6W9I9Gmaq!O,[,y9DjsQ\3X]@6C[*&3.Rsc]FϏhh@V~vP*E&i]|?^6|Sc4:-j<. ?v~yC7GZX$h7fjLttɇwȻ*OC۔C!\X4}&ng7EAd ;ENÕG&1UEP+"XFyxrCw ,jC,JGh;Mŗ81/HWh~@Z:%D&oZCi7~Lser~GX)N8gXjcJ~:~껞tlq!sK[֔ȱIY%) Ί-5CwŚkM6?cAYyn0$XCɵjj(8!9;S#GwHH7MM5/8āŔi:an-M9JyP|7P ܰze ȏ0ITl|۽p6BMY2ٴ Q !_ bG#Iiz{}sjBȰ;EF gm׃Dɼ}vK6Bn!0Cc{- ʍo0M_Wo."R7f>|d}Oo,%GhckA1^u3ǏE Lkw(mw.vWMw "F"-^a!UMxC*eyG`u_dݼA/C Q%Q$GHxmt<Hh^‹P,f5| V4ȅ2z,Lu6BH|։0# DF7|38pn d6i:Pȕ1cu6#iV+R.:t娍"q6Bf"Bb?\fNX!c r с+hQ^ Eڌ9sNqF&a%^bt(6Cr#(#F]s"ZѤ m^ !9vZ7$&8[̯ NGh" Zp/z Zڈ7m7>DQ23ztBK`Q _T(B|xu%k= Wmygm&g]Xxi VAy %KԌ3^TICkI^'lNXe=q8&Ȯǔx f@#Uks;=+8nxٜ͓'|/t2iYEk 1uc-!uߎ #`{0wB<^=+_pԀe;k,Z UBd`灴u䧝9Mzl?eOl֎8+! 1fڶ|Td3nwRBj_v.\]^X \^WL `~fuB%܂[-< c=˗> endobj 951 0 obj 2616 endobj 953 0 obj << /Length 954 0 R /Filter /FlateDecode >> stream xYMs8Wʂ@ɪVڎvJn9$B ?貿}hH*sMRv᡻`yߙ,wgG"N|aBF2P9 I6}:z-8cxfEؽ΍=l%|l8 bQ41/&1ypؑﳪ&jMԾTQ*|!{Ƃ>^V*٦)%efqD5>f'\Ea(Mܧ< `t/>SGkhOk/t芈F$QcςYQp9L$o,i@MN֝\mwUC'l>}l֕jDS䲪A55-jR+TP."YQ2]с &Lʖq3*}yjMwnŏRM&$4bPxsUNجGqj\@Pk'U';Q]yuzk.Owۻk!W K*ӗwn qmsK)i @żj; <蓸bIk b} QN|(с 127ZG6́7ےۢy#Vq=`Zߞ_o^Oc̳iFWyQn;Zbgtj\T?۸E݈dq&~Kx<˴hԚ9%6dphƖoT@)aVUr}g.p4Fbm'U@v>6E4E{+1 endstream endobj 952 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 953 0 R >> endobj 954 0 obj 2261 endobj 758 0 obj << /Type /Action /S /GoTo /D [955 0 R /XYZ 72.0 509.939 null] >> endobj 761 0 obj << /Type /Action /S /GoTo /D [955 0 R /XYZ 72.0 142.353 null] >> endobj 957 0 obj << /Type /Annot /Subtype /Link /Rect [ 174.056 564.489 249.311 573.489 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 959 0 obj << /Type /Annot /Subtype /Link /Rect [ 485.218 208.903 523.274 217.903 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 960 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 196.903 152.882 205.903 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 961 0 obj << /Length 962 0 R /Filter /FlateDecode >> stream xZ_oܸЛm`M?!9E^+Nh%gr(ѧ$搜p4XD'ymgt?2ũ$\PG,!\Dh%F8 >d.ѿ3`6|F+Q?}vt=Gޞ]Κ1 NrB>}ncSᡊ>Su-1$Y>p,Eǚ zΈW=aN<]-6Kݽ(b(!O<1|gWkyI2Ɋ?|×7_~r~ֽC캦鞫ӵ~qi?ʡ屶C:V;SJ44u#Әs y:?MǾZS3*1v?Pm֮luj:i]8$GxڔHYdў<9̙/ln.2h^loˡ\}EL2Ҧk+1'1lirDl;)vzw|RKlʭ;>MWu:`.y27wz0.-Vjao, @EnHsbjW~:EG36Cz>n[5*c#=ctJD,^ O8}[o$5VJs.cy$AL H 2Y µ]lu9g2ŜƔCzIdpRj|jq%`H>o{Crѭ6`/P}+1^zm"evM{ rR taczgGm3IgT-F 'X*onjnv N6ePmùr+Y.ul]ylɊCz>|}y, L_RtTTq7pdz.!Iz izy?+;,A_YsE# U rMk=ۏ)mGyd3#U>6+G%5{B, ٹ^_8mP \sь9Cbg$1绊^z{"dxӻnyd}$:G„ET`6~&`Х;<{bbMa)<5Rh)f1W'IvIy=Đi))`+pJ"f$H]jcU4[T)TE&{h!.q Ii:_˧Y_nݞ̨;E.;\-}2SB~<oZ]}]ٶ.mӸ|5{9XjLP|SI!F6l#=SPc{*)I Z O]gؠ3M,Բ 2*(dl5vs.E*[e\Jn;,g3T4!t7CϊMXWv[H,ޕ<(\E@~x:H$'tjki$&XN7̐q^ y*e([(%Zsܐ\3 H9l\E();6ۨ{)#S?tMe{e$D: @2NdYz d~! rhRn2ABR \˙o#!ui5 $\$n:B"aHb!#Ӊء#&zٌ#;l.ȅߨNE8."+F6 C;ϴT | $8b)@|Af mGB6K(K1z'ߺ8,/#%i@֛\$;"[bOw4AԾM"BBBVhH )%8e;G#^r{}/>}&aT6lS@]~oW"OO&|NG6bo[;;0V`ۄ-Mסe[Sz q$v#5o]='% FHFe "N;a[$M)[z !![WQOx虻> endobj 962 0 obj 3021 endobj 770 0 obj << /Type /Action /S /GoTo /D [963 0 R /XYZ 72.0 445.989 null] >> endobj 964 0 obj << /Type /Annot /Subtype /Link /Rect [ 439.413 759.389 513.971 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 966 0 obj << /Length 967 0 R /Filter /FlateDecode >> stream x\Is8W0]l 9dtzRVh 0M 8_?IPܜT X{ 08A zP)raǣ cϡ qC*кB}\{}6øf%[s?"-Ą8DP   ;{[uW*CE$/P(JP&ӏ2=\X RD0qluQסuzbK \-FHnxb7G=eq[>g#89"D.hW zVst)|P,Ja.7AŶbSلyتT$}M3H֍=~=BAS8eOWqUS8ń޴VLʮv ;۷ h}X[COu񾇅 f%wxy7/$Ɓ;hJs;.@w/婺-JUN"b#3'( Ha˔NJJ;n]ƽxƛ]&IȪ9`=Oz${Ryµ8н"nn1(Mr ڰݬ`FC>TTfHG |!^ h!nբ.4 +MWG:G=4(ˈ5}O󠴍IU7Pz2nffVi9ey+Ӥ^z..3.6#G)OZ7F=Y=0=} (( EQwڪu ჈:חW^/I)쯤oOX=+Ng(W{LPUUKU7T5S(jTui^*,cώyr՛I+Nd5sZId0:cte`a4O}fo͜~?ȸW$alg< 4aK'š9a-<ڌ2%̧IbtAr&pj7LW ۳Ӕv=Mi38ckrwϐOj_ELl6z >1/҇ϸ7Qs-tcc12zqͯlP9|r3ly_M\t;$QN /S]٘+NL5sz>1Ngg;;WxKjoƹ|q tZ z'yPB70aK}RyM#\8ԅfSFX=rmx[1i\9ʫP䶾/V5.Tf`LYux-IlcͫɱCd*wR_]:Q]}Ǿw!< `,k&zK$u8g/Uy .q[>4(J;j5OҺg2j R}<7͠X*CB*V3]L'~J ~WT Z988*ѱYL}ol."P&ur3oF^'ZʌۨtRyT~ t L̘$ET~(dk~~mtwݵ﻾]Ïy727J'[;\k VKE:FI l*2?`yݥRi2VX4ܰxC,Ü~^Xa(gL4c_,)g>:U<EYJ1(l49KtmqsCe1sr?n8Q9k!D8ndʜ A&hA=ry[i3YG%^ߨ41aݐn/zD,9(zp8+R[yH\d݆:Dm#?^`d??9 ؆E7*i,\7%V/7ً8OÀA)2ʛx)=>eLö\ǔ0eiVi`._oM90 LrtJ m؋A ;L]eݞ(˻>4Qb0V5ߕ~铋~;;:+1#)7Gmp d}M:_ev9skO%q}=ݳB $v( >!z;\:βչ`ڣ endstream endobj 965 0 obj [ 964 0 R ] endobj 963 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 965 0 R /Contents 966 0 R >> endobj 967 0 obj 2291 endobj 794 0 obj << /Type /Action /S /GoTo /D [968 0 R /XYZ 72.0 769.889 null] >> endobj 797 0 obj << /Type /Action /S /GoTo /D [968 0 R /XYZ 72.0 676.043 null] >> endobj 800 0 obj << /Type /Action /S /GoTo /D [968 0 R /XYZ 72.0 533.848 null] >> endobj 803 0 obj << /Type /Action /S /GoTo /D [968 0 R /XYZ 72.0 265.269 null] >> endobj 969 0 obj << /Type /Annot /Subtype /Link /Rect [ 471.245 608.404 523.274 617.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 971 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 596.404 138.33 605.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 972 0 obj << /Type /Annot /Subtype /Link /Rect [ 293.02 596.404 359.68 605.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 253 0 R /H /I >> endobj 973 0 obj << /Length 974 0 R /Filter /FlateDecode >> stream x˒۸@m]7l]3TG$)&ߧ9{&' WҐ4j$!E"b, <""'rIHx s#Z1?a͎0b 5GO6I>_€1x*ӕ$I(C_|D@E{}qt-A40ӅcwQ[6Q;cF8F<ֿL6/e"H{PKas-ʮ+Com^w/m +L2,P)ݑY]|?FQHS _ÔF D<`ho =GȽo BrRw3CCZq<սwWl_h ALPY8a ;3c}.w&5 fBZËqO$Ba[}pPdKh=)K'HNl!PqӐ_<n˺}RKݚC^t88s#H@mK0f_Q6E?uEtР~%Ë̊Q@×Uws[s d>o{c@M0W#2g/ϑ`]\ T'"anFZH 84}wBox| Rr }\{&"Q31ez > ˹w endstream endobj 970 0 obj [ 969 0 R 971 0 R 972 0 R ] endobj 968 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 970 0 R /Contents 973 0 R >> endobj 974 0 obj 2699 endobj 944 0 obj << /Type /Action /S /GoTo /D [975 0 R /XYZ 72.0 769.889 null] >> endobj 976 0 obj << /Type /Annot /Subtype /Link /Rect [ 430.6 586.225 502.26 595.225 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 978 0 obj << /Type /Annot /Subtype /Link /Rect [ 435.46 85.494 508.616 94.494 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 979 0 obj << /Length 980 0 R /Filter /FlateDecode >> stream xY[sۺ~ׯ3MԩtNciL"!5/ It߻/$]b{Ć+'E1I7)$tHo[۶Kg9>)X䓂 h,eQ-la0,3$|Cm[яCN8aZ6z~w\ Al h@ $a"7֞m6;Mw{dN'cZ!q1|"'.Kj_kS04 RvA{m&(m;p˷#;/yۑzGcUKvuCC &E=ۍ$i]aMءa[!T1(DE>5IkER z|S~zKVMݰ}vSbnܱ#<,dUW~%jEZf)P\j?j$w [@C. \+m6WJpvP0PTY]Fs#vV^3h)UFخ!wB^W=76/"QakA tE/xɋKz$MPp U[_|NH(IdM&Ė{(R!LVm>o&$SM<Ar0h\RKHO 4Y,:MK:s Gtuoۤ<$yu-slp={>  s l^\㑥lGk .t1~s9BР͇ͥ!۵lnmVyF˻כϏl>W 'JXS%P$J}p/V uՋɟY;n|>:Z yUo|t8.li;g6[ ,߅sf-y3u(:]NUtѸ@ kتLj8s2Ӻ4EǂuB Mamk);EU*ja!"}̪@6_Ra?-_u 3L `@dLL1]H$6:jˍqv0m+ |,apԟз\Cg>4A{(ݝ1g2cz΄:TͥP'cQ}U!X{LRfY&-F0];g}"iRk`zؾuMĩzŏVNhaU&]sja'73aqp&Zx- l$LfeMG3` Lu*L{׍'xa_Vn|JY~:LþG"ezl^*L3rl|0>QLz2F@0@ռlgR\pSӄ;_(xEtE#)rvqW480x#Ql&m쬄Ƽ836|: y­9yh4j^Zfiٽ STI8y:S>FߛcP1#Vl @ W9ӺG~d=(@ xj]dqpDIy:rKzN6SJ"{!\0`x킻pWP/BKpilXNTf0`1;1+B72L~rox:~;q`"Rq 8߱(l6Pa?>﷿͔heKNؕGb" Z.hMzyfkt_Me98ة~GpK:!u|_!bOU_Fevz;)v&|a0W@okiMt НxӦ5VTzh>Fq _ `}R&9Ty CP +}ȉ#כؿ/5:m= ;?8bD> -_2zC! ɼI?a)N~/߿U ;d5uwJ_4j렠rIc܁w?=C( "kӀ,Yy^LH-HQoJ $r&A8vb6> `&q .^--\+\e`rY$ $瓘06/[>6KAՠx8kPW>Q Y'ZʸMIJSt J7tq}jAXssG9>|\)i|UqLI- sMOFؼKqD& 0MTv}C[wcȳ wKwMb-]K@.d'G'uR(㧙b j:79 ͥ3S8p4ԷInѫwiގX9Bf ʞثэH3Rtz/6C%|7~n/'Q~|,Ž7˪|O5XQP&>= Q3 s3A'^lE2>$-Dd>T&E7*izБZZR/0n h83G!f"7-opR@0^3rz%5XcOOk7 endstream endobj 977 0 obj [ 976 0 R 978 0 R ] endobj 975 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 977 0 R /Contents 979 0 R >> endobj 980 0 obj 2684 endobj 982 0 obj << /Length 983 0 R /Filter /FlateDecode >> stream xVMo6W5MR_a-6Hɮn Ɩci$)51r73~x0 82!s G+d4!c>!ٓ+$9Ę,x ޑcw lWM,,ջ7~Oy~[yeH8#m//i Ƹ$"Y64)<,*-WOdQ߇`vlw)Y6{9SRAcj Mbsʚ'\ǔa)BSqX$S 0Hps:,3j!7]QLcΓ$NrP}KnwoyM:u>n6fyays{=jVDV ziDfS΀p@6WEa.T 8ۤ[uʵ* 2 eLXy j^/.YVTZBǫ\@EG@^!R+MKJyh!z062P~ >TpX$2M^>--+a0 ~;̟?vS8r6ŷ: #lG3n>,>¡kGpA|I% &ۈ/"^x*\K9pt̂ ,phTgvz_̃_#&dz& A'D&9TK]zLhq?OcZ4.<`f؛:-AU$E_Tm endstream endobj 981 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 982 0 R >> endobj 983 0 obj 1063 endobj 985 0 obj << /Type /Annot /Subtype /Link /Rect [ 447.964 143.032 523.274 152.032 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 987 0 obj << /Length 988 0 R /Filter /FlateDecode >> stream xZY6~_lݬ6N!u7[qKHj~*JZ aQdUE(N$%OI,lWȨ!cpEEH 2 5D߂?@nF~w# 潿a ;Vo~f@Ko,d&_FFNpǔ'B!#lN}Ѓ˜OIp҃EmLYwF/F8F7߾7țیQLc4NSDySn9O~'o{7>}140r ZK"DyF"cQ*s>r R"oZRɶ*ܑS^jLjC)W1Gչͫڌ٦ ')pZ[S.u3_G( ʴ׏few$v.rq%%bR!ȅ^Ĉ)% C`% u1g`_PWr"&QbJpߜyfI^cwGv)ԏir]`om~e5XD#40!/L,;$w,K*F.j] .vZ7ͳ_`eEEM0IC.<,Dl_7zʵ6::/[]ﳭ~x:R.˃Ve3pmGc$R*Iq9y0Ml{<?Fk7hm^ΣaA0iH%?S@$-#&1pZH2bU=]ߦCI^}_FUu~D{Aen|&I"a&x}b4_9l'@T gݨݓP)MLg95 $Ɵau`gt"Rױ 0dA9T[LB”YDߌ1W=_/a6Czs9՝+-tr[j -d']ˎ@fLB$OL2 Q*x 3$ebLRL |1" 0ltDA2Gб PRaUl\OD(x:!q*!l{?t0% yq%=@lr#6Yʆ?K0`mҝtԳ%b %ψ1X+Rumf =j+B~Bz =d@D.kMOEO F܀Ag9,TIqO@Xk}*S<*q6b#H"mG;r}J _?6.@/CUT&4=AWW ,! >5[IٱnŠr^AOa;$0bmp>!8c4a+|b44Sb=$]C 9Ӕ't 4TXO+/!"GDGMD8]Cx$f7[ ɴQH\O>$"D@P'm#Gp?:4b(\v:uuK]ƥɭalڬ4XΡ2q5"dҘGx|v4٨{3*,Cc(O!o(?έ'/=LN˖Gsb~4=K@I$xqtt;ܞ GLX@exWDx貭sݸ+ 8U 2N53Ddet5Gg1;o$ob|a>!aUAǥiS,ۜRiQz9f/]dµLmڣqXb$o ~xV:hWe`6KZx|i8&8fmqF;GN..*s1zY qQG2B{PnH-OCi24̕c1 <x%\$@u=&ދQ_ !ꐹW&!S8$))7^WdS}Ɯb]ČT 6<RvQ:x=G)* |ovGIW]6JX"G(xΕ dLY."دm4_Lx2k%MOL]OPڄ'@eEWsmy[Q"=L6$*53]I{>{S49X#(ymu?6'cE!1>FҞ/cR5Xʣ^{#|jD\ci~%?5ϴ27fu8{5Qy;jg D\]{]ّ407KLK_V7#ĩ;HeCXo<?HtA endstream endobj 986 0 obj [ 985 0 R ] endobj 984 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 986 0 R /Contents 987 0 R >> endobj 988 0 obj 2926 endobj 990 0 obj << /Length 991 0 R /Filter /FlateDecode >> stream xZݓ۶o>OD73q3mחv:LBIԉTH_],$Hyx&b?~`>O e9۝~W < bx3wsF[g4#]}糿33= %w,hNOw_~3᳇`b0|ߏY ÙtYs`|.=;UuɚK_5ug_FϳMwRDi}ѧ8yY_~)AH}C৑SwQ[o:wFeLR i'Pp>͜%@Yĉ_~̌φ{c$Ȅ]Ol y}[S<4yIo RʽxrYS+27Vߘf wǦ6Msp/^Y̶SOx+I-5RJ3}Po`ș;4-!U4]/ H`L,^xTAޮo?ư~8=TmkUE@惤62]zr3pl^MaVF:> OAS(֎$ D8V1L%ٍF{݁`E4 QeyQ xPCȏWK_ݗz_$.0WEGWզ8B -cͶ%;7PA.j{.^:}aGw lD,Y]~< #&(7E5W|$ e#K]Kch/8\''r+,}'C/als0´PŹ q,,kC@~nx\ oղ b˓$rpaRCgؖ%Xc5Ѻ ^!mE<=;\O'(}Qֵ@%#4K jk (:lQWZ*5uZS\/]c[h}u^/(KJ΍#@@{$ݱ]\w$ИC( [jInyg<4r0Wh>Ug*eCI+O2g!O{1$AD6G1[B(m${@q0r"o>A ϸY ccOCQLc Vϴ#@I5DOi$8."B?;p0ԡAjj$h:Xcٍ_@ulP-u|=qoo[`9?( D*u f<`' (v ox~ S["7o?^lGz>QMх tC@o% y{YxHu( ψ*& 4)]w?CPRդҔ8k[гTk ER˙?<<P,d(wLZbAp7z]S{qFLxizAן ȶ#@/mg{rUXfX_T6@-|3a1m:p͂d&)z)(1<+{Bl:Qÿ_ wvVԒvÆ*BIHd=G&Yh~&q0tgo_Tc٘" 22Vc$>2$`)x1Mo֭_nC|Iԫ2{|bfy>faϺYmau=*)TJDC9*QJA5);Z8D4@Th}DEsωB20MLOJe"T"brm"rȳ iL1լdIRR5qj4˭r GD\JI_ 7C*DlMuLTͩmp 2`}l1y sa0}P, 1ʽ*"V14_}j /k 骧*D i-?}Qy|zS;6~;(Iq:T2TEx- @h|<[>ëӜݍ !٬/~+yw$?-@V+"*y\ ;?kW endstream endobj 989 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 990 0 R >> endobj 991 0 obj 3272 endobj 993 0 obj << /Length 994 0 R /Filter /FlateDecode >> stream xWKo8W,@dCc6QYr(P-ٔ=) r8yyg?IH/;:uC%),i ^XP]|<PQmߒ}>(dLCOKQ'%4rTQ,>>tЧW2:잗cۨ\~xfq&)( ]9MˀfAqړ L9Z s!I)s[c&N^~\XR7|4!'>AYِ:임xB"Xzq=Ɠ6)2 4bXBUw7f7hxe+'5l^i{YUbK)/^cW*2FSr4qE`1 $ݛG.0@0Ď1h# L>֍M4jD YB- +XcW rͤmwJ4yipyZk]H Y%4 RW"XYer#Y,䈽)B)B=.Qi:&W Y]~z:$ |K$![𲓅-$eJտNg}>Tf)RVv*:p68QH84nDۗop&6I v2Q"??M'U}UAV;PVrJ({֧gT6Jf3"$ah‰_@!L%+ދ2ƣMg5P}SKֹ 2#q٥.{zҼ<")Eш -< ;Oe>9Wy «QF>.؃2E] o.wk[1;z) Z1[YhdWormNmU+#JrN4Utly^ߠqɢn6aWdr"*S`dOOqؽhR†CP΁-]O8i3t/<(=IL9' (5g. \ĵ׬~ݍoXVd(#Ǘ,@&޾uyD endstream endobj 992 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 993 0 R >> endobj 994 0 obj 1344 endobj 996 0 obj << /Type /Annot /Subtype /Link /Rect [ 280.361 596.785 348.881 605.785 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 304 0 R /H /I >> endobj 998 0 obj << /Type /Annot /Subtype /Link /Rect [ 454.752 596.785 523.272 605.785 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 999 0 obj << /Type /Annot /Subtype /Link /Rect [ 188.59 572.785 260.25 581.785 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 365 0 R /H /I >> endobj 1000 0 obj << /Length 1001 0 R /Filter /FlateDecode >> stream xn8򽿂,`0$E]1Bfwk:~Duf6dbTVBI8Iqd) "3YHH(,DG4 Q!qGgת\~ "x+@\f6G0 '?Eet'X8cLGK! 0ΊWzf43ri$ fd&,w9V/OebSqNX*;ה7_ow>ga8s&pl# b$&Dt6~藪ڼ*./je}JqȄSJQM&+:IFoVLCsĘ p@tދRYcΌD)i%=wn`5]oFJ Uxrgoqւ=c18w EsFY%َbuEmT9[̧"۸Bac^_vYNp9 Hp?-,ij3Uhx0ChS.Q8_6o:Gc#a9o+#5DQ-( nf{ ᄄ1o#Nf˶F-9rWϢuiv^z#,/#|9G*aw1ox%9)9jz `M4D>Le$Aw'p /Q@'bLG)Dy[T[cUmU߬ ʩﴉ~_br 7LN~~qL?ґ6PQCFa+ aQb^v5/6yڱGk\:ztvs=>I٣OT_ VǏL (Ԕ"m v P{ =a0ݟ\?3+MY#w7ƋeBy~W]W; $~CnG%,kFϚclNV}fe pޛ Iby2C^UPϨ{ S\mA lă4I;}`˸WUOF2hYc+MI{<*:kF&kocdCֈ/3pe`)+צрߠڱzdZ[6%!g6|rTW$|=SOC"k#bpi4r2i36-|i8'@W?]9jas6NAaDnnm3c |kˉt> I0Ip.bj0 @(UoM->.^T4% k'3ϥwJK':[*wՑ8!*DV:3ƙ_Y4dr2̙m @Lޫ>߼rNOѸgy3B=ړHV)öwY!PC -z ՜>)(MxC_Lgv{aj7 JpƧ7To=PWz\˫VVte0+|Thөj%4VJt/҂]#ܣ1(5a?|˲v$}=SJХQ}NPg=AG>lЕw4N~W!v='yB`a{+[%žP(HHxho)X?f1k;46׀:! gV4e~f|U endstream endobj 997 0 obj [ 996 0 R 998 0 R 999 0 R ] endobj 995 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 997 0 R /Contents 1000 0 R >> endobj 1001 0 obj 2643 endobj 153 0 obj << /Type /Action /S /GoTo /D [1002 0 R /XYZ 72.0 679.909 null] >> endobj 156 0 obj << /Type /Action /S /GoTo /D [1002 0 R /XYZ 72.0 395.296 null] >> endobj 29 0 obj << /Type /Action /S /GoTo /D [1002 0 R /XYZ 72.0 191.673 null] >> endobj 1003 0 obj << /Type /Action /S /GoTo /D [995 0 R /XYZ 72.0 769.889 null] >> endobj 1004 0 obj << /Type /Annot /Subtype /Link /Rect [ 249.69 714.399 332.46 723.399 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1003 0 R /H /I >> endobj 1006 0 obj << /Length 1007 0 R /Filter /FlateDecode >> stream xn6 ܴDa7 &lfEqt7[F;_EVIdKv3LW_UzRg4yfl[|%HCy^Bq1Bs6#؏7sṽuo7ޅV|vx Kyp󯧛Ǐ=*S<#S~.ȫՎUBn~x:<<~kr6,A5`8Ip l(I4wLtA4 3zL9 QPx(se]Z7eLO|?˒,!Y`zԾ>/LEh&a}-҂1J <$|dy}-QNGWv\ƻxCbe~\bXa<́.y:*vB^EOضahey1N;JiZUՎ𾞦 z~[$y7rPDZ >/Q`&.oն_UBN|UL0/݇Hg_4]E( /Gɕ1x6?_#7`N} ̥XheduHj΢F?*Um[Լ:;͙975"kk{(y%.+3$JˉP-3 0rvz+mU d`Ū|Vq+hoM\r”\]@OU̮/`氝F9'`GQrK7a/ mdzCJo =ᠢގg].*N]ʉ$=_ZNF1G(.(;m3+?hVvv S&B9D-=ne7yL~و/&8.'DNЗ~&PvQˈOSmRneBM>m>kZ: n2]]O+{^O+oz#84K= xYϫ}}5 򚏊L4z (^g>}՛őڑl :zuUybz[t@7aܠȠ;t{Ֆy%Gz]] qdb"! d;YjF]H} ̂mz kX`/.c:gtq"θEGi4enVUfLQ6slJׁ("D ;S[URĻdg}#A̛l1#l3I@2Jg)DV$i^cǾ7=4W8B4)F KGعs$W0Q0"ad#x= /sruj45!zMks=5+[2^iMF⤢ߺ%_]SkH™H9HvwִKʎ`BZABU8_wQ|ޯ<*6i$գ@$d_8 nvwXH;> BFL I& #};t6j˥_p/'kbq/`sX#mHREcWe\ݱ=i0KpKL@,$eYTw ܢe^ -|^]XrI6A2 x_LD2/Dмv$G%C_y x׭%u.tʺsܷ_$aDƘsN5I,5}Ο7֡F:REA4oz0fwB endstream endobj 1005 0 obj [ 1004 0 R ] endobj 1002 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1005 0 R /Contents 1006 0 R >> endobj 1007 0 obj 2609 endobj 206 0 obj << /Type /Action /S /GoTo /D [1008 0 R /XYZ 72.0 745.889 null] >> endobj 209 0 obj << /Type /Action /S /GoTo /D [1008 0 R /XYZ 72.0 583.311 null] >> endobj 1009 0 obj << /Type /Action /S /GoTo /D [984 0 R /XYZ 72.0 769.889 null] >> endobj 1010 0 obj << /Type /Annot /Subtype /Link /Rect [ 302.537 666.415 389.615 675.415 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1009 0 R /H /I >> endobj 1012 0 obj << /Type /Annot /Subtype /Link /Rect [ 344.007 620.811 430.159 629.811 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1003 0 R /H /I >> endobj 1013 0 obj << /Length 1014 0 R /Filter /FlateDecode >> stream xَ8BvpӺ<,LA$3{ ٦B$Q=ޯ"d:yMUEXU,Aϛ=y횛?%=ЋRIJ|G^0oNJPA3 M{{?{>;W V7,'|}x0&bRiQ䩗(,{l~-ڛz-w3#''!P .eѕfCI0K㖳Y#.$tX(Um e}[Knz ȊH>s }7}u]8gw9UkZåܗaт廲+55 m6k*{pFXeDK8Y{dko-舧m)vڲH{S^eQd~q p'+`b۱)}]z_A%%apN}9xRJ>HǾ+1^8")(BJI-J{:jKmUYFQa:,o,xsב. .A.D<__yy1?#iFd?C>X3 'l>Py>88!GC6 O9I`~'\̟y G+ߞV_2 85Y[?UCQc!% AAAe]F JS5@>AdUiDi`qJ ?yBPG8"r?Ĕ`1tVb dyE'K;H ,X '(*xyA,$\$'AEoIfK ʀ2H8 B><_L9܇ .'I Z;p\ yd$,cA>4(KSK@͡uQ0N2B©BUٓ5TL HhPYǩ]=gLGdGxMfph 9Cv8&8: Iܞ-HMˡfݯgR4S}X(?;ypau+oul*;IfX ᦜ Wj kO>cPyaJAG9v6gW24ZVYXLd0`ivnXNH#^ WSU&"O}VҼJJՊtMz⃦.ySU{Xeg$2?{ˠ|_c$j&dtXGyp]f+Xzļ$$nĨH8X @!ld=X =-P#۲.P)I*p~:H +D oٌ% [bVqp=ЂH1)&xQ8RJy\BrJ8Kuu)uq?(y?AߚF1r|H\͆=!&)N.9Ő`8-pδF<øҘ8P3Si]Y?lFtv8.4 s@mkX݈m^:@UŁ,l>b Q(܍SYkTBijAF8 zA "^CP5͈fw>OD/:`.lXԎZH%$8 $ uJWp-KXh!C%* erELh2~qA=<Bܨ볦jY{_ tËR$~VI86]=d=,յn >YK{ve?PDȕ0j#|(bP}W0q|%x4=hL6x^*rQq]pW6 .~"U;8SK|s?Y endstream endobj 1011 0 obj [ 1010 0 R 1012 0 R ] endobj 1008 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1011 0 R /Contents 1013 0 R >> endobj 1014 0 obj 2936 endobj 218 0 obj << /Type /Action /S /GoTo /D [1015 0 R /XYZ 72.0 769.889 null] >> endobj 65 0 obj << /Type /Action /S /GoTo /D [1015 0 R /XYZ 72.0 653.596 null] >> endobj 60 0 obj << /Type /Action /S /GoTo /D [1015 0 R /XYZ 72.0 575.563 null] >> endobj 1016 0 obj << /Type /Action /S /GoTo /D [995 0 R /XYZ 72.0 710.171 null] >> endobj 1017 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.28 655.096 201.94 664.096 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1016 0 R /H /I >> endobj 1019 0 obj << /Type /Annot /Subtype /Link /Rect [ 243.7 106.066 318.598 115.066 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 1020 0 obj << /Length 1021 0 R /Filter /FlateDecode >> stream x\Ks6W)eAۮuy7ImJ`@q83(s1ɑmHic'LII@7CRE?"(Qz8h) y Y@Y_\q ̖GO=8#ٻAݟUWo~vl3 P^}!8ZDNXa9&z{aƃsΓ^Y:G=6W?g%#gbX8vg>Dی(cG,1t}@i|]V#0iW봇|#]NEd1zY[;UI#[(vzJNim\4"Ĵ!L%5g!|o"we ur'uW.CDkV<41OhFYXDw>tMMNyu'(f]WY3#`k"`;9)6iF۬nq8 a#ͅ36n*q{yL.9f܋f ?@;s:8dEŘ+,ZYJ,VҖr<abLW7Yd8Fѡ2GID^O8NYqC_+",URts~æRq[J> o.F1}f?VG`X(-H~0zYi8hV!!Ad`eCP'0yw+ا"95FlmSd ר Qp{玸SdNLX|xmؠ5مċ# ީ)My4hP8mA(:EvUy5& ؎P؉rUmAVQIMiKIlr+v'}Yz b25 ;}of!%cȕu` Swd_^CtdjI7R6"Љ0F o80B1; eFʵ]HBQdڸBp8q%U&v!h %EF OzFV\TwmBQwUrPӄ(FV˄-3&<%bf~i5,3M3r`$Gn80A"m_z_`060$F*@]B[+TR$ MBk 뙻>,F()bK-M}F3oYj E!fܢeBiC?7x"o }&gBnݞvˌR8=3{ -] Ӿ֋|8Z%wb[.SJL]+7꠾o'$oy0ɧUVQ6b擄e陹V\?IQZ~=Z[JֺObVgZ9g ȒIZ~ʣ#huHˤR4=IZkad<:rVIVYU-sJU+WUUV "gVY陲VNY/Y"}8ZhjX4T}1Gv!;,Nnv辚"nGcaJmNcrW%8DX5U˷oBgiQ6iz2xsTT_$r|[3јdAKl3S{%[->?38l !w(e~]+BƄSsr+Ċx"-mUP n묺*TCOg##$&͍V#FS)_ZGߴbmYZ ]:'uWt4nmNO.<%ܙʶ( Nu]%Bk `LL~H2%p(Sz 7kcYKKB\V+ɩ֟__*QVS7gJ<ª}r|Vc1BYOe Ƒ[tv`VE7`B :԰Te75qHSHD>MOH Ӊ>:+:Ͽ*3~Fh74قFu1H3M;rMv*74=u&v/{%PaF`[c`Rϒ0OU&MJEfuYu,toǣQBx>n=nMt`i(|6-a8G 'nx\yDh@Ņ\enow*~rP2#$MjDr85Āklqx>e%  0hWI8Ywe,ˋZj+8> endobj 1021 0 obj 2748 endobj 680 0 obj << /Type /Action /S /GoTo /D [1022 0 R /XYZ 72.0 769.889 null] >> endobj 829 0 obj << /Type /Action /S /GoTo /D [1022 0 R /XYZ 72.0 653.091 null] >> endobj 1023 0 obj << /Type /Annot /Subtype /Link /Rect [ 252.384 689.131 326.985 698.131 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1016 0 R /H /I >> endobj 1025 0 obj << /Type /Annot /Subtype /Link /Rect [ 484.791 689.131 523.27 698.131 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 514 0 R /H /I >> endobj 1026 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 677.131 146.66 686.131 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 514 0 R /H /I >> endobj 1027 0 obj << /Type /Annot /Subtype /Link /Rect [ 505.503 341.388 523.273 350.388 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 1028 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 329.388 189.72 338.388 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 161 0 R /H /I >> endobj 1029 0 obj << /Type /Annot /Subtype /Link /Rect [ 390.62 105.348 457.28 114.348 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 835 0 R /H /I >> endobj 1030 0 obj << /Length 1031 0 R /Filter /FlateDecode >> stream x]o6ݿؗf!-$za8llӱJry~C %RvC 3$ׂOs yN"APO"`#ܧ" 2 HXэ=cQ,yp!ޒ``=gs1FAb{O8((Ó| GE[a}1- 2> d`ǿҲ}|71xZ\Ov#LlE(z="|7JNE1%~OHBv5YY9isdMP%SJm| %ob=TQIt֒e4JpM$acZmBN=Fco #DÑO= 69/$͟ӗ%2!5Z+Nޓأ "=x|ut`:h:Nb*@AD,<d=0?O'HyT[?J̹GBeJVJ0.fMR֛hr1E!U]CXd4k!QIz,ϊGA0OcY5dWVxƹX|\(WQLQ~ݤ:Xm74safE,{ +ʯM3ƹ̟M% &K>*۽/{9Sri:7y;]{N\@=Xzceg*V q- hjLЫ.ѵVRɴ~ڝ6RN4A_Y?k%̾ߦ <Or˗sF/|F v%( Ɖ/p^6>@1 Z)Hc܁3XeE3+0Aѐ\ _ gucbe`ޙ1|:E Ψp_ʓF ]q  %m"fF79P!1i]AImϵ(7f<o. ,j{YYʬe5.h 95gv!7+b#'V{7h¹ֶt8֖u/ ɪ<5Y!/ 4O(ueXN5YKQ jtnYA| P@c5%C'YdHRoXK0%/xE(=jGOkX3>קmŚ;_^L]Smhh#f4r"fTõY3>+:'3KHMLYXʮnv:3±Nn!d5r!U*Ǩ!ܪn7.< l&%/y#mWmZc"Dr_>&Ilw0ų:\7B|5`=t4jO |.Ag/p#5^ R&7J Z*kl{А bϱiL7թn0Ⅎ3akŐ$\?ɍxF0HY.PY%]ϣO\]D]?'ج!d4V}ga\p(R8g A&~_(!X6NZ;К=>j,Ț{Uja=\ͺq4׆e~}D5ۏ $Yjȴ{3 $/Sh/{ՄM[XfA(8R!T~\ǣFt=wdζ>2~;tē xze=| "ߔJjn uMqIЃx4ӠUVu@VCqXjFTGrY_T?-ag&Mq S?iм80.qtmu敨CyS5/fF g[ljNM78 0p)! zXXFշϙ=_}A_@Lq:S3k, 3 F(;Z$]4)kXZ;Ao*%) endstream endobj 1024 0 obj [ 1023 0 R 1025 0 R 1026 0 R 1027 0 R 1028 0 R 1029 0 R ] endobj 1022 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1024 0 R /Contents 1030 0 R >> endobj 1031 0 obj 3223 endobj 956 0 obj << /Type /Action /S /GoTo /D [1032 0 R /XYZ 72.0 462.137 null] >> endobj 1033 0 obj << /Type /Annot /Subtype /Link /Rect [ 138.6 380.878 210.26 389.878 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1016 0 R /H /I >> endobj 1035 0 obj << /Type /Annot /Subtype /Link /Rect [ 505.505 259.264 523.275 268.264 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 1036 0 obj << /Type /Annot /Subtype /Link /Rect [ 268.0 247.264 320.22 256.264 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 1037 0 obj << /Length 1038 0 R /Filter /FlateDecode >> stream xZKs8Wʂ@/|$[Iؚ݊R[YPBRx~6@ޒT5э/~{.4QR/?}W|KĊa BD"z ~ {UgW0=Bg65>=:[<{b""P'VzǮWoK8F0N`:<jW<yS;)l?ێ}&Ur;$AXS$Ç!"i 4XJxsvxXlu?q'(}JJJ%giy,k~4Pmf-8 oh#lԞ>w 5[U?lhw>6uWuikMf'PV-vNSHgaᇽI[`ͥYմ\kj}Ζٜ:<Ќ|.IDJ%٢a'A#-œ܌A'IW:`cfkaS '4 Ge*a >HF2`KcdKa7('Z={ EA 'I>` <5i'_LP~T[ S\vOctGB`ˏ?/Kx?g:V!{Z՛; qG`&kbTONNPr<5k"uұD6`(ۮEYYOĩCKBKZPhR 9[V=ZC\jCdS^ih (?TQvE%BUb,5vvE>xHH#]X.ءH G8D+kJ)O"R&Xآ, *f5TZ\v Y_\ZfJE荥VfIrT~ݥf+W4F)l0a*iR*il}P\?v,Z^L/wI eQYW E(J(8znY-3s;x)psu8 aY![Enz^[Hc!x<R;NBәshMGvp^þ I[..%M]wy:Hq@ޱ)~%{dF+D@BRO~BWo\Yd*͇O+Q^ cӿv )Ǣ)dg 0yV%ddPTse_a`m>nJkj>!d\ևza"U,T!ՃdL&<=CQmD5REi5aõ(U؇+8iҤ2 I7VUJ;/džyij[r & ";4rM@ G:pCXYt *0,v:/\@h^vC ZxGH iKywYo_ifV5z ?,\ 6! Ix,@_a8}]7/\xpՏ ΅LV6SgH8pm?Dì1VEnUgAH961P7~>o?{P[;n֗QX gyFSb*j{hK2բ#Wtv<DGM$'I[djﯭFM}uNNg`lqh-T˼v/Sxr'2Dk=~-xvT0 Q4O4슿sl"22#BL6[}GV[MKIwz:kwݞ4}q#&CSfV3ࢫ-yW7fxgwHc./i~q;P.>>:9 7>*#e|PxyjYq->n3Y=x?ppq;!ݻ!.*"'}FE;B@(U2-C4×Oj pw-벢l<[ȊAŒk N-Z[V. W召d):\vNͤ }Kґ#T˲,_xI}@(t(SY׵@ (?t~np΋8 *7z'HC$"~ג qZβ}:|2vwSQAq@oxoԋwᏍ1MpGqD8[B:Zy!,4Ya{BHPhЧ֊%.z0 |lyfY}}Ÿh(`NS9iUyВӞ5;(״5ʬQyxx:eeVddeYg[>X?I`~+1k\ 9w-ⱲXǬ>#ɑ.h42Nl]cyӞ*{zC(FYC; endstream endobj 1034 0 obj [ 1033 0 R 1035 0 R 1036 0 R ] endobj 1032 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1034 0 R /Contents 1037 0 R >> endobj 1038 0 obj 2892 endobj 1040 0 obj << /Length 1041 0 R /Filter /FlateDecode >> stream xk۸`MK{^4`8q2EQC"%QN-N!9yq8C]ȁK.eW5 /TC}8\p(@1A5X ('XE/!Z$n/nrt3L8qQ=A7eU۶N*./(be>ܢȇ'tū4#ROֽ%>H J2+ڭ vhzl'vUIu 02 A@7-*lM)T֑F3DxHtZV+C=fWod9P |nGo^_Mz]ԥ6a}y]Fg1ݮVެt{f&/3A_]ds$uҿP/dNȘ?MCBK/mΠzDǶ>V2;߽B%-/XH u[h)Ŝ}7/be:>OA#39;ϚQe5ӝAO#Lb=xG>IҖ|p$r~ӂͿy$.̠لk@VTC2-I:HBO":P+֬ϙ|'T JŲbCwy|H6|FW -s>wNR iw<]*"&55ro iט,d%,/aFKcJS CdWPi,ր;d`9SJ5BuNKPkejnY[pEr5em p"Ǡ6ilt'Qԝ>b8 C"_* #`cL!m=e8PLT`cN[B/xٔ 5vcIf(ɑHfo]ILaU6Ц6 菼fie+syF?ѐ}|A{o~rXݒC^zk$RSNv=H!1k :KP# UŢEhQBʯ/eE8 endstream endobj 1039 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1040 0 R >> endobj 1041 0 obj 2601 endobj 1043 0 obj << /Type /Annot /Subtype /Link /Rect [ 244.42 238.922 318.58 247.922 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 1045 0 obj << /Type /Annot /Subtype /Link /Rect [ 505.505 185.226 523.275 194.226 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 1046 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 173.226 179.72 182.226 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 1047 0 obj << /Type /Annot /Subtype /Link /Rect [ 205.26 76.951 279.42 85.951 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 60 0 R /H /I >> endobj 1048 0 obj << /Length 1049 0 R /Filter /FlateDecode >> stream xko8-h>%15=.. ٦cJrܯ)iCS`3=Ù!_fwf~ Ph})^% LIC[ņ_Gޢ?gɌ_ggՇn5?~~5;t P`ΔajO&搅E&hI~EaFlտf FOH"1d3_ү/5TʘOG6 G;Qke,jgOx2z>)UW >()1u,5nJw;8dj>eJa6 Y Gʆ, c5Ԗ-_FymTv{T8q+p2Fu|I.[Qѭ",yOg)W}.^^FYtc}fQ{DuR; snIktɒz`F@OsyCKa|%t7^y,:Eph(Pm)Gb)ח'Ji,btLy^we^t&Kw=ۤ7GCFY+{@/ozf}f#G:|E"fPw¤[$&,t;yѭQrӭ/cWL{dqjREn {=LpUrK'6iwGJY8c/ކq@H3}9:| Wܶ/3K}7(D!ѨP3;B,oƼGpSZCEnK]=(,q=+]6Qi8;GwQ:!c̃T]lӼH V6{GW1JBpm CJy}ukɰG @yrsBF'a!.0! ^M4 )AéShXJ K%MYE6iBYR$q/+A)CH#z r1 8@K_u]FT$䵤.[ͪĩ Ȁyc1x67tn`bL#F(Dz | 7ǫJ8-6U)}ܨzM d4Nl`CY̟@K0/yZ4+*]0w؄92*r(;!+?n_*u 3a:"9RVݤ2?ve2 d Z!@NJQf4Cy%k %%WSBpD6&'9NniC wRȔG Sߐh)Nvy J(9|``1zvE <W}89>:*;ZO[A1p`or`#N}NVp{WdoŢoYH,C7Mq]p@e5d2 fҩ̯Yy~X'hL.?I _$r mՔژțw&O4peN)áXy2_,7ߡ+#$({KNLhD=_ B.FԨzʙ8K)1lꤒV=o=J|B3ټ2>^:c".&ΠdX}sL%\Itv@(8Dyٻ8\W? ,[u!Y[ -6 WmNjUzUwL{go{{4V=6i֧Q 6,# 4lId}z-WA? Wcɡ9>+5P2o@2o1>Zb |Ux;\v0[nMN J\*y([[`eM|]OaΌezurZ}Xl'U.Lh3BZr5ӓ:}y#3癧'[U>[70)cm3f:6#j9pֳ8:ҥ-69V2oϮ8m;f׋ޟ-' endstream endobj 1044 0 obj [ 1043 0 R 1045 0 R 1046 0 R 1047 0 R ] endobj 1042 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1044 0 R /Contents 1048 0 R >> endobj 1049 0 obj 2319 endobj 1051 0 obj << /Type /Annot /Subtype /Link /Rect [ 205.26 320.279 271.92 329.279 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 70 0 R /H /I >> endobj 1053 0 obj << /Length 1054 0 R /Filter /FlateDecode >> stream xX]SF}2n3}HiMBCh"$"}rlye<جt9wÇS:sΉD~I3fL 4);f]k`0cWPg';%cd9tM8#- N‡ANoբX7YWYeNǪ˾&]Xn.&Hƨ{i{pr:DYk)[ ΓJ\ae-&<Z`e,rGw8sxD 9wSb;E]߼^+]/y}̿M=^0JF0׶UyhOKʽk yv*!s.M rAj{)z7H3$ԙ RȽ0(3dEioݏRp.&$ߗU*VU3$(A=֎IxU! h9&JR`4!*x!/'@j,$X)F$84riMsC[IapBn̽Č3 Icbn$kGUr|(Ə쳛1vѢkTۭGx29eNP*H =mU S~Nբ+,>dM5MiN򦙓+ȝ̛hi$ KIc`!Jp 93E ut7Mu;)eR}|`ns}N9AڅjXG!#Eݐ[Tmde{~4)㩳dz3d!?5f)I fmm]raʢB؟Ь$]~U,& ܆QbqOKT8ϗqk;zHN0(eH6-q=8y28Jř89̼Γ -- C=c8zW7i&v@|ec4jQ Ҵ%bASѲ?Y]fmڑb&^n ԍs,t̢.<$pG`jn1[{#?dNf $P endstream endobj 1052 0 obj [ 1051 0 R ] endobj 1050 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1052 0 R /Contents 1053 0 R >> endobj 1054 0 obj 1219 endobj 1056 0 obj << /Length 1057 0 R /Filter /FlateDecode >> stream xXKo8W'')Rȡۤ.]ICӃlӶPYr$9zP̤=$jH3'y`)C4Lk>A"?YÌrarA}GYO]$xoy 8(TL-`j=GCK1 IPQtA_Oe2^򨌳-Db m58n\<,_\W&VDB=Ts+'7<c!i q x{wֳF1x0 BP!<²l/APmqLZSЏ:1%-تyUr6Ѿ],Z/YGS9xn(imJ(Iԏy[bbҾ~zfl'+} e=6:m*޴sX{زevRC̆*:Vߝ{oC>žK i xM4N٫(Qy9B&(]Y26e hr.)c<\'Q44)]#6$h1cf{TDvPy[G= U  衊g.ZW힪TBt12]>.opY]'>ftz,Aܔϛ]qP ]C!=%y~ E+n)VjzRSB$lq4.V}YT(t #:Qv-qvW[m\9Pwqȸ,: i~d3a Nj:`] ?R\4%J\ 5>Ěb0WE~|6rG@ϩB"dHI\8 0?y{=/H endstream endobj 1055 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1056 0 R >> endobj 1057 0 obj 1705 endobj 1059 0 obj << /Length 1060 0 R /Filter /FlateDecode >> stream xY[o:~NM$Us,6&.Ai[,4ɿߡ%K[s(q8pfcA҂b}>,~T)< g*O~, Upsop95"j_`[YM6VHrdJT5uu =hqWgh#W;.$OƼ3p[cv$HzX>ve-}h*ZU>Ddh*3AQ嗨_P ir@ޠcjfq9N46ʨ\vjٸ)2mcQH$W'ĺ&F+9cU~m?]ijy< M6D&LZ*[~;l44K=(i˔+!'3M4BcOipO+8XxHxM¾4FY]1I46yp=U$Џ>JO'HeBadôƴ F??޾ǍxER-@0YfH28.V^º2m3p'lfr"7Y3%`4yj8qJj)owRH$^ 'ў.G7eyC1LlKӠ+ ʗp[Ѓ/m"gb\ZZ|0(F4TQWIЪodێ޸8;* Tf"l!;cYoD) \ct3CCkM`jv֑0G%E|q0eEOܮ%I`s+w{G m%#GbjyQyZMm(3BUBqL4 =7t!O7ҤeԡNBJMiaܿ1@L,|۠'u]aYZ2Τ8r)}|d'1n_><ςc>3T6NL-8SR&OtUw8?b;}وk<42nj|6Rm?Cu/mZP4\wEmò+ md &Ӗ61r'\7'9y#|M=Iq#us'[~`;H36PK]%JX'!B O'AO¶MP?6օ`k<8ةoQPZ> endobj 1060 0 obj 1993 endobj 1062 0 obj << /Length 1063 0 R /Filter /FlateDecode >> stream xYOoܶ0$E8}MѠAa Bwo"?+-3p8-("N8Q~͎S$ B;$L 1hCL`?oїE ?0'EFgdA/_-׽c3?E8`ahG|meRgEN%(STp+Z! G?Z nDRJLLr > `&^tc45FYoYu?q1XR2H%(YZzֻͣ)Vj|ЛWFc^Zak'rҔScA@ :VX;g-zc]Q]@sVߢu59)9c hSOY,ʪ:g$:8"6/qSQ BPTqxzu}o$-jf;C!6~٪zʦiYc%zV]՗yDa ]>#95P+*WUz 7. [UԠ f=jx|u8AXy_Gsum5"=A8nQƅR(6ͽw_Y]Yy@yOc)B \5JRm!q غsv _5*bLn:V^w+R_P3Os iɻI]gesŘy8b봊؄c;!-A JZ3*UW-5ShVG/3T{H'I;BYGVBYpbsUP.zC6>3esZD$AE؋ qh ᄲOܭ㊦wkAT>"֙j7d@:~eb/nz=P@2FGU:57k1h{#k:wp(&j?OhY}J+lP|=> ( .߲T|nj I׭Ϳ]v՚;a,h,DRA&U-iFĔuo'?9{\+lHmbT9׋ Q}$>'?~<ds) 3sy Y} -ѲE}VUV8~Tps|vOVWj~H`M%'$DRm/з:*ԫ|x2> L˱t 'sd3' 'nP4}= p]rf@1& d P&;cE7|V1hLO|wY}_)Mz=C[Z2>(aU:C4̼qpye'bBein8N-m7C}fFL;ssV-!lN[C1 8MZt%>F(}(8డpE?bxgA4y1M疇ӧ;}[Y}mLM%i 5Fp)fpS6h6Yg{Bh(+Sn}ᮋO-ac#WEY kAқILM4lW# o\= ճ T1gwUHSWO endstream endobj 1061 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1062 0 R >> endobj 1063 0 obj 2188 endobj 1065 0 obj << /Length 1066 0 R /Filter /FlateDecode >> stream xnHh I63d4;;ĖH">؏nM)AU%Vuȇw#d mo- *Z=FSG8ڣcGY"_Wx&F>=/3~[?~>-ޯ~hcУ$Co]S:-rM3ߑcT4V\ܭ@} 6ZOH <&WPA qt4XeWG6V#5~mgOd`EAW^xdi̻% zVVpTzݾըkx=~T&':|$MK TDW\!kU>U[CQ֏7zReZ<,Q=B1c*? Xm\]cXQԇFߴN)1⅔{Q}E=^T=^juBh~dt:tT:Q-xN]G(l`ACY-e2urEN'ى xz6)վl<8?=sZȂ dwܤTWHC6*־rGq :}ϙ(B meoetPe.k"ƀVyB+&32z%ڴH7caXJ:Ect;yN{ɝzc|b^֛DUq90$ LE06 2200y ky@n =q0: ambʴl~]jx |1:ӮIk#ҁY3K`O-eN9_OhEe*h5,*38P=)XX U:[tgΌN p(|%mE LZ߾ǜ`g/ 0cadG3R vAR3=ǞU*)b`?Q&'EB6Y}hYRמ.b8#/N$X'#ғ +l$Y AA%? v% S!&d@rp>Nz-=n[[)n>r0)ǰP:Wr]0B.kXXXk3&r/+cܡ.Pҡ9f#06 /gϱ[ኞCBBzCZ.[a4 YUEHҮ0&Z!͌ ?tܴyy 1 5v:ŬZF2mdۏd"S2Y5Զ:+4;벹h9҈{I[/ҪVcE<VCFBo``wml> (m=W GY%z8bߛX,LIۦ*Iba`oE@=7`N1·`TpH,; wr8ǓxXu>uNbri~eEzsZmT\M5`qJm _8lR?aϝ]8a=.^ vLj[Rb.#9Np^,H$-?S5Dl 367Y}漝Smn%z K[S~yB__ެ̻3tV-jn_aTuw86lGH,s!ZeOLmÕ ' 7ԩ#{c~_R endstream endobj 1064 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1065 0 R >> endobj 1066 0 obj 2088 endobj 1068 0 obj << /Length 1069 0 R /Filter /FlateDecode >> stream xZo8ߜXvm6,ѱPYrhf8I۲\ܧ@;33g]x̅_zN,^|Sr> "%u慎ٖ8pE# yQ__;saӅ{BTuٲMd/yǙ  <8-M.6˦f{euW/.l1,MN8?뉑K G{>dOz9ھ#14؉=/M4GNGӸ,>ڥw//h;k|v`udw bK`3GIxq4qQ8==ֆ^gU' }-wk#_͟e]4OëY'g4" B@ڑf㻸  [Fw TDA -<u$ !yKeyYˬw"&}~~>.(Xhr"M"ʎ$/?|rǙ%BpSՏ϶e!<*:sõ*IQiݵebTF47 Gљy.?n -C!>Z`j~2~^DKѸ/;!k7?tW tGzpczp{zy헛ȓKC@IZ bh%x4kMk> }AaMayD5~(+ !IuJAxv-|'X13;*hvK%0.汖N@2*-e Z`b8t=L2rlwN)18l$8!4iJ itnjXsNp%=4nwMۿ+ 6E< sھ$vqGt==!q&PS4G&߈Zjg&yFYQcIzObٱ@݋Jؾ8A`CvY6/kڭƊ/;CWe-,6o;Q3CE]ߪ릪'[]vz-AYš|#&aykruxHY#ɮ|t EX/$mn#+ekJO//hۦޟ=!]~i M8qP*pCNj`q;FO[8QLl%q\~b֙89!)27":?aӋ14 ìm5{L8 qW/H ¢L}_>m=Q7rs0P-9Waג冲q0 7 ѹ+^WW fVj"x3v OEKqWR*1ڊQ4UX FԈy5fBKJ*GN"B'8@?{5Mqgz 8:aB 5&$W!5|,+ elS>5tm4kݘ@U (L!|C]q6+&: lb-)dg+ , !Cz^=mpUE&/C}fצ㐂K}751[62?ӭN(;{séNp}z=pRDf߳$xĐʕ2b?puyE!=8د͓tᴁaa0qDX@}”9Gis+NQhza$RSG2#O",ň,k ( vI5 ؈߃ W#FNd=!cC$ |/Ip~Щ9^.,1>ʛ <ѤVk/ uB-9; q]7'3&]qCQ7F(*~5t% @][ΌLݛ{G3c -ėHcs\bV~*7Bt;ziNo0RG0>Ϟlc$RԊ\co)9tC\1q~2Ȏ1h߹]:oO܊:99{f/sSGquP\[sۆ }F]Y+DQN|wM" s.fXdR[=pn@b`kv3MYid" 5dY %EU[!D%$-o"i#P3 +hzjV0z8ovUXs4U ]H fX?|?&> endstream endobj 1067 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1068 0 R >> endobj 1069 0 obj 3079 endobj 1071 0 obj << /Length 1072 0 R /Filter /FlateDecode >> stream xZKo8-`3)2dE`9-v6zH8[ER= YTůXΟxāO8!bIhq R 9ɻ 6#77&p.'3&xb,Xo<#.'c$JxDI:,p%OޗY0:::g[VdVկ9I(#Wf ^ٹC ` fi;ٲB\4_Ʇި]Ve?/BM[g~K=X!ѣዅjW׃ǬQ&B3,%RV-yPUW)%<ڊ1K#1V옩%:[%lF p?8\BNs+b!by:|H#̈́F2d5z1WrWe#} +uI0K9"8 O4p2`g"2:rZ0Q& ]Hr/ Vx>,.3j:bG︹S..mk8@P޻JG!$c>[HUQM@GKv„uh0}|U*OaP=UGx΍A)G &σ<%N0w>GX/n÷8a lm8+GP !A;lE;7 (0AKVӌh,P$#?Y0l`%*VxbHFGmqwc=_t2h/ZA t7, +Տi 11՜`S; : 8jKxuUe%9&IG [8oiC.Kj2lS1Tg z_:`c:^V=z`+34lb3MiDh ,ᮆ\ 9=] JkJ<`["9 QnxMi2 ZD=BMx4LXJkXlӁzxh "uÏ)f y'PF%*u?~. PgYGlCqW{;ףVsfj+P5-aE]Hp#'PI v"9%~F^`vܤ &u^c2S0 X0;xs#٥fWzdѻ9׳ovs30݁΂`4y A .l zBnoЉ}h4die;i=!WKgRMB2C[17s ,w%Sp'47[k,dIJڎȰVK}q1R~߲zxj=4=4HS7uu|-A=g--Yy\rg?h2;4P n ]C":ߙ:ae(dVc胂SQ:x.[x}nJ8k%أnI,%B#r 1KV8Ǭ,B vy M<> ^֑izke},qyw8ۍ.˽J.ohJeuI+pq zn,Chc?7q}%7ξZ"eC}cW0nLo\z2az,sp1 >FA+K8ф̃?[=>Js#`eEt4+ACejV~Um:ȝpB$ ~E@9u C}H1e*5#qgC/^qF0sTC_ŦsCbaŜ@,r*ʆA*-91)5yZ|Z SXJw0d*s&P=. =6M+TwQ>4-^Muf0FN xY=Bқf OMѼ\G'8 !Ă {w뉁zkW!`"4W5X}*a AU#[Z9{J&Ͼ3fڑ"1l endstream endobj 1070 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1071 0 R >> endobj 1072 0 obj 2635 endobj 1074 0 obj << /Length 1075 0 R /Filter /FlateDecode >> stream xZ[o:~ϯ[l">M6ih[.>$/.hf(r8!?0rI˳?vbQN#8^J4l Q')5 :sч>raә{D8uЭgog!.Zn ;AQ^~<,ojo B}:HzϚۋ?g'$rLOQǎ+5z?n Z21+ֺc])"厃14>9 m`e:RVcd[۬]Eѹ{c5' 4M`"mU%=q;0 Ʈdbq4f"%6uhgAZQgbt 3!kkMW՚ MO{ȾnDdt5hV/z/Å#7sbp_7dE^=Ɖ[c觎4 `*dlQۺܓPhz]oROm,vuSc<@d0io Ɓge(pٴQ(x, 3oN=X9!lt럚u=wfŞt; ճ ]p~hfKXk0Z,֛ZXAV!Q!IG=uw ByЀpV҉Hl3[1vЄu-(rd  iI!39DZ?#U+&#OyiN,uA59Y 6Ȯ 6!|}~@!~AL0&#e8EJnh͛ ݈T#[n+IE+*}9,dۇKzl_FR]%)#_xWv&K\7}"(Ȭ0# g$*qFӐ@. ;W)/ ) V&32t8*,ֵ ha"SLttdB y=px 㶪 f,ffIY<' 9i,#[|gx'Q:Ri02gG~쁁r1vX?{PPZ:3W a\Pqws=q^:#YևL0L}Ŭ{;Jn#!H+*ZQ]]d<76˞rԟYL}\+n2+q܇V J{ᦹy Ctb=6n%$ iʓzh\b=2fCvAg[Y\h4ֱӣhfZe MwW/w՚R'd짂Nfۆ#u AoM?(w&pBۓ`l{"nhGni1elCo:ͧzM%djq*'Ag3Nh. ;xf@9s囀6 ^p]s  >|^: 놛ZӰAN7 GR^v -:RQ{@~8X2W,j+:bPUWtr[ 6u82v_\Yܪ`K JtTKCU}ABeO5Q߈CkcRXAr^VyEz>#6U̴8͢^Qt!{4tiEcSa948Sm O6?hc_>^u( f|H5=^ $?m_QoQw-/ym%ϖnHփ5/t9 |Gs Ʉ޳LrrҞK= z2OiN̜e+%GA1$ʫ:3q:iÑzql-j,CπӶ-+R] ;c{d]m"ae^y pΆJ5 B<#C* u%Z= bvsaYn͞ndӎ*YT5F'H~H:tdEZeԥWR? %y˃!L߄7[*B ]vNyB5 |4Rq0f8 T/[6dFg#ոPk$bvE endstream endobj 1073 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1074 0 R >> endobj 1075 0 obj 2897 endobj 1077 0 obj << /Length 1078 0 R /Filter /FlateDecode >> stream xZY8~[:nEQ ΁^$ YL EBd#}o%ʒZV)IWQdbU {!b8Njی{(P@0!>ڡrMoїE Ͽ`N_'+Qǎnf?~mY&@A7뎉1K(?OJ|s&%ZGc٤(-3$r~͑|BpRQzBEQG1Nuq`D+#aZ ^> .aD4=a#K(IѣT4>JZQ5[O?wqƣ]#P?~D.׊K§%oF2ˤpTA $e+C͖#*ڋ"_=b1>-뀽l*=i&T0LfⅭȧCs;u@(}t 7T{C58N&Dl7b8JDuྭ}^n:Mp& J $0Eg%7e x "[U,#ciMֲjiZYִt&Z4a~X=t)E/bzQXI0"hcS2F\|{D{QIа8bpI@SOxh,4*\LBEވy^bETct5 0\4ac 5*5+u d<+z dC؟ u H"ԟTeAa=l>ҁ:l֐a8 +`ջ-_}?V8#Rn(xZ>3S5Nm45zTc:Xjɋ<Sڷ3S}tĺ2;OTh|yn ζfZtD2,1z:62Ȅȿϛ-J}Z2A=wTJ|Nb P/å K.g*rL:F{=6M:,7[ ~aW`9u~ s1[YeE5v6Vt%zY}<0I0$J*_Q{:_{TAWM#IeT%e:>oO:يCƤv*᥾9Pt%(NT Q(YlxNW\};#Y tPyNp)s0%/rk6z$\ZVsṟarIb/oŃܒ6~H.CS8ոS:R9Ϲ wy[]|/Gw̘vdL1%i;!҉S(%y0#m6fwX2\j`˭z@GML,*Q-kKJyft gPNGLfUUEQ10Zr=>xp?|\UI= endstream endobj 1076 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1077 0 R >> endobj 1078 0 obj 2496 endobj 1080 0 obj << /Type /Annot /Subtype /Link /Rect [ 382.175 532.318 448.0 541.318 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 794 0 R /H /I >> endobj 1082 0 obj << /Type /Annot /Subtype /Link /Rect [ 136.94 73.475 203.6 82.475 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 617 0 R /H /I >> endobj 1083 0 obj << /Length 1084 0 R /Filter /FlateDecode >> stream xYKs8Wh&$TM6q&l&R[[qIemCÙ=E9 D~,rK'CtPv9أq\D\-"Zm{* KQJ׫7ywU!86N$ROHdV,nWgJp>"֠`DA`'F]Lvg~/|-k`?a$g3;uX7m~B88O8<3GB9ce} rK^8p/J˃דwNB襫O2*X# nq/<"kv4O:;Ҡ>lqYTEGR)yQxn*Jb{;qtZv$wxލ՛W2u.p/0 |*#3|ۍϖ @0ԺR2Q>'NEuAptgvw7&o?SVi7Qr h;8L>>vB.;0xgIa;!߿a+THƏ`o dO?̦܋¿@ڨ 2*aC,y>Bٛ!S9n:2:mU}$U 6Esro{eCXZZlKYqG[;B}3l۩jo B}LbQ+[S7A:;Ns[k|fnU[+;jCU@׼b3x!Bȅ)l,N*"f͖.uBZ}N) 府lŒcCَj+=Uv 8 U)3&ň6Q :O3aB2wuấ&~|JGy^NnJlu4ccXf,h(NRT 3n hȐq|e/F%NH$-Ո(N}Þ=ʎwap SICD|rY&U diq?fuKwU܌(+ʂ|JQաVNmzqL(O^]suy(d^]#FO2Lڶ.;]!:& ngMPy3ݬ(qYdUmMZQ PZu4t]![B.$ #ًC q=I>~գ#LCz>]p=X,D$o3P@Au\nksfo>q}HGYYR͞Y”>B&OS0C=<|\r[%R{̗<&7ܠHV{b eI Eacܳ9֥K|kZf0gr5"CF[(Y&dhQ,j' Y=9ę(X' |F@^q,T3 X-²) pkv0 C0kZaI͗9j;|aj&^kz #>,r=E͂pr_}(J 1sm6Xb-F+GQb U1RR@yNy!)Q@_<`﷟T8?s\ FcX!bV <4#q!#]ꗉiP.72׎ub!YL@"|'; }gͼsk}*Fy)C#d t%Z8k^\ }L=a F6ytQpJY fB2?wɰZ.8)HF ~B-ʟ͠;51~ Un/`o(v)ra baq1T#mt3%A1"fd/\moyRJ7/{\R_ /ȅ^TfYŽZ7qBJu-Sy'ꀭ0PߵUwbl_&QfyaS +FMo3=X6& <yZf[98BR?k PZgDKyCFZ?璠QB'ߔHeocY̢2@|s]f F.2 ^橯Elsp8 uZ[#q ֙rϏgH@.N+ endstream endobj 1081 0 obj [ 1080 0 R 1082 0 R ] endobj 1079 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1081 0 R /Contents 1083 0 R >> endobj 1084 0 obj 2383 endobj 1086 0 obj << /Length 1087 0 R /Filter /FlateDecode >> stream xWKs6WV{Ɓ~8iC!!cҊ} )f7K>_i4Сv^;qNJ\ MYE=ɻ |(ת:ϖo @'\tr~:\=Z)aP?S?mk#g ҔcYQ$!?a9gŖvuqr]A+?$)ROU~Z0 oѺ`];eE֋1NpyYd,tRMxϋb_Qm a-)+l-NfD{kDh)H"vJʬEAQ7*GQzEZy;"h})C162GlI춝&ߝ婺>(8™r#U5"#C=nW=U"`OK}EkS^dlJj@فl[2 am϶PI- quu~=aw7[Or=#RWdX|!$GaT{cuZ$Lڙv@t>VC A~Tuji/oHIE.SG"v(o)]B&7T}+ $c?8zTޥVE)ak2܊/ l@vӳ_3"3 S8 uPS{][NYBo NjpD߈1 if0*m.\/̀=Yaw p3hdnO;O~V*T`q endstream endobj 1085 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1086 0 R >> endobj 1087 0 obj 1261 endobj 1089 0 obj << /Length 1090 0 R /Filter /FlateDecode >> stream xێ۶_]Pw%MANڠhкXheKDGw~r(E_ؙp_VasNz$J )a4"4LHM椄T#f?V͊ϖ08bkQ>:'\ #hLIWvB, 3? SKDH >|8Gǿe g?c|71_[lbng/c,88O4'$w5*wwbn(P5y0|9H0ci.>D_[J~ lx,zAvRTCe4BE(IkrDIDEjk͕\[T6蚢rΊ/];+R{{Z4s3fvͰ>cȤ,2U1GTA#W`qXx yzy/5 /\p$nͱ}cѶٵ& !n$ꆰll3\dᙿEgXg{ azj`B6HP7Zڝ˰|.r:ECQ7/%'XYD%(Tj],Đ4VuA ZƖC6{fU.} XJ,<3|Cyl}he`7%X51? )T"IY=<%Jj2.5%뻯r OKIe/B6>]qa,mcgvbl2p=iZ}Jɯ24 vRYe=.ꮧc: ꇌ4QlG Nx{}oE*hL endstream endobj 1088 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1089 0 R >> endobj 1090 0 obj 2182 endobj 1092 0 obj << /Length 1093 0 R /Filter /FlateDecode >> stream xWKo6W1$K:hM6@($f)9wD-:hK ?΋ ڏwIŐNBtzP\@ў,XT/ɀW1M}r'u\(M.m>sq>Dcq`[;Q7 sȒ&%5\"/,oRu:6NM>Ͷ &;^GjL0,hiLlt,& <6! ]_ǸE]Ew,|~j6:p+Dj: IF*)@TTeJ~OӤǚgd…$pVߒ#"BTNWJ*(y]'{^?\ZZyr&%l /KR5WQgIs\o+,USClq>V{Tjxx[>"c +)SYU6^r n[s"S9ަl8tf0<Q>!%!>hGg(7~_ev,xuH,}ԇ0|+.8:uR,0F)Md?.֯IFXk^/UbE~p$i58WL0/ *UV5 $_XS″Ί]Aw Kd:vRWN2oֵ43H]⤎f׉4qd796iO~m cӚ]bF׃A5Q jBuqog缷ad1'ƷƼEJWh]+rMò{zdo:ד 7Fhc4OY/ƼQOO&wYOVke|s=tuaqssJHu۹Wכܜ9X{%s5#we endstream endobj 1091 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1092 0 R >> endobj 1093 0 obj 1173 endobj 1095 0 obj << /Length 1096 0 R /Filter /FlateDecode >> stream xW]sH}Wt͓a㭅I@И"PGFmD:$=9}=׎)H߯CW$Q '\BArXT$E$*ZkHEX?+z6FaG7ďR0nvz?S~ eE%Xx4̓;i+篶T"DSh18R%Sn]yZ)f$ы0HF05Q$ o:15ޓdJBiwy]QSvUߛ2cMǘr%eQ̒}i7] vAsS#g[GsD~/I(8EI,&Ej1yܔ?S/MZKٞmDörPNnżdsE.W]iW`=$c0Etb{᱊dd7"͐G12lMzSmf$#ƼI dhEmŨECrhɀbrЛ^5Ri oA 4@s]i>uN'Y 4F)pK䃆%㉗ |Գ0Y2-rsMF̄Lɸ#-1')5-~$IF:g11A \6*v@XdrBv8}6ĢF(N_gS1kҁ ^kCq@^ln0V$C|iAϥU'ٔ?iFO&,>0<%cX͟ endstream endobj 1094 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Contents 1095 0 R >> endobj 1096 0 obj 1097 endobj 1098 0 obj << /Type /Action /S /GoTo /D [909 0 R /XYZ 72.0 769.889 null] >> endobj 1099 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 759.389 201.134 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1098 0 R /H /I >> endobj 1101 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.247 759.389 525.247 768.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1098 0 R /H /I >> endobj 1102 0 obj << /Type /Action /S /GoTo /D [909 0 R /XYZ 72.0 740.03 null] >> endobj 1103 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 747.389 180.122 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1102 0 R /H /I >> endobj 1104 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.537 747.389 525.537 756.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1102 0 R /H /I >> endobj 1105 0 obj << /Type /Action /S /GoTo /D [909 0 R /XYZ 72.0 431.518 null] >> endobj 1106 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 735.389 346.929 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1105 0 R /H /I >> endobj 1107 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.401 735.389 524.401 744.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1105 0 R /H /I >> endobj 1108 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 723.389 298.587 732.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 1109 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.673 723.389 524.673 732.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 1110 0 obj << /Type /Action /S /GoTo /D [934 0 R /XYZ 72.0 248.237 null] >> endobj 1111 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 711.389 262.598 720.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1110 0 R /H /I >> endobj 1112 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.937 711.389 524.937 720.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1110 0 R /H /I >> endobj 1113 0 obj << /Type /Action /S /GoTo /D [937 0 R /XYZ 72.0 769.889 null] >> endobj 1114 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 699.389 198.611 708.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1113 0 R /H /I >> endobj 1115 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.403 699.389 525.403 708.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1113 0 R /H /I >> endobj 1116 0 obj << /Type /Action /S /GoTo /D [937 0 R /XYZ 72.0 607.006 null] >> endobj 1117 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 687.389 186.758 696.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1116 0 R /H /I >> endobj 1118 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.489 687.389 525.489 696.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1116 0 R /H /I >> endobj 1119 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 675.389 289.779 684.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 944 0 R /H /I >> endobj 1120 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.641 675.389 524.641 684.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 944 0 R /H /I >> endobj 1121 0 obj << /Type /Action /S /GoTo /D [975 0 R /XYZ 72.0 710.171 null] >> endobj 1122 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 663.389 186.758 672.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1121 0 R /H /I >> endobj 1123 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.489 663.389 525.489 672.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1121 0 R /H /I >> endobj 1124 0 obj << /Type /Action /S /GoTo /D [952 0 R /XYZ 72.0 632.687 null] >> endobj 1125 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 651.389 345.768 660.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1124 0 R /H /I >> endobj 1126 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.331 651.389 524.331 660.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1124 0 R /H /I >> endobj 1127 0 obj << /Type /Action /S /GoTo /D [952 0 R /XYZ 72.0 404.517 null] >> endobj 1128 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 639.389 373.356 648.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1127 0 R /H /I >> endobj 1129 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.129 639.389 524.129 648.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1127 0 R /H /I >> endobj 1130 0 obj << /Type /Action /S /GoTo /D [952 0 R /XYZ 72.0 150.081 null] >> endobj 1131 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 627.389 263.16 636.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1130 0 R /H /I >> endobj 1132 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.933 627.389 524.933 636.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1130 0 R /H /I >> endobj 1133 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 615.389 176.814 624.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 1134 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.561 615.389 525.561 624.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 956 0 R /H /I >> endobj 1135 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 603.389 253.496 612.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1009 0 R /H /I >> endobj 1136 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.891 603.389 524.891 612.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1009 0 R /H /I >> endobj 1137 0 obj << /Type /Action /S /GoTo /D [984 0 R /XYZ 72.0 710.171 null] >> endobj 1138 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 591.389 186.758 600.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1137 0 R /H /I >> endobj 1139 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.489 591.389 525.489 600.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1137 0 R /H /I >> endobj 1140 0 obj << /Type /Action /S /GoTo /D [989 0 R /XYZ 72.0 190.289 null] >> endobj 1141 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 579.389 188.432 588.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1140 0 R /H /I >> endobj 1142 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.477 579.389 525.477 588.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1140 0 R /H /I >> endobj 1143 0 obj << /Type /Action /S /GoTo /D [992 0 R /XYZ 72.0 657.889 null] >> endobj 1144 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 567.389 172.38 576.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1143 0 R /H /I >> endobj 1145 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.593 567.389 525.593 576.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1143 0 R /H /I >> endobj 1146 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 555.389 284.626 564.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1003 0 R /H /I >> endobj 1147 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.679 555.389 524.679 564.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1003 0 R /H /I >> endobj 1148 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 543.389 186.758 552.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1016 0 R /H /I >> endobj 1149 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.489 543.389 525.489 552.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1016 0 R /H /I >> endobj 1150 0 obj << /Type /Action /S /GoTo /D [995 0 R /XYZ 72.0 136.746 null] >> endobj 1151 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 531.389 250.99 540.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1150 0 R /H /I >> endobj 1152 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.153 531.389 525.153 540.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1150 0 R /H /I >> endobj 1153 0 obj << /Type /Action /S /GoTo /D [1039 0 R /XYZ 72.0 313.907 null] >> endobj 1154 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 519.389 237.612 528.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1153 0 R /H /I >> endobj 1155 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.257 519.389 525.257 528.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1153 0 R /H /I >> endobj 1156 0 obj << /Type /Action /S /GoTo /D [1042 0 R /XYZ 72.0 292.001 null] >> endobj 1157 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 507.389 212.594 516.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1156 0 R /H /I >> endobj 1158 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.301 507.389 525.301 516.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1156 0 R /H /I >> endobj 1159 0 obj << /Type /Action /S /GoTo /D [1042 0 R /XYZ 72.0 130.03 null] >> endobj 1160 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 495.389 229.074 504.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1159 0 R /H /I >> endobj 1161 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.181 495.389 525.181 504.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1159 0 R /H /I >> endobj 1162 0 obj << /Type /Action /S /GoTo /D [1050 0 R /XYZ 72.0 376.528 null] >> endobj 1163 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 483.389 233.377 492.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1162 0 R /H /I >> endobj 1164 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.149 483.389 525.149 492.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1162 0 R /H /I >> endobj 1165 0 obj << /Type /Action /S /GoTo /D [1055 0 R /XYZ 72.0 721.889 null] >> endobj 1166 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 471.389 274.695 480.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1165 0 R /H /I >> endobj 1167 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.849 471.389 524.849 480.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1165 0 R /H /I >> endobj 1168 0 obj << /Type /Action /S /GoTo /D [1055 0 R /XYZ 72.0 509.89 null] >> endobj 1169 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 459.389 281.209 468.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1168 0 R /H /I >> endobj 1170 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.801 459.389 524.801 468.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1168 0 R /H /I >> endobj 1171 0 obj << /Type /Action /S /GoTo /D [1055 0 R /XYZ 72.0 173.395 null] >> endobj 1172 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 447.389 269.726 456.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1171 0 R /H /I >> endobj 1173 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.883 447.389 524.883 456.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1171 0 R /H /I >> endobj 1174 0 obj << /Type /Action /S /GoTo /D [1058 0 R /XYZ 72.0 659.749 null] >> endobj 1175 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 435.389 248.899 444.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1174 0 R /H /I >> endobj 1176 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.035 435.389 525.035 444.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1174 0 R /H /I >> endobj 1177 0 obj << /Type /Action /S /GoTo /D [1058 0 R /XYZ 72.0 460.121 null] >> endobj 1178 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 423.389 335.39 432.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1179 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.405 423.389 524.405 432.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1180 0 obj << /Type /Action /S /GoTo /D [1058 0 R /XYZ 72.0 127.935 null] >> endobj 1181 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 411.389 259.308 420.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1180 0 R /H /I >> endobj 1182 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.959 411.389 524.959 420.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1180 0 R /H /I >> endobj 1183 0 obj << /Type /Action /S /GoTo /D [1061 0 R /XYZ 72.0 478.569 null] >> endobj 1184 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 399.389 271.986 408.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1183 0 R /H /I >> endobj 1185 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.869 399.389 524.869 408.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1183 0 R /H /I >> endobj 1186 0 obj << /Type /Action /S /GoTo /D [1064 0 R /XYZ 72.0 597.364 null] >> endobj 1187 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 387.389 196.722 396.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1186 0 R /H /I >> endobj 1188 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.417 387.389 525.417 396.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1186 0 R /H /I >> endobj 1189 0 obj << /Type /Action /S /GoTo /D [1064 0 R /XYZ 72.0 290.421 null] >> endobj 1190 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 375.389 217.765 384.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1189 0 R /H /I >> endobj 1191 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.263 375.389 525.263 384.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1189 0 R /H /I >> endobj 1192 0 obj << /Type /Action /S /GoTo /D [1079 0 R /XYZ 72.0 587.097 null] >> endobj 1193 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 363.389 193.962 372.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1192 0 R /H /I >> endobj 1194 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.437 363.389 525.437 372.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1192 0 R /H /I >> endobj 1195 0 obj << /Type /Action /S /GoTo /D [1079 0 R /XYZ 72.0 215.046 null] >> endobj 1196 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 351.389 188.442 360.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1195 0 R /H /I >> endobj 1197 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.477 351.389 525.477 360.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1195 0 R /H /I >> endobj 1198 0 obj << /Type /Action /S /GoTo /D [1088 0 R /XYZ 72.0 769.889 null] >> endobj 1199 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 339.389 223.899 348.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1200 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.091 339.389 525.091 348.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1201 0 obj << /Type /Action /S /GoTo /D [1088 0 R /XYZ 72.0 611.744 null] >> endobj 1202 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 327.389 186.758 336.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1201 0 R /H /I >> endobj 1203 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.489 327.389 525.489 336.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1201 0 R /H /I >> endobj 1204 0 obj << /Type /Action /S /GoTo /D [1091 0 R /XYZ 72.0 647.889 null] >> endobj 1205 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 315.389 190.096 324.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1204 0 R /H /I >> endobj 1206 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.465 315.389 525.465 324.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1204 0 R /H /I >> endobj 1207 0 obj << /Type /Action /S /GoTo /D [1091 0 R /XYZ 72.0 435.006 null] >> endobj 1208 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 303.389 182.354 312.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1207 0 R /H /I >> endobj 1209 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.521 303.389 525.521 312.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1207 0 R /H /I >> endobj 1210 0 obj << /Type /Action /S /GoTo /D [1094 0 R /XYZ 72.0 769.889 null] >> endobj 1211 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 291.389 247.458 300.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1210 0 R /H /I >> endobj 1212 0 obj << /Type /Annot /Subtype /Link /Rect [ 509.931 291.389 524.931 300.389 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1210 0 R /H /I >> endobj 1213 0 obj << /Length 1214 0 R /Filter /FlateDecode >> stream xAsq| {|y\KVv3>$D V~_@5fUDj`WUMY'"ۍݖEnxs.>=?n_{?5u~经_LJ/oǗ_9YS}~>;ⷬ˩]7s~={^>?/{^/e]Y3ܯ{v-3S\|7[f_O7w'y׿zyo?>\m=OMtY>Ji6ꛃN@VAiyvpś[n%pKrܭ/rmf=qw[M7n )pSf̀ṕ7np -[wgnw帛nҎI;6W=& p&M7n p36n ́n%pK-rMnwvMq7mݴw~Mq7m>,Kĩϣΰgѫv։PK~_n?]|}Yr{n{c{f9 @ ă b$6*T"hDЈA#"8A'N "D0`5S1dx܁`@L "DPA%FDpA:t"D0` I&`@ kb Xq5|1"(DPA%J4"hDpADЉA'AL"D0`ˁ`xLf2Jf2Jf2Jf2Jf2Jf2Jf25E3c1Xlm ?32_Gt/C:'yw緟lzy׷__˟9n7O柶G|>c7G)SԷm-TT'PRF,KiR:N,#KA,Y*TdR!KC,r KG,Y: d2e"DI,u!K].RF,KR;Ԏ,YΟgzQ9vU[6ᛃ:ϧjCu^HI]ZP=^9'㱑8@\z5x,$&A&L X &Z.`-B DPA!J*T"hDЈADЉA'N "D0`Zj@B :w X A!zlW >b/+Y@.re 7Gu|h0n"NPPn Պj'u_PM,kLjd)R KE,Y4diҐ@Ydґ#@,YLd2"EPu'kF,Y TdR"KC, Yd9@,Y:td2e D,X-X-X-X-;\_[5dYtYliK&X:OVmz>a7uolR^ֹ^\}}4L Yz:IՆ 5T+Yd9@,Y: d2e"D,X IJanIJa&5#5A KA,Y*TdiҐ!KCYd9#KG,Y d2e"$5#5AAe @݉e H,Y dR"KE, Yr ˁ,Y:td2e @,Y&Ae HM,kFjbY0PwbY0R#K4AXH,Ŀ>\;Ҭyv6]Vz 7~p u=7El4m۬NiGjA@uZ; Ґ!KCYd9@,Y: d2e"D,X̎IJfvnIJfv&5#5 KA,Y*TdiҐ!KCYd9#KG,Y d2e"$5#5e@݉eH,Y dR"KE, Yr ˁ,Y:td2e @,Y&eHM,kfGjbhhhhh-m.TlE.mi3:O1??=z0z|x:/7^/LJ?ͻyg2ziY+=loG$ujCuNUImҐe4duH Jbqt< I&\M:̤qyIc t8@p='xL "DPA%FDpA:t"D0` I&\O=:ģ1\O;:q)Gc"(D.a>zY/1=-~{izpnxeiq$W;.D Grc9S5jL՘`:3UgTS L5j2D0HbƁ!ՋGrzHT/6cə0UaT*SUjL՘1Uc:3UgTS L5j2D4HbƁ!ՋGrzW@ޑn#9S*LU2UeTS5jLu0TSuLՙ3`T&SMHbǑ^l8#ՋGrlllllt.tv'E/;WXnu{~|继;Ͽ_~<ÇGx=mG,|N7Ǎ_eDy]l@y]rr'ԅI.,G͜AސzCg#$G덝A.LU0UaT*S5jL՘`:3UgTS L5j2D뭠ITA!$GmIT[CcH#uf;ǵ%w ܢb#_~/w|w//O\_po^֓o{|Owwotgf;^7fX7#\\X>X(@43UaT*SUjL՘1TSLՙ3UgTS L5j"՚ Hfx(G5#yG5C9SZMÝ<9B3O>S!>yK_^]~^J/||x{|sSn灿>(=i4wڴ ra`y|}B

>T S*LU2UeTK KXX.,,O{g~Y|vs5fsf^EH,ws ˳N_ɍz.Bre\X>XTSLu0UgTS L5j2dTTTT{C!ސjoHw;R흩 S*LU2UeTSgKH>˕r_X.,,OGg&SMHUZ[QTkK5R-(GHT\0UaT*SUjL՘1TSLu0UgTS L5j2dTkK5ʑ.HURՆT!UHU;RՎT3պcImc:F[s`kqhM__~o>Mr½-e}Xt~A'8 ˓ua!ʑj]XօPTB$*LU2UeTS5jLu0TSuLՙj0`T&SMHNB9RHސjrZ'%#:) LU0UaT*SUjL՘1TSLՙ3UgTS L5j":) HNJB9RPT$wZ'% SXe8XtΧ ok_P;|s7^y|sfi}quQ~qu|X(_ 73TSLՙ3UgTS L5j"վ վ վ վ ސjoH7;RT S*LU2UeT볥0=Dw嵄%&SML5j HnATf(Gu3#պʙ0UaT*SUjL՘1Uc:3UgTS L5j2Du3#U]6 jCڐv H.L.&u8>h\/=×sXkz}@ 7 6T_݃?ߝz_꣎\|eS8$yGOreΣ'|X(rcy<˕L5j2dTkrZO7ZO#ZLU0UaT*S5jL՘1TSLՙ3UgTS L5j"Z H֟$H֟(guGsAz5<2l֚]o/}xu֑\Y({"\X>X({#S5jLu0TSLՙ3UgTSML5j"ՋlɑE ^\dHT/.u$G:3UaT*SUL՘1UcTSLu0UgTS L5j2dT/.u$G:7zq#9Rց#Ջlə0UaT*SUL՘1Uc:3UgTS L5j2D:#ՋlɑEHUlIl"[GrfK"󷋋l6z|\2#LyݧϟqnvF !LsY|5X(<\Y$B('R-D(GH\0UaT*SUjL՘1TSLu0UgTS L5j2dTk ʑjm!"yCH"3UaT*SUL՘1UcTSLu0UgTS L5j2dTk ʑjm!"yCH#Br*LUM AtoL;M͵~N/Obz ˇ:Y(uvtɽ6k@|ҋre|>E|֮ #UATkWʑj@9R](gT SULU1UcT:`T:S L5j0dT֮ #UATkWʑj yGLU0UaT*SUjL՘1TSLՙ3UgTS L5j"UrZ*PTkWʑj yGLUj@-MBA0ٛoqu@vU/jw?=y?ݽR2F1sz9p^W!ura`y|]X(_W! gTS L5j2D}A}A}A!ސjoH7;RT SLU2UeTSLu0T:SuL5j0`T&RʂTeA UiHURT#UHU:S*LU0UeTS5jLu0TSLՙ3UgTSML5j"U].HU jCڐvjGڙj bdN L 95JD.lw/rZۇHސjmB9RC$H S*LU2UeTS5:`:SuLՙj0`T&SMZۇPTkʑjmB9RC$H SIM9vgQ2;9nRSWOeR#uїzϟ=}za{JU;r19LOlY"dQ>F\X>X(?#Qn,ϟ(gT5(Gu#պf ʑz+wLU0UaT*SUjL՘1TSLu0UgTS L5j2dT^yCmHT^"9S*LU2UeTS5jLu0TSuLՙj0`T&SMHuɑz+7Hu;R]o{Er^f:X'(3Hk3A{\dr#o?P^÷~>wwK9.{|8;eΠq5l|>iAQ>\X>X(OZPT*SUL՘1UcTSLu0UgTS L5j2dTkʑjm yCiH6 #4r*LU0UeT*S5jL՘`Lՙ3UgTSML5jm@9RM(GiH6 #4r*L,:N1.yk}%] |]o~.RYi.L5dެI}~v?jP[ZQZP=PVdR!KCuIK=m@H.,,Om@Hn,m@H,gT&SMHu R]oBrHu ə0UaT*SUjL՘1Uc:3UgTS L5j2Dm@HTۀ!6 $Gm@@ޑz3Ua ۺzq~}M_Wuj=ї7~|Ouǐj}5l;-2cӮ77Drcy\0UaT*SUjL՘1TSLՙ3UgTS L5j"պ*ʑj]HʇrZW#yGuU>3UaT SULU1UcTSLu0T:SuL5j0dT&RUHސj]HʇrZWC9Su%oO!Kuv_()PSZ(P^[{خCg?;|qr';+V7@`y<;ˍA7\Y(oH (G5n yG5n@9S*LU2UeTS5jLu0TSuLՙ3`T&SMH (G5n@9RqʑjHޑjPT S*LU2UeTSLu0TSuLՙj0`T&SMH (G5n yC5n@9RqʑjPT`VhNu^",'q/;>}:iӸ6uƧr?pݟ<{z?߹nn?6Ǎeqg׉Jrcy6\Y(M$3DW#u+R]7^ITM$gT SULU1UcT:`T:S L5j0dT^ITM oHuJrnzyGW3ty>zun>+|6^.//ï^[ǟoe{ L0v>擴amY㮿du%' (X(OP,wwZMB9R&\0UaT*S5jL՘1TSLՙ3UgTS L5j"պnʑj]7 uPTI$Hr*LU0UeT*S5jL՘`Lՙ3UgTSML5j]7 HrZMB9R&#պnʙ0չȲiK=IzW{~ǏϏ_ۇϿ}{y/e.|hfJX(rc9SLu0T:SuL5j0`T&R!ʑj PTkrZC\}ћ|7qO|>GQ>ӣ\X>X(QT&SMHv.0#rZHޑjC9S*LU0UeTS5jKG\X>X(rcy<˕L5j2dTkʑj#yC Hv.03UaT*SUL՘1UcTSLu0UgTS L5j2dTkʑj#yC Hv#r*Lds]9B(BKe0UJ7Wy/9?n1?PGxsI{mܬkEHreV$'kEHrc9S5jL՘`:3UgTS L5j2D}A}A}A!ސjoHw;RT SLU2UcTSLu0T:SuL5j0`T&RʂTeAҐ4* JCґt* S*LU2UeTS5:`:SuLՙj0`T&SM RTuAڐ6lllllnEuXϒЮ y7ϟg(^WhozzDvTSLu0TSuLՙj0`T&SMHF~(G5#yC5C9RʑjPT SLU2UcTT,j':ˍro,W;caSML5jPTkGTkrZ#?wZ#?3UaT*SULU1UcTSLu0UgT:S L5j2dTkrZ#?#ȏjGڙ0Ȉe9֑_s>ynuS`?ͻ~yq3[Nb2?Nxs@9<0dz>c@y|>c@

1\Y(PT*S5jL՘`Lՙ3UgTSML5jrZ$)(GuJ2;RSQT S*LU2UeTSLu0TSuLՙj0`T&SMHNIF9RSIސjrZ$)(gT SULU1UcT:`T:S L5j0dT)(GuJ2RU6[R6[R6[R6[R6[R6[Z2 D㺚'\Xr<.=W:Os/o\z_?~|w_~=O3W|1$qAcQ>o\X>X$O(7#rZHޑj~B9RO$*LU2UeTSR.$6TZQՂjd2e"$݉IJ6;DjbY@݉ems"5d)R"KE,Y4dir ˁ,tdґ#@,Y&LdIJv3X^&RDjbY@݉eb"5dY;Zzr*d=n^q endstream endobj 1100 0 obj [ 1099 0 R 1101 0 R 1103 0 R 1104 0 R 1106 0 R 1107 0 R 1108 0 R 1109 0 R 1111 0 R 1112 0 R 1114 0 R 1115 0 R 1117 0 R 1118 0 R 1119 0 R 1120 0 R 1122 0 R 1123 0 R 1125 0 R 1126 0 R 1128 0 R 1129 0 R 1131 0 R 1132 0 R 1133 0 R 1134 0 R 1135 0 R 1136 0 R 1138 0 R 1139 0 R 1141 0 R 1142 0 R 1144 0 R 1145 0 R 1146 0 R 1147 0 R 1148 0 R 1149 0 R 1151 0 R 1152 0 R 1154 0 R 1155 0 R 1157 0 R 1158 0 R 1160 0 R 1161 0 R 1163 0 R 1164 0 R 1166 0 R 1167 0 R 1169 0 R 1170 0 R 1172 0 R 1173 0 R 1175 0 R 1176 0 R 1178 0 R 1179 0 R 1181 0 R 1182 0 R 1184 0 R 1185 0 R 1187 0 R 1188 0 R 1190 0 R 1191 0 R 1193 0 R 1194 0 R 1196 0 R 1197 0 R 1199 0 R 1200 0 R 1202 0 R 1203 0 R 1205 0 R 1206 0 R 1208 0 R 1209 0 R 1211 0 R 1212 0 R ] endobj 1097 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 595.275 841.889] /CropBox [0 0 595.275 841.889] /BleedBox [0 0 595.275 841.889] /TrimBox [0 0 595.275 841.889] /Parent 1 0 R /Annots 1100 0 R /Contents 1213 0 R >> endobj 1214 0 obj 12202 endobj 1215 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding >> endobj 1216 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier-BoldOblique /Encoding /WinAnsiEncoding >> endobj 1217 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier-Oblique /Encoding /WinAnsiEncoding >> endobj 1218 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >> endobj 1219 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >> endobj 1220 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier /Encoding /WinAnsiEncoding >> endobj 1221 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Italic /Encoding /WinAnsiEncoding >> endobj 1222 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Bold /Encoding /WinAnsiEncoding >> endobj 1 0 obj << /Type /Pages /Count 137 /Kids [8 0 R 14 0 R 115 0 R 431 0 R 738 0 R 1097 0 R 17 0 R 606 0 R 20 0 R 940 0 R 671 0 R 729 0 R 23 0 R 1002 0 R 90 0 R 34 0 R 39 0 R 42 0 R 47 0 R 97 0 R 50 0 R 308 0 R 1008 0 R 53 0 R 1015 0 R 69 0 R 56 0 R 59 0 R 75 0 R 78 0 R 81 0 R 84 0 R 912 0 R 691 0 R 921 0 R 103 0 R 106 0 R 109 0 R 112 0 R 276 0 R 279 0 R 282 0 R 361 0 R 288 0 R 285 0 R 325 0 R 294 0 R 297 0 R 300 0 R 316 0 R 319 0 R 419 0 R 334 0 R 339 0 R 342 0 R 347 0 R 350 0 R 353 0 R 356 0 R 370 0 R 373 0 R 378 0 R 381 0 R 384 0 R 387 0 R 390 0 R 393 0 R 396 0 R 399 0 R 404 0 R 407 0 R 410 0 R 413 0 R 416 0 R 425 0 R 428 0 R 601 0 R 613 0 R 616 0 R 622 0 R 955 0 R 625 0 R 963 0 R 628 0 R 631 0 R 634 0 R 639 0 R 968 0 R 642 0 R 647 0 R 650 0 R 653 0 R 656 0 R 659 0 R 1022 0 R 662 0 R 665 0 R 668 0 R 697 0 R 703 0 R 700 0 R 709 0 R 712 0 R 717 0 R 720 0 R 723 0 R 726 0 R 928 0 R 735 0 R 909 0 R 934 0 R 937 0 R 975 0 R 949 0 R 952 0 R 1032 0 R 981 0 R 984 0 R 989 0 R 992 0 R 995 0 R 1039 0 R 1042 0 R 1050 0 R 1055 0 R 1058 0 R 1061 0 R 1064 0 R 1067 0 R 1070 0 R 1073 0 R 1076 0 R 1079 0 R 1085 0 R 1088 0 R 1091 0 R 1094 0 R ] >> endobj 2 0 obj << /Type /Catalog /Pages 1 0 R /Lang (en) /Metadata 7 0 R /PageLabels 9 0 R >> endobj 3 0 obj << /Font << /F11 1215 0 R /F12 1216 0 R /F10 1217 0 R /F5 1218 0 R /F3 1219 0 R /F9 1220 0 R /F6 1221 0 R /F7 1222 0 R >> /ProcSet [/PDF /ImageB /ImageC /Text] /XObject << /Im1 26 0 R /Im2 35 0 R /Im3 43 0 R >> /ColorSpace << /DefaultRGB 6 0 R /ICC24 25 0 R >> >> endobj 9 0 obj << /Nums [0 << /P (i) >> 1 << /P (ii) >> 2 << /P (iii) >> 3 << /P (iv) >> 4 << /P (v) >> 5 << /P (vi) >> 6 << /P (1) >> 7 << /P (2) >> 8 << /P (3) >> 9 << /P (4) >> 10 << /P (5) >> 11 << /P (6) >> 12 << /P (7) >> 13 << /P (8) >> 14 << /P (9) >> 15 << /P (10) >> 16 << /P (11) >> 17 << /P (12) >> 18 << /P (13) >> 19 << /P (14) >> 20 << /P (15) >> 21 << /P (16) >> 22 << /P (17) >> 23 << /P (18) >> 24 << /P (19) >> 25 << /P (20) >> 26 << /P (21) >> 27 << /P (22) >> 28 << /P (23) >> 29 << /P (24) >> 30 << /P (25) >> 31 << /P (26) >> 32 << /P (27) >> 33 << /P (28) >> 34 << /P (29) >> 35 << /P (30) >> 36 << /P (31) >> 37 << /P (32) >> 38 << /P (33) >> 39 << /P (34) >> 40 << /P (35) >> 41 << /P (36) >> 42 << /P (37) >> 43 << /P (38) >> 44 << /P (39) >> 45 << /P (40) >> 46 << /P (41) >> 47 << /P (42) >> 48 << /P (43) >> 49 << /P (44) >> 50 << /P (45) >> 51 << /P (46) >> 52 << /P (47) >> 53 << /P (48) >> 54 << /P (49) >> 55 << /P (50) >> 56 << /P (51) >> 57 << /P (52) >> 58 << /P (53) >> 59 << /P (54) >> 60 << /P (55) >> 61 << /P (56) >> 62 << /P (57) >> 63 << /P (58) >> 64 << /P (59) >> 65 << /P (60) >> 66 << /P (61) >> 67 << /P (62) >> 68 << /P (63) >> 69 << /P (64) >> 70 << /P (65) >> 71 << /P (66) >> 72 << /P (67) >> 73 << /P (68) >> 74 << /P (69) >> 75 << /P (70) >> 76 << /P (71) >> 77 << /P (72) >> 78 << /P (73) >> 79 << /P (74) >> 80 << /P (75) >> 81 << /P (76) >> 82 << /P (77) >> 83 << /P (78) >> 84 << /P (79) >> 85 << /P (80) >> 86 << /P (81) >> 87 << /P (82) >> 88 << /P (83) >> 89 << /P (84) >> 90 << /P (85) >> 91 << /P (86) >> 92 << /P (87) >> 93 << /P (88) >> 94 << /P (89) >> 95 << /P (90) >> 96 << /P (91) >> 97 << /P (92) >> 98 << /P (93) >> 99 << /P (94) >> 100 << /P (95) >> 101 << /P (96) >> 102 << /P (97) >> 103 << /P (98) >> 104 << /P (99) >> 105 << /P (100) >> 106 << /P (101) >> 107 << /P (102) >> 108 << /P (103) >> 109 << /P (104) >> 110 << /P (105) >> 111 << /P (106) >> 112 << /P (107) >> 113 << /P (108) >> 114 << /P (109) >> 115 << /P (110) >> 116 << /P (111) >> 117 << /P (112) >> 118 << /P (113) >> 119 << /P (114) >> 120 << /P (115) >> 121 << /P (116) >> 122 << /P (117) >> 123 << /P (118) >> 124 << /P (119) >> 125 << /P (120) >> 126 << /P (121) >> 127 << /P (122) >> 128 << /P (123) >> 129 << /P (124) >> 130 << /P (125) >> 131 << /P (126) >> 132 << /P (127) >> 133 << /P (128) >> 134 << /P (129) >> 135 << /P (130) >> 136 << /P (131) >> ] >> endobj xref 0 1223 0000000000 65535 f 0000523857 00000 n 0000525008 00000 n 0000525113 00000 n 0000000015 00000 n 0000000145 00000 n 0000002684 00000 n 0000002717 00000 n 0000003933 00000 n 0000525426 00000 n 0000003665 00000 n 0000004157 00000 n 0000004178 00000 n 0000004198 00000 n 0000005186 00000 n 0000004218 00000 n 0000005411 00000 n 0000006860 00000 n 0000005431 00000 n 0000007085 00000 n 0000009873 00000 n 0000007106 00000 n 0000010098 00000 n 0000013090 00000 n 0000010119 00000 n 0000010432 00000 n 0000010467 00000 n 0000010877 00000 n 0000010897 00000 n 0000436221 00000 n 0000010917 00000 n 0000013063 00000 n 0000011057 00000 n 0000013332 00000 n 0000016052 00000 n 0000013353 00000 n 0000013801 00000 n 0000013821 00000 n 0000016277 00000 n 0000018917 00000 n 0000016298 00000 n 0000019142 00000 n 0000021696 00000 n 0000019163 00000 n 0000021129 00000 n 0000021149 00000 n 0000021921 00000 n 0000024793 00000 n 0000021941 00000 n 0000025018 00000 n 0000027177 00000 n 0000025039 00000 n 0000027402 00000 n 0000029860 00000 n 0000027423 00000 n 0000030085 00000 n 0000032492 00000 n 0000030106 00000 n 0000032717 00000 n 0000036639 00000 n 0000443548 00000 n 0000032738 00000 n 0000036598 00000 n 0000036902 00000 n 0000032878 00000 n 0000443466 00000 n 0000033018 00000 n 0000033156 00000 n 0000036881 00000 n 0000039311 00000 n 0000036982 00000 n 0000037062 00000 n 0000039284 00000 n 0000037200 00000 n 0000039553 00000 n 0000041085 00000 n 0000039574 00000 n 0000041310 00000 n 0000043725 00000 n 0000041331 00000 n 0000043950 00000 n 0000046591 00000 n 0000043971 00000 n 0000046816 00000 n 0000049103 00000 n 0000046837 00000 n 0000046917 00000 n 0000049076 00000 n 0000047054 00000 n 0000049345 00000 n 0000052870 00000 n 0000381503 00000 n 0000049366 00000 n 0000052836 00000 n 0000049506 00000 n 0000049643 00000 n 0000053112 00000 n 0000056761 00000 n 0000381584 00000 n 0000053133 00000 n 0000056733 00000 n 0000053271 00000 n 0000057005 00000 n 0000059016 00000 n 0000057027 00000 n 0000059243 00000 n 0000061485 00000 n 0000059265 00000 n 0000061712 00000 n 0000064056 00000 n 0000061734 00000 n 0000064283 00000 n 0000066731 00000 n 0000064305 00000 n 0000066958 00000 n 0000102349 00000 n 0000066980 00000 n 0000067061 00000 n 0000101448 00000 n 0000067201 00000 n 0000067343 00000 n 0000067423 00000 n 0000067563 00000 n 0000252562 00000 n 0000067705 00000 n 0000067845 00000 n 0000252644 00000 n 0000067987 00000 n 0000068127 00000 n 0000068269 00000 n 0000068350 00000 n 0000068490 00000 n 0000068632 00000 n 0000068713 00000 n 0000068853 00000 n 0000399112 00000 n 0000068995 00000 n 0000069135 00000 n 0000299341 00000 n 0000069277 00000 n 0000069416 00000 n 0000299423 00000 n 0000069558 00000 n 0000069698 00000 n 0000334702 00000 n 0000069840 00000 n 0000069980 00000 n 0000334784 00000 n 0000070122 00000 n 0000070262 00000 n 0000070404 00000 n 0000070485 00000 n 0000070625 00000 n 0000436055 00000 n 0000070767 00000 n 0000070907 00000 n 0000436138 00000 n 0000071049 00000 n 0000071188 00000 n 0000071330 00000 n 0000071469 00000 n 0000071610 00000 n 0000071691 00000 n 0000071831 00000 n 0000071973 00000 n 0000072054 00000 n 0000072194 00000 n 0000072336 00000 n 0000072417 00000 n 0000072557 00000 n 0000072699 00000 n 0000072780 00000 n 0000072920 00000 n 0000073062 00000 n 0000073143 00000 n 0000073281 00000 n 0000073423 00000 n 0000073504 00000 n 0000073644 00000 n 0000073786 00000 n 0000073866 00000 n 0000074006 00000 n 0000074148 00000 n 0000074229 00000 n 0000074369 00000 n 0000074511 00000 n 0000074592 00000 n 0000074732 00000 n 0000074874 00000 n 0000074955 00000 n 0000075095 00000 n 0000075237 00000 n 0000075318 00000 n 0000075458 00000 n 0000075600 00000 n 0000075681 00000 n 0000075821 00000 n 0000075963 00000 n 0000076044 00000 n 0000076183 00000 n 0000123781 00000 n 0000076325 00000 n 0000076465 00000 n 0000123863 00000 n 0000076607 00000 n 0000076747 00000 n 0000439519 00000 n 0000076889 00000 n 0000077029 00000 n 0000439602 00000 n 0000077171 00000 n 0000077311 00000 n 0000077453 00000 n 0000077534 00000 n 0000077674 00000 n 0000077814 00000 n 0000077895 00000 n 0000078035 00000 n 0000443383 00000 n 0000078177 00000 n 0000078317 00000 n 0000078459 00000 n 0000078598 00000 n 0000078739 00000 n 0000078878 00000 n 0000079019 00000 n 0000079158 00000 n 0000079299 00000 n 0000079380 00000 n 0000079520 00000 n 0000079662 00000 n 0000079801 00000 n 0000079942 00000 n 0000080081 00000 n 0000080222 00000 n 0000080303 00000 n 0000080443 00000 n 0000080585 00000 n 0000080666 00000 n 0000080806 00000 n 0000080948 00000 n 0000081087 00000 n 0000081228 00000 n 0000081367 00000 n 0000385132 00000 n 0000081508 00000 n 0000081648 00000 n 0000385214 00000 n 0000081790 00000 n 0000081929 00000 n 0000385296 00000 n 0000082071 00000 n 0000082211 00000 n 0000385378 00000 n 0000082353 00000 n 0000082493 00000 n 0000082635 00000 n 0000082717 00000 n 0000082856 00000 n 0000082998 00000 n 0000083080 00000 n 0000083220 00000 n 0000083362 00000 n 0000083444 00000 n 0000083584 00000 n 0000083726 00000 n 0000083808 00000 n 0000083948 00000 n 0000084090 00000 n 0000084172 00000 n 0000084311 00000 n 0000084452 00000 n 0000084534 00000 n 0000084672 00000 n 0000084812 00000 n 0000102594 00000 n 0000105045 00000 n 0000102617 00000 n 0000105272 00000 n 0000106544 00000 n 0000105294 00000 n 0000106771 00000 n 0000108289 00000 n 0000106793 00000 n 0000108516 00000 n 0000110845 00000 n 0000108538 00000 n 0000111072 00000 n 0000114119 00000 n 0000111094 00000 n 0000111176 00000 n 0000114090 00000 n 0000111316 00000 n 0000114364 00000 n 0000117317 00000 n 0000114386 00000 n 0000117544 00000 n 0000119710 00000 n 0000117566 00000 n 0000119937 00000 n 0000123514 00000 n 0000119959 00000 n 0000123469 00000 n 0000120098 00000 n 0000120237 00000 n 0000120319 00000 n 0000120456 00000 n 0000123759 00000 n 0000127193 00000 n 0000123944 00000 n 0000124026 00000 n 0000127148 00000 n 0000124168 00000 n 0000124308 00000 n 0000124445 00000 n 0000127438 00000 n 0000130620 00000 n 0000127460 00000 n 0000130847 00000 n 0000134332 00000 n 0000130869 00000 n 0000130951 00000 n 0000134303 00000 n 0000131090 00000 n 0000134577 00000 n 0000137854 00000 n 0000134599 00000 n 0000134681 00000 n 0000137809 00000 n 0000134823 00000 n 0000134962 00000 n 0000135044 00000 n 0000135186 00000 n 0000138099 00000 n 0000141562 00000 n 0000138121 00000 n 0000141533 00000 n 0000138262 00000 n 0000141807 00000 n 0000144891 00000 n 0000141829 00000 n 0000145118 00000 n 0000148250 00000 n 0000145140 00000 n 0000148221 00000 n 0000145280 00000 n 0000148495 00000 n 0000150432 00000 n 0000148517 00000 n 0000150659 00000 n 0000153465 00000 n 0000150681 00000 n 0000153692 00000 n 0000157420 00000 n 0000153714 00000 n 0000157647 00000 n 0000159741 00000 n 0000157669 00000 n 0000159712 00000 n 0000157806 00000 n 0000159986 00000 n 0000163251 00000 n 0000160008 00000 n 0000163198 00000 n 0000160150 00000 n 0000160291 00000 n 0000160373 00000 n 0000160514 00000 n 0000160653 00000 n 0000163496 00000 n 0000166016 00000 n 0000163518 00000 n 0000166243 00000 n 0000168093 00000 n 0000166265 00000 n 0000168064 00000 n 0000166402 00000 n 0000168338 00000 n 0000170022 00000 n 0000168360 00000 n 0000170249 00000 n 0000172289 00000 n 0000170271 00000 n 0000172516 00000 n 0000175331 00000 n 0000172538 00000 n 0000175558 00000 n 0000177385 00000 n 0000175580 00000 n 0000177612 00000 n 0000180525 00000 n 0000177634 00000 n 0000180752 00000 n 0000184062 00000 n 0000180774 00000 n 0000184289 00000 n 0000186945 00000 n 0000184311 00000 n 0000187172 00000 n 0000191025 00000 n 0000187194 00000 n 0000190996 00000 n 0000187334 00000 n 0000191270 00000 n 0000193355 00000 n 0000191292 00000 n 0000193582 00000 n 0000195241 00000 n 0000193604 00000 n 0000195468 00000 n 0000198215 00000 n 0000195490 00000 n 0000198442 00000 n 0000201002 00000 n 0000198464 00000 n 0000201229 00000 n 0000203972 00000 n 0000201251 00000 n 0000204199 00000 n 0000207377 00000 n 0000204221 00000 n 0000204303 00000 n 0000207348 00000 n 0000204443 00000 n 0000207622 00000 n 0000209675 00000 n 0000207644 00000 n 0000209902 00000 n 0000211922 00000 n 0000209924 00000 n 0000212149 00000 n 0000248963 00000 n 0000212171 00000 n 0000248014 00000 n 0000212310 00000 n 0000212452 00000 n 0000212534 00000 n 0000212674 00000 n 0000212816 00000 n 0000212898 00000 n 0000213038 00000 n 0000213178 00000 n 0000213260 00000 n 0000213399 00000 n 0000213541 00000 n 0000213623 00000 n 0000213763 00000 n 0000213905 00000 n 0000213987 00000 n 0000214127 00000 n 0000214269 00000 n 0000214351 00000 n 0000214491 00000 n 0000214633 00000 n 0000214715 00000 n 0000214854 00000 n 0000214996 00000 n 0000215078 00000 n 0000215217 00000 n 0000215359 00000 n 0000215499 00000 n 0000215639 00000 n 0000215779 00000 n 0000215921 00000 n 0000216003 00000 n 0000216143 00000 n 0000216285 00000 n 0000216367 00000 n 0000216507 00000 n 0000216649 00000 n 0000216789 00000 n 0000216929 00000 n 0000217069 00000 n 0000217211 00000 n 0000217293 00000 n 0000217433 00000 n 0000217575 00000 n 0000217657 00000 n 0000217796 00000 n 0000217938 00000 n 0000218078 00000 n 0000218220 00000 n 0000218302 00000 n 0000218442 00000 n 0000218584 00000 n 0000218666 00000 n 0000218806 00000 n 0000218948 00000 n 0000219030 00000 n 0000219170 00000 n 0000219312 00000 n 0000219394 00000 n 0000219534 00000 n 0000219676 00000 n 0000219758 00000 n 0000219898 00000 n 0000220040 00000 n 0000220122 00000 n 0000220262 00000 n 0000220404 00000 n 0000220486 00000 n 0000220626 00000 n 0000220768 00000 n 0000220850 00000 n 0000220990 00000 n 0000221132 00000 n 0000221214 00000 n 0000221354 00000 n 0000221496 00000 n 0000221577 00000 n 0000221716 00000 n 0000221858 00000 n 0000221940 00000 n 0000222080 00000 n 0000222222 00000 n 0000222304 00000 n 0000222443 00000 n 0000222585 00000 n 0000222667 00000 n 0000222806 00000 n 0000222948 00000 n 0000223030 00000 n 0000223170 00000 n 0000223312 00000 n 0000223394 00000 n 0000223534 00000 n 0000223676 00000 n 0000223758 00000 n 0000223898 00000 n 0000224040 00000 n 0000224180 00000 n 0000224322 00000 n 0000224404 00000 n 0000224544 00000 n 0000224686 00000 n 0000224768 00000 n 0000224908 00000 n 0000225050 00000 n 0000225132 00000 n 0000225272 00000 n 0000225414 00000 n 0000225496 00000 n 0000225635 00000 n 0000225777 00000 n 0000225859 00000 n 0000225998 00000 n 0000226140 00000 n 0000226222 00000 n 0000226362 00000 n 0000226504 00000 n 0000226586 00000 n 0000226725 00000 n 0000226867 00000 n 0000226949 00000 n 0000227089 00000 n 0000227231 00000 n 0000227313 00000 n 0000227451 00000 n 0000227593 00000 n 0000227675 00000 n 0000227815 00000 n 0000227957 00000 n 0000228039 00000 n 0000228179 00000 n 0000228321 00000 n 0000228403 00000 n 0000228543 00000 n 0000228685 00000 n 0000228767 00000 n 0000228906 00000 n 0000229048 00000 n 0000229130 00000 n 0000229270 00000 n 0000229412 00000 n 0000229494 00000 n 0000229634 00000 n 0000229776 00000 n 0000229858 00000 n 0000229997 00000 n 0000230139 00000 n 0000230221 00000 n 0000230361 00000 n 0000230503 00000 n 0000230585 00000 n 0000230725 00000 n 0000230867 00000 n 0000231007 00000 n 0000231149 00000 n 0000231231 00000 n 0000231370 00000 n 0000231512 00000 n 0000231594 00000 n 0000231731 00000 n 0000231872 00000 n 0000231954 00000 n 0000232092 00000 n 0000232232 00000 n 0000232314 00000 n 0000232451 00000 n 0000232591 00000 n 0000249208 00000 n 0000252295 00000 n 0000249231 00000 n 0000252266 00000 n 0000249373 00000 n 0000252540 00000 n 0000254527 00000 n 0000252726 00000 n 0000254490 00000 n 0000252864 00000 n 0000252946 00000 n 0000253088 00000 n 0000254772 00000 n 0000257612 00000 n 0000254794 00000 n 0000257839 00000 n 0000260609 00000 n 0000257861 00000 n 0000257943 00000 n 0000260580 00000 n 0000258082 00000 n 0000260854 00000 n 0000263101 00000 n 0000260876 00000 n 0000263328 00000 n 0000266302 00000 n 0000263350 00000 n 0000266529 00000 n 0000269311 00000 n 0000266551 00000 n 0000269538 00000 n 0000272957 00000 n 0000269560 00000 n 0000273184 00000 n 0000276134 00000 n 0000273206 00000 n 0000276105 00000 n 0000273346 00000 n 0000276379 00000 n 0000277057 00000 n 0000276401 00000 n 0000277284 00000 n 0000280817 00000 n 0000277305 00000 n 0000280788 00000 n 0000277445 00000 n 0000281062 00000 n 0000282372 00000 n 0000281084 00000 n 0000282599 00000 n 0000284926 00000 n 0000282621 00000 n 0000285153 00000 n 0000287645 00000 n 0000285175 00000 n 0000287872 00000 n 0000290375 00000 n 0000287894 00000 n 0000290602 00000 n 0000291336 00000 n 0000290624 00000 n 0000291563 00000 n 0000294322 00000 n 0000291584 00000 n 0000294549 00000 n 0000295752 00000 n 0000294571 00000 n 0000295979 00000 n 0000299092 00000 n 0000296001 00000 n 0000299319 00000 n 0000304583 00000 n 0000299505 00000 n 0000304458 00000 n 0000299645 00000 n 0000299787 00000 n 0000299929 00000 n 0000300068 00000 n 0000300209 00000 n 0000300351 00000 n 0000447134 00000 n 0000300493 00000 n 0000300635 00000 n 0000300775 00000 n 0000300857 00000 n 0000300999 00000 n 0000301138 00000 n 0000301278 00000 n 0000301360 00000 n 0000301500 00000 n 0000304828 00000 n 0000308177 00000 n 0000304850 00000 n 0000308140 00000 n 0000304991 00000 n 0000305133 00000 n 0000308422 00000 n 0000310935 00000 n 0000308444 00000 n 0000311162 00000 n 0000313702 00000 n 0000311184 00000 n 0000313929 00000 n 0000316954 00000 n 0000313951 00000 n 0000314033 00000 n 0000316925 00000 n 0000314175 00000 n 0000317199 00000 n 0000319511 00000 n 0000317221 00000 n 0000319738 00000 n 0000322822 00000 n 0000319760 00000 n 0000322793 00000 n 0000319900 00000 n 0000323067 00000 n 0000325787 00000 n 0000323089 00000 n 0000326014 00000 n 0000328694 00000 n 0000326036 00000 n 0000328921 00000 n 0000331703 00000 n 0000328943 00000 n 0000331930 00000 n 0000334453 00000 n 0000331952 00000 n 0000334680 00000 n 0000337417 00000 n 0000334866 00000 n 0000334948 00000 n 0000337388 00000 n 0000335088 00000 n 0000337662 00000 n 0000340548 00000 n 0000337684 00000 n 0000340775 00000 n 0000377944 00000 n 0000340797 00000 n 0000376995 00000 n 0000340937 00000 n 0000341079 00000 n 0000341161 00000 n 0000341301 00000 n 0000341443 00000 n 0000341525 00000 n 0000341665 00000 n 0000341807 00000 n 0000341947 00000 n 0000342089 00000 n 0000342171 00000 n 0000342311 00000 n 0000342453 00000 n 0000342593 00000 n 0000342735 00000 n 0000342816 00000 n 0000342956 00000 n 0000408341 00000 n 0000343098 00000 n 0000343238 00000 n 0000408423 00000 n 0000343380 00000 n 0000343519 00000 n 0000343661 00000 n 0000343743 00000 n 0000343883 00000 n 0000344025 00000 n 0000344107 00000 n 0000344247 00000 n 0000412340 00000 n 0000344389 00000 n 0000344528 00000 n 0000344670 00000 n 0000344752 00000 n 0000344892 00000 n 0000345034 00000 n 0000345116 00000 n 0000345256 00000 n 0000345398 00000 n 0000345480 00000 n 0000345620 00000 n 0000345762 00000 n 0000345844 00000 n 0000345984 00000 n 0000346124 00000 n 0000346206 00000 n 0000346346 00000 n 0000346488 00000 n 0000346570 00000 n 0000346710 00000 n 0000346852 00000 n 0000346934 00000 n 0000347074 00000 n 0000415229 00000 n 0000347216 00000 n 0000347355 00000 n 0000415311 00000 n 0000347497 00000 n 0000347637 00000 n 0000415393 00000 n 0000347779 00000 n 0000347918 00000 n 0000415475 00000 n 0000348060 00000 n 0000348198 00000 n 0000348340 00000 n 0000348422 00000 n 0000348562 00000 n 0000348704 00000 n 0000348786 00000 n 0000348926 00000 n 0000349068 00000 n 0000349150 00000 n 0000349290 00000 n 0000349432 00000 n 0000349513 00000 n 0000349653 00000 n 0000349795 00000 n 0000349877 00000 n 0000350017 00000 n 0000350159 00000 n 0000350241 00000 n 0000350381 00000 n 0000350523 00000 n 0000350605 00000 n 0000350745 00000 n 0000350887 00000 n 0000351027 00000 n 0000447217 00000 n 0000351169 00000 n 0000351309 00000 n 0000351451 00000 n 0000351533 00000 n 0000351673 00000 n 0000351815 00000 n 0000351897 00000 n 0000352037 00000 n 0000352179 00000 n 0000352319 00000 n 0000352461 00000 n 0000352543 00000 n 0000352682 00000 n 0000352824 00000 n 0000352906 00000 n 0000353046 00000 n 0000353188 00000 n 0000353270 00000 n 0000353410 00000 n 0000353552 00000 n 0000353634 00000 n 0000353774 00000 n 0000353916 00000 n 0000353998 00000 n 0000354138 00000 n 0000354280 00000 n 0000354362 00000 n 0000354502 00000 n 0000354642 00000 n 0000354782 00000 n 0000354924 00000 n 0000355006 00000 n 0000355146 00000 n 0000355288 00000 n 0000355370 00000 n 0000355509 00000 n 0000355651 00000 n 0000355733 00000 n 0000355873 00000 n 0000356015 00000 n 0000356097 00000 n 0000356236 00000 n 0000356378 00000 n 0000356460 00000 n 0000356600 00000 n 0000356742 00000 n 0000356824 00000 n 0000356964 00000 n 0000357106 00000 n 0000357188 00000 n 0000357328 00000 n 0000357470 00000 n 0000357552 00000 n 0000357692 00000 n 0000357834 00000 n 0000357916 00000 n 0000358056 00000 n 0000358198 00000 n 0000358280 00000 n 0000358420 00000 n 0000358562 00000 n 0000358702 00000 n 0000389102 00000 n 0000358844 00000 n 0000358982 00000 n 0000359124 00000 n 0000359206 00000 n 0000359346 00000 n 0000359488 00000 n 0000359570 00000 n 0000359709 00000 n 0000359850 00000 n 0000359932 00000 n 0000360070 00000 n 0000360210 00000 n 0000360292 00000 n 0000360430 00000 n 0000360570 00000 n 0000378189 00000 n 0000381254 00000 n 0000378212 00000 n 0000381481 00000 n 0000384865 00000 n 0000381665 00000 n 0000381747 00000 n 0000384812 00000 n 0000381889 00000 n 0000382028 00000 n 0000382168 00000 n 0000382307 00000 n 0000385110 00000 n 0000388835 00000 n 0000385460 00000 n 0000388790 00000 n 0000385600 00000 n 0000385739 00000 n 0000385879 00000 n 0000389080 00000 n 0000392354 00000 n 0000389184 00000 n 0000392317 00000 n 0000389326 00000 n 0000389468 00000 n 0000392599 00000 n 0000395644 00000 n 0000392621 00000 n 0000395871 00000 n 0000398863 00000 n 0000395893 00000 n 0000399090 00000 n 0000402543 00000 n 0000399194 00000 n 0000402490 00000 n 0000399333 00000 n 0000419067 00000 n 0000399473 00000 n 0000399613 00000 n 0000399753 00000 n 0000402788 00000 n 0000405504 00000 n 0000402810 00000 n 0000405731 00000 n 0000408092 00000 n 0000405753 00000 n 0000408319 00000 n 0000412073 00000 n 0000451800 00000 n 0000408505 00000 n 0000412028 00000 n 0000408647 00000 n 0000408789 00000 n 0000408929 00000 n 0000412318 00000 n 0000414962 00000 n 0000412422 00000 n 0000414933 00000 n 0000412564 00000 n 0000415207 00000 n 0000418800 00000 n 0000415557 00000 n 0000418755 00000 n 0000415699 00000 n 0000415838 00000 n 0000415978 00000 n 0000419045 00000 n 0000422226 00000 n 0000419149 00000 n 0000422189 00000 n 0000419288 00000 n 0000419427 00000 n 0000422471 00000 n 0000423634 00000 n 0000422493 00000 n 0000423861 00000 n 0000427058 00000 n 0000423883 00000 n 0000427029 00000 n 0000424025 00000 n 0000427303 00000 n 0000430675 00000 n 0000427325 00000 n 0000430902 00000 n 0000432346 00000 n 0000430924 00000 n 0000432573 00000 n 0000435786 00000 n 0000432595 00000 n 0000435741 00000 n 0000432737 00000 n 0000432878 00000 n 0000433018 00000 n 0000436032 00000 n 0000439248 00000 n 0000436303 00000 n 0000436386 00000 n 0000439217 00000 n 0000436528 00000 n 0000439496 00000 n 0000443112 00000 n 0000439685 00000 n 0000439768 00000 n 0000443072 00000 n 0000439912 00000 n 0000440056 00000 n 0000443360 00000 n 0000446863 00000 n 0000443630 00000 n 0000443713 00000 n 0000446823 00000 n 0000443855 00000 n 0000443995 00000 n 0000447111 00000 n 0000451529 00000 n 0000447300 00000 n 0000451453 00000 n 0000447444 00000 n 0000447586 00000 n 0000447726 00000 n 0000447869 00000 n 0000448009 00000 n 0000448150 00000 n 0000451777 00000 n 0000455326 00000 n 0000451883 00000 n 0000455277 00000 n 0000452024 00000 n 0000452166 00000 n 0000452305 00000 n 0000455574 00000 n 0000458278 00000 n 0000455597 00000 n 0000458507 00000 n 0000461549 00000 n 0000458530 00000 n 0000461491 00000 n 0000458671 00000 n 0000458814 00000 n 0000458954 00000 n 0000459092 00000 n 0000461797 00000 n 0000463290 00000 n 0000461820 00000 n 0000463259 00000 n 0000461960 00000 n 0000463538 00000 n 0000465346 00000 n 0000463561 00000 n 0000465575 00000 n 0000467671 00000 n 0000465598 00000 n 0000467900 00000 n 0000470191 00000 n 0000467923 00000 n 0000470420 00000 n 0000472611 00000 n 0000470443 00000 n 0000472840 00000 n 0000476022 00000 n 0000472863 00000 n 0000476251 00000 n 0000478989 00000 n 0000476274 00000 n 0000479218 00000 n 0000482218 00000 n 0000479241 00000 n 0000482447 00000 n 0000485046 00000 n 0000482470 00000 n 0000485275 00000 n 0000488080 00000 n 0000485298 00000 n 0000488040 00000 n 0000485439 00000 n 0000485577 00000 n 0000488328 00000 n 0000489692 00000 n 0000488351 00000 n 0000489921 00000 n 0000492206 00000 n 0000489944 00000 n 0000492435 00000 n 0000493711 00000 n 0000492458 00000 n 0000493940 00000 n 0000495140 00000 n 0000493963 00000 n 0000495369 00000 n 0000522685 00000 n 0000495392 00000 n 0000495475 00000 n 0000521943 00000 n 0000495617 00000 n 0000495761 00000 n 0000495843 00000 n 0000495985 00000 n 0000496129 00000 n 0000496212 00000 n 0000496354 00000 n 0000496498 00000 n 0000496639 00000 n 0000496782 00000 n 0000496865 00000 n 0000497007 00000 n 0000497151 00000 n 0000497234 00000 n 0000497376 00000 n 0000497520 00000 n 0000497603 00000 n 0000497745 00000 n 0000497889 00000 n 0000498030 00000 n 0000498173 00000 n 0000498256 00000 n 0000498398 00000 n 0000498542 00000 n 0000498625 00000 n 0000498767 00000 n 0000498911 00000 n 0000498994 00000 n 0000499136 00000 n 0000499280 00000 n 0000499363 00000 n 0000499504 00000 n 0000499648 00000 n 0000499789 00000 n 0000499932 00000 n 0000500074 00000 n 0000500218 00000 n 0000500301 00000 n 0000500443 00000 n 0000500587 00000 n 0000500670 00000 n 0000500812 00000 n 0000500956 00000 n 0000501039 00000 n 0000501180 00000 n 0000501324 00000 n 0000501466 00000 n 0000501610 00000 n 0000501752 00000 n 0000501896 00000 n 0000501979 00000 n 0000502120 00000 n 0000502264 00000 n 0000502348 00000 n 0000502490 00000 n 0000502634 00000 n 0000502718 00000 n 0000502860 00000 n 0000503004 00000 n 0000503087 00000 n 0000503229 00000 n 0000503373 00000 n 0000503457 00000 n 0000503599 00000 n 0000503743 00000 n 0000503827 00000 n 0000503969 00000 n 0000504113 00000 n 0000504196 00000 n 0000504338 00000 n 0000504482 00000 n 0000504566 00000 n 0000504708 00000 n 0000504852 00000 n 0000504936 00000 n 0000505078 00000 n 0000505222 00000 n 0000505306 00000 n 0000505447 00000 n 0000505591 00000 n 0000505675 00000 n 0000505817 00000 n 0000505961 00000 n 0000506045 00000 n 0000506187 00000 n 0000506331 00000 n 0000506415 00000 n 0000506557 00000 n 0000506701 00000 n 0000506785 00000 n 0000506927 00000 n 0000507071 00000 n 0000507155 00000 n 0000507297 00000 n 0000507441 00000 n 0000507525 00000 n 0000507667 00000 n 0000507811 00000 n 0000507895 00000 n 0000508037 00000 n 0000508181 00000 n 0000508265 00000 n 0000508407 00000 n 0000508551 00000 n 0000508635 00000 n 0000508777 00000 n 0000508921 00000 n 0000509005 00000 n 0000509147 00000 n 0000509291 00000 n 0000509375 00000 n 0000509517 00000 n 0000509661 00000 n 0000522933 00000 n 0000522957 00000 n 0000523069 00000 n 0000523188 00000 n 0000523303 00000 n 0000523414 00000 n 0000523528 00000 n 0000523635 00000 n 0000523747 00000 n trailer << /Root 2 0 R /Info 4 0 R /ID [<148BC30C0B4393612CE59DDE69969ED5> <148BC30C0B4393612CE59DDE69969ED5>] /Size 1223 >> startxref 527971 %%EOF samhain-4.1.4/docs/README.sstrip0000644000175000017500000000427712615253277013240 00000000000000sstrip is a small utility that removes the contents at the end of an ELF file that are not part of the program's memory image. Most ELF executables are built with both a program header table and a section header table. However, only the former is required in order for the OS to load, link and execute a program. sstrip attempts to extract the ELF header, the program header table, and its contents, leaving everything else in the bit bucket. It can only remove parts of the file that occur at the end, after the parts to be saved. However, this almost always includes the section header table, and occasionally a few random sections that are not used when running a program. It should be noted that the GNU bfd library is (understandably) dependent on the section header table as an index to the file's contents. Thus, an executable file that has no section header table cannot be used with gdb, objdump, or any other program based upon the bfd library, at all. In fact, the program will not even recognize the file as a valid executable. (This limitation is noted in the source code comments for bfd, and is marked "FIXME", so this may change at some future date. However, I would imagine that it is a pretty low-priority item, as executables without a section header table are rare in the extreme.) This probably also explains why strip doesn't offer the option to do this. Shared library files may also have their section header table removed. Such a library will still function; however, it will no longer be possible for a compiler to link a new program against it. As an added bonus, sstrip also tries to removes trailing zero bytes from the end of the file. (This normally cannot be done with an executable that has a section header table.) sstrip is a very simplistic program. It depends upon the common practice of putting the parts of the file that contribute to the memory image at the front, and the remaining material at the end. This permits it to discard the latter material without affecting file offsets and memory addresses in what remains. However, the ELF standard permits files to be organized in almost any order. So although this procedure usually works in practice, it is not meant to be taken too seriously. samhain-4.1.4/docs/README.UPGRADE0000644000175000017500000000777612615253277013012 00000000000000to 4.0.0 and higher: if you use "ReportCheckflags = yes" (off by default), you need to change the database scheme: -- mysql: ALTER TABLE samhain.log ADD COLUMN checkflags_old BIGINT UNSIGNED; ALTER TABLE samhain.log ADD COLUMN checkflags_new BIGINT UNSIGNED; -- postgres: ALTER TABLE samhain.log ADD COLUMN checkflags_old NUMERIC(20); ALTER TABLE samhain.log ADD COLUMN checkflags_new NUMERIC(20); --oracle: ALTER TABLE samhain.log ADD checkflags_old NUMBER(20); ALTER TABLE samhain.log ADD checkflags_new NUMBER(20); to 2.8.0 and higher: samhain supports IPv6 now, which means that the size of the 'ip' column in the database must be increased from VARCHAR(16) to VARCHAR(46). BE SURE TO MAKE A BACKUP BEFORE THIS! -- mysql: alter table samhain.log modify ip VARCHAR(46); -- postgresql: alter table samhain.log alter column ip type varchar(46); -- oracle: alter table samhain.log modify ip VARCHAR2(46); to 2.4.4 and higher: it is possible now to store the full content of small files in the baseline database. To support this feature with logging to an RDBMS, the DB schema for Oracle needs to be adjusted by converting the link_old, link_new columns from VARCHAR2 to CLOB: -- Oracle: ALTER TABLE samhain.log ADD tmp_name CLOB; UPDATE samhain.log SET tmp_name=link_old; ALTER TABLE samhain.log DROP COLUMN link_old; ALTER TABLE samhain.log RENAME COLUMN tmp_name to link_old; ALTER TABLE samhain.log ADD tmp_name CLOB; UPDATE samhain.log SET tmp_name=link_new; ALTER TABLE samhain.log DROP COLUMN link_new; ALTER TABLE samhain.log RENAME COLUMN tmp_name to link_new; -- Samhain server (yule): if you are logging to the RDBMS via the server (yule), as recommended, you need to also upgrade the server, because earlier versions had a too restrictive limit on the maximum length of an SQL query. to 2.3.3 and higher: a bug has been fixed that resulted in an additional slash at the beginning of the linked path of symlinks in the root directory (symlinks in other directories were not affected) -- this may cause spurious warnings about modified links, if you check against a database created with an earlier version of samhain from lower to 2.3.x: the database scheme has changed slightly. To upgrade, use the following SQL commands in the command-line client of your database: -- MySQL: ALTER TABLE samhain.log ADD COLUMN acl_old BLOB; ALTER TABLE samhain.log ADD COLUMN acl_new BLOB; -- PostgreSQL: ALTER TABLE samhain.log ADD COLUMN acl_old TEXT; ALTER TABLE samhain.log ADD COLUMN acl_new TEXT; -- Oracle: ALTER TABLE samhain.log ADD acl_old VARCHAR2(4000); ALTER TABLE samhain.log ADD acl_new VARCHAR2(4000); DROP TRIGGER trigger_on_log; since 2.2.0: server-to-server relay is possible -- this implies that problems will arise if your server is misconfigured to connect to itself (SetExportSeverity is explicitely set to a threshold different from 'none', and the logserver is set to localhost). The server may deadlock in this case. since 2.1.0: update and daemon mode can be combined -- this implies that '-t update' will start a daemon process if running as daemon is the default specified in the config file. use '--foreground' to avoid starting a daemon process from 1.7.x to 1.8.x: client/server encryption protocol has been enhanced -- 1.7.x clients can connect to a 1.8.x server -- 1.8.x clients can only connect to a 1.7.x server, if they are built with --enable-encrypt=1 from 1.6.x to 1.7.x: things to watch out for -- the log server drops root privileges after startup; it needs a logfile directory with write access for the unprivileged user now -- the PID file does not double as lock for the log file anymore; the log file has its own lock now (same path, with .lock appended) -- by default, the HTML status page of the server is in the log directory now; this allows to make the data directory read-only for the server samhain-4.1.4/docs/README.gcc_bug0000644000175000017500000000236612615253277013302 00000000000000 GCC Compiler Bug ---------------- Reference: http://boudicca.tux.org/hypermail/linux-kernel/2000week05/0983.html From: Johan Kullstam (kullstam@ne.mediaone.net) Date: Thu Jan 27 2000 - 18:00:28 EST Horst von Brand writes: > My question in this vein would be the -fno-strength-reduce. The gcc bug > that placed this in the kernel was in gcc-2.7.2, and was worked around in > 2.7.2.3 by just making this option unconditional. Both 2.2.15pre4 and > 2.3.41pre2 at least demand gcc-2.7.2.3 as minimal version. just when you thought it was safe to go into the water... strength-reduction is broken again in gcc-2.95.2 (aka the current release). i'm not sure about what versions actually do work. for fun, try this one out. cut and paste the program bug.c. $ gcc -O2 bug.c -o b0 $ gcc -O2 -fno-strength-reduce bug.c -o b1 run b1. notice it finish immediately. now run b0. notice how b0 never terminates (until you ^C it). -- bug.c ----------------------------------------- static void bug(int size, int tries) { int i; int num = 0; while (num < size) { for (i = 1; i < tries; i++) num++; } } int main() { bug(5, 10); return 0; } -- bug.c ----------------------------------------- samhain-4.1.4/docs/README.LZO0000644000175000017500000001032512615253277012347 00000000000000-----BEGIN PGP SIGNED MESSAGE----- ============================================================================ miniLZO -- mini subset of the LZO real-time data compression library ============================================================================ Author : Markus Franz Xaver Johannes Oberhumer http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html Version : 1.06 Date : 29-Nov-1999 I've created miniLZO for projects where it is inconvenient to include (or require) the full LZO source code just because you want to add a little bit of data compression to your application. miniLZO implements the LZO1X-1 compressor and both the standard and safe LZO1X decompressor. Apart from fast compression it also useful for situations where you want to use pre-compressed data files (which must have been compressed with LZO1X-999). miniLZO consists of one C source file and two header files: minilzo.c minilzo.h lzoconf.h To use miniLZO just copy these files into your source directory, add minilzo.c to your Makefile and #include minilzo.h from your program. Note: you also must distribute this file (`README.LZO') with your project. minilzo.o compiles to about 6 kB (using gcc or Watcom C on a i386), and the sources are about 14 kB when packed with zip - so there's no more excuse that your application doesn't support data compression :-) For more information, documentation, example programs and other support files (like Makefiles and build scripts) please download the full LZO package from http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html Have fun, Markus P.S. minilzo.c is generated automatically from the LZO sources and therefore functionality is completely identical Appendix A: building miniLZO ---------------------------- miniLZO is written such a way that it should compile and run out-of-the-box on most machines. If you are running on a very unusual architecture and lzo_init() fails then you should first recompile with `-DLZO_DEBUG' to see what causes the failure. The most probable case is something like `sizeof(char *) != sizeof(long)'. After identifying the problem you can compile by adding some defines like `-DSIZEOF_CHAR_P=8' to your Makefile. The best solution is (of course) using Autoconf - if your project uses Autoconf anyway just add `-DMINILZO_HAVE_CONFIG_H' to your compiler flags when compiling minilzo.c. See the LZO distribution for an example how to set up configure.in. Appendix B: list of public functions available in miniLZO --------------------------------------------------------- Library initialization lzo_init() Compression lzo1x_1_compress() Decompression lzo1x_decompress() lzo1x_decompress_safe() Checksum functions lzo_adler32() Version functions lzo_version() lzo_version_string() lzo_version_date() Portable (but slow) string functions lzo_memcmp() lzo_memcpy() lzo_memmove() lzo_memset() Appendix C: suggested macros for `configure.in' when using Autoconf ------------------------------------------------------------------- Checks for typedefs and structures AC_CHECK_TYPE(ptrdiff_t,long) AC_TYPE_SIZE_T AC_CHECK_SIZEOF(unsigned short) AC_CHECK_SIZEOF(unsigned) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(char *) AC_CHECK_SIZEOF(ptrdiff_t) AC_CHECK_SIZEOF(size_t) Checks for compiler characteristics AC_C_CONST Checks for library functions AC_CHECK_FUNCS(memcmp memcpy memmove memset) Appendix D: Copyright --------------------- LZO and miniLZO are Copyright (C) 1996-1999 Markus Franz Xaver Johannes Oberhumer LZO and miniLZO are distributed under the terms of the GNU General Public License (GPL). See the file COPYING. Special licenses for commercial and other applications which are not willing to accept the GNU General Public License are available by contacting the author. -----BEGIN PGP SIGNATURE----- Version: 2.6.3ia Charset: noconv iQCVAwUBOEK5Km10fyLu8beJAQE2oAQAovSZ1KDXJKdbfUmGHhRAoU/BdQXydYKr tGDtC0i8EfC2cjrbJANbZq8GQM0PMZSAgyW9/BaUmRZ/d5pxpF0eBBpUp87i/ZM6 BoPE3uu7Rwu05SSR3FRFe1lCrMDn/yHkyV9T+DUY6XaBLONdaPh7BayQ93MnCFoD 9gs3grhALsM= =uuXN -----END PGP SIGNATURE----- samhain-4.1.4/docs/HOWTO-write-modules.html0000644000175000017500000005651212615253277015420 00000000000000 HOWTO Write Samhain Modules

samhain file integrity scanner | online documentation


Writing modules for samhain



This document should help anyone who is sitting down to write a module for the samhain host intrusion detection system. We give an overview of samhain's structure from the point of view of the module author, and describe some of the samhain utility and interface functions available. Lastly, we explain how to integrate your module into the samhain autoconf build tools.

Introduction

Samhain is a rather useful file integrity and host intrusion detection system. It is written entirely in C, and much care has been given to making it robust and secure. Additionally, it has been written with extensibility in mind, and so interfaces for adding user-contributed modules have been provided. A module author can easily extend the configuration file syntax and have his checking code run on a regular basis as one of samhain's internal checks.

Prerequisites

You'll need to know how to read and write C. You'll need the latest source for samhain. You'll need to have read all of samhain's other documentation. Finally, if you want to make your module build as part of the samhain tree (you do), you'll need GNU's autoconf package.

An overview of samhain's execution

Here's what happens when samhain starts:

  • Check if samhain has been called with one of the "init.d" type commands - start, stop, reload, status. If so, these are handled as you might expect. Nice feature.
  • Initialise all global structures and parse command-line options.
  • Read the configuration file. This is handled in sh_readconf_read(). This includes attempting to download the file if samhain has been compiled to do so.
  • Drop privileges if server.
  • Test the checksum on the database if client or standalone.
  • Now test if samhain has been compiled as a client or a server.
    • If server, enter server main loop sh_receive() in sh_forward.c. This is simple enough; apart from checks for signals received, the server just accepts incoming connections, verifies that they are from an authorised client, and logs the message received.
    • If client or standalone, we run the rest of main() in samhain.c, which follows:
  • Initialise modules - that is, call the mod_init() function on each module. Note that if the module intialisation routine returns a nonzero value, you should also have it free anything that's been allocated by the configuration file reading functions, since this method is always called after an sh_readconf_read(), i.e. when the configuration file is re-read after a SIGHUP.
  • Test the setup that's been read from the configuration - for example, check if any files or directories have been defined twice.
  • Enter the main loop (which runs just once if samhain is not configured as a daemon). Test if any signals have been received, and handle them appropriately:
    • On reconfiguration (SIGHUP), clear internal file lists etc. and call the mod_reconf() function on each module. This should clean up anything internal to the module before the configuration file is re-read. Then read the configuration file again and set things up as before, including a new call to mod_init().
    • On SIGIOT (SIGABRT), shut down the log-file for a moment to allow for rotation.
    • On SIGQUIT, terminate. Note that any call to exit() will invoke the exit_handler() defined in samhain.c; the first thing this does is to call mod_cleanup() on all modules. Then it cleans up everything else in samhain and exits.
    • On SIGUSR1 turn toggle debugging on/off.
    • On SIGUSR2 suspend the daemon an notify the server to allow a second instance of samhain downloading its configuration file without triggering an alert (restart without exit) on the server.
  • If it's time to check files, check directories and then files, and then flush the mail queue.
  • Execute modules. For each module, if mod_timer(tcurrent) returns a nonzero value, then execute mod_check().
  • Do various maintenance operations such as logging a timestamp/sending some mail if it's time, seeding/re-seeding the PRNG, etc.
You'll note that in the text above I refer to a couple of module functions - mod_init(), mod_check(), etc. These are function pointers that act as hooks for attaching modules to samhain. Next we'll describe how they are used.

Samhain's module interface

Here we'll describe the interface samhain provides to module authors.

The module list

In sh_modules.h, the following structure is defined:


typedef struct mod_type
{
  /* The name of the module                                    */
  char * name;      

  /* Set by samhain to 1 on successful initialization, else 0  */
  int    initval; 

  /* The initialization function. Return 0 on success.         */
  int (* mod_init)    (void);  
                             
  /* The timer function. Return 0 if NOT time to check.        */
  int (* mod_timer)   (unsigned long tcurrent); 

  /* The check function. Return 0 on success.                  */
  int (* mod_check)   (void); 

  /* The cleanup function. Return 0 on success.                */
  int (* mod_cleanup) (void);

  /* The preparation for reconfiguration. Return 0 on success. */
  int (* mod_reconf) (void);

  /* Section header in config file                             */
  char * conf_section; 

  /* A table of key/handler_function for config file entries   */
  sh_rconf * conf_table; 

} sh_mtype;

This is the structure used to hook modules into samhain. There is a list of these structures (modList), defined in sh_modules.c, containing pointers to the functions to be used for each module compiled into samhain. For example,


sh_mtype modList[] = {
#ifdef SH_USE_UTMP
  {
    N_("UTMP"),
    0,
    sh_utmp_init,
    sh_utmp_timer,
    sh_utmp_check,
    sh_utmp_end,
    sh_utmp_null,

    N_("[Utmp]"),
    sh_utmp_table,
  },
#endif

is the beginning of that table. The author of the sh_utmp module has initialised the structure with the name of the module (note that N_() is just a macro used to delimit strings here), a 0 to signify that the module has not yet been initialised, and then pointers to _init(), _timer(), _check(), _cleanup() and _reconf() functions for the module. Finally, the last two structure elements are for configuration file parsing: the first is the section heading in the configuration file for this module, and the second is a table of type


typedef struct rconf
{
  char * the_opt;
  int (*func)(char * opt);
} sh_rconf;

(also defined in sh_modules.h). This structure is for storing options for this module to be found in the configuration file, as well as the functions that will be used to parse them when found. In the sh_utmp example above, we can see that this table has been set to sh_utmp_table - this is a reference to a list of the Utmp module's configuration options declared in sh_utmp.h. It should be clear now that one of the changes you will need to make to samhain's source files is to include your header file in sh_modules.c and add a modList entry like the above.

For a description of when during samhain's execution these various module hooks are called, see the overview above. It would likely be helpful to you now to read through the source for one of the modules provided with samhain and see the above actually implemented. You should also be able to use one of these modules as a template for your own.

The message catalogue

Most module authors will want to log messages in their own specified format; samhain stores all of its message formats in a "messages catalogue" found in sh_cat.h and sh_cat.c. For example, for the sh_suidchk module we find the following entries in sh_cat.h, as part of an enum:


#ifdef SH_USE_SUIDCHK
 MSG_SUID_POLICY,
 MSG_SUID_FOUND,
 MSG_SUID_STAT,
 MSG_SUID_SUMMARY,
#endif

Correspondingly in sh_cat.c we find


#ifdef SH_USE_SUIDCHK
  { MSG_SUID_POLICY, SH_ERR_SEVERE,  RUN,   N_("msg=\"POLICY SUIDCHK  %s\" path=\"%s\"") },
  { MSG_SUID_FOUND,  SH_ERR_INFO,    RUN,   N_("msg=\"Found suid/sgid file\" path=\"%s\"") },
  { MSG_SUID_STAT,   SH_ERR_ERR,     ERR,   N_("msg=\"stat: %s\" path=\"%s\"") },
  { MSG_SUID_SUMMARY,SH_ERR_INFO,    RUN,   N_("msg=\"Checked for SUID programs: %ld files, %ld seconds\"") },
#endif

as part of the table msg_cat[] of type cat_entry:


typedef struct foo_cat_entry {
  unsigned long id;
  unsigned long priority;
  unsigned long class;
  char *        format;
} cat_entry;

The first member of this structure is the message type's ID, as defined in the enum in sh_cat.h. The second is the default priority of such messages, defined as in the samhain documentation. The third is the class of the message, again defined as in the samhain documentation. Finally we have the message format itself, which is a printf() style format string.

This catalogue is used by the logging functions in samhain; you will need to add your own message types and formats to sh_cat.h and sh_cat.c. Note that because samhain can be compiled for XML style logging, you will actually need to make two entries in sh_cat.c for each message; see the file itself for details.

Note that there is a generic message format with the ID 'MSG_E_SUBGEN' and the default priority 'SH_ERR_ERR'. If you are using this message format, then you can log (a) a string, and (b) the name of the subroutine.

This completes our description of samhain's module interface.

Samhain's utility functions

Here we'll describe the main utility functions available to samhain module authors.

String wrapping macros

Constant strings should be wrapped in the _(string) macro. Initialisation strings that cannot be replaced with a function should be wrapped in a N_(string) macro, and the variable thus initialized should be wrapped in a _(var) macro whereever used. This is important for the 'stealth' functionality of samhain.

Logging messages

#include "sh_error.h"

void sh_error_handle(int severity, char * file, long line, long status,
                     unsigned long msg_id, ...)

This is samhain's logging/reporting function, so the name is a little misleading - errors are not the only thing we should handle with this. The first four arguments are simple enough: severity is the logging severity, defined in the enum ShErrLevel from sh_error.h; file and line are the current file and line - usually you'll be using FIL__ and __LINE__ for these; status is not very important - for module authors it'll do to always pass 0 to this. The final named argument is msg_id, which should be one of the message IDs defined in sh_cat.h; these correspond to message format strings in printf() format, which will be interpolated with the following arguments to form the log message.

The '__LINE__' macro is provided by the C preprocessor. The FIL__ macro should be #defined to '_("sourcefile_name")' (see 'String wrapping macros' above).

Example of use:

#undef
#define FIL__ _("sh_mounts.c")

sh_error_handle(ShMountsSevMnt, FIL__, __LINE__, 0, MSG_MNT_MNTMISS,
                 cfgmnt->path);

See cat.c for the definition of MSG_MNT_MNTMISS:


{ MSG_MNT_MNTMISS, SH_ERR_WARN,    RUN,   N_("msg=\"Mount missing\" path=\"%s\"")},

So we print this out at severity ShMountsSevMnt, which in this case is a configured value read from the samhain configuration file (see sh_mounts.c). If we wanted to print it at the default severity (SH_ERR_WARN), we could pass -1 as the severity.

Checking files for modification

#include "sh_files.h"

int  sh_files_pushdir_?? (char * dirName);
int  sh_files_pushfile_?? (char * fileName);

These functions push directories and files onto the stack of those to check for the specified policy (see the samhain documentation for further information):
sh_files_pushdir_user0 pushes the directory at USER0
... _user1USER1
... _attrATTR
... _roREADONLY
... _logLOGFILE
... _glogGROWING LOGFILE
... _noigIGNORE NONE
... _alligIGNORE ALL
So if you're writing a module that adds particular files to check, like the sh_userfiles module for example, these are the functions to use.

Managing memory

#include "sh_mem.h"

#define SH_FREE(a)  ...
#define SH_ALLOC(a) ...

These are the macros to use when you're allocating/freeing memory in samhain. They do all the error checking/reporting you need, so when you get memory from SH_ALLOC you can just get to using it right away.

Parsing strings

#include "sh_utils.h"

char * sh_util_strdup    (const char * str);
char * sh_util_strsep    (char **str, const char *delim);
char * sh_util_strconcat (const char * arg1, ...);

int sh_util_flagval(char * c, int * fval);
int sh_util_isnum (char *str);

#include "slib.h"

int sl_strlcpy (char * dst, const char * src, size_t siz);
int sl_strlcat (char * dst, const char * src, size_t siz);
int sl_snprintf(char *str, size_t n, const char *format, ... );

These functions are the samhain internal functions for string handling. The first three act like their C library counterparts, except using samhain's memory management functions and error checking. sh_util_flagval converts the passed string into a truth value - the value is stored in fval as 1 or 0 - and returns 0 on success, -1 on failure. sh_util_isnum just checks if the passed string is all numeric.

The functions sl_strlcpy and sl_strlcat work similar to the C library strncpy/strncat functions, except that the destination string is always null terminated, and the third argument must be the full length of the destination buffer, not the remaining space. On success, the return value is 0.

The function sl_snprintf provides either the system snprintf, or a replacement, if the system has no or a buggy snprintf.

Tracing execution

#include "slib.h"

#define SL_ENTER(s) ...
#define SL_RETURN(retval, s) ...

These macros are for tracing execution through samhain functions. You should use SL_ENTER with the name of the function for each function entered, and SL_RETURN with the return value and the name of the function for each exit if you want to maintain compatibility with the rest of samhain.

Executing external programs (popen)

#include "sh_extern.h"


sh_tas_t task;
/* Prepare task */
sh_ext_tas_init(&task);
sh_ext_tas_command(&task, char * command);
sh_ext_tas_add_argv(&task, char * val);
sh_ext_tas_add_envv (&task, char * environment_variable, char * value);

int sh_ext_popen(&task);
int sh_ext_pclose(&task);

To prepare a task to run, use 'sh_ext_tas_init' to initialise the task structure. With 'sh_ext_tas_command' the command (absolute path) is set, with 'sh_ext_tas_add_argv' command line options are added. Environment variables can be set with 'sh_ext_tas_add_envv'.

To open for read, set "task.rw = 'r';", to open for write use "task.rw = 'w';".

To run the task with privileges dropped to another UID, set "task.privileged = 0;" and task.run_user_uid, task.run_user_gid to the desired UID/GID.

To verify the checksum of the called executable, set task.checksum[KEY_LEN+1] to the TIGER192 checksum of the executable.

After successful execution of sh_ext_popen (return status 0), task.pipe is the stream opened for read or write, and task.pipeFD its associated file descriptor.

Inserting arbitrary data into the baseline database


#include "sh_hash.c"

void sh_hash_push2db (char * key, unsigned long val1, 
		      unsigned long val2, unsigned long val3,
		      unsigned char * str, int size);

char * sh_hash_db2pop (char * key, unsigned long * val1, 
		       unsigned long * val2, unsigned long * val3,
		       int * size);

The baseline database has a fixed record format. To enter data, these need to be prepared in the required format. To retrieve the data, the 'filepath' is used as key (if your data is not a file, you would provide a dummy pathname as key). For convenience, the two functions noted below are provided.

When checking files, samhain will walk the database to find files that are in the database, but have been deleted from the disk. If you enter data, you need to mark it as such by using a key that starts with something else but '/', otherwise samhain will complain if it has not been checked during the file check.


#include "sh_hash.c"

void sh_hash_push2db (char * key, unsigned long val1, 
		      unsigned long val2, unsigned long val3,
		      unsigned char * str, int size);

char * sh_hash_db2pop (char * key, unsigned long * val1, 
		       unsigned long * val2, unsigned long * val3,
		       int * size);

To insert data, use 'sh_hash_push2db'. You can insert up to three long integers (val1, val2, val3) and/or a binary string of length size (max. (PATH_MAX-1)/2). As noted above, you need to supply a key (stored as the 'filepath', which should start with a character different from '/'). To retrieve data, you can use 'sh_hash_db2pop'. The return value is either NULL (if no string was stored under this key), or the stored string (length returned in 'size').

A string to store may consist of any characters, including NULLs, and need not be NULL terminated. The returned string is always NULL terminated (the terminating NULL is not included in 'size'), and should be freed with SH_FREE() if not required anymore.

If the key is not found in the database, size is set to -1.

Incorporating modules into the samhain build

This is a somewhat secondary but important part of writing a module for samhain: how to incorporate it into the samhain configuration and build process. This just involves hacking the autoconf and makefile setup to include your module. We'll present this file-by-file.

Makefile.in

You need to add a few bits to this file. First, add your header, source and object filenames to the HEADERS, SOURCES and OBJECTS variables. Then add your header to the dependencies for sh_modules.o and ./sh_modules.o. Finally add dependency lines for your module object file sh_whatever.o and ./sh_whatever.o, modelling them on the other module object dependency lines.

acconfig.h

The config.h.in will be generated from this file by 'autoheader'. You just need to add a line like

#undef SH_USE_MOUNTS
that will be defined by the ./configure code if the user specifies the module as enabled.

aclocal.m4

This file is used by 'autoconf' to help generate ./configure. You need to add your module's ./configure option to the SH_ENABLE_OPTS variable; for example, to add the option --enable-mounts-check, we added the string 'mounts-check' to this variable.

configure.ac

This is the other file used by 'autoconf' to generate ./configure. You need to add an AC_ARG_ENABLE call to this file, along the lines of those for other modules. For example, we added
AC_ARG_ENABLE(mounts-check,
        [  --enable-mounts-check        check mount options on filesystems [[no]
]],
        [
        if test "x${enable_mounts_check}" = xyes; then
                AC_DEFINE(SH_USE_MOUNTS)
        fi
        ]
)
for the sh_mounts module. This causes the #undef from acconfig.h above to be defined when ./configure is run with the --enable-mounts-check argument.

This is all that you need. Once you've done the above, you'll need to run 'autoheader' and 'autoconfig' to generate config.h.in and the ./configure script. Then your module will build as part of the samhain source.

Conclusion

Armed with the above information, any proficient C programmer should be able to adapt and extend samhain to do whatever it is they need. We hope that this document has been reasonably clear, easy to follow and useful; please feel free to update it for clarity, accuracy and completeness and resubmit it to the samhain project.

This document was written by the eircom.net Computer Incident Response Team. Updated with CSS by Rainer Wichmann.

samhain-4.1.4/docs/samhain_german.pdf0000644000175000017500000034331012615253277014473 00000000000000%PDF-1.3 % 4 0 obj << /Type /Info /Producer (null) >> endobj 5 0 obj << /Length 543 /Filter /FlateDecode >> stream xϓ09g~'ױt[gP{@ Y 6ֿATNk %|?|Mc(VQcs)"B}tt1@(1V_+GlwSn(' X8&i7}.Z7o~|h#0Qp&E(hxF1%DVp%QSqnm u.ͧ1u`4zXiUm"}b=:W5P¼wzWh5ɓbӘ v*u_-g[Փ'va@/IitXQ$?1CvBYYAi٢qso˚- zˏDCUk8’*جoC{NWӕs^\nˮ:J}t}KC(ZCv4ftFTUtW^y;&31`,mzt)xֵ̌׌!JV}",'9+,emT殺E]䠵JwrpGAb&LVc30ĆE endstream endobj 6 0 obj <> stream xk#G͑0a0a̞sv</(7]Lhveq vOY + (a{A?hT?OW-ϛCQ]O}멧.=uNNәsu#ύg$4%uRG!`|7jo|)]ymg+.]~aeS)sa6l\yʶ.l4ڽހJ ?lC5[B[/Y~_7v^})Ԓh\S!JQK[HExEx`(cFX<h&ҏ ^N1H2~`|fS|۳/h`dVnDIYda1cV4 tB0d^#$a[%cnXbAT ##,JAUVJut<0hWyAUd^#h64+~?_KiRGXֵl6ppqY1ƽ\ #EH )̗l3v_M;FYȓҖ s8's}·42nWo4*qR[E4Z$9) }R&aٜy9M{S3g,/_66nZǍWI"S\Qpȸ(heK }Rd3(\NOPN[eXݘ;}:.9 z; BwH2̹ܿSVl*SH"#|LPc}׿xPF$$}$,Y)t!i[[ehrZ=Pkˮ$ldHRۣ^]Z:O[LL޶7W_=5ӬlI#T;3C\\X.-˓{Qg4fXh%@i,nsA@2C|Re_‡đ L"`+2gn )Y^,((Dž ,C.PV+>hq$ڽ JA#$]SEhKXjZЌfQq:#>#/֯g Y UI$H""t NDX:/#Q4fAYET1w'v &L4^ޙLÏ޾KmzGÁob%eё R6'}#5idbQ,UԾ@c!'~GVt43 lWV4EυSe^dY485mBF'.b)gcc PP%9S~ˑpڧ#l4$[ ,4Oo+Um| nm@nuc]0gϞL8Pլ!N,? vR>Xu3m ӏ# ;]V"AG2*FH&FM0p,#Ѩ;:T6ko?t'2d ߢAL06~Pq ofљ"q qjfdCw;@:66 @ 7 !|h<TC@g)>R8ѱ1!;>4_Xbn5Ʀ$yԀ[H&[ L#49ϱ ~\Uّ}ez6)'ۙF\;ˣ"]fcBw :C [ݗ72k+N43 'z-49ffpj Ay Iė/bl.{s7^uBI@b4~#v˟K_ߡ<ɀI)Qla 2 c"J]\HWSuE^Y/"XG:±?-F<%!03d\8WY ƒf1%H\js_:7|vMj'.X\z&<4?vF*(wkr:] 3dOw,ηs9sFvE2!C䳈|oZrpZ@>HɁ|#m{Q,:%K~Š*i'9a A2o5Q{ø]\\’gn_|(wƾ;ϩGF?1㋥יbOBkGq| Ԛ"`>dn~ n t+BɎ@aѮ5FaM%ȣ9"W5;CHE2P)Jl6|9}RJ5]wȺo y.Wxrt 5-7tnI21f/%g/ARLBGŹ!2 Ƞ&Ci씕ȟs{yef˜N4j3j9ޜ9VIHZaCL[lN#4+;Pm͗0  f0L_*&L3bUͪ!3+љ,9E81;ɃF[qFzGfmk;Z?3TYzX/1Zr) `:N6D{lx'G^F[, ,{P=iOw͈k:AR^*NXz>bۑ*E?>Ob)R_X9 h6_#-vJe,"F0pZwfgkʲ cͻͪ/|~;%D#aFG APt^faс] %>a|G7,IsཱྀHa3KCxƧA˵^|Wba"2F s%Mr5V)BsWvM&# ?¨` `R獩XˁvcxI&kz=O%y#$.0&5AfI<:c4-2&uL`=U$aИX ؋0,12O~ Zސ T0g`01/u9l Ig$v}"RN`IA*Rd$s"`MA' }=21M75lx"aYb&D bE$Ǫ&ClfBgdʂ`.,q}4<+¾PhE@Ec1NCei֮aodϸ`?[q%SnH5(ũQ ƎϢLF )G˓Y vCy0S}Mvf争)eKY1>X(Ǹ JK VHPpB{KLfcULS@ Scm &zDM^'cE`ҀB|d7$(ޕ;؎e/nvШGp'En(9(l(\$6l<#ؓZZ:Oa_-.=S,=S|Fa GIp>:hft"gXPVʙ_l.sYky!& w"djT}.| rlX.oE\(jʓO_PZ'6"N΅FO̲܊ %{rɾC_P.>Ut5ۜ r|H}(!v}ERW ’psGd LbȮ\/ٛz7jTPI;JITqqLhة5Lw0bd1Μ" {0) N.-eQSH|EB[1?)l="/|@(IMEj&N㎊*S OwsZ +>Tэ瓖bÎxc*@2rA.@Ø"9#&9YU4\h\7U ۢ 򅕋,a1_oYz4 UFiAceRs;9v0v7v4N5}=f,כ3Iu >& MY & !HE A"id^w"""4$0@͡wwWĬ^'Ywa!O@' Cv]/Ms'Hz b]xáWžzDP.crJ5kξww߿'" a I_>;s]pa0IhǺ&u{/;ZɏA qz>>ԜjԝSwNݩ;uGޅl AlC"[O5g(ILrۥp\VÛҽ 3KqʦQ\%dH"r͏J)dC1px?HF$%:%dO樔l)x2jx@EJGDl9T8M 2q":6Ξ Z^PGy:KyWuR^]!r0M(y }7 !}3 e38t#M 19{I7'ѹNBӅW/i}njvnw3z> B%l;S}@ɸ `a; ȅVkggpB,%7OO~^ڽ0:jNg'~PlPs$$'Om]ކ0 / endstream endobj 8 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 5 0 R >> endobj 9 0 obj << /Length 1203 /Filter /FlateDecode >> stream xXr6}Wўhc=vZnVj:m)@(Hw)"y[0^.u;ܼ=7'WLO~?%7/Wzʾy>y dEO\{S6^Kj]1W =`gi#?t%}^KwuwW=]ymگ%~hqp7[\_p;F}A*S*Vչ,j?k¦V sYt }ahqƶAm >S~Y,D[j'i09p8aؘ3;aD(l+U@¥W<D*8nB2LfT2+ xPY-畃rLb+3< 8maH5S?-!w6] =ȄAo4O;䯕jUb_,  q qFਧIhnűLРl{hJG"J@h:o\t#Cu"@%K!%{#d~2k]fIֶ)};)By)VWnӷ YPn>cka·@v[Z!{9l=|2!ՇY\jGܡO[HWb`4??5ٌ1OC4Ɛ~Xȅ<9iv-$tŶiDW΋Qq Vn(AŠ}K-jqSմmiR/ǾcfVJ <ֱ;PJ<9:?X/ Y9TgYN1Mf-uFN{[ٹ>&-E'sJ[BvX~ci.TqB,JgP.֍5޵DI>&ҳ/_$z0e*X+؉vrT,U#57pDa~xqȷ]Mr%G ɭۦ֣] Y(VGj4DL'L?84^$(I)CImˆdO5Rx?L>~G1XdxOG7;; 9EȾȏKË:U(u4~|6 endstream endobj 10 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 9 0 R /Annots 11 0 R >> endobj 11 0 obj [ 12 0 R 14 0 R 16 0 R 18 0 R 20 0 R 22 0 R 24 0 R 26 0 R 28 0 R 30 0 R 32 0 R 34 0 R 36 0 R 38 0 R 40 0 R 42 0 R 44 0 R 46 0 R 48 0 R 50 0 R 52 0 R 54 0 R 56 0 R 58 0 R 60 0 R 62 0 R 64 0 R 66 0 R 68 0 R 70 0 R 72 0 R 74 0 R 76 0 R 78 0 R 80 0 R 82 0 R 84 0 R 86 0 R 88 0 R 90 0 R 92 0 R ] endobj 12 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 676.035 122.826 666.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 13 0 R /H /I >> endobj 14 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 660.225 343.916 650.225 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 15 0 R /H /I >> endobj 16 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 639.225 275.636 629.225 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 17 0 R /H /I >> endobj 18 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 623.415 142.866 613.415 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 19 0 R /H /I >> endobj 20 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 612.415 213.106 602.415 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 21 0 R /H /I >> endobj 22 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 601.415 154.526 591.415 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 23 0 R /H /I >> endobj 24 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 590.415 153.976 580.415 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 25 0 R /H /I >> endobj 26 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 569.415 195.586 559.415 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 27 0 R /H /I >> endobj 28 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 553.605 158.126 543.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 29 0 R /H /I >> endobj 30 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 542.605 233.956 532.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 31 0 R /H /I >> endobj 32 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 531.605 184.506 521.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 33 0 R /H /I >> endobj 34 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 520.605 216.996 510.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 35 0 R /H /I >> endobj 36 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 509.605 295.606 499.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 37 0 R /H /I >> endobj 38 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 498.605 237.556 488.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 40 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 487.605 253.956 477.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 41 0 R /H /I >> endobj 42 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 466.605 257.266 456.605 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 43 0 R /H /I >> endobj 44 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 450.795 227.016 440.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 45 0 R /H /I >> endobj 46 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 439.795 202.856 429.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 47 0 R /H /I >> endobj 48 0 obj << /Type /Annot /Subtype /Link /Rect [ 94.866 428.795 234.846 418.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 49 0 R /H /I >> endobj 50 0 obj << /Type /Annot /Subtype /Link /Rect [ 94.866 417.795 301.766 407.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 51 0 R /H /I >> endobj 52 0 obj << /Type /Annot /Subtype /Link /Rect [ 94.866 406.795 180.136 396.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 53 0 R /H /I >> endobj 54 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 395.795 244.516 385.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 55 0 R /H /I >> endobj 56 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 384.795 174.246 374.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 57 0 R /H /I >> endobj 58 0 obj << /Type /Annot /Subtype /Link /Rect [ 94.866 373.795 141.256 363.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 59 0 R /H /I >> endobj 60 0 obj << /Type /Annot /Subtype /Link /Rect [ 94.866 362.795 160.686 352.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 61 0 R /H /I >> endobj 62 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 341.795 380.296 331.795 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 63 0 R /H /I >> endobj 64 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 325.985 183.686 315.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 66 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 314.985 170.076 304.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 67 0 R /H /I >> endobj 68 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 303.985 160.636 293.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 69 0 R /H /I >> endobj 70 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 292.985 218.106 282.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 71 0 R /H /I >> endobj 72 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 281.985 311.146 271.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 73 0 R /H /I >> endobj 74 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 270.985 153.136 260.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 75 0 R /H /I >> endobj 76 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 259.985 218.116 249.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 77 0 R /H /I >> endobj 78 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 248.985 188.406 238.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 80 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 237.985 213.396 227.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 81 0 R /H /I >> endobj 82 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 216.985 233.906 206.985 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 83 0 R /H /I >> endobj 84 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 201.175 239.206 191.175 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 85 0 R /H /I >> endobj 86 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 190.175 197.846 180.175 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 87 0 R /H /I >> endobj 88 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 179.175 235.056 169.175 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 89 0 R /H /I >> endobj 90 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 168.175 327.536 158.175 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 91 0 R /H /I >> endobj 92 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 157.175 218.966 147.175 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 93 0 R /H /I >> endobj 94 0 obj << /Length 669 /Filter /FlateDecode >> stream xMS0:!$C $ز#S__:eNf2Fzʛ_HD*0<$@">D4CdqChG#**싰H]5!km2<|.mjS:qˍ8)7:*|OtU7:޸B 2ijAtyk!DWV6P=u;wen*[lP4 9uT緫|yy-Fm.iS=JwTד! #˧@jd:$s`UwGav$)jTWvt:Q:ܠhB :6޺0΍NSex4FX Jc7o 15G0 W>t}.qOiF+||J܁i7R(ya!%S I.  KM9{\g8> endobj 96 0 obj [ 97 0 R 99 0 R 101 0 R 103 0 R 105 0 R 107 0 R 109 0 R 111 0 R 113 0 R 115 0 R 117 0 R 119 0 R 121 0 R 123 0 R 125 0 R 127 0 R 129 0 R 131 0 R ] endobj 97 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 703.331 233.086 693.331 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 98 0 R /H /I >> endobj 99 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 687.521 292.556 677.521 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 100 0 R /H /I >> endobj 101 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 676.521 208.956 666.521 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 102 0 R /H /I >> endobj 103 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 665.521 203.386 655.521 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 104 0 R /H /I >> endobj 105 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 654.521 277.276 644.521 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 106 0 R /H /I >> endobj 107 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 643.521 230.056 633.521 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 108 0 R /H /I >> endobj 109 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 622.521 234.776 612.521 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 110 0 R /H /I >> endobj 111 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 606.711 191.466 596.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 112 0 R /H /I >> endobj 113 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 595.711 179.776 585.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 114 0 R /H /I >> endobj 115 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 584.711 241.186 574.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 116 0 R /H /I >> endobj 117 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 573.711 213.966 563.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 118 0 R /H /I >> endobj 119 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 562.711 279.506 552.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 121 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 551.711 198.946 541.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 122 0 R /H /I >> endobj 123 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 540.711 235.056 530.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 124 0 R /H /I >> endobj 125 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 529.711 261.716 519.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 126 0 R /H /I >> endobj 127 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 518.711 156.176 508.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 128 0 R /H /I >> endobj 129 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 507.711 165.356 497.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 130 0 R /H /I >> endobj 131 0 obj << /Type /Annot /Subtype /Link /Rect [ 82.866 496.711 131.206 486.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 132 0 R /H /I >> endobj 133 0 obj << /Length 2515 /Filter /FlateDecode >> stream xYYsF~ׯ]%øAVxcJP(v0wgn@`Szzf~=lowzzy௲֡S*|&ZU]^{x}R/ pYGtKJ.jK{|;)hY&>60QSi_ƨqFNŢ 1N~[ab{}=aE^c)SO{Dž\ixd㮜2?<nT[ Erʘ+bfJt 3JfԽ$;SO'#24 m:s.4I=J*=g=LCfg՝Oo6Ƈ^<\E~%c䭣U'Q®ي8 91A3y,QXtBJfMb%I(ؚ^^[_;s?YcIgl`5Ҹ@!@tw!P&*u xnp5^T*UNFOnIj"8cv7ؿ@ ד0A9QEڒgӨIஂhZ;OG1bUO'n*0XHo9rч/ /o7N7WpEpl1`Dk%8Q%51U ˚{[nTY5;B_3ұ$ X,mӊ4>KmTh&, )Ǟ*9ϺʐͦF]G@gվ.GvUٟ3DL%tcQP0n.hZĨ/p%ʾ5%jAUgա,P|)"Y@JM8ɒH:IKQ\<0P!Xq@U<.o>kBz(th+DxX9E$ v5,}-  _ Zиtݩ 8ʔXweu(6v|3}[S{8 `M v9JS_T$`yZo=Ww5&mGĚNLZJTWt`{'3uy6FԶТ(BB^y:՞i-sN_mBNb}e_l[:PKۈS8@f 5mO>REֵSm訠}*0P)D"cU#IZO6n^#a"%FU[y:}߈o׭`X=: _\̅LAjڟ'5>tswCWmؾ|{Ҁ@ڈB"OL5푘DnhD*Yv.i3vb c7clK> endobj 135 0 obj << /Length 2050 /Filter /FlateDecode >> stream xYms6_v:gyn:MXΥ׺ӁEH"UX?߂ "mvX!B1TkNe@Ix3h翕[ \XgQaF=vGm-|~z\j|Xk~r#Ϗuu*R؁\Ⱂj)&AA 䇥0MGPu2m󻙤*EUti0WkUk.ֱMkcd/_o5> b !Kd|ƏfG7=cTqK elq4k1~9k)KYq2nQd!sGXtFpJ;͆sWsCSBR$PZl6;|3ł熟\q5_%nl5[к ngԄ%7 BkJUPu&/lk 0-}w7Z#M.F BĠ)\`p4 =9 2KZ- =0h=WyÁNKذ<ƭh*117Ps,63/ԙB[=*5 endstream endobj 136 0 obj <> stream xc`&83iTD` endstream endobj 137 0 obj <> stream x{Gkg%ےzϟ?#_q+͕Rg7'_:t]w 63> endobj 139 0 obj [ 140 0 R 141 0 R 142 0 R 143 0 R 144 0 R 145 0 R ] endobj 140 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.456 660.035 417.416 650.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A << /URI (http://www.la-samhna.de/samhain/samhain-current.tar.gz) /S /URI >> /H /I >> endobj 141 0 obj << /Type /Annot /Subtype /Link /Rect [ 338.9 628.035 468.05 618.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 45 0 R /H /I >> endobj 142 0 obj << /Type /Annot /Subtype /Link /Rect [ 513.998 628.035 545.648 618.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 98 0 R /H /I >> endobj 143 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 617.035 182.516 607.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 98 0 R /H /I >> endobj 144 0 obj << /Type /Annot /Subtype /Link /Rect [ 518.186 606.035 554.296 596.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 100 0 R /H /I >> endobj 145 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 595.035 226.946 585.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 100 0 R /H /I >> endobj 146 0 obj << /Length 2474 /Filter /FlateDecode >> stream xYY6~ׯ`M^E\LNMbgrڢDE9ߞE4 3wU ?4-^[wx" (M,< 8!~G^^GiaQQgdnlB" V0yWz]~y]-BzY*W*RX!t熵ǧ/޻`6 ӿFEVÞƞvJ.z-Ӏzyܗ7P퇲i&`S?Ϳ;^} UDބ?s.:}RR4 Ei7tH!b55oh;$q"灒pEϽ'k ء5;L0 vgK$O,zw]=!UP bUh .#hͮlQL hkEKc'//ׇ͛c[E9v]7KrM[ e7T͚CΨdRV6 .OZ"[y '#.5CAv(۪(?DQjA.SjGy<o˜$XIX$8Bs;g? ů3}hO9x:" LM3.Ǟxo[)+\4Xa^a˚"ה C1AHf$ZgjEeq-W"/2~X.l-n#B}q)(A,t Z1L0R ;4V<;ʸwyr0!E ‚"' 6:ww HV d˱hGA'n6e# 3gH 0My < z{S(W2LW8C o̠F4ggGǤ6P=\ve>q]vGgV 4XX18\uR#*CQRCw 5JUDŤE3оl3Jk;f'<  =^᣿'ۖAZ0yBsٍ8C_ۡhh%q&ɗ ݵ!UR׺b{f@5[UibQw VV4j%[y`aQqX(vI04㳙7~O;5k[L 0.~,rO!h> ;\,F]ve3_S9鳺ݐ RiO. o5qՅ!H;H'COU0ic[UU)/7<'zfE퐟ɔӓF>:_O}ŭ5WY ;6pop9TlYJGl!pbj0[_bf1A A戕| ekݩM>A!u0@__bQPs ;*"Xa[Zvo!E.Kű)s{L ӪU=BX?y(Ux "y+.'8o|â$цckg+ى"?UK ao THxת,2oD{2d]׊+տ!N;:jN;c\-cb̕ZƾIU |@xk'3t' ᄤ*o`bO}y` C7$.@:|mcG?zx}~GHb?Т%6WTd*om)AsE6gx5ٚ7]2~=uP7Z#tC>5XgZeFFMԡaf̮=[5l￷PUx`?ZW&!0I C$3ʯMQk.]N85f.e{2f(M W_TP۲ieUqfB+9id L8U̖CK+lZ&KEVpAE*'7Y2{Qih6BʛaT$;1qg& GLq,B..C(;LPͅ Txo e r xS)(CzGXP䝸A:=IaHDt`lfB!$^r&LM\aCŹ[MTv_`n5a3?{/1}iD?zoC4_s;'aX17> endobj 148 0 obj [ 149 0 R 150 0 R 151 0 R ] endobj 149 0 obj << /Type /Annot /Subtype /Link /Rect [ 221.356 386.667 389.656 376.667 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 43 0 R /H /I >> endobj 150 0 obj << /Type /Annot /Subtype /Link /Rect [ 393.816 364.667 465.746 354.667 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 63 0 R /H /I >> endobj 151 0 obj << /Type /Annot /Subtype /Link /Rect [ 90.866 353.667 298.326 343.667 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 63 0 R /H /I >> endobj 152 0 obj << /Length 2469 /Filter /FlateDecode >> stream xYYs~ׯ`Uځ}TZˊƣ8[GC桉ߞA!gǻ0Dj4?| <\\};4"p:.S'v2($P8?]o:3V0^_nXٵ]q~v&DI˜Ğ'! r*-+iF NG6-7i) xgb8&뺞syƖlԼF2}im\BC/ 4q:s<I܈]UWMZR^#xK{5O5+8Vۂ$sg0r wc.vL*󌕭PN.\qX4\.7嗪4!r^uჰnY eJRY/׌Eҏot4ڐ!أ` v;' Kġm-J8hACUni-,_Jy+{nyuFOK4Vک`U j6*}wNTu)X7H4Tk(gm!<:eiwF)j[B+4mv +.^@f M n$X*42T ]M+u#)L6.ŚsP \B@]rF)nf~vQA6e5 K`05in48.tTh8D-\ Ŭ#6:} "y%rK Sfju0L.Дb$zkIJNa& FCZp 7)@`мiFk4 죩R 7481-] x=+K^>b~ `R}ԭ>sPYh`)4-ϺZͤGD>vѼ|.!skz'Y|q,;L@pe,O7a(;2vCTH| }[eWτom+V>^˙@x$Gs"-!}3 Q{W~C؃"I_ihisXu yfGTF@QgI5̥<⁷cnSuH! 5%aԷ"HZ3s]DDevhげ9[S%o JIO7 C&.zˁp܋~j}Qu+qo :gL뒺CL3USt^ʚuCT_{ޫ? ;0#.dU+<$:5KM.~:]}]LaSi Ä,ԅR$r66]3 :@/% tx/,`H] uη \I0Y endstream endobj 153 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 152 0 R /Annots 154 0 R >> endobj 154 0 obj [ 155 0 R 156 0 R 157 0 R 158 0 R ] endobj 155 0 obj << /Type /Annot /Subtype /Link /Rect [ 316.056 503.063 365.766 493.063 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 100 0 R /H /I >> endobj 156 0 obj << /Type /Annot /Subtype /Link /Rect [ 93.366 459.063 242.776 449.063 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 83 0 R /H /I >> endobj 157 0 obj << /Type /Annot /Subtype /Link /Rect [ 466.532 325.231 538.462 315.231 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 43 0 R /H /I >> endobj 158 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 314.231 164.736 304.231 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 43 0 R /H /I >> endobj 159 0 obj << /Length 2089 /Filter /FlateDecode >> stream xYKs6ϯ`^*D|f/Jn&[n*eрD|(|H)Ǡ!5c)%a.WW\'[ pB7"3{ܡujᤫ.j_D!CگbDZqiG1b:]$P;uhI08pu|zSWUu.3s/\LA=vg:po?%Ԅum =^˲urOzPV9'z-`Ľ \2H$TL3?IQQ2ш}+`DidգRZ4GQneVӒ؈2MԝZF '"6hZ#J`l& ?j7$X^:blE :ɐ=126BbM#v+n O7JXؕتF\Z@1 <</!MRaoN!E5"sWØ{3< wZsشIۦE{Tj4<|XDU911'.vJ.r)ca튤v.EW .(.8UsP,*d.GيbA΍hZY4>L&VA"ȟR g2ou},Ra$HoxPĘWwInb ֛7I4$7nh)#-]d!{N\9AH?\6Fy4{7U^E.Y<IƯS!uzd{[iQ41#2Be "bR [: DAICU4鲱NsTG[x9}z2 5/LG憮ED 8!qKurZ"K=^"^6I'!vηFJal 6ɗw3>|px9rl>NE(ί7o\@V#m:h9lgyR5|PS5I.bk +xeś۱Bq&>JULuxIJ( MߚԦ2czaZũChD1rPЗ5*nwSs`Zl}^CV(5|M0:-4*n<pw IG1/<H+>Εl< 6x:21^\?8&?pu˅)@8丣磈a<Vת|anգf﫺Hڛ3aҍGZ7@c$K^#]VL۾vH6/Ix[ꡯOre N=B7Gzy[4  g 2{7}ײAshE&y:\~i Ȓo7VWsBZO#,S_G'4AQ]߄G\Є;.DCS#Єz==xzz~S+=s3Y*+iYc A,%@yy{/C$'v 4Z=tZL >Lt("<B<>)<1O€v|h>KQF#'c1>M0> endobj 161 0 obj [ 162 0 R 163 0 R 164 0 R ] endobj 162 0 obj << /Type /Annot /Subtype /Link /Rect [ 169.136 601.471 318.546 591.471 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 83 0 R /H /I >> endobj 163 0 obj << /Type /Annot /Subtype /Link /Rect [ 252.186 323.807 408.276 313.807 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 41 0 R /H /I >> endobj 164 0 obj << /Type /Annot /Subtype /Link /Rect [ 252.186 157.975 408.276 147.975 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 41 0 R /H /I >> endobj 165 0 obj << /Length 1120 /Filter /FlateDecode >> stream xWKo6Wk/b$-XރlQ2IN%:חib4}f8/nV_x0ɪ\Z?J8c )H$&vAL8FTr}r.U7Ͱ=Yf ibFƘ#&Ȓ5!t#^lKYױԳ9y[]Ѭ >W\@PuB;C@zM8{Y0]ɍZj0_|6d?4N#><.z#g/ ?D3dRH\mmC'T=hT$45Q ɤ\|^ܬiha0E ɦۄOa8a5O!Q ^{ A(DfD M:w#Vx{( UV~Dǭ}ܫSX7'#ǣke.{1qJ>9o"bL|F)r)|SzP ?cJiy|lgdB<1LCpmvo6{y0b@p:?pN7|#32 8݄٦WbEkbΨyӾZZ*پR+ʽu1o8@a=Gi 2LQDwl;n5Xy&b^zեw#0Jv:7jl<,X ujlV@ր[#nb^0|KWv2ੱ! mSQ WoaUI^ce)= 4ȡjt@߇<^JyT{*?5RvM% v(ubS<9i+@ Wm4;"5Ά$9kL3Џw`%<#|-kcjif~4q#t0щlw[L1scc N5ΉSssr?b}4ŁOiO6cj?=)I endstream endobj 166 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 165 0 R /Annots 167 0 R >> endobj 167 0 obj [ 168 0 R 169 0 R ] endobj 168 0 obj << /Type /Annot /Subtype /Link /Rect [ 221.762 565.779 419.502 555.779 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 37 0 R /H /I >> endobj 169 0 obj << /Type /Annot /Subtype /Link /Rect [ 162.51 554.779 302.2 544.779 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 170 0 obj << /Length 2157 /Filter /FlateDecode >> stream xr6]_GgƢIg;}HjmINfe:IpA2v] H;u ^],7zrʵwȱ0ĵ7KZ{~=;thz5/Ssl\/P .(;{[ t5IٱHUWez@eZ4zqҲFgewvsd Hrw$_ݑ I("ӧ„77ݶ xSO/m4k+ۣh9jт )BOf98M |#^̥aUA2zNI#&¼"<7Cy5Uja<7?S_]^Ŷ#o >ّDd;!vҷ.ի2 莰4/3(!k۹@E #_FL*3I x3;N.Gf %ˏ`H %rzQ춧~Ų`3AE* di\ Z,I|rk?퇖Ed,RO|sbSʿ$;׷Nߤ43&2Q'틝ꆞPL:P̦j'}ʒ]0Xhc;> 5PR$N> [%nN<}=${-Y{HEڵϳMbHBH05!"!?)#x%UV(3m~y]ݴNx+uv4fY[i2efI4yvJďmwQ 4K]{nJh&$7h7 Aw_؎kyڃoOxdwww=M5+Do^.h^ѱj%Н2ېdKNN= Vu -^cЁ?- @XI):/=H6#Ѫnَ"ijw6 Ɂu Ԫ%l,R\4*Qs 0+@nq)rMڎ3mtKH GM\1kĠMUyD6mۋM[.x*?2B63+vF(#~'Po:'!׫ӯR,9=G0ƂL)cQlG@Zo<,^P%k1ٙ"九`E wkћіэSߌHd) G؉憶Ƀz؊Ď_ҽE~,ENхiuұ~X}(x!K+ |'!iǺ6 };hH@>.oYݯ^ 20 endstream endobj 171 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 170 0 R /Annots 172 0 R >> endobj 172 0 obj [ 173 0 R ] endobj 173 0 obj << /Type /Annot /Subtype /Link /Rect [ 358.266 515.063 430.756 505.063 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 83 0 R /H /I >> endobj 174 0 obj << /Length 1526 /Filter /FlateDecode >> stream xXKo8WCR fė(ȡA i[g$٦m"_#2i- s8~ǧM.&O|o= bq8FKo5crjvvEh*ȏޤkhT8=nUaχ#@/ػzǧXxU/yݯ?_w(r E3HeD󟉿 "!E "so64C@F^X`(A06dG\Gi;o_N?*X(M6dWk~f.`gc,Y"h8jϹJQ*]ew^ul BV8]A0P˸jP#}" M)~8Ξ qnXj֓mߟ|!#(b_'Ly> q)X˟ AGx<`Wtd( Nq7[ =B"HS|8jWj˕q. M]?_@ٮA;|Wskh/_3DN3puu&bu%n12LOnJ&k8cft\. OFlݱ`}{]U|RvDx^_+ϊeYi@\*Pp/4]SW ;e^"b3^|]idR[$el9-oǑjL>ͻBRGW3(z#wb>B@ߢaThN)" l{"Nxm`Z8CQ݄hWId*Fӱm!b?(r3 (=p>ӰUAT\]mƊe/Oף;L#JU"щ + \/6**lιKBB.(cesU{#ˆT Ss'sבnA_u!j3":.)ٛip>`Gм0h볗8 ð š:ryr̩M:,c >LxQNg[w|v TIbZuc`kb=DI8tPZ9ȟ˦e #&rWG0^d rqh$I^hc ڌ8e'fS_4A'Oa / endstream endobj 175 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 174 0 R >> endobj 176 0 obj << /Length 1471 /Filter /FlateDecode >> stream xXIs6Wpg&$ZNujɴVIPJR_ (Zo[?r6:"יFaDž?.<;y8.n?q>|@_!$JBq:?zko>|+biL-7X>T6Nԥf_E-i~I-1[ll߈#p]3QH QE2:=anr6rqqҵӜQ:rk6:zBaaf A>m&wFv&i"^SVI!(B"kݎX9Kd#dKjK"rB ֍@<3E2دc} Ψ~vi'e2) 0@^܁S.%t)Tȵ6Ue*t9Ωcl)m=ZQwDR94(:u@\:2qQh!X1(RYM_j'k"BEسSԲn>JiQٲ:-C"#}+kk簝HS|;{0.vNnL f72 9R< ]Ue ^fVſm=[Q M+1ߢBCnXԐ8w0%zg.#`z42``O*G^Ppk.BzDEq'essv.y%Hta,C>I]w3d} (!~ZP^]9R3wDw$/@CrZ-b| o@BWhKϓ?gS^c ŽZX &ra{a))*ojПJhKb=K!h`2isr=qPrX=:xS!,@A`p+sW[RUL/[]c:pNƧՏ'Xe0ju.0z IUp2%L;xϖ1k%$RFuZ? endstream endobj 177 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 176 0 R /Annots 178 0 R >> endobj 178 0 obj [ 179 0 R 180 0 R ] endobj 179 0 obj << /Type /Annot /Subtype /Link /Rect [ 432.426 692.331 496.576 682.331 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 180 0 obj << /Type /Annot /Subtype /Link /Rect [ 170.866 681.331 243.906 671.331 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 181 0 obj << /Length 1660 /Filter /FlateDecode >> stream xX[o6~ϯ@ÈRaKЦv]m@<6-sL$ߑ-YG0%st=={==u3I }G 8uLj'CdYvvݝ;JqQ~$ڈFt܈ϡ.lMWCq:̗1O\:r~eHlܹu?KH9N;ݍOo5TzAe<^JyxmJ#m2t= ?5_|q[7tv"sd.|r͌Kiv],jW&hT-*s$i6ţ2K[.^Z!vOT̻ZTǿo}Q=E}bZrx^x0_!`*3w1JGߙ+m^ i~RI]Ff[j 0=|Hzǁq=Hn9CXgz.zԣʖxiWTQX(Ø@(pBuA\۱ $4qPBN/Mǃr*Ы^4I'FI'q B0,ɝTlAØuncV:.3y,Δ٪6e%*jF2IZtHNw<=#? «r'>+]yߌ;%ef۽qQCma f 5'z7Ҏߦ:U ||'(tジt؊&fDc/v^ l:uq%I9Kޫ:-4`: +v-QԠ3Z.o]Fc ot>@u%Gj|AVshL2"כv3ZQuWȀfkF:o?4bAGR)1ojQ7oZ!Ah|[\%VkdдIL_h(gP{'/T/kzKKZ2(y: Oa6FԢF`c/$8G R{/Ũltۀ;Q6!-”(ŐufɵAxLYlv¨"<dC_Ő ?~$Cw = ~ϱcOMR4a@#X0]?l2X77KVPp$XCMX,|R:VO +eՋk#@%/Pib$/ 9EB[HGf-8 ^xc#7BC:u@7, jWx ϠC8q~;sPaHB(3^h7CO koI0S'Nʠe^-;mʜWf"EH҃uڑ-^H02"\ ưf'ٍTΤ3SԤ`|;f=t2oNV).\mm,߆ endstream endobj 182 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 181 0 R >> endobj 183 0 obj << /Length 2368 /Filter /FlateDecode >> stream xY[S~WW-BKN&N NChV;4H&_4-} U4.Nߤs;wovyіY$׬#}E "L<]G E+o3i&~,:BWёf~&v|O2%nrN[ѮPd{^KnxÞ Cшۢ)>m])@CikgѦQ_x&Ք%4Veύ,+ȲKw7 >(`0ŋ>P.CGgN}E lEтAٮ %[AYhV 6aH+pQQTj#Gu:;7 BK౻DJY>+;SK2Og%I`τv }m/*◂5eMвF*m^b⚵%{٠ˁQU̷:s7+F'r#]L= H1/ uM, D^͢}~HklC MْFfQuri%2?iQHԖamUjCx|,݃C}ڄLM!v-mi猊3ehDa [s0Ñ A,]=n,yޖc"ԇ0A] |([Rx)L`2$8NU aU0$lXV33ZX367&{չ㉣ׂ[VUVM y(^x8%G{/rfGn<`8*8.A!K;ׂle!זԡmXIg  ]5NXP9c Eוj2Pt/+ L1yޒܥFBQ D(V@EKUCB%,bXK .L46Bn,"Z]ꕬ5!m&06o7Dj[Bj1RHz:g1b)͈Mjv4ItxԄ>Т;lx4|Qu-75mA!jjVߙWc/J Ʀ,ܱǁ~-Xq" 5>,Sx{|8Ь|ILjgk9.-emYj寬:K,1;2o6Q01[Ax] oIV9,P2DvX:2XSh"އ>6)wҡ#m-X ,ܶϭj%[˕=fcYQXy/hf' / i BU_%|/wd߮8O<;x  KB~j Zs݇۷nE#P& (uZN$(\KU5Ob?ei 3@Q")^37Z Xpu9-G5%8i/a^:Xc'{*<$*6\J'B6K0xHs&ʡ̳3(; _vީke)STe|Gu0Zj,$AA&iYE6KS{_A*iRl(VNÕ⬞ Y{ϸSM"煢1 J fT !x%} A(o u9D 8͢М|r^N!Uh)!KCveU+7g}=2C19XhHzh" |A0, No,hLv<Q  h':Msӡ`\ޣAt,`hMiýFnv/)Kޅ{ڋ0+l@3vP|.~04Ә(4hrФ ?h؊]F>rO2k3s0`3&kpZ&9^{ێ :Z' UBipEuuw963'eA<4'M\'\-fySFtre#=o\LFHȎٹ }h揆 y2I擁z30@^ < d endstream endobj 184 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 183 0 R >> endobj 185 0 obj << /Length 1786 /Filter /FlateDecode >> stream xYKs6WpCēdgrH&6M`@\>4 $@ZLbavWyqy߳0"A(8` hQ2؞y{m^[k_D&'Z~i5' R\>hU Kݍ]lYNIp'?{ِɩiqkRۜ;Ak&("2/a|R$NQ`Xݯ-dX0!v$3 x _ݧM# ! )Wtq?OfN΄LNy(;|T}30$@r&kvtrW0{n[blJ.هBڧ0)zc}8w`G0ܹ5')[261JKkG#/P65e_`٫SY}nq'D sxwJojm*w3a /ZA%;eYm2m:IPB-7Z]R0̴);[)Ufin+܊F@U]]*ӥY6w.̠iMwV0 w:tUڙFrٻק 9l<ɠSTn{vS7/ 'Qe2"`} 3ݦ7-|;s2‘`3g@љyU@׽*5|jxZF&t$dz^\rwTh{iC1<[5t볭;ۥZt.4|2Zu%Xeo?*5O_A* O> endobj 187 0 obj << /Length 2698 /Filter /FlateDecode >> stream x[W<_sG-߻{(|>-m~n8 =>3͌FH]"׹bs\9(\/o˖/&i8*ihv $C1m[?7#5ܐ))wYo'j56+2KJ;ٖRW[n|?fY'qo1 C'#u]o(m[D 2W.FiIᜒFCNsb@yvCi/Q{[ oH mS,6q<m=mK UV5MH#fwΦlDVsEjpPXzN,65knpvSks~rk͚\{f$awXgҘi($XP5xu}r5-;DBIx u vţ΍4!Ʃ( m P~9hdl0i |a{=c=PZ|'\ԟs0 trN"idi}bkA-Zz(:úY,o[~+S8[Ԍ/S( ۬>'14џP[^hڂxh j&RjbEMFX$EdKCb~%v!R!6vxRcV8RgٓL)1+Ѐ cUCtn MWdU95Qw٢PU_},vaRz `2&;-NL7؝0(<8PZ̃)D ZbdVjE\R`ѵ[9`kI`2@WkAehc]n|G~d9YeV:]ݷSFk-M *VK7!z:?ſvP<࠮jYQ8^!溫R"x,WˇWA"7UHuW. 2~ P(3PJ9gut'<)/R2eKHP0SK$k* zJx#Qi5D(LXO,w&妩5ˈjUɮ"VN'U|Y'd7̍C%ң?˗/BOu Ų]}H\ׅ1@o jZ(yCN Q -ӄs; 5)ԯY^h F)lk~jNҸ{ VX/5{ ?K"c:覢0;}3V{f;_+~0jV+Yͅ~P$1?-h)S^xuiڷlڷu@(ϯmJȓ'wR# ZY":tyČ XlORL-j &z$ίOXmrɘ􋚹+$7oaX+NJl%]VۘcRˇnUd9/]M7keo ɘLq'PFQ@2IOfoi+EWRəzpAT4z"tʀS/n0x:pgC [)GwH[.w fW #rTU [JmlAhQ mW|K{X|-EC{Kt*//π|f$!@ |ę{ڠv5eԌ ! n,Z$W7]#c^=lDS_ߚR*,* q$}aip+Fl$ dlϣ(qEX Xn$cEcgXv@o4׸$Y~Q?5-gfVScD䔀ȗVO <땐\NFk" r@A< )F1*%~fnіLjdf#-~ۮZr)lp-yȋ C$^[ t|^%!)%`T%w?F B8O !u{~9GkZ]'NugEU)$(DZ^4XyW{:p$~"%/p }j !5LB7Ow7C,I<ڐpD.`p{)L6B$#©NjB3лaz)=4S> 4fY;K=.TiOhE5K2z(vSFp,|<47{{%`) bKf-{6a/q1{(FcBXGQC`eᜭ04p ۺ*Fq0 _7x䪥QcG؍g"]OJO` X]%N(s;<]bRz q'H&(Vj^4}^>(tB zQa ^=9WJўy@`cXY"| H9{ TZop/ endstream endobj 188 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 187 0 R >> endobj 189 0 obj << /Length 1142 /Filter /FlateDecode >> stream xWn6}W( 8%^aI-]]qPm蔒_ߡ.& о F7>b{|b/QĘ}I= (3 y5Qëd&RvXg k8 9_mحu^2d*zoMa2=[Y҇.T,skٸ,M~sߗKMQNt.p߭ōn9NuaP`2S]*ϥ\Mlix> zzz1"ӈO+1C7M&8?۰?,g'! b$+[Ev&I7zr-姵*Js2M48 eqc));>^;8Mr1nNMź'g QtliHH3a'uu$Ƶdkj㔘-`dTBG$f_-Umv-vRb!gtt0 Zk1uԈH`〠G |0)u:EDU"θ S^QA0p"Tҽ7>n> endobj 191 0 obj << /Length 2471 /Filter /FlateDecode >> stream xYYsF~ׯࣜмqJ:[RIz=xhyh6A_lIjڬhr#۱ng]+v$hk7nK蕵B&XgY^e4h9m4osϾW߭Ar!)A؞#%)u^Ҽh:kHY9}[s%?hiW͚A6RMUxƏD3#T##5*|tFSF1 =CsSaI?ԈhASo5qd/svLǗ;&4Gi5ۜ6O-%=4 a/{ZRH }4ty}uE xA,[@a)Wf .sy~v5hJsU≭Go K/FWC*a5} i AZ,@nҀ==T2nrlHcs&U4 Wnc؇'B5ր#y;,3Wq ږlL< sv0#sge55nh oY-Fu];v,x[Ə@X[_ޜ9rw}[C6O)rfjtY/bܑo6<.+a,z'39Q_La! ٰpV۔tcq4!b3%YXpgXtWV.\[ᩦ "̚NVmIur%vB"U$'fs73q2Kb%1r@OZt "Ib3cfC?@r擼\Nn":X#l@^u`uw9DT4[ĉ. rǐXN5L.51(57cCEA^mH:˷ x;k![UGZ#Z{C.A?,0:>=aR=7on Bώ=_Vn;-q97E[>A+?H8Q v</=g0%h` v$Qc%yM xu0]k{Co Yiͱ^r}x:K/v~/ZtUX7wo[~ pD RX`o5T-SY)vEDMYYk>Q1#Po =EO'IQ!h|w$UJdMP7γ^qFX(~}p { O=B|׷R탨J+ E`5d-!/\ %QPqKl5qdÌH8 MD, :>xqA[rT16."ml^j`<\Jv I!yA3w1&5<>Ph{:ׇ3/ITY=gA+9ޒ3dg!G.'NbKƖv GV>jMMC @N2R.Ϫ c{-rΖ>"H4"C O3Rb8Z'6dlVqF qƖ6NM'2 N۳%×.`;/dE+^,>rTŅeqhB"~0$kjN4t[*]Htmp {z1xge(HJv1AURj]h!a\ż$7A0즿Hp)y3z92N0sE6˱xd嗄cID$ xXag+{^Kh^Mk,6WFtU E@6v!yBPy,h ?Ăt~g(! qD^B nOm1@! 6`E QL"sX%ϴ;r{} RB c]% endstream endobj 192 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 191 0 R /Annots 193 0 R >> endobj 193 0 obj [ 194 0 R ] endobj 194 0 obj << /Type /Annot /Subtype /Link /Rect [ 122.756 330.063 243.856 320.063 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 93 0 R /H /I >> endobj 195 0 obj << /Length 2624 /Filter /FlateDecode >> stream xYmo8_!P=$"JZ-u&;5B)[$oHQ"HޠÙ<7'۱nڝ ˁ/|lYlAMn}zWqJ-PؕO M\&7WgTXM~ut誗=mf&cq;ũֳ.)MoS^ʰ`YygWpM]YmM_>6u2S9pz En`ʡhLmx|n8MyS$`qSMƇĘm ܝ]ꋹz]cLTż`2bo dz;}v6MY$,I/G lo,%͐s.,ܞA& BkSûI,S^bd1_k"Llf;-<6ښ-2_Mim\k-dXfKi8zn ;//O q!0WvC0W;7 2ZΙZIHfOD;}a0L4*屢>:< 6:y^; DLAMz=@ a~yhN"NwE(*p&ƥM^CVPoE`c68'W:Fu=)[ B@!&񌢵ɒA <#bPkk5U*PًZ1iK VZL_QYA床TTuT Mǣu3" 5pvYNG( B3ޗy~(;3S_}zxfI,^%e6h$[ݜۑz ՐM'r ˓_N7 |YCj0+Th=')փu݊d/-p5*nZ0xugc7 \_vYqzaYv#[1 vO5츌2tKF 'cK7 0 KTÒۗW!&8/) 8s]zc< &T Z,R>4q[H?hql+vd }cڷFs% czVSI@S7<>8GVѿydhJj>>-5-uKl%td<$eY\z *(&lVݲۏ3ARA@zP>%|(ԅxB0VbkShblJƺ؁RX')e1%UzxZjx÷ Dyp 7$G?́loe,&3˃?|i?+0;'̓9T,rWy{%fNQmdGQmF*׮HJk(B;vd.YRCX|eWQORJX`{ hdQE;pR8լ8oO¢#0:ԧHy::ŵMuU{q?<5FW)ޢN}H댻}j(Ycoӫwx{2XVEtZщnF˪4R\Ɏ3QmM?mG 6-g Zn =|;ռu%p 1~m%c +[z>G?}Y7qm.-!^{ Hau'7cݦlCwfs.Ih $x)Aef(NJJ$hmxPaGF~ZAɃ>)l&];u[/gYmh.lk"E1#&|һp쵅X7ɛz*Il}qI#6cB&fWhaLc䆐o3lQJn#7'|/y<ͺ'5AV@ Z67eBKG ȇ_&!c?߶CT¥"VEkY( &s \G2tfc A-DĿ`KFAtBQ0r# % ` ArB_y D.nkB.YH@D^[,9%]`z`B)4Z_%`'bbi{m^,ZEb"\EdCİb%` #E,F<}VN_j܋!H!o"㫋`Hːoyn``OD<˅<ԽIW7 ڛOaWzJ<uLVHݧؘqFurmFĻR<ΒD :'BJ endstream endobj 196 0 obj <> stream xKθueM73<_y]Mm㒒&O[Y{܂[z>ji_˞lz;-Mw Out:Wxeo,X'76qr>TD޾]~fedu@YzAw}of`8p\ 6o|D=˛Y3o:;_56~-_Bd [SuuuYO>sfJ @2O&M9ŋEK>]kLᔋn endstream endobj 197 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 195 0 R /Annots 198 0 R >> endobj 198 0 obj [ 199 0 R ] endobj 199 0 obj << /Type /Annot /Subtype /Link /Rect [ 297.436 549.359 426.036 539.359 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A << /URI (http://srp.stanford.edu/) /S /URI >> /H /I >> endobj 200 0 obj << /Length 1976 /Filter /FlateDecode >> stream xX[w6~ׯ# I&M+{v<D"CZuN4`.fvq*|vb=q/YYs>^һJ,b}y}n;en'?gOn>FK$PV"+r{Q-R#YHDNe8N-;'bTzv- Y@7NxwMoa=S/8Xa7f(!o%OԨS<%zbB RXQ*;\(ufBe]1L[VŗUJ'"ۢB4֗d~[F{u@e7/o.RCF 87 2imJx7ůu.IDz"^)P\Asv,3xLqQh{l`]2rI{Fs p@֘n?RJE=UU wPNtt:1#ێkGd:F=HfD˻V')ZF9e\G?i;Y@gH!Wyٮ/XpΤLP5AOqӛɺyԙJҒE T#7YP9 %jƸ D4-8X|HqhG >0X0Pk™7 4|ÈoJv#}J<"Ɓ>'[?~751jV^ly1B'/C#VBGJLuh}&+0J!Oů}Wgp$S%Fc#,mǶ}}}PA$;Wt sI Ӻ?Wa x%p}Awq0ŧF (J8+l,?hHXFV^?ӯu5zi2[?f7=6>.w? 0l9 Y endstream endobj 201 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 200 0 R /Annots 202 0 R >> endobj 202 0 obj [ 203 0 R ] endobj 203 0 obj << /Type /Annot /Subtype /Link /Rect [ 73.458 437.387 153.458 427.387 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 47 0 R /H /I >> endobj 204 0 obj << /Length 2800 /Filter /FlateDecode >> stream xrF]_)TE[J@rHa' 0=C@Dz 1GO݃24H`6vgİmEA`1b׹q0߆?ҴEE'ۆD$') ~6wv~h+vZ")U;`J\[l$ئJ, O$7=NX+H; ٖcßèvư0]ˎ|$ 6?^`ES u#m\7V>hOz#`ks)cPUIVXwj"$`MP`{\#KLu)iYr.Qޤl|Սy aFZ|cVSYح(zǮdQ6<5 v`6;̉{ORR؝vĜ8if-`'Dq*$C}{d|iڱ PZN:SP4?n}F ̝ٛ|W웟x;NӁm /~"FnfuF,ߛ^'G@HWNu M:eg5ͰCIRwէ*-vǃ'{xOŽmkĞvo_/f֮hٱ]V'Er#mb9ms 悴ÃEkǐyv01M8tY>,AdEvȪ,gű6v"vn4ZE]ożSmUyR<w=<vZѨ8zjc5昐-g\L@lv&m;SY7ksH2N|]zk!ahR&N)WXtȒG$0 Flѥ\"(KCBY"bqr?1.DD*2?Rk ,dR.w}wDlGe5[dJ="״ٛw/!IǎNS2 HdA%)%D.Z%Mծx Z+C'dA4UIq'r2D*F?у(O-RuD9UEͽ }9#d-dSsQ* =?ZA_p ˂?,eD9-\|xOb|ǹRy^oj\rW%0 " Zy.U~R|a5zz%+e!vx(zvEZ:P zH9]^nzL{(iYMNҎ^!(dBkk$RFg^gP=举kqcO֤;$$pj44`#Z 2E%$rQVZءS ` LMdi-~(x%&n 8>wsQF nqdcnjhЀN#=o$gںb&s'DIK?rp;P[OA_o *e~hμw` wfBt~Ql鴻Oqgv$A)ɒZ7p,?pX{A`JEُghG"kv=b8BEpn%8YZ=9̤&,OV&2Sps[ڃŸ)!#ST< 2K2 g#rt+1Ҿtå?Ak[/qŕ7wB998Gꑴo|XB JBr "h<&ICCKYFFEKHࠤI֠Z6 妭Y'*'e^x-zx[ H2%r]υt./]BuɊxaDE^:G>ȏ-2?_2}ctbq=8jͼ#a#"-mHV5,3$o W_M^AJ,|JvtT@Im-Q&:huK"kDrt(CvBKĨo쨒iTkpKPN2msl%^z0ˢ\g/OcP=^jھ|4)٧7U_yRlJ 0,b%'X ,ڼڵ /U5Pnvz5ǃ|ֶϓ]jWDDzj.C˨W"\n*l,ΌV]lpea-oQN#I+q4;J5nJT3OUi<ۺ4>; NntMY^*WMq$$eu!A2䁺!)摶>iq`E!މ!$oŸ"&?GWR3z M46 FцJYϤY%prZ^z#q;P=A'83==fշv<=]J $+I6YèUZk\=&S߀?**؞»C"#suu~6{;UN5c7/u}UKm(}>!0sǷ.#>ζXp,Dt endstream endobj 205 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 204 0 R >> endobj 206 0 obj << /Length 2348 /Filter /FlateDecode >> stream xYYs~ׯCDqIA)vծR0gI b=8=!U&2=i5칉z#ѶMX>_H~:pᰊ~;X#hշʜvrMKY Z!nhbN\?4nj:g`zM4f/^s*zra9Xܖ4aH;'VK}/H,) }&V:9eHe󜭴ºv4A29Ў4KiyӑNsfzv4qt5[вo֬U.8h\j F7KbzRFpҵi.H[!+h ۩f-{MC+ ^ěۮ]5tٗuS݄Q5%%a3 lW9C={GG ՈewnR9uS8HQ<ސ4;җn΄WX/}]/ x$UՋKu97ڦ)oUfU8p":D&zT/fq$aٳeZ_='ϴyA__[|w A`Cd0 dƛ[ <}~>O9}MC 󨷔}}KSH! (c7Ւl^`VT-ؼ"ȿ GG"閷%mYStFnVG-X-Nt،4#[XiKԎhr.z$EK'#F0M`c/M>a!i ,vSn1^ܺ؉] x)Dr`3m?Є0 cM4NCjo UGÑ}S l`7Kw; z Y L'p bOx0F]YIqM!?,EZN\!(˲tV!P"_g*^YJ.| 1xly |#!ǒ3pcHRO}SZdz̅Q;Ju0K|R1.Æ  ׅ7LA:R06-uw]L5(!mWĀY_Qa4OL%L`z5~>"/fgk >!P|?(3.(rH02(A8|gt̸PbRNv BޑZHb]T6 oaQxMJWy~}# ce"еv!>x\ѫM.!UކPS t;-={~$Ka Hʶ[+8գ?i?6$saZ Q0 8Z$+M#`xW8H 0Ժ&@q^5PICMdyuPYtA?P&HP0TM/@du}uuh:泋ѲhZ]07 Lgب .yS5c "MF[Adrszm-ǜ /TI ˞TARpf/S4MUă/ E\s@鍂75vfX#`(kIL )ɺ1z&Tdlv } -hh~ '3_7*]UHqqh_wb}]/W~ nKNdPFi$\)V'W*/p<3uѳYO U*?1 5JՅt)QM20n\ >yՍ7VJN+0^? Kd8cICɐwhmGF^! Vckr!s5 XʯR2<3'C7.I`'W! 8 lKbP2Ī7'9IW.b=?t|$ʜdǓY(pSϿbd8 (Y -偀u-Xyvg |<(^\Q׆LO;Ђ&M endstream endobj 207 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 206 0 R >> endobj 208 0 obj << /Length 2110 /Filter /FlateDecode >> stream xYms_9ߌ#^tM{%g'7ɈI)_ EtZK>]&!N{sHD'{zJT[b̚]S毝yz=4cdrFJā1Cuc ({U-jH R2kƪ}GNMʼErUV4fEe+WmcQL"%krU}"1M`FfRҋם,W@N/pd, 6 Jy[pj.;|@Йy֕ٞ@fA@92Y頢$2QVNhͷBV͖V9VNvsF]M0Hr_G0 & sbM/$󇵼WA aoMwsp6\_'CBFh}jY>VFt}r#r[﷎h']O'W^iݔނ s/Tٿg1 /ALS:H`||;yz|' 0Uk } "-Od(F`&ɓL'|ڏ!-31ENUe)„ai,-+[bk4akZ.)~ѡVs*Xӵ;](B?) 2^m4cQM!_~v@#'_asVl%H~+;ؚnvPr6S}JˢEi #e%_ QDBحVf:+W`>XGZB_7XS2ߟrOonn+(A[50 ؇^2Yc~k.բck9fYKnIT}x ׼kUod~2Bem[9tߤ;6;}jJE'Bdl/hYaIi_UA:{vx.Ճ̾-1Mo]ՀТU Np9ml$:㬐'x iӑB'bLP}h/Cב~hm=oJSϬL!ĤeV`w5U٬%蕋IGcͤv\ 1O~TA(Plt840 nt؎֣̌ $L537bV pB9f}`)ǜt)>^S(A ڄb5O)٭=3[S4[XbfQkX"{?d-BJ"^DafJз~c^Va)^ } :vY9+Vcq9kyH^0͛T3grB5tlcIbu!Ѥ{U4S51I0G%cx PtȾT 4HOИֵetׯjm߷釯OaO}BOƢ DjWvڧ][ 02"i2sޭ?1fěi"H6wFgkj'`;MĎ endstream endobj 209 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 208 0 R /Annots 210 0 R >> endobj 210 0 obj [ 211 0 R 212 0 R ] endobj 211 0 obj << /Type /Annot /Subtype /Link /Rect [ 430.144 564.035 532.904 554.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 100 0 R /H /I >> endobj 212 0 obj << /Type /Annot /Subtype /Link /Rect [ 70.866 553.035 160.296 543.035 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 100 0 R /H /I >> endobj 213 0 obj << /Length 1455 /Filter /FlateDecode >> stream xXKs6 8_zC33ɤI=ԛhWcr)Ai% A~{r/=`tlE  0 }y8ׅssA$yEI"E%,PIr-TT BfFsauqw"@1Oq h0b8b/s^X^aD1IGgNo |pl̗2펶z|soa^37B?^eGlZHR-pnDE D3Z`1֬kHVK@"4^HU5<,uu/!N4Q(IlQfxuMUZh."&&☏w٫䥨8@l{u4.`3s{]Hű1{/&WdI>°7B {{Awk9,eUZ^( Ϡ ?(s2(1$>lu?PD‰Xf?lcV ĿuIE(Z"K@3g ̄"3Nz0nBnE<"=Ѳ΃RHW ;޺U\b6v~.h;giWb56/<ەEQE(t/9-{]I1DHś"N>Ƿ2ٗfxu7򨼴A=!^-yҏ@z3T<JuPwS0&9EY' JHZrNReUKJGٴm|k7/3UgZPMĞ,}ٛ>6!bu>hvBUUS /հBfpV}3W" 9taQ{)CiflLmJM(ceΔ'Wh{c_Y8BXf3Zc$R'M YMЯ!s>*XmwƉsM$g|` bsh{PjQItcDS,>=g"2+HTiy(S9;G[q6X+kYZ Jvװ3NZj wa&1&@3V;)6JazDHX? L7PdM aja]#BW[D|FM;k98M讴N#Lw.3Uj ,~-g ^EQEPnק QlTgZi]n0C,Ů1} uWr.2By md9rI@ۀ̽dK9)XBAB'cBxh?Su> endobj 215 0 obj [ 216 0 R 217 0 R ] endobj 216 0 obj << /Type /Annot /Subtype /Link /Rect [ 297.53 708.331 323.09 698.331 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 65 0 R /H /I >> endobj 217 0 obj << /Type /Annot /Subtype /Link /Rect [ 206.916 654.331 269.686 644.331 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 69 0 R /H /I >> endobj 218 0 obj << /Length 1908 /Filter /FlateDecode >> stream xXmo8_!>4Fe68^EDd*+u_CF. \ p™C}<=}:IDN$P:wV'9y]ơ\g `"qkhYǍqe‡:,FNuq>^p:Z<(SD9N;}Í3e9=xg<1paI`hkOE[SZ`&NIJc6.1Ԇ jοJom$\˜Hk`sz+O?j.׊wTq%;]-ȯ:J&[ʼ#})fl>ȏ{uWעlzGQ-rT/R(Ցޕr%m*8rV*C﫚KX'])!%i'b s#ȿ B:;Qeg!R#-ri; y~6~ٽUf$0IO(Ht5Y`mrө.%L, ^yrsrq񝫲ixwii7UFv׏77/B(RVj[W0%ZG|Ҿw0Y84ċZOSZ:-hL |(N>ywW+<(}Oi$RCJfvfP8|׸c3eicyBs'3W%GNm_tom4 h{C4ԁVx{ֺpvSbSu> OBTf9 ]ԪOH }Z17h H2%uQiMaĒ8b(X{b viI2ACh98K"UFbmQ ȝˢrIaa8s]/#\^IeҚ[whLy`A2sbã,Dbr;yKs} 5նhO̚ (?^>bkP(\//yY=Qo:g"'=w7fb~|.4A\ 9O8W} ~ @?n‚c۾ؽL p~S#G1TME (G<8+Lf E}yd ?\Ԫ?{fWL@@>WpR6n,6isM9BH^qQoߜ_nWX8\oAz.xWvjr\\)ƃN$(>Ʈ>4+Eݿ`ss3g{#~#0rL?'{Ja^{wμ4<}[@~A@Bjbu'KK?< endstream endobj 219 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 218 0 R /Annots 220 0 R >> endobj 220 0 obj [ 221 0 R 222 0 R 223 0 R 224 0 R ] endobj 221 0 obj << /Type /Annot /Subtype /Link /Rect [ 325.942 452.823 407.602 442.823 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 49 0 R /H /I >> endobj 222 0 obj << /Type /Annot /Subtype /Link /Rect [ 502.278 452.823 565.048 442.823 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 53 0 R /H /I >> endobj 223 0 obj << /Type /Annot /Subtype /Link /Rect [ 432.426 243.823 496.576 233.823 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 224 0 obj << /Type /Annot /Subtype /Link /Rect [ 170.866 232.823 243.906 222.823 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 225 0 obj << /Length 1705 /Filter /FlateDecode >> stream xYYoF~ׯ`(@P8]MRP(iEmLQ._p%+R;pv[lt>;p"8ZdP6%2-#aj譪m msvI nBv\@4[ #dXqM]Ӳ1WG-&iY4c2}/D/<,] m RKoxee]s<*WM9]bzM=KxtlxFGo_%Y#JMJ٠M8"i~_G3ՎEAvz9rYOgge}~y/(Gʠӧ4ڳ$Ʌk =LcUn=sl kB%ba# |l`Ku*h0H)5P$B)<^6Xf`ÓFŸբ΂4gy(e'Z-(etS)mZK9PaĸpJ\(hEOGوED m N0߰8jh0t۰N [PSs<1uZf;Y[f=Mih5@U\¸x΀K!_5DPXBM*,V-yi:lR|O$~Vp؉ vב~)r][bkyв/A7t$Pu\K̍(]ǡyl# 88<-%ijac5|6XW+hK+.Z.wM~iEP6ҶRV- 3ٶ2 !=; ؙlA]BI7PmG9;%J'_q;\ Lʯ^ "(΢g{%b3`l+ƻ7) ѥ? L(YNEo0^ +..R1m]u{@b^J4!A:_#AG<PD mr endstream endobj 226 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 225 0 R >> endobj 227 0 obj << /Length 1701 /Filter /FlateDecode >> stream xXYoF~ׯ >8vEHCl#D"UYrI./ERAܳ͌-&K&2zb 6LbȱmvmdX쌛Ec8{cL%9OΚǷD `HV"i{5iỊ,fqg,~cXdˏa"*?_#dDAm-Y)xIjxi&vhkG훎JgcQ7"͙^Ax/O9BdZ٦ AcUNsI_h*,28HM5;Bh \ӡ0M-4j[$"tԂE[HfsD7luLd,v[/_w4CؤJ1}|`҄܍spTJX$WTægrvg9axS޹T&Pv Y#|6Rwe"y3b0Zbŵ,WU {.|xb\wZ =k'ĦFku$ n-C1.SLµ#Mp@;dz珐:A:ǺDSqY繿Guu>:{$ae`]G:d#T5KzTz Uuɓ@$Yh"VIE;mvVU8L ^mny*݁x0jlۈPA։J͟{镞4V޳S[_"`xo ܠP@c#h~,/zDLtYwiUS( R6O+!.Bkx'P<̇io)gZKv`=HW@'*;G@.ێ^cxy 6Rʖ"'ugw,:4i<>b_ +lRDN31cT^Rynu8ʼe%At{9œaf{/'׮h~-~6yy A#=d€8s\p96E/VMٰ+vST"ZLA5G۟TCx3уs!6EQQ(1I ]4*&Nzڈj4K]R+Y )f7H{}7ԇ(S42A[GvDv@}s me"=n!Br<]S#J#a{{A39a,=+Ck8ƦKM7nGѹ]T}tʜ_x Xu ?g?|@Iתgv/pDO$ FK/vSmj0#H9 .W[VϵRWmEBmVޡ> endobj 229 0 obj << /Length 2236 /Filter /FlateDecode >> stream xYKs8WTE4 S'8g٭8H$F$4Hl@TMr__7Kϰ-2fX؆m# ?MϲYf|=cNjOyY1&NkΊɔf VCbmY9|H+o&wx`Ei];[ oU~ֲDɟߌٿ{^TuƊ\ƫy\Dk%K \DGs1ۻӻ;fk7y:aimEc|%!`v͗X;ONeЇq00\2y~)ǒZA?XRw-K㪭t.ź©Aߵ)# .4iv;ȯ=@/ DV\rxދϦ8BLc1Xzr1Cv7.oȊ^w:#":X8븨X`%f2?a+C^Cw @0FslN ^lorv*mw& OdԄoag[}wf埩ɞRf.L#qFPbϙQ9kn0RAiXyaeI0n4TCYK:_nw0/0Bz3VhFRE0aP^ ]qLMKڢgC\YD ߎ  D~#:+j k9Å)0;/lJgSZ/vHwk >bSٌi0|IxRB]<5O3-6"Gȕzise ,߱$U`'(_fSj M2]C?6U=MZ :afSYᆬ@nq::JwUUMS~j%V ".0 5t_hiAsr!`JֶCj I^W^jcɦPN00M=9i=6e:H"{H/b hImR7m!V ,;ŶXou&&U# h--vusHA6P&ndA[JzN|\al\XU2g+;0f"X:ϷD3 #GnDڬ@q׿{l4+& ҳJ"GBv D۰kA[^O eѹ M%bxq)ŠmҞz,C;#o:i<&H`ti72}8as]# "pNp6O`gv(9๴g>.}% ks\q;]ҸK 5uUݽmgTJĜz5 RwiwE8ZaJ}o'AhĚBx޹!qEvrvcN57l. ~bLByop8AkEJڌ;imt~L_-߃N &Bb endstream endobj 230 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 229 0 R >> endobj 231 0 obj << /Length 2069 /Filter /FlateDecode >> stream xYioF_!(%W~#n}R UQň#Β8Kq%AvǛ73of#F#Hpt͵ٚ(^߰WhlRE3îa .B.`<O7ek5@'|Z7ڬiV&m2m?7|$g9DL}<3AGLǤ$c5 dհ`2' lƯ[F2NyaUn"l~\W%/E悒HdJxĘz_S@LyhMf-C]8t"L8R 4u0-#k; y̺}(̋ {"w%eBK' J40lyNwȋ7iػvQ8joޜʭyxjwSƝF GD(1lۺAbs0K&DzQ";A0Ɏxwr?*\V֜5vAkyJ=5qH3媩7n,fp85$9xYDwYJ[" y gR;G @q}r'L~!͠\msgx۠6=aV hU.1 9.Sk&-g?7?D5~$Υѕ4zڎ[Zd+HqM\i( 4¢\^(W*n{)y26}dH߆>$FQ>[vI,CY or.RɄ%[CqD90(3&3Ȁ]%d#%e%><E*8&rSU0ǏUWUX bFi `-+48R;ЍUø:n-2#:2|A*_) U̠y&.u[_1W ⁐AuzfCI p6{>.jbJqaO.@6\KoASK~֊fA*[0 #9I'Gg3CwRg8.3N b>s(=j}V|_"u"ͨ^[w)(ӞfJT n 蕝>{vZj-uƲTsHTos-&nk^tzxJB I3>JJ$/ !G4Bl3Xb][{&\DIL\`v~ ˗ib˴x3uI&`tk`jk1Z1{ĐY3D3tGZu6:H(wAJ 9ٛGǗ;M~;:$.C"lY!+џf : mg߲7(ofZkYmZ7U}]+I_\ endstream endobj 232 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595 842 ] /Resources 3 0 R /Contents 231 0 R >> endobj 233 0 obj << /Length 2150 /Filter /FlateDecode >> stream xYYs۶~ׯc<(;Ƀlٍ;&Q( P vɏ7P:3ap,>_&W ۑE#L}iD GLϴ]nHc9,-׍b-3=9wxfHVϟ|,$fgU K.嘞k@+}u<ݴ:j`&hmغgv6})K˳#tc /HUg*p-y7i4^%\ߍL\-&L?p\ pLvzx>woWqkz orx9>-9ْYAl|*𞖖mbLF8::R$@e0-퉰k"הvY <U)BY[ŷ빐F8+@Վ|Aqmsc*_QhR61~ )ulI9P? Ҡc;^ĄKziK\[_!/>aNj LT4#<.#CX lMnjޱxs kaw* z `zZ&S}ZPJU,RoCk˳ q?>dBIݑX#ʁ| Fbej7%InR3LJ9OP`ο/ OF; 4A_0gTbƟKd%0-~4\tmjUj| A$ҳ`z-Im$7D&9uVIBX+ިT \2E5aؖMnU6x'Xf0m%JypιX|2t:e)6ώ,)}m<6S-*-L8}z ^x CNP&IUȆʴ]Yg#}>•%@HPvF[Y"w.vb&5!dW =/L`%T"nX  2a3I~-?QHΡ9o]NаuԆT 9tɥ7pOYz31Q^2 qlYފ |Ґ ڵzM9yħ% riM8Ȟ=g9,8E Zux&ݗ'nXڮVip7!(u[.k2k^If}u ap1<98`,>y_*|a 乺Φ"m>B  Ly҈IYX5 -e޹3Q'ndε=>@%Fk}yګU'T4_`V&Ly"=#z`XnSU{񵜏hCU]grX%/GAgJ94X`6l?I1:@Zo"ďL/Dmg&b&D2ݠe";=YiD6>yr2p(9Ŋ?+g{jFۓ26}OQ熒`%,R#lĴ)` GǝyݶW__mb^Eix6Ar1{$bvAxo"_x> endobj 235 0 obj << /Length 1525 /Filter /FlateDecode >> stream xnF]_AÀ8uFj6J\IKwIʉяpy쐦m p~̮2i,6N,Äa& }#xe,RI.c y[,QScj{ɟe–~23-7[& g w3/hQ"iJ}p& Ĺt\W [sVҔ8Zȅ~yQȪWZ3g'$/z;=ĞLZv "utVGqR3b, f3q^G|wyy}Qd P$,8̊造'%r<49hkM ,8u*"#7rTnߣH)6˷LN>j,I5T'bԳ-O,#,ɶjJD@zEglW:fE#]~ChnV󃮙kql_320TV8P=czvO!ne=C.yx;#.o.f9ge.\q]Vp˪UdXߝ-FP7Uj;$vyڂw3nt~9r<<ն_oPwIASϿ}> endobj 239 0 obj << /Title (\376\377\0\123\0\141\0\155\0\150\0\141\0\151\0\156) /Parent 237 0 R /Next 241 0 R /A 238 0 R >> endobj 241 0 obj << /Title (\376\377\0\111\0\156\0\150\0\141\0\154\0\164\0\163\0\166\0\145\0\162\0\172\0\145\0\151\0\143\0\150\0\156\0\151\0\163) /Parent 237 0 R /Prev 239 0 R /Next 242 0 R /A 240 0 R >> endobj 242 0 obj << /Title (\376\377\0\61\0\40\0\105\0\151\0\156\0\154\0\145\0\151\0\164\0\165\0\156\0\147) /Parent 237 0 R /First 243 0 R /Last 243 0 R /Prev 241 0 R /Next 244 0 R /Count -1 /A 13 0 R >> endobj 243 0 obj << /Title (\376\377\0\61\0\56\0\61\0\40\0\125\0\156\0\164\0\145\0\162\0\163\0\143\0\150\0\151\0\145\0\144\0\40\0\172\0\165\0\40\0\141\0\156\0\144\0\145\0\162\0\145\0\156\0\40\0\105\0\151\0\156\0\142\0\162\0\165\0\143\0\150\0\163\0\145\0\162\0\153\0\145\0\156\0\156\0\165\0\156\0\147\0\163\0\163\0\171\0\163\0\164\0\145\0\155\0\145\0\156\0\40\0\50\0\111\0\104\0\123\0\51) /Parent 242 0 R /A 15 0 R >> endobj 244 0 obj << /Title (\376\377\0\62\0\40\0\111\0\156\0\163\0\164\0\141\0\154\0\154\0\141\0\164\0\151\0\157\0\156\0\54\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156\0\40\0\165\0\156\0\144\0\40\0\111\0\156\0\151\0\164\0\151\0\141\0\154\0\151\0\163\0\151\0\145\0\162\0\165\0\156\0\147) /Parent 237 0 R /First 245 0 R /Last 248 0 R /Prev 242 0 R /Next 249 0 R /Count -4 /A 17 0 R >> endobj 245 0 obj << /Title (\376\377\0\62\0\56\0\61\0\40\0\111\0\156\0\163\0\164\0\141\0\154\0\154\0\141\0\164\0\151\0\157\0\156) /Parent 244 0 R /Next 246 0 R /A 19 0 R >> endobj 246 0 obj << /Title (\376\377\0\62\0\56\0\62\0\40\0\126\0\145\0\162\0\164\0\162\0\141\0\165\0\145\0\156\0\163\0\167\0\374\0\162\0\144\0\151\0\147\0\145\0\40\0\102\0\145\0\156\0\165\0\164\0\172\0\145\0\162) /Parent 244 0 R /Prev 245 0 R /Next 247 0 R /A 21 0 R >> endobj 247 0 obj << /Title (\376\377\0\62\0\56\0\63\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156) /Parent 244 0 R /Prev 246 0 R /Next 248 0 R /A 23 0 R >> endobj 248 0 obj << /Title (\376\377\0\62\0\56\0\64\0\40\0\111\0\156\0\151\0\164\0\151\0\141\0\154\0\151\0\163\0\151\0\145\0\162\0\165\0\156\0\147) /Parent 244 0 R /Prev 247 0 R /A 25 0 R >> endobj 249 0 obj << /Title (\376\377\0\63\0\40\0\101\0\154\0\154\0\147\0\145\0\155\0\145\0\151\0\156\0\145\0\163\0\40\0\172\0\165\0\162\0\40\0\102\0\145\0\156\0\165\0\164\0\172\0\165\0\156\0\147) /Parent 237 0 R /First 250 0 R /Last 256 0 R /Prev 244 0 R /Next 257 0 R /Count -7 /A 27 0 R >> endobj 250 0 obj << /Title (\376\377\0\63\0\56\0\61\0\40\0\104\0\151\0\145\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153) /Parent 249 0 R /Next 251 0 R /A 29 0 R >> endobj 251 0 obj << /Title (\376\377\0\63\0\56\0\62\0\40\0\126\0\145\0\162\0\151\0\146\0\151\0\153\0\141\0\164\0\151\0\157\0\156\0\40\0\144\0\145\0\162\0\40\0\123\0\171\0\163\0\164\0\145\0\155\0\55\0\111\0\156\0\164\0\145\0\147\0\162\0\151\0\164\0\344\0\164) /Parent 249 0 R /Prev 250 0 R /Next 252 0 R /A 31 0 R >> endobj 252 0 obj << /Title (\376\377\0\63\0\56\0\63\0\40\0\120\0\146\0\154\0\145\0\147\0\145\0\40\0\144\0\145\0\162\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153) /Parent 249 0 R /Prev 251 0 R /Next 253 0 R /A 33 0 R >> endobj 253 0 obj << /Title (\376\377\0\63\0\56\0\64\0\40\0\111\0\156\0\150\0\141\0\154\0\164\0\40\0\144\0\145\0\162\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153\0\40\0\141\0\156\0\163\0\145\0\150\0\145\0\156) /Parent 249 0 R /Prev 252 0 R /Next 254 0 R /A 35 0 R >> endobj 254 0 obj << /Title (\376\377\0\63\0\56\0\65\0\40\0\126\0\145\0\162\0\151\0\146\0\151\0\153\0\141\0\164\0\151\0\157\0\156\0\40\0\144\0\145\0\162\0\40\0\105\0\155\0\141\0\151\0\154\0\55\0\116\0\141\0\143\0\150\0\162\0\151\0\143\0\150\0\164\0\145\0\156\0\40\0\166\0\157\0\156\0\40\0\123\0\141\0\155\0\150\0\141\0\151\0\156) /Parent 249 0 R /Prev 253 0 R /Next 255 0 R /A 37 0 R >> endobj 255 0 obj << /Title (\376\377\0\63\0\56\0\66\0\40\0\126\0\145\0\162\0\151\0\146\0\151\0\153\0\141\0\164\0\151\0\157\0\156\0\40\0\144\0\145\0\162\0\40\0\154\0\157\0\153\0\141\0\154\0\145\0\156\0\40\0\114\0\157\0\147\0\55\0\104\0\141\0\164\0\145\0\151) /Parent 249 0 R /Prev 254 0 R /Next 256 0 R /A 39 0 R >> endobj 256 0 obj << /Title (\376\377\0\63\0\56\0\67\0\40\0\126\0\145\0\162\0\151\0\146\0\151\0\153\0\141\0\164\0\151\0\157\0\156\0\40\0\144\0\145\0\163\0\40\0\123\0\141\0\155\0\150\0\141\0\151\0\156\0\55\0\120\0\162\0\157\0\147\0\162\0\141\0\155\0\155\0\145\0\163) /Parent 249 0 R /Prev 255 0 R /A 41 0 R >> endobj 257 0 obj << /Title (\376\377\0\64\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156\0\40\0\144\0\145\0\162\0\40\0\114\0\157\0\147\0\147\0\151\0\156\0\147\0\55\0\105\0\151\0\147\0\145\0\156\0\163\0\143\0\150\0\141\0\146\0\164\0\145\0\156) /Parent 237 0 R /First 258 0 R /Last 264 0 R /Prev 249 0 R /Next 267 0 R /Count -9 /A 43 0 R >> endobj 258 0 obj << /Title (\376\377\0\64\0\56\0\61\0\40\0\125\0\156\0\164\0\145\0\162\0\163\0\164\0\374\0\164\0\172\0\164\0\145\0\40\0\114\0\157\0\147\0\55\0\115\0\366\0\147\0\154\0\151\0\143\0\150\0\153\0\145\0\151\0\164\0\145\0\156) /Parent 257 0 R /Next 259 0 R /A 45 0 R >> endobj 259 0 obj << /Title (\376\377\0\64\0\56\0\62\0\40\0\106\0\151\0\154\0\164\0\145\0\162\0\156\0\40\0\166\0\157\0\156\0\40\0\114\0\157\0\147\0\55\0\102\0\145\0\162\0\151\0\143\0\150\0\164\0\145\0\156) /Parent 257 0 R /First 260 0 R /Last 262 0 R /Prev 258 0 R /Next 263 0 R /Count -3 /A 47 0 R >> endobj 260 0 obj << /Title (\376\377\0\64\0\56\0\62\0\56\0\61\0\40\0\114\0\145\0\166\0\145\0\154\0\163\0\40\0\50\0\104\0\162\0\151\0\156\0\147\0\154\0\151\0\143\0\150\0\153\0\145\0\151\0\164\0\163\0\163\0\164\0\165\0\146\0\145\0\156\0\51) /Parent 259 0 R /Next 261 0 R /A 49 0 R >> endobj 261 0 obj << /Title (\376\377\0\64\0\56\0\62\0\56\0\62\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\151\0\145\0\162\0\142\0\141\0\162\0\145\0\40\0\114\0\145\0\166\0\145\0\154\0\163\0\40\0\50\0\104\0\162\0\151\0\156\0\147\0\154\0\151\0\143\0\150\0\153\0\145\0\151\0\164\0\163\0\163\0\164\0\165\0\146\0\145\0\156\0\51) /Parent 259 0 R /Prev 260 0 R /Next 262 0 R /A 51 0 R >> endobj 262 0 obj << /Title (\376\377\0\64\0\56\0\62\0\56\0\63\0\40\0\105\0\162\0\145\0\151\0\147\0\156\0\151\0\163\0\153\0\154\0\141\0\163\0\163\0\145\0\156) /Parent 259 0 R /Prev 261 0 R /A 53 0 R >> endobj 263 0 obj << /Title (\376\377\0\64\0\56\0\63\0\40\0\101\0\165\0\163\0\163\0\143\0\150\0\141\0\154\0\164\0\145\0\156\0\40\0\166\0\157\0\156\0\40\0\114\0\157\0\147\0\55\0\115\0\366\0\147\0\154\0\151\0\143\0\150\0\153\0\145\0\151\0\164\0\145\0\156) /Parent 257 0 R /Prev 259 0 R /Next 264 0 R /A 55 0 R >> endobj 264 0 obj << /Title (\376\377\0\64\0\56\0\64\0\40\0\123\0\160\0\145\0\172\0\151\0\145\0\154\0\154\0\145\0\40\0\117\0\160\0\164\0\151\0\157\0\156\0\145\0\156) /Parent 257 0 R /First 265 0 R /Last 266 0 R /Prev 263 0 R /Count -2 /A 57 0 R >> endobj 265 0 obj << /Title (\376\377\0\64\0\56\0\64\0\56\0\61\0\40\0\105\0\155\0\141\0\151\0\154) /Parent 264 0 R /Next 266 0 R /A 59 0 R >> endobj 266 0 obj << /Title (\376\377\0\64\0\56\0\64\0\56\0\62\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153) /Parent 264 0 R /Prev 265 0 R /A 61 0 R >> endobj 267 0 obj << /Title (\376\377\0\65\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156\0\40\0\144\0\145\0\162\0\40\0\111\0\156\0\164\0\145\0\147\0\162\0\151\0\164\0\344\0\164\0\163\0\145\0\151\0\147\0\145\0\156\0\163\0\143\0\150\0\141\0\146\0\164\0\145\0\156\0\40\0\151\0\156\0\156\0\145\0\162\0\150\0\141\0\154\0\142\0\40\0\144\0\145\0\163\0\40\0\104\0\141\0\164\0\145\0\151\0\163\0\171\0\163\0\164\0\145\0\155\0\163) /Parent 237 0 R /First 268 0 R /Last 276 0 R /Prev 257 0 R /Next 277 0 R /Count -9 /A 63 0 R >> endobj 268 0 obj << /Title (\376\377\0\65\0\56\0\61\0\40\0\126\0\157\0\162\0\144\0\145\0\146\0\151\0\156\0\151\0\145\0\162\0\164\0\145\0\40\0\120\0\157\0\154\0\151\0\143\0\171\0\163) /Parent 267 0 R /Next 269 0 R /A 65 0 R >> endobj 269 0 obj << /Title (\376\377\0\65\0\56\0\62\0\40\0\127\0\141\0\150\0\154\0\40\0\145\0\151\0\156\0\145\0\162\0\40\0\120\0\157\0\154\0\151\0\143\0\171) /Parent 267 0 R /Prev 268 0 R /Next 270 0 R /A 67 0 R >> endobj 270 0 obj << /Title (\376\377\0\65\0\56\0\63\0\40\0\122\0\145\0\153\0\165\0\162\0\163\0\151\0\157\0\156\0\163\0\164\0\151\0\145\0\146\0\145) /Parent 267 0 R /Prev 269 0 R /Next 271 0 R /A 69 0 R >> endobj 271 0 obj << /Title (\376\377\0\65\0\56\0\64\0\40\0\125\0\156\0\164\0\145\0\162\0\166\0\145\0\162\0\172\0\145\0\151\0\143\0\150\0\156\0\151\0\163\0\163\0\145\0\40\0\151\0\147\0\156\0\157\0\162\0\151\0\145\0\162\0\145\0\156) /Parent 267 0 R /Prev 270 0 R /Next 272 0 R /A 71 0 R >> endobj 272 0 obj << /Title (\376\377\0\65\0\56\0\65\0\40\0\113\0\145\0\151\0\156\0\145\0\40\0\102\0\145\0\156\0\141\0\143\0\150\0\162\0\151\0\143\0\150\0\164\0\151\0\147\0\165\0\156\0\147\0\40\0\374\0\142\0\145\0\162\0\40\0\156\0\145\0\165\0\145\0\57\0\147\0\145\0\154\0\366\0\163\0\143\0\150\0\164\0\145\0\40\0\104\0\141\0\164\0\145\0\151\0\145\0\156) /Parent 267 0 R /Prev 271 0 R /Next 273 0 R /A 73 0 R >> endobj 273 0 obj << /Title (\376\377\0\65\0\56\0\66\0\40\0\110\0\141\0\162\0\144\0\154\0\151\0\156\0\153\0\40\0\124\0\145\0\163\0\164) /Parent 267 0 R /Prev 272 0 R /Next 274 0 R /A 75 0 R >> endobj 274 0 obj << /Title (\376\377\0\65\0\56\0\67\0\40\0\124\0\145\0\163\0\164\0\40\0\141\0\165\0\146\0\40\0\163\0\145\0\154\0\164\0\163\0\141\0\155\0\145\0\40\0\104\0\141\0\164\0\145\0\151\0\156\0\141\0\155\0\145\0\156) /Parent 267 0 R /Prev 273 0 R /Next 275 0 R /A 77 0 R >> endobj 275 0 obj << /Title (\376\377\0\65\0\56\0\70\0\40\0\304\0\156\0\144\0\145\0\162\0\165\0\156\0\147\0\40\0\145\0\151\0\156\0\145\0\162\0\40\0\120\0\157\0\154\0\151\0\143\0\171) /Parent 267 0 R /Prev 274 0 R /Next 276 0 R /A 79 0 R >> endobj 276 0 obj << /Title (\376\377\0\65\0\56\0\71\0\40\0\132\0\145\0\151\0\164\0\145\0\156\0\40\0\144\0\145\0\162\0\40\0\111\0\156\0\164\0\145\0\147\0\162\0\151\0\164\0\344\0\164\0\163\0\160\0\162\0\374\0\146\0\165\0\156\0\147) /Parent 267 0 R /Prev 275 0 R /A 81 0 R >> endobj 277 0 obj << /Title (\376\377\0\66\0\40\0\114\0\157\0\147\0\147\0\151\0\156\0\147\0\40\0\172\0\165\0\40\0\145\0\151\0\156\0\145\0\155\0\40\0\114\0\157\0\147\0\55\0\123\0\145\0\162\0\166\0\145\0\162\0\40\0\50\0\131\0\165\0\154\0\145\0\51) /Parent 237 0 R /First 278 0 R /Last 282 0 R /Prev 267 0 R /Next 283 0 R /Count -5 /A 83 0 R >> endobj 278 0 obj << /Title (\376\377\0\66\0\56\0\61\0\40\0\334\0\142\0\145\0\162\0\163\0\145\0\164\0\172\0\145\0\156\0\40\0\144\0\145\0\163\0\40\0\114\0\157\0\147\0\55\0\123\0\145\0\162\0\166\0\145\0\162\0\163\0\40\0\50\0\131\0\165\0\154\0\145\0\51) /Parent 277 0 R /Next 279 0 R /A 85 0 R >> endobj 279 0 obj << /Title (\376\377\0\66\0\56\0\62\0\40\0\334\0\142\0\145\0\162\0\163\0\145\0\164\0\172\0\145\0\156\0\40\0\166\0\157\0\156\0\40\0\123\0\141\0\155\0\150\0\141\0\151\0\156) /Parent 277 0 R /Prev 278 0 R /Next 280 0 R /A 87 0 R >> endobj 280 0 obj << /Title (\376\377\0\66\0\56\0\63\0\40\0\101\0\165\0\164\0\150\0\145\0\156\0\164\0\151\0\146\0\151\0\172\0\151\0\145\0\162\0\165\0\156\0\147\0\40\0\147\0\145\0\147\0\145\0\156\0\374\0\142\0\145\0\162\0\40\0\131\0\165\0\154\0\145) /Parent 277 0 R /Prev 279 0 R /Next 281 0 R /A 89 0 R >> endobj 281 0 obj << /Title (\376\377\0\66\0\56\0\64\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153\0\55\0\40\0\165\0\156\0\144\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156\0\163\0\144\0\141\0\164\0\145\0\151\0\40\0\141\0\165\0\146\0\40\0\144\0\145\0\155\0\40\0\114\0\157\0\147\0\55\0\123\0\145\0\162\0\166\0\145\0\162) /Parent 277 0 R /Prev 280 0 R /Next 282 0 R /A 91 0 R >> endobj 282 0 obj << /Title (\376\377\0\66\0\56\0\65\0\40\0\102\0\145\0\163\0\157\0\156\0\144\0\145\0\162\0\150\0\145\0\151\0\164\0\145\0\156\0\40\0\142\0\145\0\151\0\155\0\40\0\114\0\157\0\147\0\147\0\151\0\156\0\147) /Parent 277 0 R /Prev 281 0 R /A 93 0 R >> endobj 283 0 obj << /Title (\376\377\0\67\0\40\0\127\0\145\0\151\0\164\0\145\0\162\0\145\0\40\0\105\0\151\0\147\0\145\0\156\0\163\0\143\0\150\0\141\0\146\0\164\0\145\0\156\0\40\0\166\0\157\0\156\0\40\0\123\0\141\0\155\0\150\0\141\0\151\0\156) /Parent 237 0 R /First 284 0 R /Last 288 0 R /Prev 277 0 R /Next 289 0 R /Count -5 /A 98 0 R >> endobj 284 0 obj << /Title (\376\377\0\67\0\56\0\61\0\40\0\123\0\151\0\147\0\156\0\151\0\145\0\162\0\164\0\145\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153\0\55\0\40\0\165\0\156\0\144\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156\0\163\0\144\0\141\0\164\0\145\0\151\0\145\0\156) /Parent 283 0 R /Next 285 0 R /A 100 0 R >> endobj 285 0 obj << /Title (\376\377\0\67\0\56\0\62\0\40\0\123\0\164\0\145\0\141\0\154\0\164\0\150\0\40\0\50\0\166\0\145\0\162\0\163\0\164\0\145\0\143\0\153\0\164\0\145\0\162\0\40\0\115\0\157\0\144\0\165\0\163\0\51) /Parent 283 0 R /Prev 284 0 R /Next 286 0 R /A 102 0 R >> endobj 286 0 obj << /Title (\376\377\0\67\0\56\0\63\0\40\0\334\0\142\0\145\0\162\0\167\0\141\0\143\0\150\0\165\0\156\0\147\0\40\0\144\0\145\0\163\0\40\0\113\0\145\0\162\0\156\0\145\0\154\0\163) /Parent 283 0 R /Prev 285 0 R /Next 287 0 R /A 104 0 R >> endobj 287 0 obj << /Title (\376\377\0\67\0\56\0\64\0\40\0\334\0\142\0\145\0\162\0\167\0\141\0\143\0\150\0\165\0\156\0\147\0\40\0\166\0\157\0\156\0\40\0\114\0\157\0\147\0\151\0\156\0\57\0\114\0\157\0\147\0\157\0\165\0\164\0\55\0\126\0\157\0\162\0\147\0\344\0\156\0\147\0\145\0\156) /Parent 283 0 R /Prev 286 0 R /Next 288 0 R /A 106 0 R >> endobj 288 0 obj << /Title (\376\377\0\67\0\56\0\65\0\40\0\123\0\165\0\143\0\150\0\145\0\40\0\156\0\141\0\143\0\150\0\40\0\123\0\125\0\111\0\104\0\57\0\123\0\107\0\111\0\104\0\55\0\104\0\141\0\164\0\145\0\151\0\145\0\156) /Parent 283 0 R /Prev 287 0 R /A 108 0 R >> endobj 289 0 obj << /Title (\376\377\0\70\0\40\0\117\0\160\0\164\0\151\0\157\0\156\0\145\0\156\0\40\0\151\0\156\0\40\0\144\0\145\0\162\0\40\0\113\0\157\0\156\0\146\0\151\0\147\0\165\0\162\0\141\0\164\0\151\0\157\0\156\0\163\0\144\0\141\0\164\0\145\0\151) /Parent 237 0 R /First 290 0 R /Last 300 0 R /Prev 283 0 R /Count -11 /A 110 0 R >> endobj 290 0 obj << /Title (\376\377\0\70\0\56\0\61\0\40\0\102\0\145\0\144\0\151\0\156\0\147\0\164\0\145\0\40\0\101\0\156\0\167\0\145\0\151\0\163\0\165\0\156\0\147\0\145\0\156) /Parent 289 0 R /Next 291 0 R /A 112 0 R >> endobj 291 0 obj << /Title (\376\377\0\70\0\56\0\62\0\40\0\334\0\142\0\145\0\162\0\167\0\141\0\143\0\150\0\164\0\145\0\40\0\104\0\141\0\164\0\145\0\151\0\145\0\156) /Parent 289 0 R /Prev 290 0 R /Next 292 0 R /A 114 0 R >> endobj 292 0 obj << /Title (\376\377\0\70\0\56\0\63\0\40\0\104\0\162\0\151\0\156\0\147\0\154\0\151\0\143\0\150\0\153\0\145\0\151\0\164\0\163\0\163\0\164\0\165\0\146\0\145\0\40\0\166\0\157\0\156\0\40\0\105\0\162\0\145\0\151\0\147\0\156\0\151\0\163\0\163\0\145\0\156) /Parent 289 0 R /Prev 291 0 R /Next 293 0 R /A 116 0 R >> endobj 293 0 obj << /Title (\376\377\0\70\0\56\0\64\0\40\0\106\0\151\0\154\0\164\0\145\0\162\0\40\0\146\0\374\0\162\0\40\0\114\0\157\0\147\0\55\0\115\0\366\0\147\0\154\0\151\0\143\0\150\0\153\0\145\0\151\0\164\0\145\0\156) /Parent 289 0 R /Prev 292 0 R /Next 294 0 R /A 118 0 R >> endobj 294 0 obj << /Title (\376\377\0\70\0\56\0\65\0\40\0\334\0\142\0\145\0\162\0\167\0\141\0\143\0\150\0\165\0\156\0\147\0\40\0\166\0\157\0\156\0\40\0\114\0\157\0\147\0\151\0\156\0\57\0\114\0\157\0\147\0\157\0\165\0\164\0\55\0\105\0\162\0\145\0\151\0\147\0\156\0\151\0\163\0\163\0\145\0\156) /Parent 289 0 R /Prev 293 0 R /Next 295 0 R /A 120 0 R >> endobj 295 0 obj << /Title (\376\377\0\70\0\56\0\66\0\40\0\334\0\142\0\145\0\162\0\160\0\162\0\374\0\146\0\165\0\156\0\147\0\40\0\144\0\145\0\163\0\40\0\113\0\145\0\162\0\156\0\145\0\154\0\163) /Parent 289 0 R /Prev 294 0 R /Next 296 0 R /A 122 0 R >> endobj 296 0 obj << /Title (\376\377\0\70\0\56\0\67\0\40\0\123\0\165\0\143\0\150\0\145\0\156\0\40\0\156\0\141\0\143\0\150\0\40\0\123\0\125\0\111\0\104\0\57\0\123\0\107\0\111\0\104\0\55\0\104\0\141\0\164\0\145\0\151\0\145\0\156) /Parent 289 0 R /Prev 295 0 R /Next 297 0 R /A 124 0 R >> endobj 297 0 obj << /Title (\376\377\0\70\0\56\0\70\0\40\0\114\0\157\0\147\0\147\0\151\0\156\0\147\0\40\0\172\0\165\0\40\0\145\0\151\0\156\0\145\0\162\0\40\0\162\0\145\0\154\0\141\0\164\0\151\0\157\0\156\0\141\0\154\0\145\0\156\0\40\0\104\0\141\0\164\0\145\0\156\0\142\0\141\0\156\0\153) /Parent 289 0 R /Prev 296 0 R /Next 298 0 R /A 126 0 R >> endobj 298 0 obj << /Title (\376\377\0\70\0\56\0\71\0\40\0\126\0\145\0\162\0\163\0\143\0\150\0\151\0\145\0\144\0\145\0\156\0\145\0\163) /Parent 289 0 R /Prev 297 0 R /Next 299 0 R /A 128 0 R >> endobj 299 0 obj << /Title (\376\377\0\70\0\56\0\61\0\60\0\40\0\105\0\170\0\164\0\145\0\162\0\156\0\145\0\40\0\123\0\153\0\162\0\151\0\160\0\164\0\145) /Parent 289 0 R /Prev 298 0 R /Next 300 0 R /A 130 0 R >> endobj 300 0 obj << /Title (\376\377\0\70\0\56\0\61\0\61\0\40\0\103\0\154\0\151\0\145\0\156\0\164\0\163) /Parent 289 0 R /Prev 299 0 R /A 132 0 R >> endobj 301 0 obj << /Type /Font /Subtype /Type1 /Name /F3 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >> endobj 302 0 obj << /Type /Font /Subtype /Type1 /Name /F5 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >> endobj 303 0 obj << /Type /Font /Subtype /Type1 /Name /F6 /BaseFont /Times-Italic /Encoding /WinAnsiEncoding >> endobj 304 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 305 0 obj << /Type /Font /Subtype /Type1 /Name /F9 /BaseFont /Courier /Encoding /WinAnsiEncoding >> endobj 306 0 obj << /Type /Font /Subtype /Type1 /Name /F7 /BaseFont /Times-Bold /Encoding /WinAnsiEncoding >> endobj 1 0 obj << /Type /Pages /Count 31 /Kids [8 0 R 10 0 R 95 0 R 134 0 R 138 0 R 147 0 R 153 0 R 160 0 R 166 0 R 171 0 R 175 0 R 177 0 R 182 0 R 184 0 R 186 0 R 188 0 R 190 0 R 192 0 R 197 0 R 201 0 R 205 0 R 207 0 R 209 0 R 214 0 R 219 0 R 226 0 R 228 0 R 230 0 R 232 0 R 234 0 R 236 0 R ] >> endobj 2 0 obj << /Type /Catalog /Pages 1 0 R /Outlines 237 0 R /PageMode /UseOutlines >> endobj 3 0 obj << /Font << /F3 301 0 R /F5 302 0 R /F1 304 0 R /F6 303 0 R /F9 305 0 R /F7 306 0 R >> /ProcSet [ /PDF /ImageC /Text ] /XObject <> >> endobj 13 0 obj << /S /GoTo /D [134 0 R /XYZ 65.866 709.331 null] >> endobj 15 0 obj << /S /GoTo /D [134 0 R /XYZ 65.866 499.035 null] >> endobj 17 0 obj << /S /GoTo /D [138 0 R /XYZ 65.866 709.331 null] >> endobj 19 0 obj << /S /GoTo /D [138 0 R /XYZ 65.866 575.035 null] >> endobj 21 0 obj << /S /GoTo /D [147 0 R /XYZ 65.866 668.611 null] >> endobj 23 0 obj << /S /GoTo /D [147 0 R /XYZ 65.866 554.639 null] >> endobj 25 0 obj << /S /GoTo /D [147 0 R /XYZ 65.866 322.667 null] >> endobj 27 0 obj << /S /GoTo /D [153 0 R /XYZ 65.866 709.331 null] >> endobj 29 0 obj << /S /GoTo /D [153 0 R /XYZ 65.866 672.035 null] >> endobj 31 0 obj << /S /GoTo /D [153 0 R /XYZ 65.866 439.063 null] >> endobj 33 0 obj << /S /GoTo /D [153 0 R /XYZ 65.866 200.511 null] >> endobj 35 0 obj << /S /GoTo /D [160 0 R /XYZ 65.866 581.471 null] >> endobj 37 0 obj << /S /GoTo /D [160 0 R /XYZ 65.866 469.639 null] >> endobj 39 0 obj << /S /GoTo /D [160 0 R /XYZ 65.866 303.807 null] >> endobj 41 0 obj << /S /GoTo /D [166 0 R /XYZ 65.866 709.331 null] >> endobj 43 0 obj << /S /GoTo /D [171 0 R /XYZ 65.866 709.331 null] >> endobj 45 0 obj << /S /GoTo /D [171 0 R /XYZ 65.866 608.035 null] >> endobj 47 0 obj << /S /GoTo /D [171 0 R /XYZ 65.866 418.063 null] >> endobj 49 0 obj << /S /GoTo /D [171 0 R /XYZ 65.866 336.091 null] >> endobj 51 0 obj << /S /GoTo /D [175 0 R /XYZ 65.866 508.571 null] >> endobj 53 0 obj << /S /GoTo /D [175 0 R /XYZ 65.866 210.063 null] >> endobj 55 0 obj << /S /GoTo /D [177 0 R /XYZ 65.866 450.563 null] >> endobj 57 0 obj << /S /GoTo /D [177 0 R /XYZ 65.866 390.591 null] >> endobj 59 0 obj << /S /GoTo /D [177 0 R /XYZ 65.866 341.619 null] >> endobj 61 0 obj << /S /GoTo /D [182 0 R /XYZ 65.866 500.683 null] >> endobj 63 0 obj << /S /GoTo /D [184 0 R /XYZ 65.866 709.331 null] >> endobj 65 0 obj << /S /GoTo /D [184 0 R /XYZ 65.866 449.739 null] >> endobj 67 0 obj << /S /GoTo /D [184 0 R /XYZ 65.866 237.767 null] >> endobj 69 0 obj << /S /GoTo /D [186 0 R /XYZ 65.866 579.563 null] >> endobj 71 0 obj << /S /GoTo /D [186 0 R /XYZ 65.866 394.151 null] >> endobj 73 0 obj << /S /GoTo /D [186 0 R /XYZ 65.866 240.739 null] >> endobj 75 0 obj << /S /GoTo /D [186 0 R /XYZ 65.866 158.767 null] >> endobj 77 0 obj << /S /GoTo /D [188 0 R /XYZ 65.866 612.331 null] >> endobj 79 0 obj << /S /GoTo /D [188 0 R /XYZ 65.866 509.359 null] >> endobj 81 0 obj << /S /GoTo /D [188 0 R /XYZ 65.866 212.067 null] >> endobj 83 0 obj << /S /GoTo /D [192 0 R /XYZ 65.866 709.331 null] >> endobj 85 0 obj << /S /GoTo /D [192 0 R /XYZ 65.866 467.035 null] >> endobj 87 0 obj << /S /GoTo /D [192 0 R /XYZ 65.866 310.063 null] >> endobj 89 0 obj << /S /GoTo /D [197 0 R /XYZ 65.866 611.331 null] >> endobj 91 0 obj << /S /GoTo /D [201 0 R /XYZ 65.866 591.331 null] >> endobj 93 0 obj << /S /GoTo /D [201 0 R /XYZ 65.866 488.359 null] >> endobj 98 0 obj << /S /GoTo /D [205 0 R /XYZ 65.866 709.331 null] >> endobj 100 0 obj << /S /GoTo /D [205 0 R /XYZ 65.866 672.035 null] >> endobj 102 0 obj << /S /GoTo /D [205 0 R /XYZ 65.866 302.623 null] >> endobj 104 0 obj << /S /GoTo /D [207 0 R /XYZ 65.866 513.331 null] >> endobj 106 0 obj << /S /GoTo /D [207 0 R /XYZ 65.866 399.359 null] >> endobj 108 0 obj << /S /GoTo /D [207 0 R /XYZ 65.866 296.387 null] >> endobj 110 0 obj << /S /GoTo /D [209 0 R /XYZ 65.866 709.331 null] >> endobj 112 0 obj << /S /GoTo /D [209 0 R /XYZ 65.866 490.035 null] >> endobj 114 0 obj << /S /GoTo /D [209 0 R /XYZ 65.866 194.191 null] >> endobj 116 0 obj << /S /GoTo /D [214 0 R /XYZ 65.866 480.899 null] >> endobj 118 0 obj << /S /GoTo /D [219 0 R /XYZ 65.866 492.795 null] >> endobj 120 0 obj << /S /GoTo /D [226 0 R /XYZ 65.866 595.339 null] >> endobj 122 0 obj << /S /GoTo /D [226 0 R /XYZ 65.866 357.375 null] >> endobj 124 0 obj << /S /GoTo /D [228 0 R /XYZ 65.866 477.787 null] >> endobj 126 0 obj << /S /GoTo /D [228 0 R /XYZ 65.866 198.487 null] >> endobj 128 0 obj << /S /GoTo /D [230 0 R /XYZ 65.866 465.339 null] >> endobj 130 0 obj << /S /GoTo /D [234 0 R /XYZ 65.866 230.331 null] >> endobj 132 0 obj << /S /GoTo /D [236 0 R /XYZ 65.866 535.331 null] >> endobj 237 0 obj << /First 239 0 R /Last 289 0 R >> endobj 238 0 obj << /S /GoTo /D [8 0 R /XYZ 65.866 776.023 null] >> endobj 240 0 obj << /S /GoTo /D [10 0 R /XYZ 65.866 719.331 null] >> endobj xref 0 307 0000000000 65535 f 0000105312 00000 n 0000105609 00000 n 0000105702 00000 n 0000000015 00000 n 0000000065 00000 n 0000000681 00000 n 0000007474 00000 n 0000008199 00000 n 0000008305 00000 n 0000009582 00000 n 0000009704 00000 n 0000010011 00000 n 0000105923 00000 n 0000010149 00000 n 0000105992 00000 n 0000010287 00000 n 0000106061 00000 n 0000010425 00000 n 0000106130 00000 n 0000010563 00000 n 0000106199 00000 n 0000010701 00000 n 0000106268 00000 n 0000010839 00000 n 0000106337 00000 n 0000010977 00000 n 0000106406 00000 n 0000011115 00000 n 0000106475 00000 n 0000011253 00000 n 0000106544 00000 n 0000011391 00000 n 0000106613 00000 n 0000011529 00000 n 0000106682 00000 n 0000011667 00000 n 0000106751 00000 n 0000011805 00000 n 0000106820 00000 n 0000011943 00000 n 0000106889 00000 n 0000012081 00000 n 0000106958 00000 n 0000012219 00000 n 0000107027 00000 n 0000012357 00000 n 0000107096 00000 n 0000012495 00000 n 0000107165 00000 n 0000012633 00000 n 0000107234 00000 n 0000012771 00000 n 0000107303 00000 n 0000012909 00000 n 0000107372 00000 n 0000013047 00000 n 0000107441 00000 n 0000013185 00000 n 0000107510 00000 n 0000013323 00000 n 0000107579 00000 n 0000013461 00000 n 0000107648 00000 n 0000013599 00000 n 0000107717 00000 n 0000013737 00000 n 0000107786 00000 n 0000013875 00000 n 0000107855 00000 n 0000014013 00000 n 0000107924 00000 n 0000014151 00000 n 0000107993 00000 n 0000014289 00000 n 0000108062 00000 n 0000014427 00000 n 0000108131 00000 n 0000014565 00000 n 0000108200 00000 n 0000014703 00000 n 0000108269 00000 n 0000014841 00000 n 0000108338 00000 n 0000014979 00000 n 0000108407 00000 n 0000015117 00000 n 0000108476 00000 n 0000015255 00000 n 0000108545 00000 n 0000015393 00000 n 0000108614 00000 n 0000015531 00000 n 0000108683 00000 n 0000015669 00000 n 0000016412 00000 n 0000016535 00000 n 0000016697 00000 n 0000108752 00000 n 0000016835 00000 n 0000108821 00000 n 0000016974 00000 n 0000108891 00000 n 0000017114 00000 n 0000108961 00000 n 0000017254 00000 n 0000109031 00000 n 0000017394 00000 n 0000109101 00000 n 0000017534 00000 n 0000109171 00000 n 0000017674 00000 n 0000109241 00000 n 0000017814 00000 n 0000109311 00000 n 0000017954 00000 n 0000109381 00000 n 0000018094 00000 n 0000109451 00000 n 0000018234 00000 n 0000109521 00000 n 0000018374 00000 n 0000109591 00000 n 0000018514 00000 n 0000109661 00000 n 0000018654 00000 n 0000109731 00000 n 0000018794 00000 n 0000109801 00000 n 0000018934 00000 n 0000109871 00000 n 0000019074 00000 n 0000109941 00000 n 0000019214 00000 n 0000021805 00000 n 0000021915 00000 n 0000024041 00000 n 0000024239 00000 n 0000024586 00000 n 0000024712 00000 n 0000024781 00000 n 0000024990 00000 n 0000025127 00000 n 0000025267 00000 n 0000025406 00000 n 0000025547 00000 n 0000025687 00000 n 0000028237 00000 n 0000028363 00000 n 0000028408 00000 n 0000028548 00000 n 0000028688 00000 n 0000028827 00000 n 0000031372 00000 n 0000031498 00000 n 0000031551 00000 n 0000031692 00000 n 0000031831 00000 n 0000031971 00000 n 0000032110 00000 n 0000034275 00000 n 0000034401 00000 n 0000034446 00000 n 0000034586 00000 n 0000034726 00000 n 0000034866 00000 n 0000036062 00000 n 0000036188 00000 n 0000036225 00000 n 0000036365 00000 n 0000036502 00000 n 0000038735 00000 n 0000038861 00000 n 0000038890 00000 n 0000039030 00000 n 0000040632 00000 n 0000040742 00000 n 0000042289 00000 n 0000042415 00000 n 0000042452 00000 n 0000042592 00000 n 0000042732 00000 n 0000044468 00000 n 0000044578 00000 n 0000047022 00000 n 0000047132 00000 n 0000048994 00000 n 0000049104 00000 n 0000051878 00000 n 0000051988 00000 n 0000053206 00000 n 0000053316 00000 n 0000055863 00000 n 0000055989 00000 n 0000056018 00000 n 0000056158 00000 n 0000058858 00000 n 0000059337 00000 n 0000059463 00000 n 0000059492 00000 n 0000059671 00000 n 0000061723 00000 n 0000061849 00000 n 0000061878 00000 n 0000062017 00000 n 0000064893 00000 n 0000065003 00000 n 0000067427 00000 n 0000067537 00000 n 0000069723 00000 n 0000069849 00000 n 0000069886 00000 n 0000070027 00000 n 0000070167 00000 n 0000071698 00000 n 0000071824 00000 n 0000071861 00000 n 0000071999 00000 n 0000072139 00000 n 0000074123 00000 n 0000074249 00000 n 0000074302 00000 n 0000074442 00000 n 0000074582 00000 n 0000074722 00000 n 0000074862 00000 n 0000076643 00000 n 0000076753 00000 n 0000078530 00000 n 0000078640 00000 n 0000080952 00000 n 0000081062 00000 n 0000083207 00000 n 0000083317 00000 n 0000085543 00000 n 0000085653 00000 n 0000087254 00000 n 0000110011 00000 n 0000110065 00000 n 0000087364 00000 n 0000110133 00000 n 0000087492 00000 n 0000087701 00000 n 0000087913 00000 n 0000088333 00000 n 0000088763 00000 n 0000088940 00000 n 0000089215 00000 n 0000089413 00000 n 0000089608 00000 n 0000089908 00000 n 0000090090 00000 n 0000090411 00000 n 0000090649 00000 n 0000090934 00000 n 0000091325 00000 n 0000091645 00000 n 0000091957 00000 n 0000092340 00000 n 0000092623 00000 n 0000092932 00000 n 0000093218 00000 n 0000093614 00000 n 0000093819 00000 n 0000094134 00000 n 0000094388 00000 n 0000094533 00000 n 0000094702 00000 n 0000095263 00000 n 0000095493 00000 n 0000095713 00000 n 0000095923 00000 n 0000096216 00000 n 0000096631 00000 n 0000096828 00000 n 0000097113 00000 n 0000097357 00000 n 0000097634 00000 n 0000097983 00000 n 0000098280 00000 n 0000098530 00000 n 0000098840 00000 n 0000099271 00000 n 0000099536 00000 n 0000099883 00000 n 0000100261 00000 n 0000100540 00000 n 0000100797 00000 n 0000101142 00000 n 0000101412 00000 n 0000101758 00000 n 0000101983 00000 n 0000102211 00000 n 0000102540 00000 n 0000102826 00000 n 0000103183 00000 n 0000103440 00000 n 0000103731 00000 n 0000104082 00000 n 0000104281 00000 n 0000104496 00000 n 0000104649 00000 n 0000104763 00000 n 0000104874 00000 n 0000104986 00000 n 0000105095 00000 n 0000105202 00000 n trailer << /Size 307 /Root 2 0 R /Info 4 0 R >> startxref 110202 %%EOF samhain-4.1.4/docs/README0000644000175000017500000003651312615253277011713 00000000000000 CONTENT OF THIS DOCUMENT ------------------------ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ +++ +++ NOTE: The distribution package contains a much more detailed MANUAL +++ +++ +++ +++ ---- See the docs/ subdirectory ---- +++ +++ +++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - INSTALL basic install procedure - PGP SIGNATURES signing database and config file - CLIENT/SERVER how to install and use with client/server mode for distributed host monitoring - STEALTH how to install and use with stealth mode enabled - USAGE some usage examples - CAVEATS what the name says - START AT BOOT TIME how to start the daemon during the boot sequence - CONFIGURE OPTIONS overview of supported options, and defaults - TESTING test suite (also useful to see EXAMPLES) INSTALL: ------- Unpack the source with: gunzip -c samhain-current.tar.gz | tar xvf - This will drop two files in your current directory: samhain-{version}.tar.gz samhain-{version}.tar.gz.asc To check authenticity and integrity of the source code, verify the PGP signature on samhain-{version}.tar.gz (public PGP key for Rainer Wichmann at http://wwwkeys.pgp.net/): gpg --verify samhain-{version}.tar.gz.asc samhain-{version}.tar.gz Then unpack samhain-{version}.tar.gz: gunzip -c samhain-{version}.tar.gz | tar xvf - cd samhain-{version} If you have an incarnation of 'dialog' (xdialog, dialog, lxdialog) installed, you can use the GUI install tool: ./Install.sh Otherwise use the commands: ./configure [options] make su root make install At least the following executable will be built: +++ samhain +++ the monitoring agent, without any client/server support (i.e. local use only) Additional executables will be built if you compile in client/server and/or stealth mode (see below). The 'make install' target will strip the executable(s), i.e. discard symbols. PATHS: ----- For configuring the install paths/locations, see the MANUAL. WARNING: ------- Some versions of gcc have a bug that generates incorrect code if strength reducing is enabled. If you modify the compiler flags, always use the -fno-strength-reduce option with gcc, unless you are sure that your compiler does not suffer from the problem (see README.gcc_bug). Also, some gcc versions generate incorrect code unless the -fno-omit-frame-pointer option is used. The -fno-strength-reduce and the -fno-omit-frame-pointer options are enabled by default by the 'configure' script. PGP SIGNATURES: -------------- By default, samhain will report on the checksums of the database and configuration files on startup. You can always (clear)sign the database (once initialized) with GnuPG, as well as the configuration file (recommended: gpg -a --clearsign --not-dash-escaped FILE). However, to have samhain check these signatures, rather than ignoring them, you need GnuPG and you must compile samhain with the option ./configure --with-gpg=PATH where PATH is the path to the gpg/pgp binary. Samhain will invoke gpg only after checking that only trusted users (by default: root and the effective user) have write access to any element in the path. The public key for verification must be in the keyring of the effective user (usually root) For more security, it is possible to compile in the checksum of the GnuPG executable, and/or the key fingerprint. See the MANUAL for more details. The public key will be searched in the gpg home directory (~/.gnupg/) of the effective user (usually root). The key identification and fingerprint will be reported. CLIENT/SERVER: ------------- samhain supports logging to a central server via TCP/IP. To enable this option, use the ./configure option ./configure --enable-network=client|server [more options] NOTE: client and server are __distict__ applications, and must be built seperately. By default, installation names and paths are different. Do not blame us if you abuse './configure' options to cause name clashes, if you install both on the same host. The following executables are built: +++ samhain (client) +++ the monitoring agent, with client code included if --enable-network=client +++ yule (server) +++ the log server (no monitoring, just report collecting !!!) if --enable-network=server +++ samhain_setpwd +++ a utility program to set the password of a monitoring agent (see man page samhain.8). Use it without options to get help. To set up a monitoring agent, do the following: -- select a (16-digit hexadecimal) password. To generate a random password, you can use: ./yule -G -- use 'samhain_setpwd samhain ' to generate an agent 'samhain.suffix' with the selected password (you can rename the agent afterwards, of course) -- use 'yule -P password' to compute an entry to register the agent -- in the servers's configuration file, insert the computed entry (replace HOSTNAME with the host, on which the agent will run) in the section called [Clients] By default, client/server authentication is done with the SRP (Secure Remote Password) protocol. It is also possible to store configuration and database files on the server. See the manual for details. STEALTH: ------- samhain supports a 'stealth' mode of operation, meaning that the program can be run without any obvious trace of its presence on disk. The supplied facilities are more sophisticated than just running the program under a different name, and might thwart efforts using 'standard' Unix commands, but they will not resist a search using dedicated utilities. To enable this mode, use the ./configure option ./configure --enable-stealth=XOR_VAL [more options] XOR_VAL must be a decimal number in the range 0, 128..255 (using 0 will have no effect). The runtime executable will contain no printable strings revealing its nature or purpose (strings are xor'ed with XOR_VAL at compile time, and decoded at runtime). The configuration file is expected to be a postscript file with _uncompressed_ image data, wherein the configuration data are hidden by steganography. To create a suitable image file from an existing image, you may use e.g. the ImageMagick program 'convert', such as: convert +compress ima.jpg ima.ps The following additional executable will be built: +++ samhain_stealth +++ steganography utility program to hide/extract the configuration file data in/from a postscript file with _uncompressed_ image data. Use it without options to get help. Database and log file entries are xor'ed with XOR_VAL to 'mask' printable strings as binary data. No steganography is supported for them, as this would require image files of unreasonable large size. However, if the database/log file is an existing image (say, a .jpg file), the data will be appended to the end of the image data. The image will display normally, and on examination of the file, the add-on data will look like binary (image) data at first sight. The built-in utility to verify and print log file entries will handle this situation transparently. To re-name samhain to something unsuspicious, use the configure option ./configure --enable-install-name=NAME 'make install' will then re-name samhain upon installation. Also, database, log file, and pid file will have 'samhain' replaced by NAME. USAGE EXAMPLES: -------------- Review the default configuration file that comes with the source distribution. Read the man page (samhain.8). initialize database: samhain -t init check files: samhain -t check run as daemon: samhain -t check -D report to log server: samhain -t check -D -e warn start the log server: yule -S CAVEATS: ------- Permissions: ----------- samhain needs root permissions to check some system files. The log server does not require root permissions, unless you use a privileged port (port number below 1024). If you use --enable-udp to listen on the syslog socket, you need to start the log server with root permissions (it will drop them after binding to the port). Trust: ----- samhain checks the path to critical files (database, configuration) for write access by untrusted users. By default, only root and the effective user are trusted. More UIDs can be added as a compile options (some systems habe 'bin' as owner of the root directory). Integrity: --------- On startup, samhain will report on signatures or checksums of database and configuration files. You better check these reports. Both startup and exit will be reported. If you are using samhain as daemon and start it at boot time, you may want to check that startup/exit corresponds with scheduled reboots. If the path to the samhain binary is defined in the configuration file, samhain will checksum the binary at startup and compare at program termination. This will minimize the time available for an intruder to modify the binary. Mail address: ------------ For offsite mail, you may have to set a mail relay host in the configuration file. START AT BOOT TIME: ------------------ the easy way (supported on Linux, FreeBSD, HP-UX, AIX): su root make install-boot CONFIGURE OPTIONS: ----------------- ------------------- -- basic options -- ------------------- --enable-network Compile with client/server support. --enable-udp Enable the server to listen on port 514/udp (syslog). --enable-srp Use SRP protocol to authenticate to log server. --with-gpg=PATH Use GnuPG to verify database/config. The public key of the effective user (in ~/.gnupg/pubring.gpg) will be used. --enable-login-watch Watch for login/logout events. --enable-stealth=XOR_VAL Enable stealth mode, and set XOR_VAL. XOR_VAL must be decimal in 0..32 or 127..255 and will be used to 'mask' literal strings as binary data. (0 has no effect). --enable-micro-stealth=XOR_VAL As --with-stealth, but without steganographic hidden configuration file. --enable-nocl=PW Enable command line parsing ONLY if PW is the first argument on the command line. If PW is "" (empty string), command line parsing is completely disabled. --enable-base=BASE Set base for one-time pads. Must be ONE string (no space) made of TWO comma-separated integers in the range -2147483648...2147483647. (The default is compile time.) Binaries compiled with different values cannot verify the audit trail(s) of each other. THIS IS IMPORTANT IF YOU COMPILE MULTIPLE TIMES, E.G. ON DIFFERENT HOSTS. ------------------- -- paths -- ------------------- ${install_name} is "samhain" by default (see --with-install-name=NAME ) configuration: /etc/${install_name}rc state data: /var/lib/${install_name} log file: /var/log/${install_name}_log lock/pid file: /var/run/${install_name}.pid mandir: /usr/local/man bindir: /usr/local/sbin/ --exec-prefix=EPREFIX Set sbindir prefix (default is /usr/local, ie. binaries go to /usr/local/sbin) --prefix=PREFIX install directory (default is NONE) IF PREFIX = USR; then configuration: /etc/${install_name}rc state data: /var/lib/${install_name} log file: /var/log/${install_name}_log lock/pid file: /var/run/${install_name}.pid mandir: /usr/share/man bindir: /usr/sbin/ IF PREFIX = OPT; then configuration: /etc/opt/${install_name}rc state data: /var/opt/${install_name}/${install_name} log file: /var/opt/${install_name}/${install_name}_log lock/pid file: /var/opt/${install_name}/${install_name}.pid mandir: /opt/${install_name}/man bindir: /opt/${install_name}/bin/ IF PREFIX = (something else); then If EPREFIX is not set, it will be set to PREFIX. configuration: PREFIX/etc/${install_name}rc state data: PREFIX/var/lib/${install_name} log file: PREFIX/var/log/${install_name}_log lock/pid file: PREFIX/var/run/${install_name}.pid mandir: PREFIX/share/man bindir: PREFIX/sbin/ --with-config-file=FILE Set path of configuration file (default is PREFIX/etc/samhainrc) --with-data-file=FILE Set path of data file (PREFIX/var/lib/samhain/samhain_file) --with-html-file=FILE Set path of server status html file (PREFIX/var/lib/samhain/samhain.html) --with-log-file=FILE Set path of log file (PREFIX/var/log/samhain_log) --with-pid-file=FILE Set path of lock file (PREFIX/var/run/samhain.pid) ------------------- -- other -- ------------------- --with-checksum=CHECKSUM Compile in TIGER checksum of the gpg/pgp binary. CHECKSUM must be the full line output by samhain or GnuPG when computing the checksum. --with-fp=FINGERPRINT Compile in public key fingerprint. FINGERPRINT must be without spaces. Only useful in combination with '--with-gpg'. If used, samhain will check the fingerprint, but still report on the used public key. --enable-identity=USER Set user when dropping root privileges (default is the user "nobody"). Only needed if there is no user 'nobody' on your system (check /etc/passwd) --with-port=PORT Set port number for TCP/IP (default is 49777). Only needed if this port is already used by some other application. --with-logserver=HOST Set host address for log server (default is NULL). You can set this in the configuration file as well. --with-timeserver=HOST Set host address for time server (default is NULL - use own clock). You can set this in the configuration file as well. --with-sender=SENDER Set sender for e-mail (default is daemon). --enable-xml-log Use XML format for log file. --enable-debug Enable extended debugging --enable-ptrace Use anti-debugging code. --with-trusted=UID Comma-separated list of UID's of users that are always trusted (default is 0 = root). You will need this only if the path to the config file has directories owned neither by 'root' nor by the (effective) user of the program. TESTING: ------- For testing compilation etc., you may use the test suite: ./test/test.sh n [hostname] The argument 'n' is the number of the test to run. Some tests require that the (fully qualified) hostname be given as second argument. Without options, you will get a short help/usage message, listing each test, its purpose, and the name of the configuration file used. You may want to review the respective configuration file before running a test. Also listed are the scripts used for each test. If you have problems getting samhain to run, you may use these scripts as examples. samhain-4.1.4/docs/BUGS0000644000175000017500000000252212615253277011507 00000000000000AIX: --- Samhain must either be compiled as 32bit application, or with the --disable-dnmalloc configure flag, because the OS provides no way to enforce usage of 32bit address space. MacOS X: ------- (1) Pointed out by David: static linking is not supported on MacOS X, see http://developer.apple.com/qa/qa2001/qa1118.html Solaris: ------- (1) This was pointed out by rog [at] iis dot fhg dot de (Ingo Rogalsky): "It isn't possible, to link samhain statically with Solaris. This is a Solaris issue (see Sun Infodoc ID12624) and not a samhain problem." Linux, maybe others: ------------------- (1) With gdm (the GNOME display manager), GNOME version 1.2, using the file hiding kernel module (configure option --enable-khide) at system boot may cause problems (keyboard locked up). No problem observed with kdm (the KDE display manager). In case of problems, you may need to reboot into single-user mode and edit the boot init script ... it should be noted that on the test system, gdm sometimes locked up the keyboard on other occasions (e.g. after a fsck). (2) With gcc 2.95.2 (and glibc 2.1.3), it is not possible to use --with-database and --enable-debug at the same time (the code will segfault). This is apparently a compiler bug, and it does not happen with gcc 3.0. samhain-4.1.4/docs/MANUAL-2_4.epub0000664000175000017500000064647112703400302013240 00000000000000PK DRHoa,mimetypeapplication/epub+zipPK DRH META-INF/PKDRHXaMETA-INF/container.xmlU;0D{NamCV$$j8lٵ c(tS{3>Ds1V%b/]sLV05vV{a4s.Ց`1z'? 5GCbꥁn{8^d I=>Ry)Q R.el[hPK DRHOEBPS/PKCRHra| q3OEBPS/apb.html[r6S`uQSQڋmRYnqjOdW-DB$eYdJrd G"tgFTZ7<1QD*Er{sKCiËgǽB~?ߗ?`囗g'῾? Sׯp0 ß^jL< g`@UIx:!Mh?b#Kxg*x<i21~Q/ޟKmH9D`,Sz\ CDFU=L)(qTE/z~:gWf a4{;G`xe\o0eKxǙ{ #_:k' U 3O.^nO>QU,*gKlL4"-Ivuɋv˔kAHς "W(ăQHu]0{3 FWHL>0TU"T]Wϙ,IGk9b eXg:|Tɚ}S,?N$\q%xvp_Ȉofg@ `#)歮j(@)I=FA2``y,{3sKhzТERUƪ>'ZÉa*=2  [h"-){>P4v FS=}_"'0܌Ru<Kax̌,cu?ѻ\eevk)N!ߓbLjE}&MʸGY/SxkRgTf cgLѠ,xN j`|JZPf:S >Wi+C|n8Kx 弥r@:>JADJɸ1>l3U}BXGdƫUw@ A>㙨 xpZf`l](Gh]oJefUvB p->)T_|uh{YDViy`gWevQ J }NMHǀn7HBÆKgY!G#hH9k[m7湂;ATIBSmrYQE*oAIK01 W5}j+E)fR,1HMUR~C[^♋=)GA!Hſⷔ}q] Bkκyr"nET#'k|x? }ND|5ߙGHF ܭڔmkRĈ4/acKVU`Cs{p_iXELۜr4ΙBU:l4![i@|͵MoiTx&X0>`~ӺZ{x^k1ݦzEt% O=?]SG"CϦ˘apCxY` xJjRۡ0f.[ޖA2fuVI3_^hCc#M+U*`oB{]ueYiOX[Z@)za-g{X;V䈼r1ڝ{b5`Y# b>BiՈV8o46[D0;?Ŕי98hU9~YjGZ¦ krMm{ox%U s&s$XcF0qa*JX/\\ӽK;2 KRJ a~`p="cV"Wf Ms{\gbA*&̑lUW :[!%fG5ȥ)WkX%9t.rWlԮkنǖ%Y^-OdǧmvBGnUGܴH;9thbpR*Mt=-8vz(k-95ÍN UQ B9A]>}VDE0UL5\ Z$:츄 =rՉZMlsj"vNj}ĴL T[zKTʦ m RUgqgn*:+R弒Ij64Rrp%b/4.Hլ9)vNmZds0z:oO}bMȻk,# ,!=fC]~JUBYPeo?x>!!\ PKCRH^ OEBPS/apcs15.htmlVQn6)آUMj8^ FNSJ+b)R%]_,=JO!)iw0jLr޼y3TꡑFcV$KO@UJ$p2븪 'ɫY/P;s ~>bl:§o K3Ʈ'εm6tsjdg7UI\<ȫ"wI,@ly 1_BÝ6 Z9:6I| >J51K_L9s]mk(%Db`)lr} IB$bOȚ܍\3?-fP^ J\s`x̶\ xJQr>)Ĝ"To#'\-v>πK4:ղ7WWrFzFGGil[KP ;ҽ~ &ga3gO qjz;{zBP$Ka9UKVyRBP 8Mm!]s)٘mzHgF)BSjBXu5wa)m r qH5s%2h ސWsc_^tZU!#|l*Żmt G:9 /jdmA#4}ϤRT e i͢Dzc aBYc䡏)&\+ߺvlPV]MJMbvMsæu2pO|}RgwS1%TJK;Ј@W/g4vf7JhHcCiuU 燗9; Bg5k-*#Cen{|+EzJ~ŽGT܈)/[|k"u+SKj$7ϡhMPb!%B:aO߁M b"k p5Rԕ~)zB !"^t*5BYHٛKdӀD/FKhJa4cuqnWa۲A='n|oQ PKCRHQ}[jOEBPS/ch05s16.html=rF/O1斗dB86#%[J[J9{vC'@0dm{{{{{동 !RrUU4z{{O?q) g~k2 (N'Ͽz (HTҬ೽{G=?ۛc1-a.DA `$GE@}B0| FG$/d>* )V.CfU@햱7ޚq~C]&^sde@HR#;Iz`Q@2/f (Y;xpx,E&hjꍮeg_ 7i,7DO^:NssαKF׺F6jֱ}RI^RcbMd~RK&˫_,˰H[O ueҘKoohv%:nzܴɏX pf9(iWq "HS l(ZgmWjYpgdraJpd#*J&$;&:`G^ _z~b:\R1M-Tc ܙ_ O#YuZ:;2h:9QfXJGm%fH L.lCiɩ+tn~iP>ozZHŴW>5XY*`Q^ ֒BXdb6's`]J2HPtH歖*gX7ɨunwA02!G!nh,!Ŷw $N Rb%xvK: .Q\A0RYJ2ȃrz3•Z<܏ IfK+X܎+G[92.\WjnJm`>Vi]F,?>ۄ6)wʛW˝m4kgAO{85X}l#DXѿKK,?ʰqj5]2HSMp8- ʖRﺛÂwCq%!]^C:x%}ye/bħquD)N==mD-:E%*e.v+q=_|GYo>@;VRS CRh<mN}vD:ojU{QwQbYog/Vc{07҈y_FL+}HXK'4Bk%z 6}d^a)BY9|Pnb_X"g`!/J @wx{99rƴ+eFNOXm XhXn揙v+H㏝T8ʥ-uɆB,z|J;a믫ȽAypѩGP ڼ4ip@Eq'P&F}Ɋ+PAomn IHOm]Bj:;nM>;3\fA(=.$Ed*=U 3;&F3c\|Z s}du~::J9Gfճ5 d7EgQb֬2h3oDK(UE'ګ"PP|g+b27`-wtd3Cx~~3 C(z`:5mcg8T)R^7R~dB,)x۶N)^/D 43SS;4d[j|{ ^[$g1pRibr` yU(5S;IEcpـ1,W\e`s^;Rԍ c;|g~vT5E0H@,6kW[6z$f_=bVW-HJLFǽCK:yoDzuL= !\>tin,ӕ,L{=I tvWe>{pɀċ'D@\rZl&>8W%օO{@:ON]u΄o6x.h73.up$efZЯ.R+HLum.D`Z]csyLo_h?FVO˘Ɉzz{IOc=rp?Qdz91a+`ҊI  >q&W'h/޿lTO؜c{W ]YeؚCԬ%w/* ܔQ[30f 9n) bPm?:BCpU,<6:ucZ7Y뒵@ZJev]'d8N2iaL6M˝YJ-:8/]0)+k]X::G {fKjǍ܃pZBCFA0ufMT9xhP_F}:dA(Λq0&d}qXJ~-_k 0=}wż`,Nin8ۙoXCNm ]HX' g+ wáhbDt?|ЮwC\epᖗ(U[sohѽ$unmomBCn*ECWFE^HrlauƆC怇&% ՜ ͊'ɹ=/ W5:漆2v!Ttfrr4 pm51i'|?^w4egkDa$l]0,sC{GkdwoJ8@H'(Sw,i?ff8 $R9€uks1̌ zVWڪtOaLA8eQہ!056d}f{m$-:;]^d$1~+*N? w v/] f14 :+j ۠~A5onF>i^Z<.ܖ%Aj`mgKZnh #+(>7Dr`g-ti_+궮Vi.u;ۦ:z&MF@$$aL Z>MO%E' \O+ v+j#02K?}=`rB+q1Pz_^^{Xחl0Lr2_59;O&߿dlƛGc]&&wsfS/dSo/WgS+m!fk^YQ_R+[kHYLî[h`2N og\޲g^AKwjW~{3-(zd'?~sK~~M+3WQ"^U35؋ޘdNVsfezɔذඩaV3^z,HDvpfBIcʫ5#ܩknB/>۵`)Pmt}cֺ(v.\),%|̌.[v7$)usQp$=}!6-ON'`.2'2dk}xcuI i16*DŖ^!VIM2n`ʙECFh =狲I𢜑Ά˥营'<[. (8X~-=w_h:v0- WEaز֥{y+ ]P隽kx!`@;i=IN-' 5z+sHXj 'C9;TJY\mYk+F/,E.,5dqs]U! ":GZo?VgU:d) 8fPr)S-6(ݡހQzF+^AVD=(qnX0T ămP7ςQH%>b`q _'#H2rJk]D/UeJp# B-e(v(x_{΢#D/rXɳ5L4ڇYٍOKRQ]54E,S{ Ơ!5f﯒Q:rM5 PzlDHW#x^–^*/(\ Y{_}_ݣ~QqQPp_?f?x2oPJrI03Wlu8B+t) }Р7J}M6 .Ml.Gvh5EI)P}$/o7} )8EcG/(;=(#Ј^w6u ƛġIKz.AMHbSkDZTn@|1E }yo DP|YDXDѨ \6 Uӊr , OLqSvC)Ҳ-'I +1CA;QI?(BUiq6C?xY츙ve`f)꺫ΆX{L>`hT@B WXPB 2v- RPS:Wf-w߲-B!ك'& mAıeU#R Sg$Y4tH)4#j]>ֶ+y[)_Hexѯ`/v'D1:84!()\+(Sm^@~p $agOP,^x #jmwb [DFqkt3]+ wHCk8)N$8qg#jn8C ", S}LsGIJh͋n^P %R7oðGXAxmo=',GXWF=v^_M R+v[# <6p[irdT_zލbr z]KDfsƮ>g!||? kbaO1 Lӫlk$|7ȳ)t\-g12Ytq|*Wz@}&JGpy$ۘxy:hV7j7zViOizFsK|!d ,vhϤغK.)[vj7O?3 %5UnQ=KġzсE=vylL {2y||[Dw,R/&G|PKCRH7h OEBPS/apcs14.htmlVn8)fuJVC@RX b?X쁖QԒn}>>Ɏl*nA-yDqÉ_+ K4VhQ<T.Z$ͳXUVJ'/ëu#1ŀtFwcˆ}A\}j W/Bmlz֭z xKܔMPw VE;$ڡQ\lW8(^*4i@C`ZO1LF-Qx2l?& \rK,. -mm|e({Q$zddOV_\C % nfn6j]Zm2Q'wL|~n [I0(yM߾߾(r@ O4 eƓ"fuwK$ۚlr]UT|3V1K$Fz=L9#>lǦjTb)`m7XK#m3J';T6od5w%sl%fXa_Sq㬇P\G81ڢA*~lNtSvF9NI6 nN!4A7/R/5CX-.Sp%vU$S8)T_º/o̓ ߲ɒ{FԃW+aɍh$'F3G8 %_lS>}kvɿ3H`H.m?΍m[Uu0pK=l7ߛ[r)ۀ\q$7BR|# .;޸ vj}mWXPPwʅ˾\0g#(pr9>Wr;ȭZo4 ݉gIӝsЭՃЭU;BĒN =7yiMaS/qt0'w̍iDvU<(6fi5xn7,T֎lPKCRHh)OEBPS/apbs03.html_O0)n~@LZEH4HMG7&;%~Ĥ ;ғJ=:$~Mn2ń,>E |F m N${]L?/Ϡ dys:2q`l1ϋsHo XBzb ytXɲt،2*7/% eK}UlNÂy=gWcUnpv[yPKBRHꇯ:OEBPS/ch03s10.htmlTR0[zJz8m:e&B Gؚʒƒ6< Oֵci{kGoJ 4:fadR1~1p^L(1fڰ z7Mo.?\ 9~8|<× AVxoO8_.00UΧ|ðA3Dm_]oM), Z{Y"I;Ԕ%*ދ~%=y]Ra7D/@樑JLGc661?nw~0x'߰lD\@# Sv9nGӞŬS4a?l}o#w;ų")շm7 DK+9 bDdUAAϘ ; 3kQgrt򏋗,sx30<<= 0ÉN(3+nӊ %䩨/7ٰs8 ǁmdC ˬ}c3*SLepq]>fK^HxY*s4"bs1mK ܭPT шq6+V81fW?ʦX7e ܴЎbWFgJjoU) XftQeE6U> yt4d]̸Ayd7qƁl߆,1{UC]9cP%;2"y.W4_:3Uc-=S19bFɊf }b0Aߝ>m{d㮫D(Ec#rO33=2F(r=:1V@4NRzNW0鐽]7|'(io(ޠ t3X-8yOHd- ԮBaV뉏%]SOdZڽvXV;Vv%4!f+#(L( R嚜"z%uJ5gyfhwM_QMw)KsC;.N:L:45PR+ǃ[gg'Jzv-HʂO߶.k1R?%K-n0LLeآE4`! Ðqc<|4JP,'4_8mKCrhf8!mǺW*#w=zߺ1YcVoEPQ#R &0@ Ꙫτ\l.]ƶ2TAD[Ed$ʬވwh]!]!6_ֱ(&!1dO;+6Kd-#蹽tl}wp5dtҍ;Quu6)q:T7HV>R0Z+W«o7fI{ܪ#)F|6)ݻq}x'Z䏟._iAz*9͓yZ/-'Lc=JΓ:z %/'KwW ݟ.a$=kv7OC:8y,qu\Jn8i9jm-d%fwrB:\I܃hr!X+ΛS#vAZbR[N{3۰>N$TQR-t@: <%) [Z|r.hpKFѓ$*DU B' pѮ{O-JR)(Q!R0vD:&"GSȼq~چ!"9@IHƄJ@.T$JBµ%KtkV~k$ADU_1.gW}@0="{@P[s0 3)8r2^Xd+}';A8t\-څ@}\aS`68>qG[SiQ맷v﮿; [.m"E1bdR2+D Ux;86EHìy3(D <"zY(SؖOp f/wV;s#&" UϘ22I9TzʕN-\kԎLC _RsKqh?9WqJ҅c,cͺ L%b$P*E?\oFPz˃6`V;n`ۧ]I` 8ͭ]>rӕV!T{fŠ"³Cy!|A'>1WW4&övRKK)e&s1(k+ j]qP-8(uOcǚF ~wp <3nX%5-5#]Yܛ=-eWjۥ>4tM`'1xDR:Δn4Qy)5j5 뻾'2=kI|hoڻfq}^L=7i ;L|^xdY fwk[ kkhTOP ۷{dThFтƑ`"Wnpl/{lTm: 8@cPc/[Өٲ7`q g#qa+۬ > daXhb@et˩2{meԠzw^Cz wm,[d=\rE2"n~ ٨=o`˿PKCRH[YOEBPS/apcs07.htmlUN@ӽJ[CF%*jBK8lIl޵CBn}>a㵝 *f33L"9V63:^$j'҉ʍPh#?~y )qIDOo})\R )Qy brE_t{/DDܴ ($ (~TP;M`Jbm6͉@RUbRd*фB10139,|{/dqle$\Yi1&_<29RM1K?OA"nsXI}=X}گLC͙v{[*ݱMQ3/K dk V8k2OC=pL{aESa]*FccrT:W `O^2mR(N֦vL MpryJ W5WfrNrm1Ԉv͟+ CِI9ˬ†"ȗT:×z [vΖ2I޾XT:WJYl"YLn|${,Elڮ._|Q"Kt Zpؙ+mfek`o4Ϧ84044ܙ&b[E&c5ty.N-e/^(Ҥ1bBް\q-nM5/<|{|ǙX` cq"nD> ?WZgkt5k%s ctY^\4ƀhf =uZ 1eG1? "ppZ/ 'd5wg4@v]I-q TuɭMy7ClzNպйdIsl  ΂7;ӤqKVzȕDM,4c dMjq PhZ=cteNOcO)ΰ,UAx5H奃J ʋZ % O(Рr1\U44wYf.}ijŸ:;nuKƕ2DIYW(pp44~ӖZ#9 Dq/bDGU17Ry_k<* _Xkm?{U= ϯC>=i1Fѫ0z#>*=DS{?:hdot'[Sqf4G v( !{\?c5PA F9iձt>nRֺɈT{H{w72A\Ą^N+ŰVmE/Z#!ilkkbȃ\&.~ὃ;ztpɇkJ|E$tPKCRH;H&^~ OEBPS/ch09s03.htmlV[o6~ϯ8*q^ ,@v%")TcEd6L|;߹PǮF(yL@YJ(}L%`,oģDCqpd KӛˋHRƾ=atv ~}I6a=c"[͔=:Ye=.qh0ȫ"¶Xû ɫNH0Y;$(%jnNTҢGɩ*oחpm-2~}MV,Sղ+e 4XI}ư>ql&G{#i&D#m|ğ/.$X0UB5]J/EG2B7+@t[ma.d!Lݑ=D][f>P )KLN7esm|V^6^Ն\dʵƄ 䮥u7$M.%AM<3gτs U8 ܺ_ ˲ VB->9LpsM%*LPzgs{k<L$D36wxgԓƍQν^ϽxczK`z>:s] R` !At51o[ ŀt^L4\5/]wX햩G֏/4 pw-fφZ]!"M.Kit[{;x&5V1!fR9S)Y=W4#ޙ*T\?`9 ;;NfA\F62kߩ/hH ;ѥ^W o/PKCRHsoOEBPS/apd.htmlXr6)P&&Y'nf؍ۋ"A 5 hY} :~e-@[O'].oRD}r~r.c:e w|έ`yb'QyRǙʄ;mkraן'ʅ],}"t:YM'eq- G[fKzX{3-5b `^uß˅؈|:OH1 ߍ9+@RFΖ\uehLWU.&=3ݹμgC}KUnCFHr`aDQ.-$&3zi_1x};WS[;jD ?[*:i]I0@̈B;PZW{L~Njһ$2McnU b;qdJ#6_yhόH{!\`#+tzNr=Wi-yJpV-XVU8@Z,{ 6g{l>)"YOڰ+do/ .^\U02V7 drn(6PJb^]l[ n&O-EL8(uX9h^.*Ga[PȘ8QMס]]2!U& (l>-dGHt ۫}ĥփFV(I"V*VFt߅Az )b[\;nf48܃diogO5r#<72?M{1.U"a 5+WJ]Mw[ȂN5=aӶFLs{,>\Ӗh[[s4u$FY#-7 !I[Pm -Q0HhpUbif}uo7S:+tp]l ت` V+E =DR ۞l&@jFGRepٳG#9IɕwzێDYd'K ><>?TC. jZR5,l&!'tCDS&[껓U?`b#f!Vz<㬝Iip03Vf~P,3*وh4^Q '6ggNwAiOpq CŮq3*" ,?CaT3l-NK3Ftޝtm]QlZ^,TC0g*4OTAVfd/)T{Ō}F8םq5 `1V*!RTH`$ggAAcznA)-'nm$;B$_zնq-!f4$i VSPӘ7Ė͔]XߌSKS['32ov)wo %U4 PLl`3 . ˥lj:%*VUYN I֞=*aN"}-'K>ÂN(:.Mjр EI޽G']D̈^NPKCRHAsOEBPS/ch05s21.htmlXny[JBJV;E6t4fE 3}>agCrHP԰i{shmU 7Fj<"VΤڭCɦ`/ElVIgVg*7é]D'q8\{$uCl>"3XXzs]p%WdUq&0(h 052IF o5M4uTf's{IT𬑻bxNɿ/YB]{ 3W6@?sk].E9G 3mi>i+q+| R x D4~ ޶NƥP!FI߱7= oo5@CE#,Tjmg7FX7KUҼ@wա&aOm[%nf2jʒĘcaeom;Z8@߅p8/JB{mѽAnThh ܡp#ʖ]D5\ncp7iBVTuy,nlmt7-{;d1w'_˚A~ƋN皍?ajLa YмDRRI+E)M-ٗH&pfm-#·g⻙69h/[n tk{T!`B|K4-,gh>DސmORtR٩wc+Z+яk!8HcVj [fDFTh{FG=t>_E NH|: B~K7S`V[4D'2 Mp( =M ^vr(~w]Y\;D{b}/J6PKCRH՝ OEBPS/ch05s05.htmlUn6}nbJ؀W]vQM䁖FaHʻ7|Yu>HZrfΙ33dzS+xDKG' Pg&\O_8/t.Ѹdڰ??^A㧷7qz>zwqs~o9_42[ q(9K..qnk|vv;SyxWL<R"΍b捕zF)M(sREMy gQ%4[c -ůWQx̽ɷiGȔp#-u(_UO{ddBEϘ`cUL;t4' 5Yȼj*A=F g_a цOhvܰn*ᤣNKm,ۄӿ4#0 < tɪ!$MvVa9:DиEp%IUKB)*>/1s*y2>"$豱X0dYuҝ; \bеݎ4zwJHa_0hu8h!N-l)Ba$z)/0YYVb':t:E%tIz^- bUiڝ6a&CU0 ]&oʨ܅u%ual-DbBzbXz NP2A2ңpjt踡 MgBNC=OKJUU9C6*i?}?J;Qm)/jD`ZmBpп(ed\_xo% 듭,# i8y?Jyxa>] mD֨Lj."r_ĝE&${l.lvxÜ PKBRHy$ OEBPS/ch02.htmlVmo6_q#t*1jdvXܭH'D $`?&%7qZ(=9eYZX1@Dl>^yX'T" pĔf/GsO?x3ql8?ǀUg/ qk|٘Ac0KX~ ϘA3ENq.*w;e% ?HEygȻaN%啡B#6 b*7b>^^[hsDg0 ~U&rq!,A;^gv}iLLF+ 3< P߭Яm(Y\JlJa2SwG/R}Yl>|)\H‚!IqTve U4˥(Hu\[\ղHܶ қډ}x>{[ !F6561>1 rHd!w]5Kc ipRdANm#gg2ظwԐi7!nC."x⇼6|N N_p`I+ U]%Bg=l͓XCPqUt(v ]]mRRX-|r4K\P]_tU; UhyXATl G+XXdC DZg4qϠ2 &"CX)%y_ӋkwM>hjΗΈq!L_Oʌ֎29fx1|>/$ @Tx^;Á)`BI܏ ЮW>_o{j;>b{S6\!寶N %ptיxo: uE'$]A?}.9xؖnOTnRwc| wNN͛{I PKBRHa7 OEBPS/ch03.htmlVn6):T!n YM4n;mZ[D(R%8gGtG&A@X"gf*y_HCcV  UPip8 :8Z4P:x/f?]@IxpE n]@Qt}A\Mm6psjWѽ7coA~ 'LE '1=Y|t~-*4LBeAi6sIbQZǜ6dZ9Tntv-/`m,_ J|&\A&%Y!y.y<ا=O0xMWob*כGw744Cp%S] ,ʜYa)EA)$V$ r)# ) o`mqVԲ"gBQ: mgKGe!AKXH0I-] ){۷rVN|Vs[n`U,iقg4LQ,9mRhrə.>h|k֜;KIG 3BuγR,I!D-/(<11|x_`%:CևBU4@'V +z?Yde*&V"םg8[jޛ1P 4a!JH̯]~wb1sh55*ŭ(׽a !zk%+xIzo?JP4a4\,,,w^ W#wAUocqp ?ؘ_ ( `n Vl?cs)ޞMFII _87N!k8aC`~ v|f!XDwێX LE\>`$d$D1aie 6-Ajf.K!20v6&$t&1x]n-WLa-rFTg \0ikb:pl}A",zWEvwGl͎Q+I2:b=]2LNr98 `P%Vj8K8P=3 $V(_wtW>ZT4*ƍCv‘,Ů霟L9QS+ `JI87d#'|9c\uGJa k5aVK{7\9Ϟޔ=.Rߛ4pΡI!x"zB#-5!ًz4Q5A\!{T4?jZʡe`E's`){a&~[TCVqs b b-fKpoݾ;I*H70全 P'~ [)1 m :(޲26`s/gT*p۾\Ga~bRczZBD RسHb P)J_IrqĢëpE>x\1W[ AwFYN{e 0byҷg/bUȮDbawHk) ^]79*Ï Dڳ1-ؿHOtgsm rrat;_ Wce~kP^ /<8F tK7373c~lt3!m.7Fw^}rW/ _l/؍hLLq /=rfTYKF7~6?!\2G~w+DqXfBJ^wUZ_ÏEy_V|6-;B h/ f[г%Ê\v%CЊA|?:u=TNZ{ĠB%" GLiv&?ƳsH-ή?ǜOfx\C2`cηۭ{,잿9x8@{(x)6Uv@pX)$ Fa*THp,.%h%6Lbh(SzKTh15Aϴ~5Lma"opG!c뤌Dn DA ǾT.Wbuwz *7roiEAj f( jQh5`?|}Pky!_f4rZ# =u{~pDd:.E' |? {~o#=Ut&E%4Ijpau 5r\ȩeC`9U֤Zb0OYZl . "La],ה*0GQf(Jyz/j=$5WT/Vfd+m JS3l9L1v/E>59Yz#%LįZ"Ŷ\`n~X̼J,.*p޵ҋYgi^)h/'&j;;z޻Nl1:%KSlB^\qhN~DF3YZWS ̣mY3fzPFɜ{4YR2:յpl-}sr1<1Q^t2x# &AA1E WR s2"lљ, i1c78f[!Y3 (&r+ϤҠz);J!=3nZϸ- @P5\ʂՂ+cO/ El Pp02n!Cʞ\7>Y,5sϴMc7ib?(^ CA_cV  Kg"/ 'u~)AVF)4]c aEAQWӕD@#EYaBD4o _ }nxs`RVĢhL|o3ZmƵD>R¾l81^﨔n6MaemTFǣ $5f+uDNYxچI#%jY8* Шc Cެm4M#.j]84 `x>Ǩ+f[&2 MKgN6679Wkq@|7o*tFRCh?_ 2+ı[?T)F A$!BG т۩}j(fKDqp^ZpV08 /}v,E_mYKxpԭ%o (NIaQ-+eJ$v쬣јfzirhĹV]:P菱XapS`I5g{ ?dhP? %Wlpg(ɡhG;A7> dqRՉ]!!qݳ+H" _{k5"4%n n9]"=pqU 5J# {P1B2kƾقg(kʢM鏣(к(Rȡbvcw:2Id @2-4\;(NOiz1_BdiCQCԾJzOtWzԳ,('UQwl: (I i_Ih .BC–o]KB $"O{P*ᙔǒh$lExi> Tj4>/0;UѶJ8Jw#É4cݝvwwh@׺ VJzbRV+$w ؎VCΨFxurSeWw;yq @{X7hB Ю$I?t~jp@MLɲ PKBRH!F<j OEBPS/ch01.htmlVr6=K_)KdشӸ#)3V3n=BJ8hZ|KHuꎧ>P}xoR{N=OU SJ'77 8/t)8OI.Ƴ.W~|7gsHYy].oy@Rye]ץm={@F**r@Lpk2-[B\+XSXpd{uСRJ-NvK;c\ ϣl62lamP֢oVb7Xz laY-D;eCښRC#EK'ϤVLBZV+8х"sh4vWl@x_!96T?5`^9jܶ6H K eDQT=^-ItĝDTMi:(icKXS^D$H2}xDHv=Fz}{JQBd0y1x _9OT/Mt57j$s;'Dırl=Jގ;O,PKCRHmROEBPS/apcs11.htmlXn6S8 lhSC֢6]{-D"Uc>DO!EO%Ρ98 }73t%'sPI1 ^@@2c"_&vD*2ʥa d>y3h1) ڟ}9<=9"nh2"_?N>O cA.b/UN>`[Jepv2zU@k&^jRFBBٌ?Qu5,917sW$N*%K5;5P6h6]*59.C\`a EQC wzMaB8zTSkÄAn+EŸ 66d6X\Y&҄~-ۆnqyzvlh!eU7$eSmjV2NZ#L>m o4 ZY]5Un%ͭ#[mͰcr$BEɦR)64(~_s Iw{Ŀ} Oб?z9uWנ]b6_6oRnv*P;=n4%rakRbǮ*noKR*ʼV Ɲmw,2׈$eRPs8SG:RZ{>GțJrhUr2R+"xnr%b#uU{SOς2_zMn~!W9gv4Gjb!^l/wK!PKBRH[] 1OEBPS/ch02s10.htmlZ]r8~S`Y`WI3ɬLϸɸbe'ebg٣I)؎jH uyFnT\`Hx1'Q DFA! t˛߮ޒT?^^!A?~}&&gϓwdQX,Py4D'xhB6,z.&:cs1E.IdrI2Fv0g氙9+0) (4+(8BF>]_kq)cZ^ #q*xgTN 7dttHsxF OFE *vm## 1A'9s^36ߓ!nLy Qw Nx ך]\ UIz%-ˌTkcEb1I"\fXD1MČlpX>ֲR%RF\Q*%נ>#3f#uLrK,`1ӌ8m"[ Bo)WN E^ ‰NƑjVo1), $W&Q% EfB6r@')6Y&8$ fԚɀTza[k= [37~#!*u& T@N[ζJSAJ!m]FTe]j_j9;9RT^=l,by!l F.ju%Fˤ pbu7j Bf5էE3HɲqH!4"=(f8 9o}ܣI qdՄS[71; Zzqw).NY۾8K\$\8ikEJ~8_dYrl*)gw1 ,HZK1vj[ 63^`E-lg-tHm< d ?_CL9K7Bw S:)kHUO?֫jgS)7U5pPW 8jKyn=p p~=좴!!yc6,6)AAKZƁz-HʌƆwoV;DH~MYa.6-;l4`IMxJ< .C[7L M)qs(qIlYr4R9{°UjB,+bg/gBiQ*-@ff֙`&RuM'L9VRY*E+e l3 UP(gv#O;cr+qC4V`vS!DGhL3ߢMjv6_j C 7S-=djz4BaQ-vԌNϣBW#-*%-Ga7TKx! ŴmlJd_闫Ɂ# z۳qvnnlrg?;[1r;C 7w4Eb_N<߿wERVؿ_A1o6W=Ui´[󖹚vռ@\ʹݛ@t|RdΠj!Aϥ^慃6ل*[r-lkj٭F^Ey&u#56;[-|b;hkѠBuw"um?*~Qؑ-Uxõ* m`l;oW6^W8KkxasuͿLU^Fd)kJsg|)z0xݹoL;" U(m(9O=,(/ { K B<񝩳)JvL3魄㑺*CrA35U0l`Hh=&oq`,*LܻjpE4 9==%%]aئNFSH^[pT;Petie_:`DŒ\u7%n.] Njp]ï(OVŦm?+M c<\o9^Oo/?3o<zނWF).WSsg6pWVբ|rg {{ئծNNMium}S^1Սzkŋ OiIF`GuL1].+o{i>":p 'QT8? ڎΰ=g:{p qh pt?1µVmCznf'{PKCRHn)OEBPS/ch09s02.htmlmo0_OqDi{@iP׮bx+OrKbͱ#Yٷ眇ncE|wr_$\BIJu&T1 >-*R+JQx~ JG>^ 3`|9oo/ #կ[ Ԧ`ˏw"0˂$n-I"ϒ '19W+%wTN̺BA Th&T+MNOpn$YGa$f]n8אJnbRvAd@ MWQFFAqŶjȓꪢcLW}B> Px#W'EcZ ȅDXa&HkF QmLFW 哘yS=찧h&!p嘨'b}ޞדl~4ݟ.LJŋA4ΟΎ/"Slo^No{fW*P0vJ1Dn|Ib=÷TstHǸ;x]Kvf(0XkzW? \ o@iWr0TnAĬL Cz0B8a]N! ` 3IZbz<!.QuK6g38>W W]Ϗz<|-ɭ;ݛ"ua6iZ_eJ =>s!hs{X/ s4^\6Fc4BVT;]|m)*l#]8Р=]_/PKBRH?~OEBPS/ch03s03.htmlXQoF ~p]6p\I֢vvog9 w';ޯd)uwúpI$#?~:}y[(ؠuh?uj2W/g#p^L("&z9{47d뷗%ɧ'IrϿ.~I֓}'@fQG~Fr yߑBS}>5-gz09K Kc<8ҏZlɬo})VX@$:G!,b́v^ F)G \c-**g `adQ9LcK媢Ot4n" _9Mטv5}8 HҚO H(1^AWŒRKk|>Mپ47NđT fJ:O=7lo6Ag4U u5{xN%SByҦQլa+օi8nYŁP]M1膦5u$% O@纖Z~Gud>XS+z`#ZV !lڪ#2Nj@qU~p9_Ax`iPaE.Ň# C !nR\-D1WltQt1SdT;ִ4kJZ,pRAhM9{_0Bho1k%΍VPG//,`>?+(2 w%iz)2lRqikV3խo cꉔY{]( 6:}?h2zm*ǎ%&E Z?SZM;Jhw+cM rkuc<{=} oPKCRH;jaIOEBPS/ch06s12.htmlUo6޿/n1[KYX j{k?Y"F4~G@!Mw޽:ɮ,!%)mu߽]]$JN,%gwWwPۿd%/6ݻ[L $u/B2%WGqó,Tܬ_?]^^Qȃm Uߊ+Ÿ7$XpZt2K$Іu џi{ 5b{|f(r1f9\Fz Y`k IZ':CW`Ly;o侕vFmkt)3)`.qϧ.OAYcz (9hBYhx$b aC`PsEj4.G*V1v 9;s8AQsՆspcA*frlZz9;6;\b{8 m .'Оraxt_9 s6󬼑%FI8'}.LJi.x-Li>u3Psm(|-艑A"T o99}ƀrPSh[X9wsVr\xMgD߿(rִ%\gj8mUIky8hr&yh6$IsR+~n&SY~g~'r+UR<7pPa瓽Gf7{LN,gwXz1jO7[+˄a!к1,k1bUSL{ʔъTdZ)J[z'$ni-EM򱴤J7L ؃`JlˡVrj<yAm hB I<ڙb $*=,PA3vnZǞeYc.amcNiUEń,D8|N4+i-$8d SVv]tZj/JLe$5mō0$5˟>|>\ݱKZ2Qr-6QNx{q驾wd\3;aEEŀ&Qjt5@tAsCӖt#$)0u*MPU'jHk8QO{ oc#8_̸z*P UQ_=GxQ< <ӵ2>vR#f'\\3sݑHᄷdC%c] :ƶExӽ~y'M[ufMjawVmz̰o ,P/ Қ B _=Ezjʉlgځch?gPqꢊȠ] !3Õ>c7եlnCFm%')( }v!^;ZXᜍ2x|;-w?E "pc0?γ;ǫkG?I3.)EgփOpңS&k$CL2]6 xTT{ygY33 _E}}`1mB[j++s?o ܉aAgDNĕ#4,V-WԶ[ѠN0-fkC }q:8]wqtsP=- Ɵo}y3R-r(l r<9kd}m>/~Quч=dU0]p94\oմ߲ٟ i>A:h&pXGc3ЀNp@ 郰^m?Kt7_z]%ԛ&͑(pnsɵCd] Z$Dc@%Qg_Ot?¾*fBbDb kL$9o?T3{l!I5pf6b}~#'SCDukx^,g7M؆j颫qۙW,H6Qq]G꯯FD5(P)uR1)pA pީ~%p3z^n&ˬ_2}ґHOt 9;1]F=3R1%6l1C6_Cqpܥtnqoa,q1JF#{X/q ?oPKBRHs͹OEBPS/ch02s06.htmlX[SF~n~ũ8c[1LۄLfh€itN]uwJȆȭ<Ksw.uF(9 FgqD$<X&)'Tه#J-O/N){a8M Gax. j5\ ^ډFN>LlDJ/|frŋ;Y%ͲqX_snI%\3t@K; *>P#]й]gܤ[C>0J8Wg)c; 6nU6 m6#LQ, l#HG0^i|>ѫLܘE!>UI1Փayʄ5uL"jujke9͐^+MpMpe>kh"c}:W>_))~ *!6կ+jw P8#\NjvĢXiNpU@t-J8ȗ$}t[UG=nݻGĘt*/z`?Վ{p.f jWv"YG%Aŵ,dդ붍z*COú37tkdu)y`cϦgШ#ϯ00ct7]xn/XlN¿҅nY(}Kk}?YJƾrhA~ LL 38 U!^YuVf ]l7C0nRSOr[ejʼn;GJ3L`ei*j F,|) -߭ՀoNSۮMr|*, E60^N?;xo>a΢MX:h>zfct.խh6Fp^: rQ!_}z6Y߫{ۚ3uIO}/yk6Nݷ?6C[,j6n|]Wlp<Ҵr+k6x>{Yp;{} oShu.5#tDPKCRHŢ]hOEBPS/apas03.htmlUM6WLyZ#l#)h06=%KI٫K~{ZAŦ>Ȃ43o{Q RGpUR:% *ԊDi.{ڞC1{z+J>_!bJo{!:i~KCz>*}Id)~'5>;;B(gex%>[b܁VҪugGt<1BH:f&- kd`m Zy|Jֺx|;cfùwG& :ve%C!/|LfLj>>>^x1eJ42Y9T_;nbu<Cl'·v忽Y S_9pےl<,kS󫄆e9QMv\n{ ^U-NAlY~p0NxOxUbϡs.1){Z,ԬƼ!< ||y_hT-&4$fAH jNSQ ՐoxYۧd`NLuuA[eo rVi5;0*~ mV#+8ІJpH9gu "fX|Ȝ;UmpZs!k&+["#Q1^s%pqpGEË׵|Sެtkp >0k߰!cG03+v· 8U)@3Lf#Q M LzV,:IT&ܠM sn N '`kÆ{xu5+TCbYa[7 ءA·ˍ>l{ g~_-Zӝ?} oPKCRHN*OEBPS/apcs05.htmln@}a/ohV4 R Ihⰱ'U{nC< 㯆7, 61:`wuhD62NHFcaH}ξ\!v=\99r>js>ge')V|W_9tIQ%6mG\`8TGQERĥ(o cbԬi4kASUFPc)F;: /nϾ7 m Dj1t>[5sfbo$Qʖ_~OODVmV;3_*-MRP'U_5^&9SL,3vj*T+MB}oϠ]>'N!q#bŀW+e; =\~,+C*QH%D$ʣ nrTBk,K܏)pGz$,LRykt O>|x;;8H_vTX(P,Is%SӅ\$ڏLyI944inO|uT-O~=>/'?Mb)tc5Iڙ-&.k[X"'=Oh;[>2˂^Փ!I+ (Ȩ ?&>caFϣ Dgt-6ʢ云E"a,z,A8RAyڵ!j?]W16,t=`lfOA:ϛ14$zS#Ӓ>nFuYoS/Fiw(TZ8f^ҬhfCԏ;X?v;BWPKCRH|Z OEBPS/ch10s02.htmlVMo8W6MZllHKckH*}g(mYlȆy8PǶ4VjHyJ]I]$/gNJ4Z"Q:Xz~jGn/!9˲^f <>/HjY6 C:Mf?G9 ~O+W%Eq'BSoEQV;FG,{' ٴ(AMV[$W5<}>'YgS"bO>g'8djt3b~v`N);R='6 _Ȼ6IIG@::m$Dp!`vBkd)y')hk!UjBW pzT"`3n6TB3XX)a@pbv8ސ-)AKT?-ć7M'D^a*Pyz۩ Tm" Њ[-: bÆg!Ϻ bۖT&YgRLNGxULO1%Ͽd@: pؒa#ɥҢnF#SxB񳁐7@4RQ-9zA~%]JdĊBcQx\(뤺u܍ʒZM檤!sk3<sլ&[>h *=ZA*N\^ iJ#[QUᢡrT#ާ$%F  |M+-_.$4eޝVkDXj f>yocPa,8jIt,vZ t5U3 dYŜV`k=@Gu} ׊i}#l?iTT>Tc u}}KU0q#X NTxq<{KG$Jc1q,#kD|V2 HzdM2 GCt%ЖFvi,|ja-y T5oޛ|!)?k5 bCAB,zb.j"fxх'6֮*LL|l2~*~PKBRH)OEBPS/ch04s07.htmlmRn0+<!rp\P E (mzdD" ɷJ ݝUj8ʚpzNMi+eB̈*?6ů5c?/֌m _v)glibt;NtAYu=0i+anfBVзrUԘoH Y* X-F F52ZO&m|K ~):BeHWjT$$)a%ix2/LNU:U9<ȶwP6e',B镋9ok/AۺN? W)D udYcI?P( 9`xJQ?嬺x ФjΗtX< fdHePKCRHqfcgOEBPS/apcs13.html=r8g)5d;>ǻĮYL p& .Zغ''@RNfLr2G݀rGVdZVDP&w[7[Lt}:^o1~X,:ͺp Mux@l~oၑ&gR"x"TA, g HDƍʶX#nkJݰOS62HF_zo:A.2Q ,дLok򙰏ݏyo{3ۊJ`mGFc$lA7=,uNyTö d*'._]+|UV e΅iXW0BZB1ydYv}&=[?Oc Trt6*fS,k抬sϣH-`;W|<Li2#}p4@b*-@Y"KO< /ು.|F< ]7Od"X2 ,|pk֊ln ineGL&$6k>n2N-06Z[݇7Xxev 2L(L%$!r=`Cnl杹\iڌH FXWZ͊M7LȔev=т-"A5I"q3Lmr`@#lzV}"}{dz ΣH>s px beio*80b&&qF)tZʓȀ^A$uKcĝr@iz*P-@hjXm5TɶH͈C4j`u AҌgF#QYjXdZ"[C;hZ.Sl1l/ͤ&?X=1i&Zb&\`pgG} ;ņQ7C gxzUۏk m`A=o&yX{ ?FTJPVu[ӊaw"B.6ZJ4(zV>U`‡{܎A<K&8܄`.0,;m5('0>tr#hgmh1B`M9t4'"D~BX^BL~8 ([~`2F;rf+9].i Rբ[?'S*`-$7P B\s0 B%-dyq 'v tmT9 LvEDK2v)yЅY4b!6G.rѧݬx 86IO. Z}4R뗙 <:ԆT!\рA KQɃ Eo)cˉu>j}w@3<>(QA~$E&ecZZ/o$ZN#Kk;Obm֪CN _ij\}GMDqi D;%mPGׄ ~ϑt? wy~֍6/X 4 ED %@ Y&0 7ѣ.$l;ĨKUV@`/ל 6"'a}>K‚ mNP70G}]01g (cU7(J? bCY %y ׀d,wAiʙ?7J=`iCU=0m7| F"PSVNLl*E>Kaj cAYݤN@ebƗf^%75ZEYB_1h~ZE# -숎U3SuN DTvƛ*9MtzS@1Ṙ+ZS8mz*Tiɬ_wM` 4i$W u],}Hv;?ط  5N տ_`8ޭ#gnF\YнMهC58E']px V{lNESCeU4[XV6x|lLib<9X5Gvm{NC0aQ us[-*@`n'25M$}X3a䢈N`nP7B~ʦ"suݝ{ 38̰~ MH% $՞i=(jaưfȚ]qԅ  9mg|tU4e%tg nKZA]اk3u12](L-L16K@y;7OAOy%-eZ>UG6y /S-j\|vD=`J8bl 3j&;霊6# Z_O}V|d?-O*oXtevA0>5@rP!a-tmTKwα*8i!df%Mbxcb{wl|gx"Sƹ}# ḍ?m(ڶE(j[ ~&l }UɭQ ,%S-YPT$rudOldoU޵հL%JŻDK9_%p `1 `@=cГ]G^HHnNuz518k#x4'y5w5jYSc*n}z].j ㉦ҕ=%@HNZSJi1:vVt:T٣fи/͑?`%mnE72z=s[P^n8.Ux0tY.ljvMd0 - Q"MGhl<ѮtHO*,p/Eٝ0˚YFa`TC!-D*tivFD#-#pYx6Ȱ!v!"I1։@,wQy'qH 73&}­*4v-6 V֋ru5}=-[*+eG>ME &RhV jVHc|i[ _}5sLx; ~ʬGٰ`)c6q]焰]0OYy ]ū~/n eZ{{{{n| k&x v _2.\Ɯ5t0~v<Y3b%:d{;:g×WuNy_F2Ji!ކ N+Zj>T7y8zE0,~]=ۆIa^f )8ރʜQID SXt`- <5QaMbt"rQ͈I6a3Ȝ'x,:}CLhM H6ijoijM #|HHx0?8}B<`AteiA_Ž}.?G/kN6*2-|yUX@R;hmTPY9^(eԢۅQ|biS} a.˺Lc~7W" o Y,>ָnؽ}DV)kCjG2v] .ڷkGu֊]^P]b_m1W@S_f8(W ][Li:I5Ҹn0Ge͜\TjC@+X(7ݪ5~hP\>ux,u\i]WhY4Uf2E^)FVPkZ}Y:v6CXLҪ/1wi{٩Nf/t* líO8zEQh&r5:jwj ldv]n6uc6wzmF%n;m P{UPܒg7v[_^ztZT9cܾn<g; jb_VSn8bi¦zZܥc nW%)ZQW)_1Ѩb]@ I^!**xe7aez,mU(!՚8Yg_;"-aGAYq3kjUpXC ϐF]iOJXu0'83•iZ>/,{3\ tw3!IRي!Gi!П>#iP,F_>9w}{Һ̐7*;KI9+ Jс4xQ 5(ֺ\ݎJ5\ =Y1PUoZSzrk )nx4ګp . Z@/1`g/72"ގ (/ڽJ'QC R%Vve]fnL Že p*'ets ^@={948U )}M䋨x5>LORPKCRHjOEBPS/ch05s12.htmlUn8=7_1$-FM -ZbZ[D%R )+Rm9a29͛7C:\p@mIT.> 70˜JbH|L/ߖ>Aa x`؏w Ɩ%<}ܯ #>@PX[2ֶmؾ ޳wQshO{D^~抡4""=kt&h-4u` a@ՖFaAZIľ8ǬNO=˱"SPMj%iȎ4G|oKADu5 5*#IFaSAބ,rA_j|Cqӝo* j-2!lʛњ&.X <`J\ #pB m*i-^>kĻ%c߼#v^^/8r:^3F$VoTqt֍43R㚜[{ͫRKco{wzpn^MiI!sthUևq|} PBɾ<@*QȬ$N<0KK%IE02>ܒf0w!cqEr5;˭O[,W:cGṽtc_XEaKl0 z-E.(O- -+BPViR%-JbLC&G>?XT(%7De01yB=ѲG< _ф|ӁC: Y=~mG465TU#7V+E_;BNр, siuigv5A.n9VbuSfk(09-Y2N\l=^ yiOT)/\KSlB]p9.Fc`4iuqa˽]v5jjjLZ *<ܛ;qh;[?aeP>[ɇJJV/ 81}[(-vf[#]'n ^?:EUF?UD.TUm ?MeA9Д{wܭ5DӴg ʇkGџ떛|7Y"lS)f{9*[t)S,2VkOUS@Q]ů!'ȻNuPKBRHsF OEBPS/ch05s02.htmlVo6~_qSR,Y3*8] ?[HS'E "IV?شĻwL~$acV _Lb|Y X2&yt6}tJK]?`EGrWq]| ((M<_͂46eOƧۊ,K+tqDŽdkK䷦ o$Ѱ'2P":*lM\+΃gZכ+DބqI4\l&.!G}̚8<x=c 2L9)ҏ1A|3$uljեb{aI;f[)몢B 6Z߆`-G6R!akD*JhO[2 :jq)yb;?gb3L5rF+9'mݸe!L犺k HXз27?(FDt6<. y|sW;h7PKCRH OEBPS/ape.htmlrH)rTm`I.&icj,`8O32Om *VzF|{߬ᕕUVCIqdj(MC^$Z9Jy!}ӿ 0\xҚȦEaE1BбAUE! owrQWrU rR'>qymy5쑪`ʢDYf:nYd/;j(PXO2[3w[V F2ذ:"B\Pg^%߳# |{ݙͶ*Vie)a/e*>"$:"v'A@ ѳMsȽϡE!5͞xB͵u{vxSdkh'>;7i { 7>/ ;GM5n,ݹvÎMA ԠLΊ8nwW"', U|^;5hG [w1{K__nlvI7>/izȹ$ 4F}x=)<SfNB;`!#/0?W!PsMb]9tu?ȶC r SCXO mȂiF6o xM m13Jl?@PE` nhciM]6/7&l^/PKCRHpcOEBPS/apas05.htmlXn6ߧ$@, ~LVqc MZ CAKEL"ٳv/%ٖtqplsyIGnR^ *ѩT^p3t`W)ϵ@C*y2>:!~t|xAߏOlaӋ̹=c"\%@>L]đ)ۻ}]qE<.>Dp/0PpMVN( :_26Y ߼ #VtG$S"qݠY/Y=~ADq:ᬋsy+OtQ\/a"[@yfkH2nl)LI&Eb:DƝBc"V?7A V>z. i&*?;>V`:&LY#H0KєFYaT%%{VY2|LBr˯PxAzg 45j1;b<0be#A[JbI؂T\L{8 _Kόe-#e7StJts5k e,Ѵt*Sad#$В[_{K=jk!V T@^2OW!,| c](Y|N}@#sf{ y%fljtˍ\:*/\* 'L`-y]pt"KdC /|PoV>DjFK,$:$#rM GmК,!( [1*/, {h2\´ln *iX1_~VcIvxdVy$ @ƵbىT^=F*1u>{Z6hf#{%dGD?Nx,7T=IL,$z7兑{'m&儵oEq+-(D~Ќ5ĮRkEZo٪+#NJge<~BvF @0lҋ;~d%,2싀TY-^ռX! kZ]`4os'QʙxtzyVt(`x~eΩa#&>tO $73<nmNA/%ãKƥaOg4_-BLxf\^}=ˋ6Oɤ}n= sH8`[d{x+l-QaAZ68>5vg^,Roǚ( 'P[SqܮKN/$j0xH-M]/-45񉦻Yx vd>+R oJt&*S_[ȔBl|GWw FPKBRHãs OEBPS/ch04s06.htmlVnF}WL)ic؊Q&+r(.vwiYYu1hjwg̙L?KOh,j,Tθ̃oe11WO/7_?BQM-WK=aE?Εh݆ۋPM=zq 0sYHjM 1Geq'pq7`PBIԬ$$ߠBÜ6Z9Tn,uz#|h Dg8|{AH&ZgE'Hb`oY 6i"HTЛ:Q3zG'f8[ :J-ꡢ, ZD@lz _L%fjCۢ, 5C],%=ڐmp=:O i%<߁+MW Tcn CdfUwV F%Y kʒ7faǪ Oe0,dfÉrw0 Wh ~&Gʋ7\尣"nru4}XpSii}(DAVRt=rA>U KKC*6EYQ y?fax; @uWamMPm4[%4wG}:cEȍw&uLg.+ :x6z bkMymN9@KdBAC̉Q&:GGi> Klh_јeer,aˌR)rVјL .#3LY=^Henn_VK6u Q\S u~h&A/C;?'LFǣR`a,Wckq퉤s>mG2!vڨOC9qF[=[diABn4J^S(|;9dtig?u|,Rȵh آa:Pø}N^Cu݌74,M f%.H?vjK~ @B}29-`8f/vDc=(6>N\ 7sno?_0gSIF[S=YSTn(Gin7wd^PKBRHuaNVOEBPS/ch03s11.htmlWr6}WlP36IL'gc9mN1 (E/}iP?2={,<},h-SFFqDR&Szu}~<"Da<^M9Qo):JO&9}MIQ{_LfoNbcWU'vǙϢ4ܴ;uŋƁMfS|!gWƑsI.EQ§NpZJ/H5_FѹIό/4B\JIx%i^l;fjMi!u2h(ĬJ6ۏ|2xwTvuY#' p# ?i5{HPeHZKBU~Kҩ@a*\EU a͜(s4a\U6;љׅ7V.Ohv?W^N1;8$:9v #O. I-g-%[W %LK+%Iku1]2n>$G=COqN7$VQ\֚](oݶ5OjŒО2B6!gHR*MUJ6ѫYK 訍vSXaUqY5oPdFJB.Kz?UϬZC[Y2CZ\_'BZjoCmK&ؘh!џ U pa*cZ7C^v_'W^XrRAL78"LBlh^MM992 0!#-ep.-/WFb t?(]=u0ZPt-A9xyQǥ/1}^ _`ړu"ьĝf&Y1/r%pr{,MlnB,1nŹms ٰ{6XAX FAMށT{21E*o9a"хYZ{vE {͚&S +LFmft&@q7Ɔ ^caӆa}b 7uq_6ڂO=עGӤO.+gPKCRH3]} B"OEBPS/ch05s09.htmlZrܶ<!"r؊v3dԒd:.KZm'weǕ.I\o݈HYt0aB%:j=|zrŒ*Vb>Qz?]^kYoOd?4Ϯz͢Yq&Qo6h,:zٌ4Ԧű ݔ߳t+<][is8Dr ݙ[\05Vl+v,[J+)qrx B[]MX'g:Ak[vi0ְ͢o_FI8KnǩaI 7"۳k/_lp8)2Mk4b31A;Ewx*s\.4-J6c.K]Y'f0]ZȔFa% Zu]p8. MUc)QJ"[1}2~X~-W/L^s63ȸT,ЊYMƒzb|o&UmGaDmX-T)f`+S (6je)ݬ*ԭ\r˗܈}(ji%oܹ%uVx4[n׷q3J'SVT͊[o4ՋAw{}!H 3 ]ԅ\;JwBPKWsn)6$̚bB4K5,8JUEPק%rQ( ׇD[k wו}A3hq+ TtϻVFkڜ˄AL B "כZt$AI>v$tXK8`WD(,1ly=n:y?4SixSnd"ww(tšѭу> RVNf΁FWcgیEQ4m#%C|YK=bscZ%Y{ӳAg=v< "t=/Q#=oy|(2P(Ӯ.LɕsOHȆ/dSm+to#d쎝KAH:G\c#n$㨇 (3nRXX9)tΑ-Kjd.A(.^-BDHXy"(`) !S}m4WV;O5Mij۪4vܑg 7Z{w?Ad)(΍<Ӕmu݊#)_ӧs3,8Zdz'AD%ILU$kCiYQJRZrq∐,LVH wb9bMM[+o9KJV& [\(&;NԁڲrvvXgĔzC$I]* !r_v]@|cy%"o7kȔ"-"HF=ӓJ$ KȐ!~c1n>iLke\"> _hѮAR?OaN+Sbe Rp5dz ٥!4#+jCoe3;ߐ_1-J638e+ǘPvz6ltjtԅ$;QDIc.%n-+eG1tjC][ֻz-|;,./E]w_%" ,uZ6"iMau𣏕~Gy},>HU `$@ԫG;t谢Ǫ #b3<PaƸ2VsKXJ!p=ەmEgKѵeB$S.tpɇW:;:yqqG}sF5S MGPfܗi*?Trm7@m]& J,_Bޠ 5<|GWZ#*"LW])TJ!SwA \.@ z`Mx>&Ea0mJ޾.ױ'dDa+"yAc$@nյr'-R׹u<[罷1}B UŝCmU+xwfOIPl2n b%j05)á4)ڐ-nHKz2 htPGv,}T>=y"~W1gͰԵ":q Q{6R9ҪV9OJ4 !8%bJCkӯ O)דIʥd3YZ uaߞgQ݉Zy/Ko K7Vĉ{ Nہ;(]"'LP ˛7U 3φ?36}{xp׬3|A+/a==;튢*eעI=N?0Eyd?|fŀɊg1OL<dOgW~>-+wo_d6ɫ7{NzLr ?=i\Ńg4/-;~j>*x|JTZoE曕*VlJ>短DYWpKWy9`QU0u+;vQmR!BT/ٳZǛgqr͢Ku2>U ~)=|Y?vP-OaW4#?)-o`߉jSa)Xy&7][gYED*IZ${6'XEi ɸC,xI+o;U(M<)!f&9mu X#/'/7z|+ddqX-r JSjGGιiy">aoN.Je$ErY1 Vzp)~Rla.R a-.6G3bl8C`UQ&x6΀2*\^AdUBT.a}H['0ܜM A4F ߑ56uj=by@ 3"I ٬,#;)D"nVBxgrN(׷:R@ktuSŀ-_m PB$Հlx>xG>k ,ߞMI`h4CWi Fx<{򿳩&)H;--sykB^X:ӔuFraERJZJq84J%,D,6Df,HBOŵHۛVx G6//lE}:c}gerj~h?DE'Vu@ *#\0U2X2Z&.az/RB5;eU8&MA$$/$S^7楝'tv4hd`C]A]eNF2óm`32%Pw+Q&Vg1r褑J+x]8,e3 lL!9[yE@\=2 (RL";ύ(vF.Q9[&Ɓ.Ry="uM_p$"&# |ժ+{UY1Șȃ[ M~S] ܙƇgZHvȏ/ZYQ ?,@`.6dT |@y]f"EBf0nD( |3Gkل& @PmFY5֙brT!dMLO)K `@k\M[Eyd(3yWVYOCt 蒼UR܉}ɤ.]ᦤ2'!լG|tˋڽ(MK"ͬB OJά"ilE^ӈ< #X~l*ǞmZb{7ֲ_aYkD8#E`\6Yģ^|ǽBwEW&fg+#(*| v`8M$*<m|Z硉~E@ HfЀ9NV|Άxٍ!.8cI³B!f"Q:v Ic/yrmSy*`j)')YKUЮQ]ǁ} /o85LiBfr)*="H.ek/Me0_`逶/ {؋ M<55< Ås+[/8=D bk3`8 ķ|*&` օ[1s%6v|>7ܙ`L+ S:N( !osR˲P{WNw]l$W3_R1U^( _B゙Ma?$FW)elsJQXQ:4[/K)yYx||ȊHy_ZF?2r63-@0(q\yL[ Ѹ,s$M=v 5Τ.+ *A D>lXek~:DC$8g<@E~kȄ@Nʉk8_=˿l ՊVX i0, 余 Rxڕ'xA $:Mf: q=s`<,-%m J6o%Zs^n3g*}QWIznD-ُWzQ#ݵiwqKCd:WW~l(n8FmwHyqԎaBO[RŤ[ A5/td1N}QyfQ%Jp~V_DCQ4B#m%~`8}HVCUk|n/~"仓S*(%CK# wد5+bbb&sb+Iнͳ}6z=[Fl(V ZgݥK>{}O| vfnMهJ~^@2lRνr(<TDҙ7vuU*FcX"/U-ϕ?Pq0cNYJ2r2#؀~3VXnw@Ai78 d KՌlq"pE(0(C@bcPKq-\Ef<-p_~^ ۈjVJ2nIHθ4ۦ`GO ɳx'THS$$ YO;`͗a65ӸHXnۄЕ?LB 3ٔ&+$-Ѹ` uW41UlY6Rw7ƕ}na5R#<ʄi̍p9t[v%2C\Nt`0;ք nw;V7}d Hhr ܸb+sv7ݍh۬/W5(Tg$0jh5:j9eHtH<!FK!N$\ժeN5UL(׉S8(K6I# u@}f+0SuR+<}6)I}+lcf_jV]w~AXUA]w(.g2_{ eҖ4s#((Ax}x<$+ pw ?1kiZ[c``0k0{RGJ„io(7hsE[]?7@>Y\fi+ߒJMh#&y {cvŦt^ 4D~NSg;y{e-Lq6EB"^_2=30y}_|xuw<봕g ' B7¨[?O+UuP)GE6Ԥ\ClR,%3iOUMA׆`ҋ7 X"w}wqA.%s z:Yg*^aGu .s2t;?åk#Ɣ 혔4 cuI<^Ü&0ojA+߈GQݰ=j}nFIYe(h v#TtSݹP@BH\u(:yhv2'AMHvєb۰ok ~vl8 1lt}UVX e4Er]܀On^,%.{ >p W=zv-0ϛWX\6hw&QncjXT`|uĵ׏F?W鱘(x[r}|O J)/gtwIVx < H,=.p0@C]EǺ3%b/)yκ<}33خ n%šAYgQa"Y]\wxMȲ(qSQ9xQ%[x{וeFwsZ跧y+W< rob @BNԇBVb*)60?G' ޏ-F$ӣhdQwTO Vb l$ IG]Tx׊3Y6hl&v$cLy9cXőeKOw.?JxqA~uGI|Ԫe aMl?UܥXͬ,fԖdo ps-ZK+(kȭ(]Ui3fse6L~nwO# xH^x7㰮J(/ ƳM rGDڐuc8 4Ж񗭂i>iw#jw}fR/ |s1v`43; ;T=ժA{:l: =H`WMD u҃/zF.v0WmW^`{iS)ޔ@7)jV)p*S;ag#icBveLpƗ|k|s@DVU٦ˑ\5wE{uZ s:K6qV #c֪k;㿣3srE X)Dv08&Gv]Lfk +,Tvq?GJ[{m̛PV抈#;>Irݷ@Lq1Vo!2ZFHS]jpp)+wR~.D v!4齒ZPay4MS{ߌ; 4NCPTm*k އ;v(awg^yA; m \Pv1J;4T"֚cd_Y wMA-0n,;twDS =}a {Iuys4iNi+A5!Z9L`O0"o`:=AEz^Xbc%}1`6Ju9zK̥j,s&fP)w4nobJulId\'1 @,t0gV m|X ^;#/ 66zj?:Pz.M6XsL#S^ ӋU|yuy{XV.3?&@7);brw{Rs7/"Ȯ'_z瘉9~╄1;6lȏ1т,/2OntW|tJ){ǣwA_1Ť:0Fjit)[{6-!'hzѨl]լCÎ:?-vFpL*5|:S0Y?7 6e" 2R>{aSe}W{;-Ώ !%_vߎFoԲTEdntL~DlĪuhb]{ ՛LO(ę:Q'~˔}zTK  "%\AkVtb4֙6|&lRȊ"0 tn,n<)uA.DJi^u~>8cF@B 1Gf\7Z`;٢opղaÇKjUq_?,qS;/ƟWq-fv_qA]B0M*u@DZ@9-ҲG GɈղZ|ᯫSf]V]wsa9{s^Ļ9wsw^iHbG7IA6!7؈g{YSED QY%2;y>k^bN.X~Ts-ywu%} ÆA-5Ɛ;E4 g3QE3M3Y+]eݢ+g"ztO"b^rV^p~}dz69?PKCRHlƖpOEBPS/ch07.htmlTmo0_-n4Aڤ-oX8u7-etl$IξyF:/42@]R}Z=8bХPFi^ɇ)ԁ/?8; |=[4I9?}π!ؗo6dsˏ:it}'e(Yuq ǽC<̳ |^ ޼HnoΌ2Nɨ!ufD3ޟ h5jt"Ǡ0:3vb7..` }<|NGIx>ʔ<+JxB]PcՊ5a'@3lJuAc[2ЗB k,D ܋Rg<:s%KGR PPt։Ã== BCі2@pB}PmTXil34J-H;bl @!BWˇrS%R._zw}t@zڱR;} <<%yxT,p`2=-Zk)CL#RW&`*Բ[X=@7ӎGb_\Af݋\0\_/! 0z偗S^a]A}H WoO<;HM/azv4N݊,džKY\1'Xb] 4 +(- THA"AafR&/o_[QgFQp> "/ak-,=6W| (F#ǧp2rmzu8&dzԋ$uP@2|R Y&sDwiX5*`-d*L6)T{92,&IHjn&[z|]?oȘr}ϓ`BU?iUI20+kvu=>Qz /&p}vy bt{v9it!{b[}ʑPnˠ&Է]Wr?pхF_ɺ!(ݝlpt&_N|%1 ݄E{+dv@`MN95=G{ìKv Q{͝7cIR@3d,t$iP"CܮEd3t!mo?IzT'wo_PKBRH[* OEBPS/ch02s05.htmlV_O6O1vWMwRfs*pQAdvؖlŇOq{hY'ǿ?doh,WrN(KUq^DW˓^1Y1$."_.A(y(Ipay~i&ɻ_"jAl6x:Vf,?&w>ymUJ,dtiQfkK>9ZD\B0G _5mSڸ~t}/e:iì5֔8:XP Z;-kje9lU օݢO J4$1qL) " Ӵ4jh,9U挢Ê"Fva-ح6?@bMJg;,[ 0Z4@CPk0/ȵm>$*R9(\+ib'@"MRh $q2H;K1 +,,b +eP=x:9lH5ސ'YhVސ)?㳄u9v5- ePp6ĆW+fl2x>^f:c,8TX{҆R0qştb~urYHɿTnl t:j V:M;_DԳ\ Co'.wHs}~ F[R?QMy +KeqG&+ٵ4fCj`Sf[N6ߠ)4A\H3+qVٍ t{U~߿>g y?UJ~FpYT6GP^r.G0R GR韼P0'$ !stE]qp후gx\I~7dzy(%b7ǵ(V%|nr 7yC kp&*NcZ~&Ooi;Ϟ PKCRH幉OEBPS/ch06s07.htmlTn@+_HZp\IRH wjZI=C 98̛:9rښqФViˏg8FWIje|z>@p&>-o72u]yhX~{_E*RA͸_JˮTILrLHFC.]<.$Y $*q0鵵OÂ]HEị0 Dʪ&q 阥QY v#9&A+oY[?'LfAiӫ,8$@@u ֶ ŶhC= F4@-sÁ]3VG NmI6Ro sTYIHlG,pexZ=ڏ[ҟ]=̜zõq¬SD jMz#z)la^+ }}Aᩄ4k[/޾M?O Bg X}bہ9^< kN2$jv ^kPE%^arK0s Q{VhQR9j 5ӱLzd-\M/;v$mɖI{Hp0!jbV"v{ᆞtdV;hf>l)K!Q4,SO 5.#uk,,-vo:V61[(c]_?#.PZ*n?UHHvEjʒJ5:O\?"'̒u["v.\Z-G;,;+)Ysm`ҕ*ψc_ML~"!{њ54ԒgV?١hv{kV/^R%v/vzGuaQI};~FFGeU'iRO|N_X ^|gi:}+nӔߒDP ^iI{dϬ蚹ͷ|>{65BF/03Cد'5,H5?|]'4#2k_-gVDsMrs5HZj$R*&~i"Fz@Du9aZ0oЅf3:[U,<Ԥd1*T)md\v[ɢz@/A18EݝE'`_ VVqSgl0EUk^sx/%3y =Gyb;!xm;*o5W CUp#8t[ Μ rX1OdQ)A .Aoo@2m,qܦ6#9NrtѼ``Ah6/%J*.Gm$ŨNZrY! eE$gRqݔڸf\8AK(dM>Sý ȄgM {9Z~ApH-+ %rkb;[MgЖd1i#[IP^w{}`q OLWe-$=s^ z.kF^$ȏJhTmy}`[ӠPȔٶ! {18vxwpڂXvp-K P*z n&5-j{Ʌy -yfۮ/ZM!MBmlzuuLФM8 4v#'j[2c:l 0Jp5pY @ +NGR`i fT%yp];a,,FJqicB+*wjg~@cWc{k@,g;o\5_Ә 3>\ZYyz,n]zG36m_b?ȷm\\8o/Ǘy|CpGadMR~.8 =<s*Wα'X%0;NAϳg|9,7LsAz9 6Sq+W~8Aŋ!8|xlƪ;0Żh]٫2Mm UJݸl5 tN[lVoPl7vutL"+cѷN=nX$b@SȞo7[i7R]$MDnhKT_fh8>}'5UkE]yaO 矈[$N4x,k[$\O jށ W Z6:jc-&P_YLv= \|z .do+(Xܔv3PKCRH>? OEBPS/apcs09.htmlVn8+fuq $bM*8 FY,zDD"(vne)q v S${Ù˪N= eS)O?HLF0&x<}8=>~)B|98b4_ HQ},b~KoEޠeAM#oE%1)*19-0f07 e\^o,fP[sb2+$ ZV.GVFj#3&0]H>G0 Dn8S71q)Eg-s\Mw"zkT6 NkvS>֞ϠuqL('x|:_F[*Gn;+7.kXܧ68[ P!};ɕke*KXkf;Z*\ 0] LCuCc<K* F;7J2Ku}l<0Z*9Ǔ^-ySqzཡseX6 =ήkJ7=Xh1wNNzG_М+]2n(_/@ 08W$PKCRHEZIΡ zOEBPS/ch05s15.htmlYms۸ iF&E+cWMN'I7Vzw@$(L Jֿ.Ic_3iq$ؗgwY^O;͘Z1g蟽C/fn!m4KU`b#gA>v?Va='ˣnB|E߬\ 1zETUѦW\J J1x$!˪d,(VUAE: K)4j#&"cGhőqrE=hl. <*Tk-"EV!G +^'=&_BǁfGdQrҦ,AoO^{HUZʜ̀jS: {Qt(2) O&bH+ZI; -iJL;2lj~Y2UH(^2Mya`uV"lbc;`O& Gh۳m6 \MekN";;?9o/mj/[Ir13xcd 2FLCz cxnnkA#y6թ_d(Xv`2^xϐPrZ.8X/?=+rQ`Dzlݞ;n]&5e̫^[-K7▹Vf[!_KǠoвe߄d.wXH֤-iL7 1gV@. As2cT/z'B/y EOpL%Y%BVޟYنE He b1,h`ݭ]rSwI<75*n{@3mf&(ccF庀'! LWvf< ߸U< } )jzkV0ߪ"{G |{Bo݈ Uc `[U3يc۫/_]Qֳ`'wE`8^ Ȓu/_@x|OoHnw۞[ 9>~?gtUaB3kӐ (cOf~rzu8Lp>pSE>ݙ?{TG6 @|Puh%;ЌNhimPKCRH l OEBPS/ch10.htmlYr۸ߧ@ugjiT֎7?tl&qt:; ICuׇIDZxg\(spʂ]HNFш TdxČ*Vd7?O_Blj-y++_<~4Mx^ nZ}6^hZ ˙% %jnu=bVV({2zﵾ`?AtU a $q4ųi썘t5%70=zݪτ>IwƙLOF`=7O`S ?1fo+&T,PeJ/͹ o yU2hfxs11cҰQ s aKYVeV3{I׈;qV+' IVU(vN$Kl͓ȭ L"\D(v,; v _"rgnJ7Zl6 Ex~OZ)Q2 5\ٕ4vߦ(4H aw %v7oF"-A۟}N$2oV8Err.R'װ8|D WKO(CPFa`}P#sn]CCJr Df`ZNLϪYc2GOD{ 0o|[>ٓnyT7cXQ#ۤr BJHPg:Cn^ZJg=6t^K#PF.nmVp+^}U~-J$rb PER\T^](Hb]Oj}򇞼,\&y9]U%e*`eE |dT:j\}EO jC3\V( 16dĵ@Nʅ_cْ+/X?Կib佀&i݂fKv;pCh9"{d}ÈQ+V{*b5@ݯ~r-d)hW+*pDpTm6$s}_w)"6"LnzL^Ѣ%ٞnGC|d@^KP U˶Uzt-drѱ\-yWXآ:K cT[YYUܫ"E*LEqmcTR%qf3dX|jJ$+"ŞEsR'EK% uQ"k iW_GlڑrwĨIvB=P0$RAnYxhN wè#h @mz{EgU Ah[ϠLQPxk }پI%?n_XQ/y;XL}12o?!ѩò)8-ED7J%/lkt*lxzC!7jJ'?NN?Jqz۰`@ߣ?{\hW֔`\[%URx=);孚(WΌMcy!kc{ktgk ozyC<;vC RBvO~ utRzVz.@ cq/W4v;ǻӷ/oMolHGR6k31-ܐZ*OSP2H@k=XI!]lt{0rtPXJ#Zp]Y54Q}<;-vm5ɓeHS4$H0E#+iC̓U+L]2P riw8Ϩv@A߃.ɕe]0`/2 jPx'* k&uAl.X3ı6Qe*`%K@82ҹkK~Bq~" >.$ewcwLt0X_jv*Ccc8INaf{ 1v8~qA#(}r+V[<;8Mi<~c_y!` Z-J}w p ~=I o,] \ FInDjvnXڬI1/™E@&9ĥoN-t9/PKCRHQ5. OEBPS/apcs06.htmlVn0)&0Avq'<Oȓp8*6zѺssEU96FjQL Ip:;= X/$P:xމN^g^@a)1#36M1Dac*\u`7 6Š .iS&Ch[4Җ H;亁фMM %u{ -+@ ʢI0SvM56 < 18ZXsJnHF)Yv) GdRt""Q;>')ɣsV=A=Y^MU/UEO mZ$˩3?G I+6͟5P=!AX! %ϐ]b:׺Db 7߿~h f%mVV3yDEV.ņknku?!:Iݬ=6Q+j~2FW` wBx5E1@BFLI+QD+y0~u`c|>* PYOʑ}؆{'^am6әڋv,+i1klzV }_~Vw=6+^R (Gs,|\7zTxؒޮwR7~: hK޵V.=h(Z%Z]hT$|a52qw5!l ߐx疲YG/<ㅦGD,U-}>a; * mP !2C{PKCRHOrOEBPS/ch05.htmlXے6}W`JCZum&u;XϘ1: f`/Ks=V\]iMG2) .q0zQ0ߊU܆$B}¬ܚަ72oJWI-rBdOgRukV~4^Е_$ER , \#B0:ɕ9o =(j#J@I0gZĬEBWcۊր: Uď< |V*EtVU`δX7ˍ8_ Q tƐ`:P>%"JGL)PL#cmbg!C~+&n37&uDAU+r-n()xQ0!*`d6ៃL~{'C<[3`Ǎۇ۰n 9ݵY6L$^4` Eq9f1Bi\s+˨Oؾo;ΰ!E+;+ K͓g0=%⺒DgXh(Jc{vF776~% v\zgķaSͧztwR Iᗸ.jӬl)հ B1Ƴ &cdMZ VWsvT<̄{r PB~h1 s0<nBF)ÄBNuq?Ï@|<8ơ/q`gՄNQr,t6#$ل52`]H5 vmM}W3ЕĭoMR^#f<4'Bt3׾|Q^jZPuIND+7KߤeŸb0KgSG}G4 P y<~㷌6r+' ѩZt<;c/{4؅?N?\Ku8M!a} +QooI7~,h9r,e/dxN“6FjqzCЄNX܄>ųs7F %z9$oM!g'/OX3z,PKCRH҉OEBPS/ch05s08.htmlTMo0+Zi@n+ Tt &ƪcGmI?h=dxޛ7oΎ 9e\dJ[)ށT0V寲׋'P{_\8')\_~<4I<$@޷l6f?Z.ȻOI+g7n!3|Y&pjmA tmH֐G0p5k2ԡO–9\Ai I3MYjȳJBѱPGOœO1gk~udT5P'k5uB"ۣ+/k#ńr)4 aWd2P P {g#Z%)?8]ٻNj[+U1D!8 %((mlMiC^5d`P(mIv ;5nʏ 2Z ,oSiLXY`r\Q36Jk0ևؘnmO)b>+KXyXc4E[v;,KU0į6GZZ>Ѵr-;V"!"GL/k*o\<[ķIٯ0:|`2ou(KOmKfgًJglF$?L +M`Y}ǃksjlYp1R7 S/(yЃ(oo.PKCRH;# OEBPS/ch06s03.htmlXr? jG RX* _$9֌h$ӉW@" QYd Er[5х9߹}9]s3)^zE,L3a"a| =>hRg_=="o?>B? wy1asK5 &BċF\`zjxpp.أ%d&9ep(3.(pF7+`ƌ ʣX ScXƯo,rS΍ Qt]dBczGΒ͸{H{c%c!б݂4ZGT5FetPQiCT#'4Ll3y.0;g#ڿj*c|Fv5,Q`ܹ~KO[Ow4^gf)[UNTR[BwTZD4&`= wmLZHAxIޟlaƱ}337q`Au_f< +&L>j~ݑnX/ݿ1ۀ?PKBRH] U OEBPS/ch02s07.htmlVn6}WL>4-Z ƆVAnԛ6}JI_oɗuHI{ƩkmRgfxv Z'%YzRWBfɇR+%J''w׿'o!9gsƮ[Ҍ7$4ޛ+ƶm}jb.,WIǸTr" /wV9=[} -&PjQYrZ-^k߳Ǘi"gC"JYrsay|4>q,{*Gh2* F9z>3~fZȝjōB,Q[tּ>RUg# jA|@-8$p IzuW*H48>-S)TYx8{4iɭpߌ-Uߌb"}^H_D[G|D%ƞ#vAK;RBh0dr_6RҲc^wv (MM`5x? jPzԤNVD:MmT%z"1 nh|*= %"[<|)pr1"w>H́k< ,RIԫUhiK!? ߹cNN7EPR_hv$WЗlIqhgN,)g.H8f~DbS w?SxOSXhO1 ^/ٕdhuɁHS4~2bC eB-Yl%@DWUUxk.rʇ"Ǟ}CKUJ82W\8Xew$g8 >$y|0D40"EMӄU6^/.=]Bo M|]&MpxXaKL'毄 J##lDT#;C&QThHVQg[U:\IҎozX*aDiǯ? {KfG̚m}?>ܵCﶊgiŪ [յ6J--Ue-iITE{s*RueVrѱ1c8D%]$ɠj{G9u)raU>u`ՑYm:m,0jԘxf ktK'Bu+`~(T&!(}anNZyW8Z AM_73BnʝZhN j hGƞWȉ}vq&CAZ*9y.5,ye͐Gh2+ɇar18b0RhkpȌe'^al@ۇ8MFx9CŜ0`Eg뺎ȺOs#F~d,Mui||| P2M k+}»פ s4DAfM@ldSk~ aI1xG4S+i"2-KedW]lM3,8; BZ3uHdzYOBDwnwt듳_~url |DY6b=N$>@ 3:2za[׈Ld%|UNE"  T$;1MpRY. AJwK48i,Ǚ$Z.0y3"+_ᎉP\K~LDcR9΍ -d1N?fbBpյޑ?;(II0lĀ4<LMf JLƚe s(aRxnfs`AuѼe*&yJ30LND&7GA$s6WH0d#H-XL%p`tjG>!bH;h&ˬYc5 麳UǺ<X KSsYSYd,3rh%a˺sm8wHeվx7|q2 D\.r~JVt-@j)w/LC 1G\KXr$f#Gpq`tC_6PRO-m`_xSo *kP*>s-C^*b8£ Ji9KElʔ]PF Bz0(Q(nZ-{,Bi&BG/"& eH1O5ԵoBGbT 0-f)5jx蛏\'}+cO_(eKPqP>vZ]MeChٿVm \Vtk Ps.pU4xC9MDM f pa)$bLcLzBjN :hL܌]i5ݛvwpU>*qINJi@[dn,ȌB /1T@ׅKs8{&ζn9()DR}PAÔА24=Ҥ;o'tJש,i-kKy{63ǩ:IPjDy 惽$hFr~j$n1D֭[{VQ~韪e {= 1#]c&>~/"Ysb# tŵ=[!j߻ཿ O2.~ O!Kٸ'Osw~s7zDew7,_5:c5zFltퟍK|C˟~Bkrv3+rx@fzHl_-  ]HNT%l C9<泇"FMDNI+Bfavǡ3JgA}7r{O#Jd *8=,NTLyy tOPGtXk,e+`uZn#PxFWz ٨jYgD3ɐul_ي*kOS˭mEIcKCK Xa ͔[58EUiɛz31lN{ұA"M-y uoX~O}e5axhs`|Դ9ѕq)"/Eu0gc]x[O2_#*J|>-DFG-Tz^Y; On:Ak).E@Iά,V+!"zYn: zj!Q^.}S7ߒ5=}K1xKgkF]϶^Lh6խ= IĔ$7\ mB==7\݇n^=]toC߶LZA]4K1הR@LDngל@Om7o6m"V]CkoP~k\*zVjYnq1tWo:jk}Ï;PKCRH6 &OEBPS/ch07s03.htmlZr6<Va{F!-8EN#QJX{#sfA>v^=ǃNdᙇS,Op3bW(RQ ~+$ cnDH" P[$тHY$NiG k ՄJFr*BHb2^mZtv`ԸTrpE<ٟX?lN'qi"臵hYaTUL&'64u{%1 pIF5J IƔv pNr U\HX6T:FᓓecQ1XY7)J$ 7ȤloFP,"y.]>aʼPP=]V:TلK@ PPOKiC&~y뎡EdopzC}4nMI,9=GژWo3vHiJfa/mTjRXЌiL0u vF Ty.8oomUl-em%xm7 !wL I%v/3l]7ڏ[MEjIcjW Eֲa:Æ槍k(±ypֺ& n!ؼ6o[;-y +E(kuge|-7|.i 6 tO4UD%=?ZC@}6@FR&\ 4m3SZ@lc.xbڏV oA46|eaxڹg*jQ^l (çeJ۵+/$HBUi)oYLWOTqs*[j gKM+:FS+$tBgSRC1jlɕFw Cӕ,`a LNbQ* f& AJB.@jӹ=2Hټ؈bQN{Yb^plC=ԝ퀜c(0gPC~yf+\whҍV#͜h,oxw$JVuƌmU<uضFjJvbFcTt{`rSxÆPnFQ"J@YNv%Nqmbyzw|>9~?:Yk&r\?ɱZYf./N?W|zWV 1T _ٳDա >d8PKBRH OEBPS/ch03s09.htmlSn0}+󰭴7*%Qn<:jbGd7| _$)yp39'ɺ*aMޥ"+nّ@iUzp^d_?o.ܝ^]IL9__AR^| QAʮ0Rοu_}4i%C_BBi|||-询YBJ.+&d]:UϜQd}"W ISZC>;BG8ũp{)1D =EY"йכ,vEXP,|0kb'|TQƌe̞ɘ 2Ěy``xvH`~#X` U S|A0-58Sۋ<^AӄCPqVijԆ,E[N.:оi?Jd=Q01 {X \^%V>LK[z=ڗ, ` yl=F_ .^SQwmg#`0>Y_}D-H3A#ZU]syoYPQ%AӺdծN+c6@jOgɠ&VlrK ] 2m;АܳsM<ܷ[3h疡pn%O(PKBRH<OEBPS/ch02s09.htmlT]o0}W\,ИB:ֱ%c[ͺh"}H{}=>N1p!jg"M^@[Rj)DRTY\ Itl9o/>Ky8r^ HT/DMOnvP|iIIȳٸ 4=99RTe&ek!Vfr(e V_Šb۫ X#Riu grq] " XP*JL*NS˥Ж5F?l;KѨPi;7Sx z*vk]kϧrqojdߟaظK H7kD@= _#k&yV$y^xݥG5XXך7mc#*ax_VC|gдE @c8p{ۖPKBRH>bOEBPS/ch03s02.htmlTMO0+>ƍ8lD)*KK&l,OO; Jspߛf):8K~/vev qqdǮoMArZ^[n;0hS1Jr6&Zo!6;'7UX:+to/PKCRH , OEBPS/ch09.htmlYRH<Ŝjl C@@-R\vkkkkl9$nf}ȳQI{fdlC R,{!M=8haP<nͷQf1MDƎL?v^rs32@Gf}E)i(:`u~E4Bۛ[-$(XAml:^C:<<*qNX7fns zфՅd!8c1lDžNtJ5PH'L#˯2MIFSP}2/ 4qp*'Bܑ_>^zƴ"koVuڑo Y{2LVԠrӜ1ǤUy(q"J G=C6OC|s'DOeX#=ک ( <h> ѓHqpnLNȆvD;!97.E#Ĝqמa8SooqeyMtȀ{ÄQك&Yd0#Yq~Mjml "MApRd8#w jlrzv$Cv,Y܎໣'"GYFΉ g~S*Ҥ4zJ̄nTML i YZ,Oсa2ӿ:kG3YidQw2Ǩ 2WPȔCL"υd$LO#Oqk8 }e*uT2$5gXd[ebJj+&!rY\ R c)Yif*eúA%g4W|偲~E S'ԏ6"~ސVlw~ײV{Jv{ov"XͨW^BTJ#A`{6P9.i⿳*K`+$Sr6ĊI/O87ʄyᐡ{%^CčCh@0/{`B#8M%dn?ƾZLZJֲP Uy=wTkێ1v p3sPK_fw[o}my%Mm &hTVEaQquw*nVeCsؔcZPrms {*9ƅos k`W'7ݛ_^4C n7RiPn9r  $ _p' VNpb250E:Cԕc݇S7M!¡0]ĖlAۢhFƚ2,Z̔^3g,K!8&Q[U 6u2Z)0)Ԍ tol[ZshJx"R7:j1='-0!b4npMlAV-KJ?Px'xl4_Λ0~LxHVT^sPH $^pk^)=KS4e](&-EGퟛ񧈖L ZgDER7*3l&0;yLpg'x2ݥM-dw=bKJLʺѼ-lƲ!Ob0'4Uw & aA C\.7uYLn^}wWo"˻Л_/CA:4n\gj*K4_k8~ a["8 cE Ʌ2ȥ9s51 `~ۊ蒥J&+##.^f}UB!-41&k%e m H- 蠐09CېyYJDvuW`"t><"P $ }D>F39kuf7l %9 ^: ND+}?u ^= u曡SBr yeR NA+0L[|JFkY紐mpu/ϸ/7XZi  '.1]HXEV%ŝ85!m2{ 4e] C'1m]wfV8!{^n6=eJFGEw{x%7=9v^dGvvNtw5jzlJ%>wo>\~8_?<+a*nBa㨽:_#a6MYslo_s :w KF>Zvj&Vpk*{N8&<]_i.o91!PKBRHR4*8 OEBPS/ch04s02.htmlWn6SjlB0d`[ܭcEj$eǽC $=Oli1 I@!H~$y{_JؠBI@i.T> //o)ΤV8 ަf7_ (/ޟ_ͧϓi͖3 0wsYmp{jGߣ{/^_ M䛲'DV_E '1eÄd+ uSf IIJt +) ʡr`sܺD[ : Oo8$jm4ߥ $`YSăs:c $ '"|ޑTK ORͲ"c*l]U8ɹaۡy4WgI5m!#r)k)Fò*a$ },5ljv tcz"8 G:$x? +s./-0`Et*J9kݣa#k0R@0?aQ}z kJg 8nN bG}~(1VQ+H$(]kHNdhG T&kD ˛ >#/3^kWoXY$I26^[4^/hpՀ>%5%KN=|ރAˁ0uXh-$LPi]i/F:t)#|}[]"A蓡qd BW~]_7qXnp#s#Xhr~=1,g|JΧ/ 15OlQ8w%HZFfL2M ɔLXe/"?sYC>>}6%d.Us~M2A hXfGItɭYG1=Jx~p 0 A-8bm0X-#Ʃ}~CܟϸdSYdT+%Vˊ C%ɲCnֈ޲2M*PijZP V@AAa$D_jY !(`AC@ѵM4Rj%gaښ6N5"&\Zs!/d jkι-l`SQs!ȌK39ZXL=waDMoV dbhYP.;c)A’yԆgk 0-,YuN^=@*tbKdm deUP ʉTv¿f7߿*aA#,lQS˜iFBeT<ӪɃ8+2äz@}Nv+ 4Ed|=0~"mzPNzSiIOUqQԦ\d?=l7[Bhl>!=3:&m1Dz~ö>~tBX=Xz`CFfTkpLM]Y, *S^E1큀5r:spz* n!d+9JYo w!U7 F kE5ug0ԙEgxP(p(:΅R_ 6.g=0^3@=1yA @GQ׆h$FΌz$hmUIgb*\1mwNhP2]7;V9g9NB[a;EgN7d*qm]&gs 8ը+ƪ~]2mmXsSKlu(g x#?U/z|b j՝^tɬ Lb%Hf1Ö`p^=Lt-tA {-4Fػc>ɳ݃trJFYqB#% eX*Ty-!؊{rnSΆ-Ab–g}k|GwĀl'h .Xˉѣ Kг6 -X*l(f2_vH~,'i7o[ף~[[1@$n v6@  >1|wJ)N!D|i-@ٽ? S骁\ٺڹx''"fxb@gھKmf3t nFbvпB#+Yb), ØVeϠOm,E?{L[Qy/mv[ ;,nږYo[)rhBGd xLژEC]מ1B,,8 ]<%5Ev 8צ@Xc 腫)B @H%)jk7 &‰?@zlҡQd(ppU )CsRסSfK[ KDZa=fhKRcE ˲3DmbNomkU449?(Le=lԘ5,^LƦN",P1ArOVvRP=}Tw8B˷6Y,6~ ⢡8űvN [_PKCRH% UOEBPS/ch05s17.htmlX[o~`pH:Z8āP<&9,ghY"ʖ‹>4@,i8{&(tAGPP:X2)tR,?}~{q>hg3Åz]~Ndm8t>W-wLPBv=di%_%{V٘k.lDJC0"26_R/!+E*3riuN-sZ_o 1˘LDd^KS.P݈  lvdfrNq'=3)TxYBXuLG[S0XžN"J4oāJ!\ͣ{tGӣéxhaQ-:d˴W,2𾸦 D/Ŝ,>Bau T _mHNSr0FĊL(#BUL )Ju^)! =1(rf/[JLѭ˝>J{>CjP4-婴ZquX{y#U,1QmUR";^y+"D}v$S1 xܢ|sMj`5+fu 5ϕ] =8@"0QLjBj> ӕU1#<>CO$ӬCiRBk1oДs)yBY~.>p 92XiHLXD1[8 j J\yЮٯbP=$rh':UǬ(%x Si. 4 u@*uJmPH*ʠ%!ם|Um>\U8>z~=x2}y짒rHtX sEN\6 @yWGu0q*lɲz))%5aNY,bLԟjܯOIZ84|+OpFfb7,bd'~=-Gih~j j*9b)2`øY\i7gAMg0".|8Ѧׄ`sLP*«fU1zC?y7V afM4^>%`rZ iY N{֚Hr? GbdhJ7qVrZβr" ic-(pZ檌/gޟ7Go\5-:hF vw&;{F-}55ZyC0* 0ø.N$\UZ?:ܫ a.XU6}Srh:,ь3cr )'׫YZ}QF|k1Ct9:8q#f9^$0 P${ ahWW`@ZK.1l5 X+bg2Ŷ!"b1@;n}ܣ2@oTۆ]CPVJ>=0׾6١(4tיִl[ d3ݹG 瀲ts:j:}1oi7XS(}VC>,uc=c"dh0ɸ.qZ+g@ sWiPW'zŢz%䵞!܍ ,ɬ Ya*v*")~EFG,H%+EKɻ8U'E>0(#t4b_\ySb)W]׻\jª"$޳Q%vˇPT`z9X:&tPKCRH(JMOEBPS/ch12s05.htmlW]6|ϯ@(y}UWvٛs b( J $Z`zzgA;{[m7_Ul㔶=D*iʺ/_D_r'gu᛻~yR?^f[?D8/c}-L7*jK %tŋKI.hhYqSȏ|%g#x[tΝo_j(tD1n7>lzg*PգG) n{|'V)fR ʿݰs8k7s] )b:^F:7% d8yuP8\Lyj'ljhz2 #L =jdImw5؋N"3rσwG/݇Nˉףȋ]N\*V(B8@7kяM' q" CPn`N yvZfW=|LG;i⒊ҹia1Z^N\sd+ܒcKi#}Dx!cfuIqX ?VG-AO'5޻Ral[ake9k ewMoGVR-)ݘGNIqmH-JZ0cƃ>񈳈&s6j_Äj;&/?H#br,j3pG8}3#%?sq0ypnR)5ĝ]A 'VlMnjX(#cgP2Әˬ lQEM̺[FFd$?f^z:D-%L584뤪 ^qǴ:v"dӰdIQs q4 "%Rj89M>8yd|pįyٰ\}QӜ14& wj Bj]]Lph /sy\92s1v3C:1ip *xY$ШܳZ|^t3صS|}J6qI])g-_QtӍm>"0rYvpRM=srggZ_8&'&l&9(_P@AZӕm<=[ֵ4R>tf[ ~]:YS^s)\gVwDb#w+;N3 ΂*LͿPKCRHD0OEBPS/ch05s07.htmlUO0_q˧MjeH4hecIEbGKډ?~g'{/ BiG@\b\ξ;he+%qH[ɻP?<8=9 d!cG#>;;8;@P1u]mG-[89M%nRO_wwwy&F )G'hrnܓj!+1? &5פ@-7 SҠ4HeJ)\UD4~ї(X>Wi;*hlxUƣȧXzW@7YDY~.=)kY!avS V& CE:Źp22 [*ntU:RoGE0#inM\Hm .^ h{ kGkrRMd\zQPc >ŦL{G{I&a/]ky(]T+ s=3q T*`&+Pr@+!ޠuTΥZNo>n R+|?;<=vˇ ( ^9%q^8A\}:YHY7?Y .&^/٦˗//E&Ng3'W‘P咯 R: XҡZ+h'iT(QKThfVuF[ݶD[ : '.$ uMr<`߳ァwdNwt[3<w~vU{Գe@!V{kkXՅҒX,NRp%=,"vD\ \[LY g&> u,)gx?3sL/vfwZp]jz E9M_f#ԭs'd8*uJ2LJ[O1Y&)q$!ߐ8 =^Q1/)n; 0y`gza7F 쎝V7$*< p:љ^ecļ,P=FOq;[ӜVSki&.RXZ""l#ISp,se=9Bcqє=bpM=AP|Z t@N׽J oJdjIrVTA6dF{?_IrQEׅQZlc."Z 4!ޢ;:F5#U}&">F߷mKg;=RhV7B杼^ŝnZ[(dc2f#m;ʠ=ݣ 牝ybA.F_ÿu3-יkdKֲƓ8}̇?Z]x |Pbi*ޙ(.y!j%=떺TxwfIV'n6p-Vx:e~إ3:ݏ矴 ?}U5(3OU`vW op+~,xHPq@ sq_nhjkڳ" O|{Gxo^_}x@[Dexȝqb{sگ8!??'ȇ65hkaVy;T4\lQʤZ ]hmi\816rmP˃]<փ`q>9j?PKCRHO"OEBPS/ch06.htmlXvSl G' qkslImuDJ^.!.D1Og.*J,9M;|37wd2i6O2Ami*nNv2˶ڴt&fOߞ] Q{wg";.g=|-A/|kW^ |d\x5-jy9̴k-b^L6"E1-RA|jJol&Jzjivnʷ܈މ+j"Ŀ_^X.vEnEOv0X䆆;)Tu0}&o:&yuZңْ^zpb-oA( UVmx]N6TmRVB)6VhLP휧&BؿNZ/̚ rުUχAarqiNX,UBވ *8R++Bkc\ Vj@n7=?>|Q:N*p4kcMkZ/TWYLJtQx `*"(`,GH(4jZ:`%WGP)9 ,lzŊĪWG:dһ\ֲ݉~ϴ]PI_;<*U6f8+^ED875 (: ")gts.`)5; Ggh >9>^E )>t:+0CŃ AP4i7IT1r%54LHYqwukIド_:=ON[Q翇CO;)5gnQ51x&0j(@cJ0 i+:kJr e=9S3qyF{iC!-2E1Z`m&pښ!,1HI=!+Q_/ vBYەF/_}Յȯ`DO Vң_ѕ7 `r/l1o#~-m8BN<)ŠFЈ=424YZg'U'/r>_IWjEXYMV6[^ *?_r)3ҝl\2 &Q"r#á0*"3 a|ێ䣑1|([LoVXtȢM tܪ >~M{AS9q 9Enj$8Wޅa[08߫C)77/^a]}SʶA_KE+:J\oz9X毾:^5]Rǣ\ Lj2x++2@LhR^H#jس`rMdLs*6 A(밶{|RușŚ Ƭ$q)::Pspe C) ˺!9|Li/2헴!69nI`qm߬Ƌcli@롂Fީo&*]Ndzw%c7[)ĥqɲ 3^ ;fhal5^AubA mycfk ?p[v$Z;$c$2a/eZ!:٩M ྽3--:$o֯l^뺃-*(?*= 5*&4MJz,qLM3PyXVVt jkqUƕsj)zB{ -}ԾHo`L'`0y@:cgXOPU3vRB$B|?芽QMw~gPKDRHpjM6:OEBPS/content.opf[nF)^ [@R^=4I[D$J&~F]2!X@۟og93Zvg5K{69gytձnM?޹՗w}Z}OJ0fWc~WkǶ9oK[˺>au:ժ7@^Vo]|["6O޷y]}.>뛧sۿd?aϲ/9~0XƂwq퉮{s/bt<Dz^i_aPv&ej7zu3' >6~na{[my׿iVe޲vWgs{|5=NtELY0~w!j2Z T!8Gɝujvl(j͔VJ:pFŤJʌb6S)g2`ԒIn6SG$u=tRV3*ӊxOeR=9phQ Ƥ¯XQglT: f3jY)1)U U)YK>7YQS\c5-9)]Q)6]>󵒶^- |N,| CZ@ Qp,|iX1S𥚅9)uOpFH·֙8kPTÿ".|k%S*S-(@ia¿n9UQ𣤙)UQ#PdEIɊR&bdE)KvzRdE)dE)azC)3%^ZcFzԳR8@zԃcO9#%kT2/&%kTheldC eLOf'Qw'kL%SfǙ5Qv,XԜ(x,>=)fDKN ,Z]bQķ QL3eͨZ2EG_)tBJU[I4-t΂n"%>{o$KTbttF|ؕ461N@m HJ)SI&{.`#),zNy-$W7{N+CyzI0\iq S7L]j3"ϬX8!LOILĞYdSLzGE1 xNKp5c/ hۂ.H ۈ VLj`#trI&6LJ>QM?4©l #Dyv9]굩-0'>-ϛӚ?1 DŽ134}Õ E1CU SspLhg0cwR+(fJق%glI`|ZopL8IqLh1DŽPpLh*A1C |Cz2pLhHaR>?6@Ǩ8&4DŽ> zܦbR: 3Seh3TqL(P1cBE KqL(&0cBq2QP:1cBaDŽ: 4b8&_B1C DŽR#ހu 18&WPP-I`|PyBuDŽbCkfG1CDŽ{)czǤcF1C:bҿ 8&[Q̐?1!cB~ R1!EcB Y<Y6#3d0̘1!K¤$c Ǥe, YgavYgH!c޽鹭͹?K/+nʇ}OǮ~ϓl[PKBRH*J,OEBPS/ch04s09.htmlYQs6~N~7S3iM(:ؽxNssm&W"& wHJ|N䥧8],]ξPHv UEx?bP*(zwYČeƥ*(*U/? -ʿyK×Ir|y~yuy~&$IN^G,ʭI4MJ/˷LH |3EӋ[ <Ϭo4:Y`9+y/ͭKUiGѱJP=]ؕX9>'Q2%+L\TrFH$ZrkV| O֞3DvUZ(: .d3 - ? KX)ۏcZ,nvaۓ;}{r~8 kv2-x*+Zh0ܲYί=\TBBaN0Pe*^ rnA$6Cph9SE2(Sz3uU)mBi%cMgZ h!ŕ҉R %zX)(>%U _ר.R5xJ ?[UVNJU-3zXIz\?T-hw: Dw+.@S'9.UǣNE0.S ]bK!+pьĄ5hϋ ܃-QH>TuQ<Բ [9v^<:-*M=ڐˇHƭ ziΐQ\ ~%A c)m|ֽD :~{7=s;k>(`vfC>!6zM1`="s"U%L9d.(r ;)lp]1 tBH q[Kq&x\[K2*AbRݖRVtpbb'}36)؎(!䈘lʇs: )TXN5ܬO}\0NuopW t[]\-[MQ J~0USQ#qKq %~A*ZOޓ!]' ,ݾK, nM'U ]ΏE\+ 5[-]WXP2۬oSj Z z̳Lo5o5 V }#Z[Q8!S6PSA|A&Qr=m|P#[XcaD:Ar͚(.ZI*a˂ /GCfn +TCW^hSx?PxJFE4*hRsх_Fȩ 9B6ۼ׶#c[ۖr^iN\o X Z=F6P_D&$s|Kc.Gst}ĺƪg^+Az8;qáDhl@nKx OLgRwG8NȆAQa:+ +i(4:m XLOuBkٿɞHrձ0JCXYfQMj"P&OlǓ)$L7o3&"g PUb+*tXҵ \A0>;u)GO[~?uoH)"n뭾$=?˘֔/bF7P.dʂ 9gmJ6v}3CCoٕBH`RBxk[Z8&U?s" 0}&ܓA۟>ycN5W}zZ__! -Q -mGzHR$h؆{Aׅn3 .J)&*p=TsДmyIJ\5"Jag7_+ #ޚ(]?1&VJ];uC:վKMPKCRH: kOEBPS/ch05s10.html}Qo0 )L,;fҮC X1x8jۓw$D};P U\АaS68QRL,wr=ܬ>,AKr)eUWU()o? -s|+~/ Yϣ\Qp:0zʛB*!UbhCS!c>s-^6pLcRTm~|0*\JH\pM`;h:2fʕxjF}4z,xW)WO# SLh'_ ֈi~hÉƎ2a[냖cEN؟ Rr:QГ0wwQSeiO PKBRH%dcT OEBPS/ch04s05.htmlYQrΞb|"STl,Ɏjee^F`1(+|%'0)-݊?dt~z4>M؝(T`<0E*xaj|tɳ'*ǃL }3wlUb///N`?<; óK6 &ax~5`UYGa^@p> -2̦.|񎥓/^lZ2Kd ih?OSQr/E& ^b""+g*z-t}ɮM"JR/σ MCkFś4w,JWZDd_I9q&c|**]X4סj}b7sM ?x!M"Kr%yA9gHUywsۋ;df,T""Ox$[,"ŌTNCq?](;ny/LT08`2cJ+V*{_4~1€%-GCkq"^(Uև0lXNdum-  G=U:VfQRةA(!;SvӺ32Ԗ&`.A`<)PjTg#18(AՇoA,XQF0SmlXq^4#WhA=8Y?Ax\! PP2U d+ǃK(2+srj$+̞%jd(pQуy ym['< Pcf`_뗓8Wf 43v02>U%VjFS7J"Q09{Q'r$Qk?ЋBDjX+DP>ĺEޅ%kUp⃣>ې ,JkI,MN$( '> 3KhoBN:jR3RiѴWL+eO%m,(q9a4T$HˌfV-vK2i;Fx.5gsQU'[&0LɒWth_SlJ?=Ԏn,4wT̚DI/ KS8U҂llf.C,f_I `JB,`/[ d#Ϯ[9.=ub OLL2pT V{߆tgۛ\}zs uS5S߾['F w⻅"m?Ar1j^4gE$`g|k.%*OɢJ@UjZ#|i1ƕdDwj&/k:*c'hNG1*ɼwRC˜Հ .yeEhlбYdDД}X<}[xՔiG mfj]Rfp#d~vSLc!1?i#ڜL [q[P4jeYas{y⊽9>y}n~޽|Uz }Nq,<;b;^_:x.oI @O..8;Z)]q~u)N\A)e Fr!-깲&7<̻rjw"DclQeH %T߿S_vZ~E!}opo.'˙([>7 ;P%: SWːkKG(mԷ!m?PKCRHń7v6OEBPS/ch05s20.htmlXms6 /3&hNے<4ILt:7DT$e߳ )|ųϾ@㋻,eX$ &Tce*Vb(\Lq엏Y/Y0ïGax5b޿c( _X8z,٧G#R?cӱ lNNOOKY |ϴulaO7vˤ%ɭ>T s IXY9W5`刜Bdu8ćqHB&TU؇lH(5kOn-]In#2[9gT"KCDD+apH rwZiŸ]=@*W-#EkҶemUeŲ*snEJdOIHe&cra3;Ɖݑ|臭u|@z6iI\J=!72i`Dx}䊵5_wFAZf[ ~7eYl:'>,Rnڙ%|(L^۽}2Ur*k Zp>ᐄR)3J=bq+R#upF+zB\|zѥ uZUUk`FSvp9$Wb.aT]ߟha#~tq) 32"0l Li4$7EJ"}E*^R#bb "'Uܯ l ~r1U[Zw.DwΔFL `tm"0u&@[ *޽!lW+'#7&C]Y@azyåWyN#$+g4+&1Y׷Rn&/X*_qγ]S7Q luBY9z@$ʟI669"Z{kCwnFW @@HMU\95"&R]ea|(7qv;:U7 dZj54_ >"ޟ{)g_SJ!|(Py+[ҹP/1حtrrʪUB@uIef6%Vٶ)v?̩QTGDmnPh6y:MK LL/P3YAFPQk ʺB6F=z\xϽkᣮii2Ύ_xyr|ni{7M4ÿ4<%H^_ |(%X,x wSbW#Q[*w'X'z.d0> (Ӷ>%=Snoȇ6a3{zEMlk\y\{gZӾMB0Gq"/Q&7nNkbmkeĎrM4PN־撍N 1 ק(8.L1Gjj:}kSE:l碃sqqmVɅ&2U[.5mc î=<{׃{w\O]P]t> wjCȕ +z$ Ug oMˬsPKBRHaЈ6sOEBPS/ch03s05.htmlRKo0W >71QtJ݇XiUh"-{q^r"g<1sWF,3@]R*eO*eIR6Fcʴawٕx:ϟK)OX9|O $q VُNtW;xt)K*Y&zM h2@W)j0ۮW >E$A6XPdhBM)[ޘ{#]5"ynL)/(FcA {5pHK:gT2ʨD~ۮXƟSBx+D.mT!)<$˼lk]EcAId(Rbk4Xg >gs1zÑj+2}B))Զ Ix ¹Y~@҆ ]e1Cw4]eZo|R88*r^rC)||fPKBRHYlm0OEBPS/ch04s12.htmlSFtj3% iM=Nc|It:wꮄ}0N#rˤ"9iz ’@z;lcИp9- "3łQ{itcQC@WwⅢ@VAZ1 !O nr36VK&if)?]kkp} -H4KD8 c?T7rR+mW/?A0Y8 2~ ls!.Q9xLC6 5*Yj MBv>Q2A!ax{j42HqUUR‘hM.ddtFZ)HG -S#Kjx- @s#%ZD1L#CXu\''jF:]=< uܷ}YVbLRy%--GQRR j'~C hG<[DvОrS "&V{! z8jIlEv!Gt?/3@:[H7aiӠMRy yJ:XH4Z! 8ӕKʓf&C~+JeV|$UKZh#+!!bQo%1V OTX|Q'JU&9$;Q Z $O3NpOx:(:)Gzʨ8JQ&b.7]QR)Zo#?@)ܦxftmi6 gZ{GjgxFǓ+BW-eFZk?#Q$Vc jE YbC c'[ _dOS2 zpO] 7|_3Mt2rղm!'šV4ܫ!0|"qs؛ߪGL\hΪъ:Yr +ɈQb ̐_)+5Q03hǰz_UĪbp0Vu5N{ۘpݹ(R_+vt$x2Zg,hR,1.RTNuC)*xVq MR2qcs:5E$7vF $rBSǬ8@>ݘhu%zKAzhYd)O"؄,WTVچwUָf]ol< [/.fj$ދ&e6~Z`w -\`=}bV+}l!t0lЫUN]r~9D_aX$g˳@@_5wcxڻ>a asu\~>:=ͯct\w|9"qG6F~ nP6ez~PKCRH`5/OEBPS/ch05s04.html\vF>MIb _CW@ ؉/ 뿪q"qƻ0tv8xyxoKF2Ru8HG_HKb?}OO^<:, X.qV̂% ۣ8*n>\3t޽{f=dttPe4NƉ\E%q+/sY#r$L,4. 0" tRUH0KK,|eū'\%Jϕ*A`Йd /DHEh{%33e.?}ܓ"HM1-O䩼! ?:Z` .DƩ&D60Dr Pi*Ќn# sEV(.1+J"1QmTd7#EZ,p V ]j߹ﬧ ~w6&"sdjpbđȦSc=N+HLD^6^E=x$AlJU=sE V͖iflܸfimSiiDR.r> DY*˪PHq~,%ъh$ɊwClC cHt195P-4,F?ˮ^?;/ :(Etm~dgj0|b[Vϋ*}/j<cB cHۖdJm, 1xf_I"0Dab2nr0ea3إ[ c6:ډ*Zh]9^@+jm3 k0s g 'C5dEā< ߓec5fRgpdY0"L}L;0,Ut3VҠ(iVH!KCA swuc [o&v'Ac5ejZ>N%VKھ_E<ʛF a1]V/6(ϮnGpPi֡t碌Oْ<W_*_;scrsSnޗʝ/_*~$Gh͡ J3?sVQyEk\b;bw8^kE<) |;`~ :pruRƺF6駱[vJK$~6 APH t !Gիףx >7&;7nfHK& E)R0r;Zp{moƏg/{?x.,? \?ҏ8;HH8~wtKd5Av,Lн0x<H iu}1=PڲX4?x˱>1,r{dը7zk1stg*sGqU!ŌmĢ&W2{VeѶTGX#c_d}Zk_|jc#[6(G4AQmJ"";b*5s hk`/k |s%=P~%e9,RRwVzo\7_KސHm -ΛqL$A56z x22Œgn(N̋Cabxqf+ť慄kM_J4BFf(W8WE ,mH?ojS?IR 7p뛭&M@ʋfI6pf>zT"1-l&:j,4T\/(V*E8bL*WO5&Ix4*橉%KFփ=j/; Bu @!YEe_*jUy%졑6 $~6[&3o)D*N1t(s7=v8QRTd2Ê*G/iJxfG. L`n8G,o-炫|ֿ g66z# -ẍ́~@B>T|eU-Tx6UKW^dB.ɝ~}Mb7k q(jw~ aePݿ}+\8\wBu]E$PmRɫԵX/ܯ9Or*y0-z8>):.2T)xr(dvz5&ӸgRB(M_ƴ ne2 cqr&k#9L}jo G\9^Y_bo|Wֱ׹3ֶi-]z&Knń yfiu5MI&'^񴶴qu.G?ܢ7K -䪕hmbM%6ĝԮ5Yr7-JU%be{Ldx+!ِDL:'7 i+*BUbo[xf[%'ΚI>6-]^f#i(ݭx̃ca>\Duk"vP؏OmPJµ?P%p0yeqZO.7y9 W E% !Rwkb7] 8ܸfmK~*"K@gX`ea.l|dk.;0hU bQJZ,WɆ7;@ep#"B^ݺxCɗWl1"O[&ꦌg!bORQ1!꺪moC3m,/ _.>(Q^%j.bo8{HR8`qnPLu{)|2y.dDuCYd~q+U%4.5;T Wsfja{"Nav ő\}zFi&ЏK+rQ-Ϧ51Q]^d63$!Qfs?\Jr-re!`ج3߄:[ՔXgwvhNMnUڞ]LIr^"0>w;0cvc V>V 3ٝX*#Hƞ$^Yi芫IrHR45kT*s6]v)Y0 mecWB\ 뫻ӯ+\OSK+ƲwL/GABg=iKhUʄz0lw)T5G#rvkeOsvP꼇bWPڐaFk]**#%kT"Vu^o2;VD WYbwYa :Dg(s.LHL/T _R<5' v4Ӹ`'i6 O3D [@(ƶ{-_PYb)!s\N7Q|lσtp}Y[Xuӷ9놘_{8Lڽ{|s.jYz!dcţJ9dNv7`lȹ# >(W7W[ZE-ieO4JJY#HLڐ+8D]S4f:: Vu౶}oO'fYU9Y\|TO+<^vq6.Ri4Dl97[H%_dHMN#$Z rcOvfEd `!*ِY_*Ur CFgo{? ]~<][f 逧0e(S#tQkgdXVa45U`'ݩ"Ƚˏl";@E?g}B)O$[jL!L^Ӷ?ܯOE|:5W% LDE+3xNYқ7uOo]9.#xJ`P%;r戢;dK&Dv\KnGKAJI`z]f;WzꝖ[!Do14,Mk@~[J6?s1q -BO^qo'kF^. ,$Vk3U65h2@ SeN\'[snT[B;0@Ƣo @zo \-&&o жM[i +')w!Ѥ>XIN1LPvY.`qnAɵ6 ņFKa%s*cT<Жi!tnVC[hPO黱ub Y=Η æM tkz~2C6l>,[{{mX }cRNGC@QcqڰZ yc\TGeA_3TIC&Ep} e%{ɽOFuVy ED?BvT{,moE+V+6%"" jʯr";Zn%ο>q v|95PQuu3ZԠje<7ѧv7Q1Q9z:C\`Pw߸wq:i{.x Hkr 4o0dM͋ҬΖ :Z٤1;7/Mk0ގ U轩K{Oue 'Dޫعh:\4/_ .]*py7-/]1ə%gٓY#:i=ŧug_LGwdԧMw0{дor-#WSk<(VQ9_ep?wy?{qc;%Z{ D|1looV^*YS֫iwe͛Ab:ַpoS[N_EJ&9m,Kֻ'Sɔq;MlLwWoWJ%yޗNotwF6~o9;&$ Cn%rAly9.LhЦy$t}WZkWo )dאX!q^Ծu75$QHs g9^ ҫl%0l?էh^zqmSKER1v4kje֬PנkSH,dzؿĵ_$v|-fxD7jVl.Ɇl4e)ʹt½fpG| Wj>Ǜˡ:Ӏ8V?8ҘQ:&]b:- U3y65co98OpNR (jߍ΢xNR-AN20fZD蛡{~ڱ$&b|PrQEoB_AM(D4<:/(>$W&kDvˏEەG$5e!<.x:?Ez#~oԭG &awE:e1hlAf"tl*_zY< 1RxWdl{_YZls-8\ (AĕZ6N$77yLGK9%U&3*O7,5;&wu!JD wI]90he a5\*\γ)ݬe3o"ZPΨ {ܕdH#~C-N;_NLLy_$L-pmA .y:5T t!ݍ( >ld~_21xF};Zv '_e.dSEwƋhC4_%6[,DOKC Ds*"fM\V3@B7[e<!(p)I|dhkЅLi*GmgglAپ{*8BE0& p!(FxsoA:[u_XcKqL~fd"n֦IT*4)$na.K'URPȃc"N]%DnES:nMldI@pМ$ A:1txyJ;F~iW!,ޅcԺM+<3um)&TFm!3Ϸo[ o;]a>;ϐ}d#ؚn&n7-7U_oƪ2=hwT# v(ŤW~s%;|jp; I}m|qel`I. Zzϝ8xN80lZ8 "['[kΡHH9{" LwGmi;JȽ J"GjC".GVDU0BQ~7AshUlk({39GVd@箏Ä=]DL$!`H} <^fτd7 h&@qr?/ *"y u=aŃ0]lwS?R6sM*O}E ]vTF-IQn[:z1)5ݰfc īQ*Oa28 G],gOȴh`RmUZU0[<,kvrgc#%gtPXmRrL0gh hg}h4ևM?p='B,v+u< 4z̕2͵.K1 ^#Iqj+3+=4ւm-*xrh?ӹ'Tt kJ8#>qɑ& fo\ \Fr.qJyL[2MH,J b"#B’踯R$FlpO=nYN5%x7^}EOn{"OٟIXBFlUvC)CƯ4j ST6/NO>ph&=*09o >z7Mz-ni)(\F"X3N]G4,|i<1$6V&E&-ug%5GX+1<8WȗÙB.Nw5Pֿϊ6::~E,8On}cYF,P_GF [b> \SeBqJ|>Ra죫w|G7%rˡ+`v(uﻄ}4˙+Q s(l+>Bo_NϴJNDX>"vȰ1])] זͬ1՘I\y+k⼥k#(Nә^/Es8(Ud9О+!ѷ:Ŗ֦F1&Yzs|Ѓ  qUcXzJL`IJif]q㹻3O"d!.d0Fc8-pH`pEt#^=u> J]ҝN8%jghklҟ iI.Q#4LM)Kn8B{Ef*>R$>v zFM*,Eπ<') !FCB2#q>'e8EX1|M86d(1%UW-8ʄ| [BBX39] fXSI!(= b:Q 6B]Wp*euZ) hL~T[qwh~IKpޏ~؈d!U_`g3))u,Fp/`c^"ƍrCevL¸kPt`yy4B0ނ˲n0/ITf`0>DrU 2)<Ϋάx2>$8UHؑX}Eefĥ"ݜ䰾17l(A%H*M'K"Yg.WӣWd2@ \ y+[*퓏d d~ S0Ǖ`]J9vj6KXsFoc_>HAOh@Sklw!L QEU%ٝ50O}HFrgE^/ŸlB. 3zgR5ˆ~1\ʡuI|dzt+t $Iv̯=Owo;T$c"s(Pb'yA tK݉M|*# m#BV (􋬲ݞ].%:1HQAm(lQLuڵOԫ#C҂C/ҺjQf&"(*)\!>3/ɵ  iTdxaDg|"9̈́g94YOZ zv٨&wk #$8()3'\{qp%0(&Z!]_w?|[Ztos9|.۶ۋCu=PXi݉V#"G1ԙ/gAL_͠`cK CX/2Mۏe=XA%.0:Ƴx"kD28]*'K 𽔗[lDYUVK(K/:w>*DyU"0YNY@ I$rJIb:nu?!җxuf<-c7]u@4ѥVxmzH ˌɰ0{rï-bǐ;XXޢ_xk=gP%4}h+ f-h< ()v D=M5O`woc[և]G-dcA,x_m﵈c ӳCC}P>mS|VߤL!;ݏ0dkx%#J :,Q͆xvC 1jΞ3XBkC|~RӲa , }w'0*eV\Ewtj*N; f۰09~/"qW@Gu/bTO4ppI @aAѨrEͫC$#E׃C 9I1{A:;x6{M?:cb{m-9)9uYP߿8er[q/m"*6TwZ,ao3bOncox zOgIQ(e)8jw|CB!{Aؿ_ 7iiD#,՛{wU[Pp],1ٌSRiJhuӮlv3ҝhJ@lE 3mN\I0ԁf)Rcڐbm, 65$.YHY,>jRFֿYq Xr5^ڨ*&R1p_ dY- /ڊ%5( &+7(NU%aV\ -x:޳ ؎hJǐT1LmaWAh;oQY|†8 RیUV˸@fh&mﲼ鶫}ζb4y]*אhKdXi("~$yO6rFeV0.X4v(ެ=9c:Gb H,}sc vYxq>ss1o;}sq55hU"ꣁd&`,&tpz08=> ɱHVwו~pGJdV"XI|ceJaChѪZ߶9x||{ȏ{eP :tP21M^0 9y|^ MWU(3Sn훚6u79LU6!{/PKBRH&ךL"NROEBPS/bk01-toc.html\r8}UH8]l<3yHHB$yڏ//n\H"^tHz!{ EOd-ۯooߑNq 9% YKrv{"^9w_|uϓ^gvpala~ʨ7\lvfdN5!$סd$B.E #]"Ypg.&) i[!GCs)ܷBlo2;%kdB~Φ~Ǚ]8z `<À.<~O\&0])\U4Hd,.|FĒ#J.Ʌ= OF4w5$J1[~O3áK] pPŧ< &̕"ȓu7[{]W|}vg':HQdc`1w0>m3' b(+`s>c l_,Тm54PbzAԕ !GnWRX j4vY-JO&ó||>/EH bOV\'"—cKfZoS{ Y31Z-ZBHj,$0bgH? DX gMKN}Rj ƈG%7 HCh j>pjAx\;ӝH VF'[ڙ H?Uo]mmCz૸jrAPu,}|Kv)&PS֛ە,It-֦{䣊 |,]1 YĔ^E#Ŷ+Eb:+%Rs5AsQ@ O^$<>I*r!a tPNVM!7s s~{}t!(BwMC@k}oJB∫_# 8A4ng%+ކ'0E3 W"`>ʡ?\o0$\b.y7'yxDA=1( q::q-$4OVeMA~<_o3 w!Aȶ$XPs564Q#<:3cp & "yFܼ!>\T4DŰ P ̮&"1%&+6'\( o!PgVn jc 6|`jSVCwT+}RPY0Ipox K3~AZNc%ӡoJa7!:rl.E[T\^{aS"yQoc^[5h'ssn1/{&x:z)J uH}CXJRSYb\ ࢡ,aK@dA/74X#Oxnb1 617z.a iFdTHd;mG!%\ufv(òCkU3nbGcʑ< ]5,!TZ$R=yunlĉK\ˆqQ̢R$ 2 ,Rh6Tax+I$@\^ʗd!lԀ1(r;P|;Ž8yB9yvȯ@δ*  ]TmL2 tgJ׷x0@-mMRyai5 p J1z,Bj+ K$/i(̮RhH`)_BFYq3\0Ȁ)8R07!S7a@1_Ҥ/"ͻSp1kg]Wx*0Ə\'Z}! -Z"}HYQsczT nMWRR5>Tzhm7--ІG]}eQh,bYcL] *R^`B ZJ* xRd.^ר<;Vu >$饘f"2 Ru )جy <|gWcV J_/K&0ro6؆@pӻ SA]scQ!)^Pet2v 1#SF\0BMFQ[+N,;+rxmBh|\h~gGsǧyU;i uy5šZTb0 Ӱq5Ni yA7v"G:~.ypz,xxVYͩO%WUςe!rG gPD@6d"MvKwgm?tufzIN*{[# E:}JmVYU [JU1do҅]-)n%cJ<,@bݳXOg:9 ࣼq&'f+&Q˶L'*:U$o |S_ВS`#n'6ɛ/ܕA=V/1 F"&{{,Te(1Jy,Tw]*7iEͬ/ES10 Ki#SSfam$$pl htszVөڅy#WBl:nci͎~GXŗ&\8=>D~ڼ,mv<5L1Rdx5MBbjbzQW%oujB')'^e=xʣQQL@D5nS.UxD=@M BTFpG5:3(0C61m4_o7<:*u=8bRtKlCɂkڊ:Srʍ%{=i5 zLs čytQE$,X]e`9+]]TbJgvn+'naU, ˶6z!Ѕ fM/Tb$kH;,i `+Ld/vX,,Ru/Y?6>|{3Zx+ZTs 1ٍBg̩W4,?iy&XKe6 .Egg`hn͓{Q=}qO@  n]lJг7&Vskll[mFJ2K$sZ'_n?5L҇CȫZ{\@͓?4Ug!Khv+#c!_2x[+U'mhJ Xtd%]uVZ1m6F`O~(dɽSjȣ i eLŊa=HQ݃hƜKQy rVYiDPQ7-AԺwE=WEKH͓>*)~UyIy .NEM^PV::PGW Zu& pޅPSmTL>TY"e穞Ce)\VIbhFvXe)͚sV=>wlZCIT;v{ɹbd({o%I5SͳF`\݋] 蹦UF?]s\vEg̍ݥϒxּ|"s5V*dyЭפUfG"\l3أ]xOeV *wGVV ]cGB rI0+eTaڳ\w U_{YK[t5\e [Hf2d!rY3WB&rWi{APKBRHG/F &OEBPS/ch04.htmlZmo8<ixKlސ8]@KMU!Wˎ.[ gΌbv(,qXD XM7jcrS84 <0"cb#)Jװm lfijF q\Xȸʊux/@hh;5bRz;-v*;f|Z*?ofj ;sP* \Zo#܆~Ȃ"7J$Tݗ#8 5JLrRǛr|{z*d*`L[?č 5-]ٿN^, Hxj߹O ?TRrDϑIO3q2LŲ4a1T#>!,uG=lF0 IV\SR$0tQ!#$s0CRYJk3Z'X2 .bj as {L?@ޠbtEYk_qCwȌYkbMKuHElθRs5S&~J}lZf*شU*xx4&tL0\y xoXv"cV6Hj86l*Gڪo  8Uϡ8ʳ/k ;$H!Pk69h\YYYgl $ߨYu8[x@e %P'{x:XoBz+:f-YC|,0yNA|d+"=0x $ sQd}xo+cYدY;+hWѢk)ob;6`6Dlێּ=ϡf*ݢv$Y#]lX|)m5 c Z;:UiN?=W7:RDkq!r0krza4D({}f-v}9P̆טdU{MqqC$:etX GGXETcRɾG ~hO\)@Z@MSL07- n{Ni#/4vܧԬ[JB18rKPۀ2c aavQq,J,{ͽR+6+c#S a+07FZpϻ5Kg/,Q|(S$ )rg]zM5N:pm6kߣ`Z'\Z?@ڊeR!zYW6¾p;:e62Rʝ`Eʌj՛O]ՉD,yK_[MQۓl&]Y K ]=;\Ԑ+Ͼ㢅U^PFf8}Exv 6zUEyc.|?q.z%`ANẺPoJ]ci$ ׏_cxݾw@dSyZ]P(;[\:b((O1_MUW$;tWuƖZmIim{@Yovh><;*uV9@"O$1o?}4>3rx7TƑԴvFG'* 9)559uKwXnU'-FX8{JάPM&j>o",}PKCRHO/OEBPS/ch06s13.htmlRn08Hݬ(! Lk㧛6ŧ “qrV"+7"=V8@M\j6kMu,F:q_/_fwog FJ}̔ai ,@dD[BĊD -1_ouAR38|@, vj輴fβ i9|5{nW^w_/:/^.t\7˛kȒ,M~a4l6Yb].ߧۨeQaND{\f|PG"2(,^Ieexh<s<Р:5M-_Z{o6t }<%?=O2y:YYP*2dllxd5Q)9Qgdy>f)4JOO1^QΉVi+M=J,?9>D+f LnФ6058x'+KW9Jej7Eoؠ|5Z cDxer]y 5b[\t &sufPӛʻ>9'?$q?0b9F<{)Z\&S+Vmnr)*5PmJCH;j"(f DPKBRH.nOEBPS/ch03s04.htmlXr>^=U7f32{f=캖Lg:  ++y>K(i.B}s*YX'>ͦ ]Jiv|UƜhqi}36ݧ˟.Xy-N⇗o 6ͧEq1cY}uQl6|27v],[bNax+_eY ۴;}uի@W^B5WnVįVx4oaZha76c^h3cn؏ [%\#wiiVgE2v>gV*`fWAg"Ntt3dTL/0}>c/uO2b}MW%Al#e%Nx 󍐖Uylf<1UxhDjcG}}q$Y5{˻ԫ-dv֔9Ѧ1N 0^z,ؘ^UA7\Y' j `:!Jd6Iuv,Pϊn~ [8 =_\o`)_=S7he8-bX*u߅o!*<J?0.J4nhqt wr%ڮN:KsL |D9g(BGbniM݂9Ҵ-ykzo$+&A$:eɪ${W6APXXLIxLtIT(&c x_і? y׫GfwBl׋(W $[BڎDk>;~ Jfulv:/u x$oW̡G\8DV蠃7NXd,vt0(ڐ.2^$HD]h'f{w࡭oKQy lȏ V\=_q'&#QTfP6o-׽)ښ^cг"JD 0HŶ+Mzi"5֡JjВ/Le4 ngQz1MFI@ @\̍ؖުò˯ri r8Rc,& £ Rf ]6VVc`xh/0vl-?*miqy~s55zdyh. *ĩra3;kص#&r5MXK+RnT$D`W< ǭL6&bT``S҇lQX2>BkE1Dl^|^-ןXϜf kM8 >gOO#l\ a'}RV]x}$7MTO_-Gpp򆮅uDb&}"N620ez܁j4RĄNه׾S$+'JɬI:QBR2ʁ/ $0uݵ# 5t3JP _Zj;VÅeEII`F!uIn9L-8:T-f%KKG }Jx<=tdkk,>L;:heQhXz^O0-\a7x]H;y4XG й5+k2 ӛ3 x=mY+Zꐆ䪉X6\fe%@S٥Γ3KN?Hi~O.#MpvScBܮɧYMTi~nv;B{!E^[-kR|kr =MVa;54x:28>cƩ8 _C EghIW;>Xm!)+V+7/}lTNnxXi:[Դ|xE ^lϙ%r`P0sqv$5d4&4 Ey9G"[& @C5Ox}(/PKCRH*v0)OEBPS/ch05s19.htmlWݒ4Oq0d Z0m Iw;d e.K5%#I$|n;:9Q&߿mui2N/:7\b6!L-6GϯnwzAϗ9%Yy]]ћ^.iMBI}4v]{[dw?ex)DV2Rrm;A@sMafEiR1^PbeQfeQ?G70{|WTle/F][JIK}lˤ {"Y5YL4,DV,V#Z^={u>Q+VcX{"w "Ae)uX1 ߳p8M6\@ "y}eMj 1PRT|%|Kn:E$Sc_`fc'(=Ody%l.cooF]%hWB=>crypB}D@ nV ?4.I+Oi_F:4z6VHXr'[J0Y#1y>LIH;w{"J)Ӻ.3:l7oyW k4֏o1bWXpS$=A}CaYw٣~{)];=싸!bd+wф`2TN+oR'[̺ݞ DoP(]cV 8DwER}!JcU!^ ,UwvF@cKH+\;xIq 5\­ʽ:[/7wUcwqGH 6_tgXWсWWc~:XF)ݵj$}E .ѐ^vӯ~;?.:Y5PKCRH,OEBPS/ch08s02.htmlUM6=T)l +$DZ8HQ}kPd|yoT*#$O%@2B:}z*ih*/??ƳW7!Yeϯl7y@x߽̲G0`0SER_M2,JqE<Ɩߓ&*=iN62/~P"["͓,bgPBAqb*''[cG뤪zHc{tp\[LEW.. A:sʴ-79oޗ7YJ:*lXziɁoQׂ,Y5PKE T U$1aJjc4{f k΁j;S),.;:ƶb@78O-FK\..1 ~)W4ִnt-=]27?\3ާ-3z9^CNL}ސ ؠGD ޚq }ȴ3ɝzB3*wXq$ZL08yV"Q@K؁/OHɶI\IMTaM!x!Ի:Zo{ ۱qX#jCɽr`;c={ p%Y˩cv5W| B>zKc㢙h<X 0E $\Qnj㲞pCVwJaG4+L]+> rXޓ lHy\oSӅe AfLƔt `vLn1j-YE/Se|e>q>XE(e׷cl9FVgǜL Kn Y~" 09#5:99cwlT}[iz5J|tuwb6M0(D7`v'ƱejIOJ7ţ3_,~Q!/PKDRHO[2 OEBPS/toc.ncx]rܸv}Wʴ)bXv&yJA$fMbIK}Tα<.X}o~~XY7yU=ag#˴I,iE*ۓ:?)FۓUn^/gțdz]%q,W')Կ-ɻ7+)woֲN)謽~ىVe+e&N,Ϊ[ݛV>ᆳs%+Χi x[*5Ǧ7K=rR"6egoOl^q}?B<^g_,eg /4u =[BX.>ʺ:]03Cxәݽ3XFu^4Nz$Z7C9SLѝ _$@ez,CW[+fgT<-q #;s~EzVJZ~%?UN[AȤtU/jn&UBFۙk l&_煨Ua.Sڅ(P!<w !vaz4<6QJ !)i%ǓCx"8׊#? ["IW2a xCtQW b<;_Բ0 oԨvY@{>:o83r-F5X*ud4= -JЯ Kw˺.䚦ќ[,6M7cxF kl@!2%sEu:E"?fh# W9̃dЍST(݈t8CO$<6]uWG}//$#8 h ꨌa },Ri]΍ATǺi-VCއjdRa0ZZEF#V胙[ DWvNalV d"Z+КNQk"mg箙OR)!Cy t:ix: (pbFLѐGĔDaB]tY)*N{ ykɕj8QE~/ͬJ='ଃ{jzϟDo*r=)Qٗ, 9ÁJf]47yza[L)U<< G;y3p03 w- :Ęoms3 L}ޮ@W4Q2<̨X󱁓M*`^C,9=<)1 w# }s[ *o%g zOJu#S" 3б$4K!Qt/3-<2>71,Hb&3w.8 Ny(ƆGG=?Ezs(~. `?Jufm,gwfǂf:}> դ<<QKFnteJ5eX 7&DH" ^&BN{cgSy ^k~%ڟӾRb7Q-7̈4B,^wd=)1 j >3fvß&:$|h]1IŐgJ 8tM8ZLr]e 3<D!kNJөt^Ha 4}F#TvгDzPqCm?Иv l٦]DQ̴4ª \#רvpVP=% ?²=:!}Tuo=_nn9-lQ0fV}YAyݟQnwR6C7S17 Nm B;ӏkv1es^vh:!}yY5g;n@ FyF2Fȇ**!f>8K#z2~Kw+Ё;Ak+CVc ^vE1,THP{#gy1*RQPM)Q~w#,1b/Y4}A' *N+?FL>J~` >ԣT4h" Nnl.ݨ3$'+"T& )Ø;]' j[P"(Cm`3L4dLfa<Ltt)cqV\QՔH՚~kcDV4Մ_6s c`5QjR#qtȕWfa=1/e ^Z(mv%5lDI+q'^;|zYfHg?Q(?Lmsw۬(LQF`L O]QcۤD=IV0EY A@^i3E){C\,w 8?zS"`T/ic[;0sxo+lZُ{^O.t.`hoēEA0 vF#`5}EV #+7G M]WAhW0R\,C4o(̍+D0FgOl8릮֯p<n681a'v͈Q0Q7zl8.ij(H?4mƓ}l:-4nRc= 4rSzm[&EU| o_>g@]iق ԡelV*O`2pF8#@OiT%d{G_bjӍ5S.90[n.RKY`d@!?Z\u;3NTe Xe;a#LZPGQYy"n O^Z.Q e!M& cBϊZe&a\TUw 82!/Kf0 Ftim1Cc~J!w'KɎbV"K 0NZu[j2i$n0)a,1ldm+8퇼$pf è1:ӢGu0^h5I0LN?Ɓh*h~P=$2CWA/"]wR.r)t5B_sCPZ/]dSHh3 _ é lADagU9@#D\F>+GڽO(C _ @HΜY+D=Gݘ&C/ĖO71\ 7[V]Pkַ1r@zlaF G[xSdt7*y"D73 {h UjqӮ`Oy6V LVANWz/vß"bmt7+϶)eNUt~4cyb2kVy\kxJe":\nQUKPkڞM%ǣhLiƈ_d2kGl!}%csMFжGD}8ڟ}]i_&aBfrV~2E ],7~ r2S="n׼0p3m ~jĦ%W;y֬qa&%u3ևhDZa/ى+/oՠgE̩aJR@Ƽ7Ţ/{'zZzVVA4Q>KeV$ϽXF_V}EF/f\t1Կ:_aR Cm3Sj[wR}t@G=+/$K#),{G=YM=' &(/Z_c+2o!qw"S%yBێ|Vl!| #aXl[4B/FnA:o9o5!`HH'$JYuC~I'cAa=oR:_/LZo <>i9}Dj={(Ŏ1@ԡ!`Hn]Z.^^CtT1ͬơs*BBT|}NdkzFmU sе);"Y$8=.ڲ ,Hn.۪v~ۖi3S 8ydE) |_p'es\L? (!%:^*=}" ڼyGenOQ/PP лX_ K$`\ۿ K$L{M-(¶A@n̻ӳJᴱn0QkeU]"RE |G(sw+ex-즂g&]~daj !tV.e0 loPKBRH)Z>sOEBPS/ch04s11.htmlUn8+fui fbu!hl58SAE"!E%V4z3|||3j X(IL(+^M:ZQt>1Nr{w9!yEȗ7cB&~*RBʹ!~3fK%94 9YܔIMa࡜҄i5;PJjK^(-oR`X 0eHPH+u̫ 'g~/k@fi(ÓLrK a/9Pe%unUXNp B9 󺩨:oCcn3n1ja{.#\OjMMk/ID &` 툫Zn5tWvW^h 8he o6"-n”v=⦘O{jTr1[Y{9].1?J5^Ί0*>̧S :p~_45[Ăf =6seE >5Vv15xJc.8؟,Zf`8 OEBPS/ch06s04.htmlT]o0}n%<mJim:6 M{ԚcG/ X=s|S*xEiG@!uIs-2@<&o7 ,=o/W#Bƾe~=8| Xz_1^qdlwlSHxdIKڴKOOO[@]\d^a6YvP(7-LX[9h^5Z 7ڣi061/0o%w->Dq]f+HVӳmwHЛj/˘5-Ch~#Eʕ$ TTh,y(`-rs`kVj05-zxUY=0[, K'坫cXbEЙTxD C]u \bw`{*\6DYhK|eE$}fqfeQ\9ϸC@?8W.7*I%5Mjkc_Җ=a]-%G2JXrlxY)ի:A^ MT4Ȇǩ)`8x\kͭ;=F?2TҎ4;>^K? 3D?k.^#e15_Sf&ng;y#:f YS'Me]<. Sr#q/j w#~~PKBRH5i OEBPS/ch02s08.htmlVo6޿* HR`X*8[3dm:[N$HHp\(0d=>{wtJ.4~B\am1Y2$.#wh?h$]\'j/ֿAIr1qN_%Iuqw+S'?'>`,7iGB!/EVN`~+L\a%sȒa]֢c YKGQaN %JVx#||]/6Ÿi85) Ϟ ƏLOLNւa(mYW)haӏqj53BwCPU8I[-,1t *hG&%mdh Tȍ26G: RY{Jy/:5c𶢫|*O7gN=4e+Pf\w\&X}egdzOlβ%s,.힦ڬKH`Hs){pŋAX̝tXՍ601`vUqǘNyqx wB Ý6 ˵rBPo>gN٩+aK!egY-Ys~1/+na%ђ߳kK9g8H &wR`Ws5o-ӫ1HƳts6\VdwH}[yFUu[iaxs$W#/d%2rkA-? )[c Ʒ F1a{tU[/r)*ݱٓ?LOI d6̕U"ô`u~.F Ea2|Mu[y,Y9+[ƥ9|'ZYbix4;~.…5<+;r#x3);RHۊɗnE9PP'֪"if0LQngXr(]t5fX "?IHTAR&lGDrove¼-<% .jbY}&ũJȩ4Ejr+ Q+*x=&5l_(B>*0cĈ⹠ K,x8)cB@bf2 /PPF6qΕ,+>!㈲4c){oxsz8? GkT̤'_Mٗɍ8saj^{.H6A٩8Cq*RD Mƈ!FO{+BK Yt>:JmR@ ŖKv*mOI'dT.B(ƕ#{=2,&~)bxL ˕msKP~q[8&Hk+@b {f-c\YȀapԞN9f # k֍ii:`<[і˭)>oɵ fd!IK_E(Sj~%h|';Kr:(coi? (fJF$h9G$F]'C"߉6TxFwv;>Hl6Wi5zX.7F`UD4vF'`'m*QFɇ&@ZjU =PYW7G(4kHéESPL!$׀0p{>rM@ -Ȑ+>4Eg%U۬Z%GNk>Lr@E<ŽcwY뵒?B*qtb'j:,)5Z߃a(!wc' 1dO&}M`gFve=AXsqN`.;f(fEg|^Ae*l?PKCRH>B%4OEBPS/ch06s09.htmlXms6 әJ32Mi4Lfb r%ZV}w&Vg_ŷwd`,OХPONu\\jgɷŧϯU9KNgY^_u,!aI\se6>Kdo;I=-] ){v@t @G '!?n58IXΒ.^h}~zŮNe?ӯNI/}](-+$BIlrGǙ(ϒ#+zo"Oh,>`ޯҧa6\񦑢%h;g2&f|PȍkgB 'xe3Uxd[dakB _dM>700Mܰ]7.WV-2:g4^ԝi-yYo#;9 ֜-Oh$/fT)L}A7"d;3#:OuPki[ q1«@G|'Da\;PWc<`e]/Ӧ;p{V{ Y~BZKhC'"ed{( ̷f#ԉ;eO/ukFla^&]= x F0" 2R4l فI͎2tYݚذ>R>ON̓7w5r}Ac䋩ɗS6J|(^ Mӱbь2 όC %1u)uOQW瘥hSKKk~nj;baXĢ}RmfT]wNtX3 Y3EK6PHf^rrrɡj6RiPREc]ȍ?1<4RSVF$|ƶ(*a֭bGTzcv#ٮTؙ׃{^"F po1$Xxˑ18 -0n;=S@;8G5^^}TOmzOo?DzB7pW~a3D͌dTPĹl* ̃uW>(Yʹǧ̛z+[.>hHZP%),љz'= ֳW.gUgG{rXǹV7f [MYcmGWd m26FMTE9dUjBW1̍(?i$6oԅhГwCG k/ )t?Bip0z.:=:r "\Q4qTi; 34`},%NZj_ p4Xn“)FG 'J8|It͗-R==L?Gz6<;a?(: zJj+N"p_ m7\s]W .XawԼwg} EĵP_1pzlP H~!c5Rި޿ =S*Q Q1fqe),=w>c#Op7}و^88{7/O($X(B ,*C>UlaFso#G"όPKBRHd[3 OEBPS/ch03s06.htmlVo6~^h-E4iV,=2"JIYq#ڴYb~e}w+l:i*Jes#ެis-2W6lts}8>gb}߮$N{{Q}i86v$axQq v\ϟwR/[O)v=K"A{c#ȍ*0+c>ǫK;@J_O$bYʺne[wahԞY vWLi! -`:!EB(9'́* z8W9e:e"+e@˪N:Že@{22U025 .Ib" ym-vc .Hr PgԢ];:kbq2&sS;o a,VoQ+`F6Z]7 'l)K%e z <,>`\;Y%VaUr ԅ 033Z3$=ʢG}x ƕIgu vrH rg&f `PFc@BI@^WrX d FZZBTmz%ՃHb鹒Qpl/eJ>Vw24o/g!wЋ M"! KQ?9Y&GXGN{i^%rM`˭ -ؗ[omlU^ٷu{[rbZ}@ G CN;GE;<}\![䢦U tD:T{-0M#tנ3rT&7tQ)SAR-d$kw!3!n+2ѫT0i4QtOER INZ ^+Dk [%,E7[r,QVrQY1R%~Z9KPe|7ƤbRPrZ™I$P d\(ʌ*pkPJiQ)Tj(G%̍1#+QҜPD %4W}”_F(^{Мnp>0h RS?bhRjN@2^V];=>c ݚf %hqS}AoȲ~<_J?)SԠю.ve=Y94$ 8aܾ 0if'jPIް5bˑ4RH>͜ YP\*He-D@4}?y'Q;B׷e]Qi9bbb-=A@ +{pw6O{s9 yNy|iFB<} :B֡Rr2P%$l;fXS \It9Edi( )CcMRٜE#Xht#"hun>_0B8`2h~+ v$yn_O Mhln4ZMk)k֣K)BFVj2o}UV<>+aNNUBïaqw}6Ƽ (f}L`\ꈱZ 3ӗ~roQRZzEG2D=^=9,#v+3,dw!`@(crkABU{@[ffύ`tR[Sƣ fi rxLR(ŦdpVJcAk gD>[SvXiy29a +a/0RcP(K\pwV˺oJCD!S<``£? ~ T^s{Q;@JQI ˔Xremv'VStUBc{tV,!s Aaq'S6QMq%x.[kv4ÿ=(GSBz BrLs7?̚N XzԱ \E>*Jfli]c'!Lo_,@)[~ilK2%ՙjaIK H4>iFj{캠m.Np9 2g%:]ᝩ҃2J"x}Qַ`|ʾ'A3てzN 86";hqjcn-~pԀ0l" i[,}2nrbe}1ʕSxvg_HtQѵ1ø AlvB";3^0U` N6n b0;ɑWfh aFS ʴ{vm0٭_J-|?|8NOY3ٞ+2м-V~di1{4HWޝ {"GikUbp75l|WXrl"x:` ڑ^A||yHX_݅ )ȓv'ٔf``a&W[H7TeK!rގ~.]*v6#1э`23KEAq=/6*9>YBe҃6iM)fas25Jf'FK=&3<9k$RڶmǺ^I1diuޔ<MNOO;_gVb6 $7 X .q.j^``Rځ-Jo kfuM ʢ2p;nmh |M'qBhRMr\2mB^͊{?dj \:NS3Tv>OZe W:.{܀rS* nbk4=\iˀNF72eǺQےVJUOѓأR| b (ajdkV (ObX$"T~Q EJ::|+Լd| æ!.dK>Kצ=|С v9n AqnL\׵lxmS67(^΍XOk~Lcako^.Ǟ=Of_46e02,bYL]->+1bG'b6[NjkP_T%{R)fUKwhE;C91Kg |8WZA-2f'Z+bz@˒߿".6PjQ iބWɃff+%.Kz^Vz9S M4!Lu]=`ENtq _/ (^VDf 7oC:qan MZMOQp4 L'5%%fs$QghHVR2kU:LIKqph Dk&߇qIE\IC&!bŁWbkߊ{N|d-iُ{ o1j]_A?l)Ppc1&bruJg4h7Jߍ;QG;Q poY$tʊ  HrdG n5Lj3ιi)So릲O<̡7p"^&SeYK1ԌKAPߨN|0yJ+2%*`5uDj>UW~ŌuCY r#RP!ԇycYpCe(6H#r24pD{N-ubpC[Y8+T N#ͪxq)Ao5\]^|'5y}7##gN ᆖY ,&3pO*gnB8D-V4n'>mXjDzFTQ6_u{M-p) ఐKҕm .i11ji+A74gXtB[a)MƦY+*)?V inK.^n]g_F7홀'vI@ڊpㅦql(Y;ԽbMa氲.О%ROBw_5쬵R#]i:Kl{?yx!u]͟lr/Jntv_?v9ḧH$](Z ,C8~x|C9"W WQ5lt=W4#`U6KAcܵewlÌLf 0akuEPewuu0,O9GWKoPKCRHu{OEBPS/ch07s02.htmlVQo6~M{ آlh*$E $kYHKgE$e~GZr, 0Pdwww|x$X,ƓPe:E_o#Kp)}H/_o.td1c3voW0]AT:WclěX-f|:{O'ӹa֊DpJFs{cϭ`S9*mPbWr̡5!p<:K8!vxB~"tU µܣ59nIudѪHcTR9iSZ Yek°G^(f  K4_WZO/V\,oR3y3l3-ָMjpTq:FeGP Z4fjed5JX/GX_;D! 1x~oM97 ^.A2Rg\9̅9IdW%*ɯ') 1I&O@_yЄvzL{Cf*’2G:R鍐2LaNJNSrB*% R5ut5Ɛ:tboEޛ7u]wDZn{w\">.aSnykrrr28SEz%f+oڠxC+Th6\+/SY%;+_e)_bA.#PsDG}N+Ǐ:9xN8bԂ (ՌN(m{+5ٕwHPN[bנKjףp==ap^mwPplZYj#E= N9\ :!%gG(K!12FY>l2(zLv9_У.jo&~ŧ,etr'<5:Ә J] ,aH)keB-kc8e&BN5k]+(u04&#"ۆVrjUe_? #Sa֩́ 5F"JQNФ=98ڢߥoBOPѥ {~]ہ=0}A &}U mϏ g֛fPKBRH:ODfOEBPS/ch02s02.htmlW[S6~_qꗆХde!.;>(bk%W¯9 ,lY}B’+F^\%:*F_g#I0R:<0j<>9ܡ8?1|y^?O.#r?xZV=mxvߑxO^h4z7eψ], p0Aw ++n&D+׆ѱNLZrs,׏ 6:]XB"E,O\?:6Kp\[#0R25ΣX>um7([n-l.֑gn4%SrSDF+rh%ݧ'JYYJ)+r&TmVBJJrL@(`^9bT! bԨ%Qvm/ joEs:, 篺ZuzMTlKf#!K^Na$,+!:]W8OQio漥`?/k URrIz.n9w1!hU)< b驮5z:`AXX{p WF9y)r] ĒpvgvJBdƒCP *LэCiWHԒ"9C#:҂wnyhWOp:ϥMJɩ &dV% ED j2;<T59qExaQ +„lY2NK) /K9H}%0 \eN:YD:#_OH9KdL3?U!!9On}C,5n LKnVrFK!eO'ۂR\(ڡɅPb^9J?١VCerNPy^S="0)$ux{V)8DIHv^۴K.uIya?7|m m;m]҅ڀZ߇݋Hj7dFZT%؎cth4 [ 0_#m W 枖ݷAΖLHZzGp[ ^9H?Mxt+8_B+YӴ3ؘb}ӵE.b<'s r91i-*ѧ9+jK\KGhzkiHk  H\h EmL Ag1"6\ 7'w NC:vD^n"_&O"~wYa q9+Nµ}O %VũlB?\m^O»RLhPKCRHQR_OEBPS/ch05s11.htmlXn6=y cc N?&M:3Ab?hD`'sIʶ6In({y幇}Vl-'t0ry>~0xSr1O|rog+7o{%,,b?p%,DŽ%+ڋ,l6i2){O)i$y`@C/NnKd1,q-E# M 8 'WNwm+!e_?KIϲ0B|V5+jEKj:xwrԺ)E)~/( ?Ϭo4ª[Hbk[man%-ӭҟ <3"emwpo[q`DA$,4۹YǢ %>b5ˢn/km,8!LrM>9ػt:QS>Msm +ɕC~l u#zh#%yvѻS[MjOȊ Q[٤ hD+,e2) mGeG=2.k IG[mIJR~[aUͪ`QV=Ę}MqaXUl( ) J+7T [ײ!j\s#JZG>9a$.u!3F(b~tWqxtpV8PFHwUJޕT z_1CTqr-prS/ %6=gV46U@8djǭCp`LV`@Y G9/vŭs`~.Eu@7imh>7`>P5rY/յkoيuL.zQG0bQxN˱x AMV~ lkZriDz 7Ԃ$yz`{ڸvPFNJA55`Z!Fm'*/ /WO {g`;Uw|-)!f!E'1dt\ z$@_KAa;֋kk#(-1jcL6o3P->N =U밍a@FAR7#lK0 O8#$?G]jM5zxh.Mz6|{TmhKk]?Z:5ϷzZ0pf|?N)e:ԓd2Np=>_:bzXgS ȟ6H@zpTNN_s39}?>2Q&hoCMwa:ղ霠Ey!:O@g15))Ț'OIɓ…} OB+_U5CN|wU[R6t@Ni`K;:"̿LwO*uB0}t|'Ϣݖ25q\gLF!o2Q<ιl*=|qF;bK;̈@eQ,PKBRH>OEBPS/ch04s04.html[mo9 Ȁ,ř݌֮'\ybPݔMwmYk/Wil/p3bǖETS_HܩjozB% u2?0]O\&LNzew_>E~F?}~4:\]ht~EGr.l>|CP> 7>fX[bO6 =zTp|"i&zL\a}'OzXL , ?PlWqy|/q:ȅ"5iDnDf:QʼnL:ة2:R@L H`!2fZK0*+nfNDPA1äC/\z&0AR CeGǣt\om*R[ B6L2ߪ 8 Lz1J#(9ոZ>?L))eP$"Sv4sŀ!2m r}&@گʛR~[a!RGm6\t n¦1#Kƣ(sE[s.a}5ŝXV_ UXVD{=ɏ ^TYc漦6d "^f%)yNgd{ 5]奉gvlNZ<5뻭a F=Kjs5ROK.'{ Q3:D)ALMA'jfSM3WpEHi!;"^=HU8m׺KG_":&=~2O{e#F]:MzU /2ȇ bF#4Z㾚TRV ^KH&sds(7_'ל7?c̼dF)E@l ؆%guy;x&$ۮ `D7D7+Q&J %5*Tۓ7 ID@X&C,"Ϛt(>'5BG6Sqڸns1 M|z}V~[SL%bMlLn0D3K/ (n;cA[x `= )t YZJ;8KnMy||qm6&v"miB%QѣErfYiK:}ߛ%1qDIi!t8P 3iy~-t`t dVbK ZD%tL-n;]]; skrw;|T\b+ Xd2{R!5 1Ӓ_L*j-H*l!$t #LX$yĥpK0TU5}0/nlF8_xRS% e_E)i(]{1=Fz Ltvϻ?}d)V--:\Rt=_ƒUA;UDQ+ಸP78`6#-rfNa5;_^xӻ.'WՖ|+;ėqr bbVC5<)ct >:ߡ"0Kթ6\HeFd+cjI!n(Ns÷YZJ E4R3ƒz\ +eGyDJ6^(ߴ07iwYUa\ݞnU趄W_s޾N" zݠp8m1ECE6mIV ~ "M O/eF@gyq3;b=g=OC@`뤩6JXn?GxT6[2z_L I)`$gVDBϘNcg؊9"N NB8۴`}2[#1* }՚ƾl;TfX哯z0'?Ϯ}]q7Ԗė?Sݤ1[zwB '`AVgƉ NI sNI?oX:dNF<1Z7{+m O.-\r!9%9uYiܐB7/ڷV.u/hdعKܭD_끸~|v-ʅAj}V)kuꍋ?{,9kR63Q p_3:\A U=5?dVDg&%ajɡM=f(̕Yy?QLꒂJK[y<++J8E+"hI.6*AYUrkݪ_~mΡFmb(L5iа8ֆ7q7J;<|Pj)5Y.43fS%Ѭ57[g\y2IX$>ȤkW6GL^eI cɪ9*5NbqeKosfK@kF4ET1N([ Bm?]jA v&JB T/OAu׮3IomaYcܙ*6geNsA&{ΟI5*S9 w.gA=zsF)a͓qioߋwosMRi56TGHCE%HrSmyOڶIuŮID4//d}Ҝ}.sF.$7yGP+S]aE͋" fnުq2d`{w> 9rUM=L`=ɥed e 3̹xH#ΆCUyYO,r+?#ɞNUcLt"ذ&G;pa]Izȼx_ :a7@TDΔ*x񕉌؜] \m;Ӕ.e)nB޲MgV4Ñ!9=TƍiShj$U$" Q>,HB5Xy3(}޷$Vi^+$I"&߮ BSe#mo "REg0 -̼wjhrj,Q2.P@%Yp^xl7ѥ/`}aq :)vاz\NWQ }>Yu|,[‾9Z\ޞ~wί$:(6 ,4B{C ]N~XLL>^\~8;*W95{PHy*yk4Sv0@Yr6Ƿ0(&4Cw*ьYQ**)m1/U(j"SP  JUe[CQ[l?L}{DӏPKCRH"3OEBPS/ch05s06.htmlXm8 bttW`-}HNn2mu;[zN&mnd<3/;̍jt,r.O0Kp(<>?:{{:Kn^^>`؇SfgFሱ7 c*\:_{řFΠcӱK)30={4p"c+L9,Dn͘w)Zb snu@Ee'^j} /ڮ%{4l:fNsXA$ Fv_b\}$}AzQv]PE]5>k6͂ɸ4Ktz%L4ft1f)8$T˂r.At ȭAb~%[$avH Ew}T.JL'cMWW;QG:M)hcskɻ pô1LSM",pu X3PҊ$tXClg8DP[CaJP:u:i%[R96;ӪnjȽ'ʔ(h0ؕ K!s=?20ִJwa< zC\- IOٕVË\.jEI CL$ +wvl:b#`ZZIЄd7)= $Hyj(qaOqDZ2,:=ޑ7䈄x[ۊ%iZQq  m!A|c^AY?ؑgwGYX4,!#譇=fNQ)ewXCrc VHgV\R贔rrD%ĺ>չzπ҇VrsDfcl,ӹuubjjh[HKkr',_]BsC[p7jsIMGPe\;紱 qǾLuWg7>W?Ks{Wmu\i|eSA- ƒ-0 sG,Ü|M<5c&štB)Fzw{N@گk @v|4[wOJO}4[޳DBmlt9)rz:14 jRiܼoJ-.W|mrN;~P{<<&A暦LPq8w̺@)dӡ.hðZ>^AESY(v]{[)V{v/Kv 2xµ;pC@giXgͦ EWaݰZ4Ȱȑ4&{ZR8Pȧ `?t+O7A/kS9q۪"<$"PG@=ʉ(xjXGNTywꔈV {B#m x1BTtsl b}"8 v*t&eWc4"Ҕ cf,ߨ;E="tVOD0i~lZqNH7!痼<=zN!Vk <ţO<17s<6ihpRL/c/u?PKCRHg OEBPS/ch06s10.htmlUmO0_q6i LC}tkbͱإҢ ĴJ#瞻Ƈϥ'4zĢpdR#v;1NL(qĴaɧ GWg'''cx58(8?d E?{({%qKi;EN:5ZWԁHStQ VQ_c޺%:ZT]kL 5ڡv#661nR-(F'1oSlę|T K[L]6ȱ=EqOwd6b]C=?A~*9`f}S{`um+WT82cr0:lӹTYeUej3Sa@vNFbzZmCS i0!f$QDyB|^ړHS<`YJK0X&AVQƼJ^4:JNC|>f@6j)sRop@=L*g GXgCY%@ nwn02ٍ׆A~PX)\@nMН2/V~⇯咀H>J g3X夊u."D+@jڢJ͞<8]Ǡv7:ʫ  ;> a,Im/3 ,R|Жeۮ=$PKCRH5_OEBPS/ch06s14.htmlXrF}U$!+YK2H*IQt⭭}C`J f~Oj;> NTUFO""*M"NTFiM럮zAwW Wq|w4!(wzǛfy92u/ǟX|h?^Q<Ҥ$UkJ a៕GGJd2n?s<iTV >Q>3^ I5]qt!*%R&^-̆tS? hkV:jpKF|V8FrڬfsvA|IʲeUDU'gNbmV\zT*W))}}qAt4{mx[\f W#B1tbh}^}7kYIj5[mxQ,)\ CWʒEڹЬV !Xx 0*؞|Y:E2Jᗣ .U}Tޏ.'?UJkQdUkjiv{5!m[ws"P`,+]R>|~+S"*$"݉ EtޟieET*dǰ?h ]i,šsІ a0VP (CmSF!QJ%]m@d@K/Bڒ]!N&i5M*bb 8o_}a#(ǭu<"ZA{Mt{k>l o2-uM?{7aWQ 0(J{_+U0zQ"9:U(M` ʑf Ս:k0uťȲ?8R<̰/PTgtdɈ|I*w*4P)ӽ@cOC:[P%O!"[i PW-In\؜z.۷7*}8o;A&a%{]JHtO8C oMk{B7\^K{ d-m@R; ~#j^ux*6JQcV rob^|w'K7 lM/|EQ}i tdm+lOD$>pSBc0eVҗ*x^2 >;J֎qAiɞ.t_$b#²QL]~Tڏ._2R$]b҆ߵp`Oi)\ 0+(mCv6?noj]6rYܙv9IVPRwF0gp{/?!PKCRHBx OEBPS/ch12s02.htmlXs/gH G)&$qO"XWwAivz<]}vOoFܒul ҥ^d?˄RW1.2moW_-꧗xZ?\}Rdx(^]xb/Ld݋v<7v[\\ܱbs^*[-_Ħ=ϟ|dZzZўV0kNTZ놖ptْBYmIL.^ʘ/o/~ߐ_O勬X-kSWJ݊;*";z- zq=BU ;Y_O@(W",{CxǶS Us@hkrwT]MzDm%DZQ+U*n(NpLZb*W{QFfkeWR6Fo Ǧ8X.DއXR:!dZX n/`YFR⪥\\׽ bֽjV4|@JLN56HR Y2qT$BI9N: oZF[$6|m| o/nu ƒ_h^ieW"zM#b>'j%!j1fY˂'J1 cj5 3Bq@!4&tœOSp!?b2YeN <|}\ }gBeŽɷ#MkhP>0b[t>&68vϬ :JMCw߂! !==3oBU9 3W C EEE1ԲB tWXlj!86^ [?9)qȿ>AG 厗_@)xrm>4k%0CPxxGhs}< QxSDww P)`)0w,>!xe?g85Vf1UUFYڵl&mqnvˣ5r7tAZa6-z~^ͻ&ćLf}wa8wt:Xv^7XdlgQz*a 6^) ?PKCRHqvv (OEBPS/apa.htmlZnF>Ŭ.2`4m9v#qQQ&9,ghYXYdRN$s{A"(ϙC{QhAo1*YIDIK?þyMiәK3Y4qD>(3/S^&0 ZJFEP*_ą+paR[ӟ<gIƆ\*cӳہS T$]xI)ӑOikV0{@͊l* mPQiPC Ec`YtR.=#%lJGQ!sh,d6~Ⳛ~1yϪu\M±*_ /YY=/ \R<r(h]ZTZGLơ`?tٻ.Y,P#K̀y0˚']uQ.E4Feݭ6L4$J B+;uW=LQ 'i{I1WJYDNmU譚P;h0%l*Fu۠!8"ПDٖN Džl2D:r|#caX.9&F5ZgSs%e%4x#oKcGR(ݔ~qw(r@-ŅDơ$b;ӎUJ~2sUm`|$4i`y?!`mJF=FI3fˏ:mR(!OW<Nr ZXK`ao8v_va5:8 5B R3}Xh \*ٝr{H]Lg2d3!7$Q##d*LW6}43&1BDR&-:1 Q^@6G..r><>tէ. Z-E kq>ZI]v=[R m^_ڨmZ)tNV"G+2}(rԎ 4: yt섾ͤpCʆd;9^,Zm3,T@=նZHf%nΩmG*mbaSUv[9&\qo`Rfєz't6EI7"2F] #hH tFUJvmwʑXo?]>i(Ncj<އa<҃뷯߽.o7煳ށ?s:Mb9aA!C40V<|M'G\+j#%MlDs|psڶߜKzj'Ǧ۩!HİPi!M:-Y;E;UX nPtlR [h~bt>T4 7Jۖ rN`iǑʹrGuviϤAv3*E©Ge (r%P2 t%\9jv>3iף"VK:X4 >wİ5-OBc-x^|HI%|:m̂hE0yhK[(ɢê9i`NLAM~ ,a}"X҉@/qjCQJ7&D;P8ll-pw"O4g;*0lU4>ӸdbgRFthˆ5Mk**]@^5t#6&9 v!@Ti>į{5D]0[UoF)m]=GQ-i˭#6Zbx *u'xn ǽ'>! Z@3Z_^4)rh'Cj}-Y# 6&<փƑGP,7K7|=DW^cԺu34L0 m!BC6)]F,IZzTi K -|ۺ["1z AϱCʪ6g(g-+vt2uG Bɂ-w{^Rpi-= &E䮢jv,ps٢;ZM!11cΌQ}} ;qVm enpPVĕ(c)o` H/v4\h>lzcWPiP+B<[B&+9gaa.@Նf^=Ejgl9_y(#ԭ>ʩ'\lA[e}f%{fmpB9sGyS?ݣ7(Kj9"y3Tȯt^$q`R@@q7p}u[5#vm6ƽ<ݽ>W#FeqNNHn 5mmܸD跂-{Kk[Co·fVevAe &_yT^%S<g㴇}J K jBݫ;]ĥ?Oʘ=Pyf{Hժ4 \;6ZP -=jFf۰AY3Ń}tܻOE-F5|#`J œǹ(hDde9`)"iRIB歡.緬s]8ZА) dxdAޚQG^ hA{_PKBRH#jwr OEBPS/ch04s10.htmlV]o6}N~ŝV{E &U$qҠv)%ZB*I1]RuؤM-iÕFI<\\bmRYP$FREPY?8:=9hLDŽ3a)$qB怐z_Jd8$qEI34 ܣYj,0H +%@Ғ+fYL2MJZ&4H+2?f*Ƭ?׷q,%å*6YZk5HӰ&lhɺQ%{ 3EDQ%HMvLnt@i=窮1Xd5X,% I{Q-V\V LycpXas:GY^27"% 06]\Jo-oCz8( Qek`]aT\5[ݧmsO@ȳ d7,[)͠P>ѪXSi{}ۻ:aICbuc+%Z;bKv&V6ZUGaD5SA:Hp֣H7E mM/BE ,p(6\Ւggk FQ Ԛs"(]U}A-XVw C.m+?]JBZB2#kW>BHH`oX,c8~D9qp{@mDS쀸%Vxx6؍$n`/>/,yC4q*CϏg ApJr?X7 9ВK^]J^ ed2~RRTiU+S\~=]d 57xc܆nrTS}kqħa@ +$}їQ?ýn_a<ƒ;:Q<^;hcKpmdKckF*s\3іnjyEe\q4,v^L^< sϊM!MͩuW 'x|t ^ۀwPKCRHHѴOEBPS/apcs08.htmlTN0SE R'cAЂ@KnL~mQ6bO'ٵؘDT=QG%ֺPr~D̆tr<@.S.ġ'oDoƗɗ# ᯦g#}16dr~2vtၗS14l[xZz&6@`]qd #0ܑvkuDA2Pb͍=H4(P;9"dh4| ;~8bmJWqKH$RcbBŬx{s:PC/l5<$)[*!QXe/bUxh+.תUoҥMdRc[:m?z{$M]~>ڿcM׹% ,א+3W:TgJ 2b+bXQ0IJXe>_NvRHV/8]'^70`Ȕ&9{ry~Á\,ț:t^p!L 5m0 TRqVMCKպfsf5͖bwK.eeqXWU)E̋"Qh|8Saz:H6<݇I m+5`̇0`:ٮp:x-RPBm-c l0 ʅ60C$)h'{_PKCRHQXIOEBPS/ch05s14.htmlXs6~n {"g'NsIMһ\-鿿]Dm\ OU%‘׷`z[Oa 7inU&]X|M^Mׯ_>"Mt%= ҵx E;IĤB'@۠B#6ȴrtpZ?{X}@t~'7 MJ$’37^y`xq;} :qPds+W~ߤ-5ZղDJWmZ BZе#`\@c^`1OzvPB`DYg̒SIFĪQdCQH gvV:o(vu]L߃U!j;[r.p =6k.@&iEOJiGWpfD# }˵:*">'"4F @g‚1k%Ds~&H5,([tlyϢ0YÚJtP& N0}Lx0Q K7$ 69:u> uaQc< וP5paxTR#-(wdEtE^g\^%ȐJ<]TJT \&;K&\Y>p&UV6<’B_bOiAdv X߅=| Rt)<Pj4ET4xpp4hRa2%3tG%A%d4L <^ 9t-'*ꉽn(LTqd<7?~? U+Fq"C&}eWgI&)VOALc1`C=Pc{%zbl}y? GH#xt4YC#3( i 6v$Gev((G8=pI눡i$px>L%zX JP+\X6zni`kNx2}$Gi`H'>ȼ־|ZVշW77ׯn}}MNs=D^-*ƈK4 _97-hMs9G߂ EBI8׾Qj6TkR_ ӭ0*EcҌDゎc`5A 4pp~p _tߖy)N5 z-\Oqj򹃵_[ :͞Hʘx:&0H"VUoFAZJyNVS vAxTxXaA%'-]utɊh=6+jt~b"VѺ[xQ9r?rݔAcdMxT} UqHaB~7Y\9+e44'bG+ k jy R|_Z. H˴ >wa4LM::_@܃ R]KkCa1ł$r<9W~54["Ee[ F1U O!mIWR}IF"'𷋔2/PK DRHoa,mimetypePK DRH A:META-INF/PKDRHXaaMETA-INF/container.xmlPK DRHADOEBPS/PKCRHra| q3hOEBPS/apb.htmlPKCRH^  OEBPS/apcs15.htmlPKCRHQ}[jfOEBPS/ch05s16.htmlPKCRHVv (m,OEBPS/ch08.htmlPKCRH7h ~9OEBPS/apcs14.htmlPKCRHh)K=OEBPS/apbs03.htmlPKBRHꇯ:@OEBPS/ch03s10.htmlPKBRHkBOEBPS/ch03s12.htmlPKCRH ~IOEBPS/ch12.htmlPKCRH[YPOEBPS/apcs07.htmlPKBRHN0 dSOEBPS/ch03s08.htmlPKCRH;H&^~ XOEBPS/ch09s03.htmlPKCRHsor]OEBPS/apd.htmlPKCRHAsGdOEBPS/ch05s21.htmlPKCRH՝ NkOEBPS/ch05s05.htmlPKBRHy$ oOEBPS/ch02.htmlPKBRHa7 rOEBPS/ch03.htmlPKCRHm/pvOEBPS/ch06s08.htmlPKCRHVJ}OEBPS/index.htmlPKBRHG9OEBPS/ch02s11.htmlPKCRHa2 %OEBPS/apbs02.htmlPKBRH!F<j OEBPS/ch01.htmlPKCRHmRSOEBPS/apcs11.htmlPKBRH[] 1POEBPS/ch02s10.htmlPKCRHn)ݞOEBPS/ch09s02.htmlPKBRH?~6OEBPS/ch03s03.htmlPKCRH;jaIOEBPS/ch06s12.htmlPKCRHfVWOEBPS/ch06s11.htmlPKBRHs͹OEBPS/ch02s06.htmlPKCRHŢ]hŸOEBPS/apas03.htmlPKCRHN*\OEBPS/apcs05.htmlPKCRHw ' OEBPS/apcs04.htmlPKCRH|Z  OEBPS/ch10s02.htmlPKBRH)OEBPS/ch04s07.htmlPKCRHqfcgOEBPS/apcs13.htmlPKCRH~'7 OEBPS/apcs10.htmlPKCRHjOEBPS/ch05s12.htmlPKCRHOEBPS/apcs12.htmlPKBRHsF OEBPS/ch05s02.htmlPKCRH OEBPS/ape.htmlPKCRHpcOEBPS/apas05.htmlPKBRHãs ROEBPS/ch04s06.htmlPKBRHuaNVOEBPS/ch03s11.htmlPKCRH3]} B"OEBPS/ch05s09.htmlPKCRH?| !H OEBPS/ch11.htmlPKCRHlƖp-OEBPS/ch07.htmlPKBRH5 =1OEBPS/ch02s03.htmlPKBRH[* Z6OEBPS/ch02s05.htmlPKCRH幉:OEBPS/ch06s07.htmlPKCRH8 _=OEBPS/apcs03.htmlPKCRHщe  @OEBPS/ch06s05.htmlPKCRH>? HOEBPS/apcs09.htmlPKCRHEZIΡ zLOEBPS/ch05s15.htmlPKCRH l UOEBPS/ch10.htmlPKCRHQ5. _OEBPS/apcs06.htmlPKCRHOr}bOEBPS/ch05.htmlPKCRH҉iOEBPS/ch05s08.htmlPKCRH;# lOEBPS/ch06s03.htmlPKBRH] U sOEBPS/ch02s07.htmlPKCRHnCܻT xOEBPS/ch05s13.htmlPKCRHzeq{OEBPS/apds02.htmlPKCRHjρ0~OEBPS/apc.htmlPKCRH6 &֌OEBPS/ch07s03.htmlPKBRH OEBPS/ch03s09.htmlPKBRH<wOEBPS/ch02s09.htmlPKBRH>brOEBPS/ch03s02.htmlPKCRH , OEBPS/ch09.htmlPKBRHR4*8 OEBPS/ch04s02.htmlPKBRH`\T $XOEBPS/ch02s04.htmlPKCRH|9zOEBPS/ch12s03.htmlPKCRH% UOEBPS/ch05s17.htmlPKCRHڇuOEBPS/apds03.htmlPKCRH(JMOEBPS/ch12s05.htmlPKCRHD0OEBPS/ch05s07.htmlPKBRHz+tOEBPS/ch04s03.htmlPKCRHO"OEBPS/ch06.htmlPKDRHpjM6:OEBPS/content.opfPKBRH*J,OEBPS/ch04s09.htmlPKCRH: kOEBPS/ch05s10.htmlPKBRH%dcT OEBPS/ch04s05.htmlPKCRHń7v65OEBPS/ch05s20.htmlPKBRHaЈ6s/OEBPS/ch03s05.htmlPKBRHYlm02OEBPS/ch04s12.htmlPKCRH`5/OEBPS/ch05s04.htmlPKBRH&ךL"NRKOEBPS/bk01-toc.htmlPKBRHG/F &[OEBPS/ch04.htmlPKCRHh1_{QgOEBPS/ch05s18.htmlPKCRHO/AjOEBPS/ch06s13.htmlPKBRH*p? lOEBPS/ch05s03.htmlPKBRH.n]pOEBPS/ch03s04.htmlPKBRHfwwvOEBPS/ch03s07.htmlPKCRH*v0)zOEBPS/ch05s19.htmlPKCRH,OEBPS/ch08s02.htmlPKDRHO[2 OEBPS/toc.ncxPKBRH)Z>sdOEBPS/ch04s11.htmlPKCRHq@>OEBPS/ch06s04.htmlPKBRH5i ݤOEBPS/ch02s08.htmlPKCRHt / OEBPS/ch06s02.htmlPKCRH>B%4OEBPS/ch06s09.htmlPKBRHd[3 OEBPS/ch03s06.htmlPKCRHujiOEBPS/ch12s04.htmlPKCRH#? *OEBPS/ch11s02.htmlPKCRHìjTOEBPS/apas02.htmlPKCRHC{OEBPS/apcs02.htmlPKCRH`ET OOEBPS/apas04.htmlPKCRHu{OEBPS/ch07s02.htmlPKBRHr=OEBPS/ch04s08.htmlPKBRH:ODfOEBPS/ch02s02.htmlPKCRHQR_<OEBPS/ch05s11.htmlPKBRH>OEBPS/ch04s04.htmlPKCRH"3OEBPS/ch05s06.htmlPKCRH|lOEBPS/ch06s06.htmlPKCRHg oOEBPS/ch06s10.htmlPKCRH5_nOEBPS/ch06s14.htmlPKCRHBx ] OEBPS/ch12s02.htmlPKCRHqvv (OEBPS/apa.htmlPKBRH#jwr : OEBPS/ch04s10.htmlPKCRHHѴ$OEBPS/apcs08.htmlPKCRHQXI'OEBPS/ch05s14.htmlPK{{P.samhain-4.1.4/docs/HOWTO-client+server-troubleshooting.html0000644000175000017500000003253212615253277020621 00000000000000 HOWTO client+server troubleshooting samhain-4.1.4/docs/HOWTO-client+server.html0000644000175000017500000003010412615253277015365 00000000000000 HOWTO client+server

samhain file integrity scanner | online documentation


Setting up a client/server samhain system



This document aims to explain how to set up a client/server samhain system, where the client (samhain) runs on one machine to be monitored, and sends reports via TCP/IP to a remote server (yule).

Please note: the server (yule) does not perform any filesystem and/or kernel checks. If you want to perform such checks on the log server host, you need to run a samhain client on this host as well.

Client and server are distict applications, and must be built seperately. By default, installation names and paths (e.g. the configuration file) are different. Do not blame us if you abuse './configure' options to cause name clashes, if you install both on the same host.

Introduction

Samhain can be compiled for remote logging to a central server via a secure (AES-encrypted, signed, and authenticated) TCP/IP connection.

In addition, both the client configuration file and the file signature database can be stored on the server. The client will then pull them from the server upon startup.

This requires three basic steps:

  1. compile and install server and client,
  2. establish trust between client and server, and
  3. enable remote logging in the client's configuration file.

Compiling

The server - yule

Note: the server can be started with root privileges (e.g. to use a privileged port < 1024), but it will always drop root privileges irrevocably before accepting any connections, and run as a non-root user. This user can be specified explicitely with the configure option --enable-identity=USER. The default is the first existing user out of the list yule, daemon, nobody.


bash$ ./configure --enable-network=server
bash$ make
bash$ make install

The client - samhain

  • If you just want remote logging:

       ./configure --enable-network=client --with-logserver=server.example.com

  • If you want configuration and database files on the server:

       ./configure --enable-network=client --with-logserver=server.example.com \
            --with-config-file=REQ_FROM_SERVER/etc/samhainrc \
            --with-data-file=REQ_FROM_SERVER/var/lib/samhain/samhain_file

The path after the keyword REQ_FROM_SERVER has the following meaning:

  • for the configuration file:
    • if initializing, and the connection to the server fails, samhain will fall back on the local file (if given);
    • if in check mode, it is ignored. Samhain will abort if the connection to the server fails.
    Thus, the local path allows you to initialize the database from a local configuration file before the client is known to the server.
  • for the database file:
    • if initializing, the database is written to the local file;
    • if in check mode, the local path is ignored. Samhain will abort if the connection to the server fails.
    Thus, init (or update) always requires a local file that must be uploaded to the server thereafter. Note that if you use the Beltane web-based frontend, database updates can be performed on the server without ever running an update on the client.

Establishing trust between client and server

By default, samhain uses the SRP (Secure Remote Password) protocol, with a password that is embedded in the client binary, and a corresponding verifier that is in the server configuration file.

Embedding the password in the client, and register it with the server

To embed the password in the binary, there is a dummy password compiled in as placeholder, and a utility samhain_setpwd is provided that

  1. takes a password as input,
  2. searches the original binary for the correct place (i.e. the placeholder), and
  3. writes a copy of the original binary, with the placeholder replaced by the password. The original is left untouched. The copy cannot be changed to another password anymore.

For convenience, the server has functions to

  • generate a random password in the correct format:

       sh$ yule -G

  • and generate a corresponding entry for the server configuration file:

       sh$ yule -P PASSWORD.

  • The generated entry has a string 'HOSTNAME' that you should replace with the fully qualified name of the client. This entry must then be placed in the [Clients] section of the yule configuration file (e.g. /etc/yulerc).
  • Finally, you need to tell yule to reload the configuration (send SIGHUP, or use /etc/init.d/yule reload).

Example


rainer$ ./samhain_setpwd

Usage: samhain_setpwd <filename> <suffix> <new_password>

   This program is a utility that will:
    - search in the binary executable <filename> for samhain's
      compiled-in default password,
    - change it to <new_password>,
    - and output the modified binary to <filename>.<suffix>

   To allow for non-printable chars, <new_password> must be
   a 16-digit hexadecimal number (only 0-9,A-F allowed in input),
   thus corresponding   to an 8-byte password.

   Example: 'samhain_setpwd samhain new 4142434445464748'
   takes the file 'samhain', sets the password to 'ABCDEFGH'
   ('A' = 41 hex, 'B' = 42 hex, ...) and outputs the result
   to 'samhain.new'.

rainer$ yule -G
5B5CDF18CE8D66A3

rainer$ ./samhain_setpwd samhain new 5B5CDF18CE8D66A3
INFO   old password found
INFO   replaced:  f7c312aaaa12c3f7  by:  5b5cdf18ce8d66a3
INFO   finished

rainer$ scp ./samhain.new root@client.example.com:/usr/local/sbin/samhain
samhain              100% |********************************|   592 KB    00:00

rainer$ yule -P 5B5CDF18CE8D66A3
Client=HOSTNAME@8A542F99C3514499@744C3A3EE8323470D9DAD42E2485BD0B138F6B4116E964\
A9991A0B0D221E1AADE5800968804B99B494C39E7B9DD5710D18F1E6703D1DB6D6393295E05DF6A\
6AA8D10BB4A21D7D9DC4901D444500D4EA358C1B44A3E3D44ACEC645F938F790A11AB0D03586143\
977E2BCE3A2D689445AC89134B409E68F34B0DE8BD8242ADD7C0

rainer$ yule -P 5B5CDF18CE8D66A3 | sed s%HOSTNAME%client.example.com% >> /etc/yulerc

rainer$ tail -2 /etc/yulerc
[Clients]
Client=client.example.com@8A542F99C3514499@744C3A3EE8323470D9DAD42E2485BD0B138F
6B4116E964A9991A0B0D221E1AADE5800968804B99B494C39E7B9DD5710D18F1E6703D1DB6D6393
295E05DF6A6AA8D10BB4A21D7D9DC4901D444500D4EA358C1B44A3E3D44ACEC645F938F790A11AB
0D03586143977E2BCE3A2D689445AC89134B409E68F34B0DE8BD8242ADD7C0

rainer$ /etc/init.d/yule reload

Note 1: the verifier Client=client.example.com@..... must be in the [Clients] section of the server configuration file. It is convenient if this is the last section in the config file, because then you can just concatenate the output of yule -P PASSWORD to the configuration file. This allows for better automatisation with a simple script.

Note 2: samhain comes with a deploy system that handles the deployment of clients, including password embedding and server configuration, in a semi-automatic way. This deploy system is tested and used in a production system of more than 50 machines, and described in detail in Chapt. 10 of the MANUAL.

Enabling remote logging

Samhain has multiple independent logging facilities (such as a local logfile, syslog, e-mail, TCP/IP, etc.) that can be used in parallel. You therefore have to specify in the client's configuration file, which logging facility you want to use.

Selecting logging facilities is done by setting appropriate thresholds in the [Log] section of the configuration file: each message with a priority exceeding the threshold will be logged via the respective facility. Setting the threshold to none will disable a facility. For details, refer to Chapt. 4 in the MANUAL.

Example

To enable remote logging to the server for all messages of priority error or higher, use the following directive in the client configuration file:


[Log]
ExportSeverity=err

Databases and config files on the server

The client does not tell the server the path to the requested file - it just requests a config or a database file. It's entirely the responsibility of the server to locate the correct file and send it.

The server has a data directory, which by default would be /var/lib/yule, but depends on your compile options.

Config files and baseline databases for clients must be located in this directory, and they must be named as follows:

Configuration files: rc.client.mydomain.tld or simply rc (this can be used as a catchall file).

Database files: file.client.mydomain.tld or simply file (this can be used as a catchall file).

samhain-4.1.4/docs/sh_mounts.txt0000644000175000017500000000326312615253277013607 00000000000000Documentation for sh_mounts, the samhain "Mounts" module. --------------------------------------------------------- sh_mounts implements functionality we had in a policy-checking Perl script we have here at eircom; basically, all it does is ensure that certain mounts are there (for example, /, /tmp, /var, /usr, /home) and that certain options are specified on those mounts (for example noexec,nosuid on /tmp). All quite simple. It wouldn't be too hard to extend this module somewhat, to report any NFS mounts found, for example, or to test that _only_ the mounts specified are mounted on the machine. Here's a bit for the manual: Checking mounted filesystem policies ------------------------------------ samhain can be compiled to check if certain filesystems are mounted, and if they are mounted with the appropriate options. This module currently supports Linux, Solaris and FreeBSD. The configuration of the module is done in the Mounts section of the configuration file: -------->8--------- [Mounts] # # Activate (0 is off). # MountCheckActive=1 # # Interval between checks. # MountCheckInterval=7200 # # Logging severities. We have two checks: to see if a mount is there, and to # see if it is mounted with the correct options. # SeverityMountMissing=warn SeverityOptionMissing=warn # # Mounts to check for, followed by lists of options to check on them. # checkmount=/ checkmount=/var checkmount=/usr checkmount=/tmp noexec,nosuid,nodev checkmount=/home noexec,nosuid,nodev -------->8--------- The module is enabled as part of the compilation of samhain by specifying --enable-mounts-check This module by the eircom.net Computer Incident Response Team samhain-4.1.4/docs/sh_userfiles.txt0000644000175000017500000000156312615253277014264 00000000000000Checking sensitive files owned by users. ------------------------------------ samhain can be compiled to support checking of files that are specified as being relative to the a user's home directory. It is intended to detect interference with files that influence process behaviour such as .profile It simply adds the appropriate file entries to the main samhain list, at the specified alerting level. -------->8--------- [UserFiles] # # Activate (0 is off). # UserfilesActive=1 # # Files to check for under each $HOME # A specific level can be specified. # The allowed values are: # allignore # attributes # logfiles # loggrow # noignore # readonly # user0 # user1 # # The default is noignore UserfilesName=.login noignore UserfilesName=.profile readonly UserfilesName=.ssh/authorized_keys -------->8--------- This module by the eircom.net Computer Incident Response Team. samhain-4.1.4/docs/MANUAL-2_4.html.tar0000664000175000017500000517000012703400302014017 00000000000000MANUAL-2_4/0000755000175000017500000000000012703400302011726 5ustar rainerrainerMANUAL-2_4/timing-file-checks.html0000664000175000017500000001466112703400301016267 0ustar rainerrainer6.Timing file checks

6.Timing file checks

In the Misc section of the configuration file, you can set the interval (in seconds) between succesive file checks:

SetFilecheckTime= value

Alternatively, you can specify a crontab-like schedule with:

FileCheckScheduleOne= schedule

The schedule follows the same rules as crontab(5) entries, with two noteable exceptions: (a) lists are not allowed, and (b) ranges of names (like Mon-Fri) are allowed. See man 5 crontab for details. You can specify a list of schedules, with separate FileCheckScheduleOne=... directives on separate lines.

[Note]Note

If you need a list in your schedule, you can either use steps (like */2 for 'every two minutes/hours/...), or you can specify a list of schedules, with separate FileCheckScheduleOne=... directives on separate lines.

6.1.Using a second schedule

If you want to check some files rather often, while doing a more extensive check only sometimes, this is supported as follows:

  • Enclose all directories for the more extensive check in a %SCHEDULE_TWO ... !%SCHEDULE_TWO block like:

    		%SCHEDULE_TWO
    		dir=/check/only/once/per/day
    		!%SCHEDULE_TWO
    	      
  • Define an optional second schedule as follows (similar to FileCheckSchedule, you can specify a list of schedules):

    FileCheckScheduleTwo= schedule2

Rules:

  1. All files and directories will always be checked at FileCheckScheduleTwo.

  2. All single files (file=...) will always be checked at both FileCheckScheduleOne and FileCheckScheduleTwo (rationale: this is required to check for missing/added files in directories).

  3. All directories outside the %SCHEDULE_TWO block will be checked at both FileCheckScheduleOne and FileCheckScheduleTwo.

  4. All directories inside the %SCHEDULE_TWO block will be checked at FileCheckScheduleTwo only.

[Note]Missing files

If you are using a second schedule, the full check for missing files will only be done at FileCheckScheduleTwo. For paths directly defined in the configuration, e.g. with file=... , samhain will detect immediately if the file is missing, if the path is checked at FileCheckScheduleOne.

MANUAL-2_4/send-commands.html0000664000175000017500000001602112703400302015346 0ustar rainerrainer11.Sending commands to clients

11.Sending commands to clients

It is generally not possible to send commands to clients, because the client does not listen on the network (the client needs root privileges to perform its tasks, and you don't want a root network daemon).

However, it is possible to send a command if and when a client connects to deliver a message. As of version 1.8.0, clients use a new version of the client/server protocol, which includes a set of pre-defined commands that are understood by the client. Currently implemented are RELOAD to reload the configuration, SCAN to request a file system check (ouside the regular schedule), and STOP to terminate the client.

Pre-1.8.0 clients, or clients build with the (optional) old protocol version, will simply ignore such commands.

11.1.Communicating with the server

As of version 1.8.0, yule can send a command to a client if and when a client connects to deliver a message, e.g. a timestamp message (clients are not listening on the network, and thus commands can only be sent together with the confirmation when a message is received).

Of course the server needs to know which (if any) command to send. Therefore it can open a unix domain socket upon startup (in the same directory as the PID file). Opening this command interface must be requested explicitely with the option SetUseSocket= yes (in the [Misc] section).

A separate application yulectl is compiled together with the server that provides a command-line interface to access this facility. Use yulectl -h for help.

11.2.Authenticating to the server

There are two methods to authenticate to the server. If supported by the OS, authentication is done by passing the credentials of the socket peer to the server (this is a special feature of unix domain sockets), and requiring the UID of the the socket peer (i.e. the user using the yulectl program) to match a UID as set with the SetSocketAllowUid= UID option (default is 0, i.e. only root can use the interface).

[Note]Note

If passing credentials over the socket is supported by the OS, it is not possible to fake these credentials - they are supplied by the kernel. Therefore, the server can rely on the fact that the user process writing to the socket has indeed the UID passed via the socket. Thus, the access rights to the socket are basically not important (on some systems, they are not even recognized/respected at all).

As of version 1.8.12, if (and only if) passing credentials over the socket is not supported, you can specify a password with the SetSocketPassword= password option. The password must be 14 characters or less, and must not include the '@' character.

Of course you must supply the password to yulectl if you want to communicate with the server. To do so, create a file .yulectl_cred in your home directory, and place the password there.

[Note]Note

Password authentication is not supported if the OS supports the aforementioned method. You can use yule -v to find out which of the two authentication methods is supported.

MANUAL-2_4/all-except.html0000664000175000017500000000762512703400301014665 0ustar rainerrainer5.Excluding files and/or subdirectories (All except...)

5.Excluding files and/or subdirectories (All except...)

To exclude individual files from a directory, place them under the policy IgnoreAll. Note that the existence of such files will still be checked (see next section).

To exclude subdirectories from a directory, place them under the policy IgnoreAll with an individual recursion depth of -1(see Section4.5 ).

[Note]Note

Changes in a directory may also modify the directory inode itself (i.e. the special file that holds the directory information). If you want to check all but a few files in a directory (say, /etc), and you expect some of the excluded files to get modified, you should use a setup like:

	    [ReadOnly] 
	    #
	    dir=/etc 
	    # 
	    [Attributes] 
	    # 
	    # less restrictive policy for the directory file itself 
	    # 
	    file=/etc 
	    # 
	    [IgnoreAll] 
	    # 
	    # exclude these file and directories 
	    #
	    file=/etc/resolv.conf.save 
	    dir=-1/etc/calendar
	    #
	  

MANUAL-2_4/the-configuration-file.html0000664000175000017500000003706112703400302017167 0ustar rainerrainerAppendixC.Configuration file syntax and options

AppendixC.Configuration file syntax and options

1.General

The configuration file for samhain is named samhainrc by default. Also by default, it is placed in /etc. (Name and location is configurable at compile time). The distribution package comes with a commented sample configuration file.

This section introduces the general structure of the configuration file. Details on individual entries in the configuration files are discussed in Section4 (which files to monitor), Section1 (what should be logged, which logging facilities should be used, and how these facilities are properly configured), and Section11 (monitoring login/logout events).

The configuration file contains several sections, indicated by headings in square brackets(e.g. [Database] ). Sections exist to group related directives and avoid eventual name clashes among options. Any particular section may occur multiple times.

Each section may hold zero or more key= value pairs. Keys are not case sensitive, and space around the '=' is allowed, as well as before the key and after the value. More specifically: the line is processed by splitting into key and value at the first '=', trimming whitespace from the beginning and end of both key and value, and converting the key to lowercase.

Blank lines and lines starting with '#' are comments. Everything before the first section and after an [EOF] is ignored. The [EOF] end-of-file marker is optional. The file thus looks like:

	# this is a comment
	[Section heading] 
	key1=value 
	key2=value 
	[Another section]
	key3=value 
	key4=value
      

For boolean values the following are equivalent (case-insensitive): True, Yes, or 1. Likewise, the following are equivalent (case-insensitive): False, No, or 0.

In lists, values can be separated by space, tabs, or commas.

[Tip]Tip

Each section may occur multiple times.

[Note]Note

You can explicitely end the configuration file with an [EOF] (on a separate line), but this is not required, unless there is some junk beyond that may confuse the parser. A PGP signature does not qualify as 'junk' if samhain is compiled to verify the signature.

1.1.Shell expansion

As of version 2.5.3, it is possible to use shell expansion to define the value of an option. For any configuration file option written as Key = $( shell_command) , the string contained within the $() will be passed literally to the shell (by invoking /bin/sh -c shell_command ), and the first line returned by the shell - after stripping the newline char - will replace the $(..). If there is no output within 120 seconds, samhain will ignore the configuration option (and report an error).

[Note]Note

You cannot define just part of an option value this way. You need to write the shell expression such that it covers the whole option value (e.g. by including an 'echo -n foobar').

The PATH environment variable will be set to "/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb", the SHELL variable to "/bin/sh", the IFS variable to " \t\n", and the TZ variable will be copied from the startup environment. No other environment variables will be set.

In case you are unsure about the need for escaping: yes, the whole string will be passed as a single argument to the shell, like calling /bin/sh -c ' shell_command' from the shell, BUT since this is done from within a C program rather than from a shell, there are no single quotes surrounding the whole string.

In the following example, we parse the output of ifconfig to supply a list of all interfaces to the "PortCheckInterface" option.

#
# Lines broken for display purposes. Must be ONE line in config file!!!

# Linux/Solaris, FreeBSD, OpenBSD

$Linux:.*:.*
PortCheckInterface=$( /sbin/ifconfig | grep 'inet addr:' | 
    sed 's/.*r:\([0-9.]*\).*/\1 /' | tr -d '\n'; echo )
$end

# Solaris, FreeBSD, OpenBSD

$(SunOS|FreeBSD|OpenBSD):.*:.*
PortCheckInterface = $( /sbin/ifconfig -a| grep 'inet ' | 
    sed 's/.*t \([0-9.]*\) .*/\1 /' | tr -d '\n';echo )
$end
        

1.2.Conditionals

Conditional inclusion of entries for some host(s) is supported via any number of @if.. / @else / @fi directives. @if.., @else, and @fi must each be on separate lines. Configuration options in the @if.. (or the optional @else) branch will be read or ignored depending on the result of the test.

Supported tests are as follows:

hostname_matches

@if hostname_matches regex will succeed if the hostname matches the regular expression given.

system_matches

@if system_matches regex will succeed if the string sysname:release:machine — i.e. $(uname -s):$(uname -r):$uname - m) — matches the regular expression given.

file_exists

@if file_exists path will succeed if a file with the given absolute path exists. Wildcards/regular expression are not supported.

interface_exists

@if interface_exists address will succeed if a network interface with the given address exists.

command_succeeds

@if command_succeeds command will execute /bin/sh -c command and succeed if the exit status is zero. The PATH environment variable will be set to "/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb", the SHELL variable to "/bin/sh", the IFS variable to " \t\n", and the TZ variable will be copied from the startup environment. No other environment variables will be set.

You can negate a test by saying '@if not ..'. The 'not' may be replaced by a '!'. The following are all valid: '@if not file_exists /etc/motd', '@if !file_exists /etc/motd', and '@if ! file_exists /etc/motd'.

[Note]Note on backward compatibility

For backward compatibility, instead of @if hostname_matches hostname you can also say @hostname .

Likewise, instead of @if system_matches sysname:release:machine you can also say $sysname:release:machine .

Also, the old method of negating by prepending a '!' to the '@' ('$') is still supported, as well as the use of '@end' ('$end') instead of '@fi'.

	  @if hostname_matches foobar                                   
	  # only read if hostname is 'foobar'
	  @else
	  # read if hostname is NOT 'foobar'
	  @fi
          
	  @if not hostname_matches foobar                                 
	  # not read if hostname is 'foobar'    
	  @fi                                               
	  
	  @if system_matches Linux:2.6.24-21-generic:i686
	  # only read if $(uname -s):$(uname -r):$(uname -m)
	  #   matches Linux:2.6.24-21-generic:i686
	  @fi
	  
	  @if !system_matches Linux:2.6.24-21-generic:i686         
	  # not read if $(uname -s):$(uname -r):$(uname -m)
	  #   matches Linux:2.6.24-21-generic:i686
	  @fi                                              
	
MANUAL-2_4/updating-the-file-signature-database.html0000664000175000017500000001200612703400301021663 0ustar rainerrainer8.Updating the file signature database

8.Updating the file signature database

The samhain daemon only reads the file signature database on startup (also see Section4.4 on this). You can update the database while the daemon is running, as long as you don't interfere with its logging (i.e. you should run samhain -t update -l none to make sure the log file is not accessed). Interactive updates are supported with the command line flag --interactive , updates using a list of 'good' files are supported with the command line flag --listfile= path_to_listfile , where path_to_listfile should be the absolute path to a text file listing the 'good' files (absolute paths, one per line).

If you are using samhain in client/server mode and keep the baseline database on the server, then there are two ways to update the database:

  • The preferred method is to use the web-based (PHP4) beltane frontend, which allows to review client messages and to perform server-side updates of baseline databases.

  • Temporarily scp the baseline database to the client, run samhain -t update , and scp the baseline database back to the server. If you want to keep the client daemon running during the update, you need to avoid concurrent access to the log file (use '-l none' for the update process). Also, you need to avoid concurrent access to the server (use '-e none' for the update process).

    If you must access the server concurrently (e.g. to download the configuration file for the update process), you need to suspend the client daemon process temporarily using SIGUSR2 (note that SIGSTOP/SIGCONT will not do what you want, because the daemon must inform the server that it is about to suspend). Use SIGUSR2 again to wake up the daemon from suspend mode.

MANUAL-2_4/checking-ports.html0000664000175000017500000001040612703400302015537 0ustar rainerrainer10.Checking for open ports

10.Checking for open ports

Section heading:

[PortCheck]

Entries:

PortCheckActive= boolean — 'true' to switch on, 'false' to switch off.

SeverityPortCheck= severity — Severity for events (default is crit).

PortCheckRequired= interface:portlist — Services (open ports) that are required.

PortCheckOptional= interface:portlist — Services (open ports) that are optional (allowed, but not required).

PortCheckIgnore= interface:portlist — Services (open ports) that should be ignored (no reports for this port).

PortCheckInterface= (list of) IP adress(es) — Additional interface to scan (up to 15 interfaces).

PortCheckInterval= seconds — Interval between checks (default 300).

PortCheckUDP= boolean — Whether to scan UDP ports as well (default yes).

PortCheckMinPort= integer — The lowest port to be checked (defaults to 0).

PortCheckMaxPort= integer — The highest port to be checked (defaults to 65535).

MANUAL-2_4/checking-processes.html0000664000175000017500000000777512703400302016415 0ustar rainerrainer9.Checking for hidden/fake/required processes

9.Checking for hidden/fake/required processes

Section heading:

[ProcessCheck]

Entries:

ProcessCheckActive= boolean — 'true' to switch on, 'false' to switch off.

SeverityProcessCheck= severity — Severity for events (default is crit).

ProcessCheckMinPID= integer — Minimum PID (default is 0).

ProcessCheckMaxPID= integer — Maximum PID (default is 32767).

ProcessCheckInterval= seconds — Interval between checks.

ProcessCheckExists= POSIX regular expression — A process that is required to run. Must match a substring in a line of the 'ps' output.

ProcessCheckPSPath= path — The path to ps (default: autodetected at compile time).

ProcessCheckPSArg= path — The argument to ps (default: autodetected at compile time). Note that the first column must be the PID, except on Linux, where the format 'PID SPID ...' is expected (spid = thread id), as shown by 'ps -eT'.

MANUAL-2_4/chroot.html0000664000175000017500000001676712703400302014135 0ustar rainerrainer9.Chroot

9.Chroot

As of version 1.7.0, yule is able to chroot itself after startup and initialization, either by using the command line option

        bash$ yule --chroot=/chrootdir
      

or by requesting it in the configuration file:

	[Misc] 
	SetChrootDir=path 
      

In order to prepare for the chroot jail, the following is required:

[Tip]Tip

In the scripts subdirectory of the source directory there is a script chroot.sh to perform steps (4) and (5) (only for Linux).

  1. Compile normally. Make sure you use either dev/random(default if existing) or EGD (Entropy Gathering Daemon) for the entropy device. If dev/random does not exist, the default is the 'standard unix entropy gatherer', which uses the output of many system commands, and therefore is not suitable within a chroot jail.

  2. Install with the command(s):

                  bash$ make DESTDIR=/chrootdir install
                  bash$ make DESTDIR=/chrootdir install-user
                  bash$ make install-boot
                
  3. Fix the path to the yule binary in the runlevel start/stop script installed by the last command.

  4. Prepare the chroot environment. Basically, you need under /chrootdir

    (a) an entropy device, either dev/random, dev/urandom, or an EGD (Entropy Gathering Daemon) socket,

    (b) minimum etc/passwd, etc/group files, at least with entries for root and the unprivileged yule user. Replace passwords with an asterix, and make sure the homedirectory of the unprivileged yule user is correct within the chroot jail.

    (c) files required for DNS: etc/nsswitch.conf, etc/hosts, etc/host.conf, etc/resolv.conf, etc/services, etc/protocols.

  5. Create a symlink /etc/yulerc to /chrootdir/etc/yulerc (no, it will not work the other way round).

Because yule chroots after startup, there is no need to copy shared libraries into the chroot jail. They will be loaded upon startup, before the chroot() occurs.

[Tip]Tip

If you are using syslog logging, you need a dev/log socket in the chroot jail. Modern syslog incarnations will allow you to have an additional socket using the command:

          bash$ syslogd -a /chrootdir/dev/log
        
[Tip]Tip

If you are using a GnuPG-signed configuration, you will need a working copy of gpg in the chroot jail.

MANUAL-2_4/miscellaneous.html0000664000175000017500000006620212703400302015467 0ustar rainerrainer13.Miscellaneous

13.Miscellaneous

Section heading:

[Misc]

Entries:

Daemon= boolean — Whether to become a daemon (default: no)

MessageHeader= "%S %T " — Specify custom format for message header. The following placeholders are supported: %S for the message severity, %T for the timestamp, %C for the message class, %F for the source file, %L for the source line number, and %E for the status (might provide additional information in case of internal errors).

VersionString= string — Set version string to include in file signature database (along with hostname and date).

SetReverseLookup= boolean — If false, skip reverse lookups when connecting to a host known by name rather than IP address.

AvoidBlock= boolean — Run stat/lstat system calls in a subprocess to avoid that a flaky NFS mount blocks the process (defaults to off for the server, on for the client/standalone executable, except off for Cygwin/Windows).

HideSetup= boolean — Don't log names of config/database files on startup.

SyslogFacility= LOG_xxx — Set syslog facility (default is LOG_AUTHPRIV).

SyslogMapStampTo= LOG_xxx — Set syslog priority for heartbeat messages (timestamps). Default is LOG_ERR.

MACType= HASH-TIGER/HMAC-TIGER — Set type of message authentication code (HMAC). Must be identical on client and server.

SetLoopTime= seconds — Interval between timestamp messages (60).

SetConsole= device — Set the console device (/dev/console).

SetReportFile= path — Set the path for file check reports (none). Can be an absolute path or 'none' to disable. Format is lines comprised of a timestamp string followed by number of seconds since the Epoch followed by six integers: bytes hashed, dirs checked, files checked, files reported, errors, files that should be but aren't directories.

SetReportGroup= group — Set the unix group (numeric or name, defaults to 0) for the file check reports.

SetSigtrapMaxDuration= microseconds — This directive allows to configure the timeout for handling the sigtrap signal in the antidebug code (enabled with the --enable-ptrace configure option) (500000, equal to 500ms). Set to a higher value if the antidebug handler is triggered under high load. Note that for security, you can set this value only once while the daemon runs.

MessageQueueActive= boolean — Use SysV IPC message queue (false).

PreludeMapToInfo= list of samhain severities — The severities that should be mapped to impact severity 'info' in prelude reports (default: none). This option is only available with libprelude 0.9.

PreludeMapToLow= list of samhain severities — The severities that should be mapped to impact severity 'low' in prelude reports (default: none). This option is only available with libprelude 0.9.

PreludeMapToMedium= list of samhain severities — The severities that should be mapped to impact severity 'medium' in prelude reports (default: none). This option is only available with libprelude 0.9.

PreludeMapToHigh= list of samhain severities — The severities that should be mapped to impact severity 'high' in prelude reports (default: none). This option is only available with libprelude 0.9.

PreludeProfile= profile — Set the profile (sensor name) for use with the Prelude IDS. This option is only available with libprelude 0.9. Default is 'samhain' (prelude 0.9) or 'Samhain' (prelude 0.8).

SetMailAddress= recepient — Add a recepient e-mail address.

SetMailAlias= listname: username@hostname — Add a list of recepient e-mail address.

SetAddrSeverity= severity — Defines a severity threshold for an individual recipient (list). Must be a subset of the global MailSeverity setting. Applies to the last defined recipient (list).

SetMailFilterAnd= list — Defines a list of strings all of which must match a message, otherwise it will not be mailed. Applies to the last defined recipient (list).

SetMailFilterOr= list — Defines a list of strings at least one of which must match a message, otherwise it will not be mailed. Applies to the last defined recipient (list).

SetMailFilterNot= list — Defines a list of strings none of which should match a message, otherwise it will not be mailed. Applies to the last defined recipient (list).

CloseAddress — Explicitely closes the definition of a recipient (list).

SetMailTime= seconds — Maximum time interval between mail messages (86400 sec).

SetMailNum= 0 -- 16383 — Maximum number of pending mails on internal queue (10).

SetMailRelay= IP address — The mail relay (for offsite mail; default: none).

MailSubject= string — Custom format for the email subject (none).

SetMailSender= string — Sender for the 'From:' field.

SetMailPort= port number — Port number to use for SMTP (default: 25).

SamhainPath= path — The path of the process image.

SetBindAddress= IP address — The IP address (i.e. interface on multi-interface box) to use for outgoing connections (e.g. e-mail).

SetTimeServer= IP address — The time server. Note that the simple 'time' service (port 37/tcp) is used.

TrustedUser= username(,username,..) . — List of additional trusted users.

SetLogfilePath= AUTO or /path — Path to log file (AUTO to tack hostname on compiled-in path).

SetLockfilePath= AUTO or /path — Path to lock file (AUTO to tack hostname on compiled-in path).

The following options are only relevant for standalone or client executables:

SetNiceLevel= -19..19 — Set scheduling priority during file check. — (see 'man nice').

SetIOLimit= bps — Set IO limits (kilobytes per second) for file check.

SetDropCache= boolean — Drop checksummed files from cache (unless they were cached before). Defaults to false for performance reasons.

ReportCheckflags= boolean — Report checking policy (check flags) for new files, and if changed also for changed files (defaults to no). Added in version 4.0.

StartupLoadDelay= seconds — At startup, delay the download of the baseline databse from the server for the given time span (default is no delay).

SetDeltaRetryCount= integer — The number of times the client will retry to download a delta database from the server after the initial attempt has failed (default is 0, i.e. do not retry).

SetDeltaRetryInterval= seconds — The interval between successive tries to download a delta database (default is 60 seconds).

SetFilecheckTime= seconds — Interval between file checks (600).

FileCheckScheduleOne= schedule — Crontab-like schedule for file checks.

UseRsrcCheck= boolean — Check the ..namedfork/rsrc file on Mac OS X (defaults to no since this mechanism is deprecated by Apple).

UseHardlinkCheck= boolean — Compare number of hardlinks to number of subdirectories for directories.

HardlinkOffset= N: /path — Exception (use multiple times for multiple exceptions). N is offset (actual - expected hardlinks) for /path.

AddOKChars= N1, N2, .. — List of acceptable characters (byte value(s)) for the check for weird filenames. Nn may be hex (leading '0x': 0xNN), octal (leading zero: 0NNN), or decimal. Use 'all' for all.

FilenamesAreUTF8= boolean — If set, samhain will check for invalid UTF-8 encoding and for filenames ending in invisible characters.

IgnoreAdded= path_regex — Ignore if this file/directory is added/created. The path_regex argument has to start with a forward slash and has to match the full path..

IgnoreMissing= path_regex — Ignore if this file/directory is missing/deleted. the path_regex argument has to start with a forward slash and has to match the full path.

IgnoreModified= path_regex — Ignore if this file/directory is modified (3.0.11+, useful for transient files that get modified during their lifetime). the path_regex argument has to start with a forward slash and has to match the full path.

LooseDirCheck= boolean — Ignore changes of directory inodes if nothing but size and timestamps have changed.

SkipChecksum= list of conditions — Skip checksumming if the list of condition holds true

FileType= definition — User-defined file type specification (to be used for the SkipChecksum= ... command).

ReportOnlyOnce= boolean — Report only once on a modified file (yes).

ReportFullDetail= boolean — Report in full detail on modified files (no).

UseLocalTime= boolean — Report file timestamps in local time rather than GMT (no). Do not use this with Beltane.

ChecksumTest= none/init/update/check — The default action (default is none).

SetPrelinkPath= path — The path to the prelink binary (default is /usr/sbin/prelink).

SetPrelinkChecksum= checksum — The checksum of the prelink binary.

SetLogServer= IP address — The log server.

SetServerPort= port number — The port on the log server (defaults to the compiled-in port, which is 49777 unless redefined at compile time).

SetThrottle= milliseconds — An option to throttle the network throughput when downloading the database from the server. The allowed maximum of 1000 msec throttles to about 64 kB/sec, less is faster.

SetDatabasePath= AUTO or /path — Path to database (AUTO to tack hostname on compiled-in path).

DigestAlgo= TIGER192/SHA1/MD5/SHA256 — Use SHA1, MD5, or SHA2-256 instead of the TIGER checksum (default: TIGER192).

RedefReadOnly= +XXX or -XXX — Add or subtract test XXX from the ReadOnly policy.

RedefAttributes= +XXX or -XXX — Add or subtract test XXX from the Attributes policy.

RedefLogFiles= +XXX or -XXX — Add or subtract test XXX from the LogFiles policy.

RedefGrowingLogFiles= -XXX or ~XXX — Add or subtract test XXX from the GrowingLogFiles policy.

RedefIgnoreAll= +XXX or -XXX — Add or subtract test XXX from the IgnoreAll policy.

RedefIgnoreNone= +XXX or -XXX — Add or subtract test XXX from the IgnoreNone policy.

RedefUser0= +XXX or -XXX — Add or subtract test XXX from the User0 policy.

RedefUser1= +XXX or -XXX — Add or subtract test XXX from the User1 policy.

RedefUser2= +XXX or -XXX — Add or subtract test XXX from the User2 policy.

RedefUser3= +XXX or -XXX — Add or subtract test XXX from the User3 policy.

RedefUser4= +XXX or -XXX — Add or subtract test XXX from the User4 policy.

UseACLCheck= boolean — Check ACL policies for files.

UseSelinuxCheck= boolean — Check SELINUX attributes for files.

SetFullSilent= boolean — Also suppress informational messages during silent file scan triggered by SIGTSTP.

The following options are only relevant for the server:

SetUseSocket= boolean — If unset, do not open the command socket (server only). This socket allows to advise the server to transmit commands to clients as soon as they connect to the server next time.

SetSocketAllowUid= UID — Which user can connect to the command socket. The default is 0 (root).

SetSocketPassword= password — Password (max. 14 chars, no '@') for password-based authentication on the command socket (only if the OS does not support passing credentials via sockets).

SetChrootDir= path — If set, chroot to this directory (server only).

SetStripDomain= boolean — Whether to strip the domain from the client hostname when logging client messages (server only; default: yes).

SetClientFromAccept= boolean — If true, use client address as known to the communication layer. Else (default) use client name as claimed by the client, try to verify against the address known to the communication layer, and accept (with a warning message) even if this fails.

UseClientSeverity= boolean — If set to 'yes', don't assign a special severity (priority) to client messages.

UseClientClass= boolean — If set to 'yes', don't assign a special class to client messages.

SetServerPort= port number — The port that the server should use for listening (default is 49777).

SetServerInterface= IP address — The IP address (i.e. interface on multi-interface box) that the server should use for listening (default is all). Use INADDR_ANY to reset to all.

SeverityLookup= severity — Severity for name lookup errors when verifying (on the server side) that the socket peer matches the hostname claimed by the client. See the preceding option.

UseSeparateLogs= boolean — If true, messages from different clients will be logged to separate log files (the name of the client will be appended to the name of the main log file to construct the logfile name). Default: false.

SetClientTimeLimit= seconds — Maximum time limit until next client message (server-only). If no message is received from a client within that limit, the respective client will be reported as dead.

SetConnectionTimeout= seconds — Timeout after which a currently active connection to a client will be closed by the server (900 seconds). This timeout has the purpose to prevent bad clients from hogging server resources.

SetUDPActive= boolean — yule 1.2.8+: Listen on 514/udp (syslog). Default: false.

Remarks: (i) root and the effective user are always trusted. (ii) If no time server is given, the local host clock is used. (iii) If the path of the process image is given, the process image will be checksummed at startup and exit, and both checksums compared.

MANUAL-2_4/docbook.css0000644000175000017500000000672012703400302014065 0ustar rainerrainer.book .title { text-align: center } .book .subtitle { text-align: center } .book .corpauthor { text-align: center } .book .author { text-align: center } .book .affiliation { text-align: center } .book .editedby { text-align: center } .book .editor { text-align: center } .book .graphic { text-align: center } .article .title { text-align: center } .article .subtitle { text-align: center } .article .corpauthor { text-align: center } .article .author { text-align: center } .article .affiliation { text-align: center } .article .editedby { text-align: center } .article .editor { text-align: center } .article .graphic { text-align: center } .article .abstract { margin-left: 0.5in; margin-right: 0.5in; font-style: italic } html { background: #fff; color: #000; } body { background: #fff; color: #000; margin: 0 2em 0 2em; padding: 1em; font-family: luxi sans,sans-serif; font-size: 1em; line-height: 1.2em; } pre.screen { background: #e1e8fc; color: #000; padding: 2px 2px 2px 2px; } pre.programlisting { background: #e1e8fc; color: #000; border-width: 1px; border-style: solid; border-color: #2d4488; } div.block { background: #e1e8fc; color: #000; margin: 1em; padding: 0 1em 0 1em; border-width: 1px; border-style: solid; border-color: #2d4488; } div.warnblock { background: #e1e8fc; color: #000; margin: 1em; padding: 0 1em 0 1em; border-width: 1px; border-style: solid; border-color: #FF9900; } div.note { border-width: 1px; border-style: solid; border-color: #999999; margin-bottom: 3px; } div.tip { border-width: 1px; border-style: solid; border-color: #999999; margin-bottom: 3px; } div.warning { border-width: 1px; border-style: solid; border-color: #FF9900; margin-bottom: 3px; } table,tr,th,td { background: #fff; color: #000; } table.calstable { margin: 1em; } td.calstable { border-width: 1px 1px 1px 1px; background: #F8F8F8; color: #000; border-style: solid; border-color: #C0C0C0; } th.calstable { border-width: 1px 1px 1px 1px; background: #F8F8F8; color: #000; border-style: solid; border-color: #C0C0C0; } /* body text, headings, and rules */ p { margin: 0; text-indent: 0em; margin: 0 0 0.5em 0 } h1, h2, h3, h4, h5, h6 { color: #206020; background: transparent; font-family: Optima, Arial, Helvetica, sans-serif; font-weight: normal; } h1 { font-size: 1.69em; margin: 1.4em 0 0.4em 0; } h2 { font-size: 1.44em; margin: 1.4em 0 0.4em 0; } h3 { font-size: 1.21em; margin: 1.4em 0 0.4em 0; } h4 { font-size: 1.00em; margin: 1.4em 0 0.4em 0; } h5 { font-size: 0.81em; margin: 1.4em 0 0.4em 0; } h6 { font-size: 0.64em; margin: 1.4em 0 0.4em 0; } hr { color: transparent; background: transparent; height: 0px; margin: 0.6em 0; border-width: 1px ; border-style: solid; border-color: #999; } /* bulleted lists and definition lists */ ul { margin: 0 1em 0.6em 2em; padding: 0; } li { margin: 0.4em 0 0 0; } dl { margin: 0.6em 1em 0.6em 2em; } dt { color: #285577; } tt { /* color: #602020; */ color: #2d4488; } /* links */ a.link { color: #33c; background: transparent; text-decoration: none; } a:hover { color: #000; background: transparent; } body > a { font-family: Optima, Arial, Helvetica, sans-serif; font-size: 0.81em; } h1, h2, h3, h4, h5, h6 { color: #2d5588; background: transparent; font-family: Optima, Arial, Helvetica, sans-serif; font-weight: normal; } MANUAL-2_4/extern.html0000664000175000017500000000747112703400302014134 0ustar rainerrainerChapter7.Hooks for External Programs

Chapter7.Hooks for External Programs

samhain provides several hooks for external programs for (re-)processing the audit trail, including pipes, a System V message queue, and the option to call external programs.

1.Pipes

It is possible to use named pipes as 'console' device(s) ( samhain supports up to two console devices, both of which may be named pipes. You can set the device path at compile time (see Section5 ), and/or in the configuration file (see Section8 ).

[Note]Pipe full

(Since version 4.0) samhain will do a nonblocking write. If the pipe is full, the write will silently fail and the message will be lost.

MANUAL-2_4/database.html0000664000175000017500000000733512703400302014372 0ustar rainerrainer12.Database

12.Database

Section heading:

[Database]

Entries:

SetDBHost= db_host — Host where the DB server runs (default: localhost). Should be numeric IP address for PostgreSQL.

SetDBName= db_name — Name of the database (default: samhain).

SetDBTable= db_table — Name of the database table (default: log).

SetDBUser= db_user — Connect as this user (default: samhain).

SetDBPassword= db_password — Use this password (default: none).

SetDBServerTstamp= boolean — Log server timestamp for client messages (default: true).

UsePersistent= boolean — Use a persistent connection (default: true).

AddToDBHash= field — Add a database field to the set of fields that are used for tagging the log record with an MD5 hash.

MANUAL-2_4/change-control-integration.html0000664000175000017500000003117612703400302020052 0ustar rainerrainerChapter8.Change Control Process Integration

Chapter8.Change Control Process Integration

samhain 4.0 introduces a set of new features to allow seamless integration with an existing change control process. This feature set has been drafted as the result of a workshop, and is designed to meet some key criteria:

  1. The whole procedure can be run in an automated way, i.e. it can be executed by scripts and without human intervention, once a list of affected files is available. It is expected that the change control process will yield the list of affected files from the development or quality assurance stage.

  2. The feature set provided should be rather generic and not tied to any particular change control software.

  3. Immediately before a change is implemented, the affected files can be tested for their integrity. I.e. it can be verified that the system is in a known-good state before the change is put into effect.

  4. After a change is implemented, the baseline, i.e. the database of known-good file signatures, can be updated.

  5. The approval of the change(s) performed can be securely communicated to the running Samhain daemon on the affected machine(s), such that a subsequent file integrity check will raise no alerts.

1.Use cases

The following list shows the use cases that were considered, and how they may be handled.

1.1.Case I: Machine taken offline for a large patch

This case is best handled by a comple re-initialisation of the baseline database. The running Samhain daemon performs an on-demand file system scan immediately before the machine is taken offline to ensure a valid state, the database will be initialized after the patch has completed, and the Samhain daemon will re-start when the machine goes online again.

  1. Before taking the machine offline, a SIGTTOU signal is sent to the Samhain daemon to request a file check:
    	    sh# kill -s TTOU $( cat /var/run/samhain.pid )
    	  
    It is possible to perform a wait-on-completion (with an optional timeout) that provides an exit status to indicate whether the file system scan found any inconsistencies:
    	    sh# samhain -w <timeout>
    	  
  2. The machine is taken offline for patching (e.g. by switching to another runlevel), and Samhain is shut down.
  3. After the patch, a new baseline is initialized:
    	    sh# samhain -t init
    	  
  4. The new baseline is transferred to the server and the Samhain daemon restarts when the machine is taken online again.
  5. There may be no feedback between different parts of the process that implements the change, thus the new baseline may not be available yet at restart. Therefore Samhain has an option to delay the download of the baseline at startup:
    	    # Delay database download at startup by N seconds
    	    StartupLoadDelay = N
    	  

1.2.Case II: Installation of a new package

In this case, because the package is not installed yet a "pre-flight" scan may be deemed unneccessary. After installation of the package, a DeltaDB (delta database) containing the added files will be generated and transferred to the server. There, it will be merged into the existing baseline database.

The approval of the file system changes will be done by the server asking the client to download the DeltaDB. For security, there is no client-side mechanism to trigger an approval of the file system changes.

  1. The list of files (package content + files affected by pre-/postinstall scripts) is generated in the QA stage.
  2. The package is installed.
  3. Based on the list of files, a DeltaDB (delta database) is generated:
    	    sh# samhain --outfile <DeltaDB> --create-database <file_list>
    	  
    [Note]File list

    One pathname per line, optionally preceded by a '+' (plus) sign which, if present, indicates that the content of the file should be stored. The configuration file will NOT be read, and the policy recorded in the baseline database will be ReadOnly.

  4. The DeltaDB is transferred to the server data directory, renamed with a fixed scheme of the form <baseline_file>.<UUID>, and merged with the baseline database. The merging function is provided as part of the Beltane II software:
    	    sh# beltane_update --merge <UUID> --update <baseline_file>
    	  
  5. The Samhain server (yule) is advised to inform the Samhain client that a DeltaDB of approved changes is available for download:
    	    sh# yulectl -c DELTA:<UUID> <client_fqdn>
    	  
    [Note]Location and naming scheme

    The DeltaDB must be named file.client_fqdn.UUID and must be located in the yule data directory, i.e. the same directory where the baseline database file.client_fqdn is located. The client will only ask for the UUID. Similar to the baseline database, the pathname of the file is constructed by the server, using the client FQDN and the requested UUID.

  6. The client receives the UUID and requests the DeltaDB from the server. In case of a failure, re-trying is controlled by the following two configuration options:
    	    # Maximum retry count
    	    SetDeltaRetryCount = N
    	    # Time in seconds between re-tries
    	    SetDeltaRetryInterval = N
    	  

1.3.Case III: Configuration change / Package upgrade

This case differs from Case II insofar as there are already installed files, and therefore it is desirable to verify the integrity of those files before the change is put into effect. To perform this check, on the server a PartialDB (partial database, containing only data for affected files) is generated from the full baseline database. This PartialDB is then transferred to the client and used to perform a verification scan.

If the affected files are found to be in a consistent state, the procedure continues as in Case II then.

  1. The list of affected files is generated in the QA stage.
  2. On the Samhain server, a PartialDB (partial baseline database) for the affected files is generated from the complete baseline:
    	    sh# samhain --outfile <PartialDB> --list-filter <list_file> --binary -d <baseline_file>
    	  
  3. The PartialDB is transferred to the client.
  4. The integrity of the affected files is verified before the change is implemented (success or failure indicated by exit status):
    	    sh# samhain --verify-database <PartialDB>
    	  
  5. After successful verification, the process continues as in Case II.
MANUAL-2_4/droproot.html0000664000175000017500000001463212703400301014473 0ustar rainerrainer2.Important installation notes

2.Important installation notes

As of version 1.7.0, yule will always drop root privileges after startup and initialization. You can use a privileged port (port number below 1024), because setting up the listening socket will occur as long as yule still has root privileges.

There are some special considerations that need to be taken into account when setting up an installation of yule. In particular:

The unprivileged user

By default, configure will check (in this order) for the existance of a user yule, daemon, or nobody, and use the first match.

You can override this with the option configure --enable-identity= user . The user does not need to exist already; the install script knows how to create a new user (on Linux, FreeBSD, NetBSD, Solaris, HP-UX, OSF1).

After successful installation, you will be asked to run make install-user in order to: (i) create the user that you specified to configure if it does not exist already ( make install-user will check for this), and (ii) chown/chmod some directories.

After running make install and make install-user , you should have a sane setup.

Logfile directory

The system logfile directory usually requires root privileges to write there (otherwise log files may easily get corrupted ...). To enable yule to write the log file and the HTML status file, a (sub-)directory should be used that is owned by yule. The configure script and the Makefile will do that automatically with the default layout (i.e. a directory /var/log/yule will be created).

Data files

The data file directory is now owned by root and world readable by default. If you chown it to a suitable group for the unprivileged yule user, you can make it group readable only. Note that it is not required, and weakens the security, if the data file directory is writeable for the server.

GnuPG signed configuration file

The unprivileged yule user must have a .gnupg subdirectory in its home directory, holding the public keyring with the key to verify the signature.

PID file

The PID file is written with before dropping root privileges. Therefore yule will not be able to overwrite it later (which is a GoodThing), or remove it upon exit (it will usually be able to recognize and handle a stale PID file on startup). Still, it may be a good idea to remove it after stopping yule. The provided start/stop scripts for various architectures will handle this.

MANUAL-2_4/portcheck.html0000664000175000017500000002274512703400301014611 0ustar rainerrainer15.Checking for open ports

15.Checking for open ports

To compile with support for this option, use the configure option

./configure --enable-port-check

This module enables samhain to check for open ports (services) on the local machine, and report ports that are open, but not listed in the configuration. Reports are like:

interface:portnumber/protocol (maybe_servicename)

This is a non-RPC service, e.g. 192.168.1.2:22/tcp (maybe_ssh). The service name is taken from /etc/services, and prepended by maybe_, because samhain cannot determine whether it really is the SSH daemon that is listening on this port.

interface:portnumber/protocol (servicename)

This is an RPC service, e.g. 192.168.1.2:2049/tcp (nfs). The service name is obtained by querying the portmapper daemon. The portmapper daemon may return a service name as listed in /etc/rpc, or just a number (if there is no name for the service). If the portmapper daemon only returns the number of the RPC service, samhain will list RPC_number as servicename.

15.1.Options

By default, (only) the interface corresponding to the 'official name' of the host will be scanned. Additional interfaces can be added via the option PortCheckInterface= (list of) IP address(es) , where 'IP address' is the address of the interface that should be scanned. You can use this options multiple times to specify up to 15 additional interfaces, or supply a list of interfaces.

[Note]Don't specify external interfaces

While it is possible to misuse this option to specify an external IP address, the check will only work for interfaces on the local machine.

Services (open ports) that are required or optional (allowed, but not required) can be specified with the options PortCheckRequired= interface:service list , and/or PortCheckOptional= interface:service list .

Services (open ports) that should be completely ignored can be specified with the option PortCheckIgnore= interface:service list .

Here, 'interface' should be the IP address of an interface, and 'service list' the comma-separated list of required/optional services. Each service must be listed as 'port/protocol' (e.g. 22/tcp) for a non-RPC service, and 'name/protocol' for an RPC service (e.g. portmapper/tcp). If an RPC service has no name, but just an RPC program number, then the name must be given as 'RPC_number' (e.g. RPC_100075).

By default, both TCP and UDP ports are scanned. To disable UDP scanning, the option PortCheckUDP= boolean can be used.

Ports that should be skipped during the check can be specified with the option PortCheckSkip= interface:port list .

Here, 'interface' should be the IP address of an interface, and 'service list' the comma-separated list 'port/protocol' pairs (e.g.: 22/tcp,514/udp,...) to skip.

This option is different from PortCheckIgnore=... in two ways: (i) since it allows to skip ports only, it does not work for RPC services which have no fixed port, and (ii) since the port is not probed, you can avoid error messages by obnoxious deamons.

[Tip]MySQL (port 3306)

MySQL counts unsuccessful connection attempts and may refuse further connection if some limit is exceeded. You may want to use the PortCheckSkip option to avoid probing the MySQL port.

By default, all ports from 0 to 65535 are scanned. To change these limits, the options PortCheckMinPort= integer and PortCheckMaxPort= integer can be used.

15.2.Example configuration

	  [PortCheck]
	  #
	  # Activate (default is on)
	  #
	  PortCheckActive = yes
	  
	  # The severity of reports: debug/info/notice/warn/err/crit/alert
	  # (default is crit)
	  #
	  SeverityPortCheck = crit
	  
	  # These are the defaults
	  #
	  PortCheckMinPort = 0
	  PortCheckMaxPort = 65535
	  
	  # Services that are required. This example specifies ssl (22/tcp), 
	  # smtp (25/tcp), http (80/tcp), and portmapper.
	  #
	  PortCheckRequired = 192.168.1.128:22/tcp,25/tcp,80/tcp,portmapper/tcp,portmapper/udp
	  
	  # Services that are optional. This example specifies 
	  # mysql (3306/tcp).
	  #
	  PortCheckOptional = 192.168.1.128:3306/tcp
	  
	  # Additional interfaces to scan. This example presumes that
	  # the 'official hostname' corresponds to 192.168.1.128, and
	  # that the machine has three more interfaces.
	  # 127.0.0.1 (localhost) is not listed, hence not scanned.
	  #
	  PortCheckInterface = 192.168.1.129
	  PortCheckInterface = 192.168.1.130
	  PortCheckInterface = 192.168.1.131
	  
	  # The interval (in seconds) for port checks (default is 300 sec)
	  #
	  PortCheckInterval = 300
	  
	  # By default, UDP ports are checked as well as TCP ports.
	  #
	  PortCheckUDP = yes
	
MANUAL-2_4/checking-for-suid-files.html0000664000175000017500000001025712703400302017224 0ustar rainerrainer6.Checking for SUID/SGID files

6.Checking for SUID/SGID files

Section heading:

[SuidCheck]

Entries:

SuidCheckActive= boolean — '1' to switch on, '0' to switch off.

SuidCheckExclude= path — A directory (and its subdirectories) to exclude from the check. Only one directory can be specified this way.

SuidCheckSchedule= schedule — Crontab-like schedule for checks.

SeveritySuidCheck= severity — Severity for events.

SuidCheckFps= fps — Limit files per seconds for SUID check.

SuidCheckNosuid= boolean — Check filesystems mounted as nosuid. Defaults to not.

SuidCheckQuarantineFiles= boolean — Whether to quarantine files. Defaults to not.

SuidCheckQuarantineMethod= 0|1|2 — Quarantine method. Delete = 1, remove suid/sgid flags = 1, move to quarantine directory = 2. Defaults to 1 (remove suid/sgid flags).

SuidCheckQuarantineDelete= boolean — Whether to delete rather than truncate, if method 0 (delete) is chosen. Default is truncate.

MANUAL-2_4/modules.html0000664000175000017500000000575212703400301014276 0ustar rainerrainer18.Modules

18.Modules

samhain has a programming interface that allows to add modules written in C. Basically, for each module a structure of type struct mod_type, as defined in sh_modules.h, must be added to the list in sh_modules.c.

This structure contains pointers to initialization, timing, checking, and cleanup functions, as well as information for parsing the configuration file.

For details, in the source code distribution check the files sh_modules.h, sh_modules.c, as well as e.g. utmp.c, utmp.h, which implement a module to monitor login/logout events. There is also a HOWTO written by eircom.net Computer Incident Response Team.

MANUAL-2_4/configuration-external.html0000664000175000017500000000452212703400301017307 0ustar rainerrainer7.External facilities

7.External facilities

samhain can invoke external scripts/programs for logging (i.e. to implement support for pagers etc.). This is explained in detail in Chapter7 .

MANUAL-2_4/signals.html0000664000175000017500000001344412703400301014263 0ustar rainerrainer4.Signals

4.Signals

On startup, all signals will be reset to their default. Then a signal handler will be installed for all signals that (i) can be trapped by a process and (ii) whose default action would be to stop, abort, or terminate the process, to allow for graceful termination.

For SIGSEGV, SIGILL, SIGBUS, and SIGFPE, a 'fast' termination will occur, with only minimal cleanup that may result in a stale pid file being left.

If the operating system supports the siginfo_t parameter for the signal handling routine (see man sigaction ), the origin of the signal will be checked.

The following signals can be sent to the process to control it:

  • SIGUSR1 Switch on/off maximally verbose output to the console.

  • SIGUSR2 Suspend/continue the process, and (on suspend) send a message to the server. This message has the same priority as timestamps. This signal allows to run samhain -t init -e none on the client to regenerate the database, with download of the configuration file from the server, while the daemon is suspended (normally you would get errors because of concurrent access to the server by two processes from the same host).

  • SIGTERM Terminate the process.

  • SIGQUIT Terminate the server process after processing all currently pending requests from clients. Terminate the client process after finishing the current task (from the terminal, SIGQUIT usually is Ctrl+\).

  • SIGHUP Re-read the configuration file. Note that it is not possible to override command-line options given at startup.

  • SIGTTIN / SIGABRT Unlock the log file, wait three seconds, then proceed. At the next access, the log file will be locked again and a fresh audit trail -- with a fresh signature key -- will be started. This allows log rotation without splitting an audit trail. See Sect.~ Section5.1 .

  • SIGTTOU Perform a file check. Only client/standalone, and only in daemon mode.

  • SIGTSTP Perform a silent file check. Only client/standalone, and only in daemon mode. The config file option SetFullSilent (boolean) can be used to switch on/off any informational message (e.g. start/end file check). The result of the file check can still be queried from the message queue via samhain -w For security reasons, silent scans are not taken into consideration for the time till next file check.

MANUAL-2_4/installation-build.html0000664000175000017500000001005312703400300016411 0ustar rainerrainer5.Build

5.Build

After configuring the source, to build samhain you just have to type the command:

        sh$ make
      

The standalone/client executable ( samhain ) and the log server ( yule ) cannnot be compiled simultaneously. You need to run ./configure && make separately for both.

If you want to use your native package manager for installation, you might rather want to build a binary package. samhain has support for RPM (rpm), Debian (deb), Gentoo (tbz2), HP-UX (depot), and Solaris packages. Instead of simply typing make , you need to type:

        sh$ make rpm|deb|tbz2|depot|solaris-pkg
      

This will create a custom binary package according to the options that you used when configuring the source (see previous section). For more details, see Section2 .

If you don't want to include documentation, you can instead use:

        sh$ make rpm-light|deb-light|depot-light|tbz2-light|solaris-pkg-light
      

Finally, the Makefile supports building a portable (Unix) binary installer package based on the makeself installer ((c) 1998-2004 Stephane Peter). There will be no documentation included. Just type:

        sh$ make run
      
MANUAL-2_4/file-signatures.html0000664000175000017500000000741112703400301015721 0ustar rainerrainer3.File signatures

3.File signatures

samhain works by generating a database of file signatures, and later comparing file against that database to recognize file modifications and/or added/deleted files.

File signatures include:

  • a 192-bit cryptographic checksum computed using the TIGER hash algorithm (alternatively SHA-1, MD5, or SHA2-256 can be used),

  • the inode of the file,

  • the type of the file,

  • owner and group,

  • access permissions,

  • on Linux only: flags of the ext2 file system (see man chattr ),

  • the timestamps of the file,

  • the file size,

  • the number of hard links,

  • minor and major device number (devices only)

  • and the name of the linked file (if the file is a symbolic link).

Depending on the policy chosen for a particular file, only a subset of these may be checked for modifications (see Section4.1 ), but usually all these informations are collected.

MANUAL-2_4/logmon-check.html0000664000175000017500000001342612703400302015172 0ustar rainerrainer11.Logfile monitoring/analysis

11.Logfile monitoring/analysis

Section heading:

[Logmon]

LogmonActive= boolean — 'true' to switch on, 'false' to switch off.

LogmonSaveDir= /abslute/path sets the directory where checkpoint data for logfiles is stored (default: same as for pid file).

LogmonClean= boolean delete old checkpoint data unmodified for 30 days or more (default: off).

LogmonInterval= seconds — Interval between checks (default 10).

LogmonWatch= TYPE:path[:format] — File to monitor.

LogmonHidePID= boolean — Suppress PID in syslog messages, 'true' to switch on, 'false' to switch off.is an option

LogmonMarkSeverity= severity — Severity for reports on missing heartbeat messages if the messages themselves are assigned to the 'trash' queue (default: crit).

LogmonBurstThreshold= number — The number of repeated messages within 12 minutes that must be exceeded to report a burst of repeated messages (default: 24).

LogmonBurstQueue= queue — Set the reporting queue for reporting bursts of similar log messages (default: don't report).

LogmonBurstCron= boolean — Whether to report also on bursts of repeated cron messages (defaul: false).

LogmonDeadtime= seconds — Do not report a correlated event again within the given time (default: 60 seconds).

LogmonQueue= label:[interval]:(sum|report):severity[:alias] — defines an output queue.

LogmonHost= (perl)regex — Causes the following rules to be applied only to entries for this host(s).

LogmonEndHost — Explicitely ends a preceding LogmonHost directive.

LogmonGroup= (perl)regex — Causes the following rules to be applied only if the group regex matches.

LogmonEndGroup — Explicitely ends a preceding LogmonGroup directive.

LogmonRule= queue_label:(perl)regex — matches a logfile entry against the provided regular expression.

MANUAL-2_4/configuration-logserver.html0000664000175000017500000001073612703400301017501 0ustar rainerrainer6.Log server

6.Log server

Server address

SetLogServer= my.server.address

You have to specify the server address, unless it is already compiled in. It is possible to specify a second server that will be used as backup.

[Note]Note

If you want to store the configuration file on the server, the server address must be compiled in.

Throughput throttling

SetThrottle= milliseconds

An option to throttle the throughput when downloading the database from the server. The allowed maximum of 1000 msec throttles to about 64 kB/sec, less throttle means higher throughput.

6.1.Details

During temporary connection failures, messages are stored in a FIFO queue in memory. The maximum number of stored messages is 128. After a connection failure, samhain will make the next attempt only after a deadtime that starts with 1 sec and doubles after each unsuccessful attempt (max is 2048 sec). A re-connection attempt is actually only made for the next message after the deadtime -- you should send timestamps (i.e. set the threshold to mark) to ensure re-connection attempts for failed connections.

It is possible to specify two log servers in the client configuration file. The first one will be used by default (primary), and the second one as fallback in case of a connection failure with the primary log server.

MANUAL-2_4/winreg.html0000664000175000017500000002022112703400301014105 0ustar rainerrainer17.Checking the Windows registry

17.Checking the Windows registry

[Warning]32bit vs. 64bit views

On 64bit Windows, the same key name may get mapped to different keys, depending on whether the lookup is done by a 32bit or 64bit application. Currently samhain does not check the alternate view.

This option is available with samhain version 2.8.0 and higher, when compiled on Cygwin/Windows. It enables samhain to verify the integrity of individual keys, or complete trees/hierarchies of keys, in the Windows registry.

[Note]Be careful what you ask for

The Windows registry is huge, i.e. it may contain a huge amount of keys, for which baseline data will get stored in the samhain baseline database if you desire to monitor all of them. There is the potential to blow up the size of the baseline database in a quite spectacular way.

17.1.Options

All options for this module go into the section [Registry] .

RegistryCheckActive= boolean switches this module on or off (default: off).

RegistryCheckInterval= seconds defines the interval (in seconds) between consecutive checks. The default is 300 seconds.

SeverityChange= severity defines the severity for reports on modifications to the registry.

IgnoreTimestampOnly= boolean to ignore changes where only the (write) timestamp has changed (default: off).

SingleKey= key defines a key to be monitored (of course it is possible to use this command multiple times). Valid key names must start with one of: HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, or HKEY_USERS. The Windows path separator ('\') must be used.

Hierarchy= key defines a key hierarchy in the registry, beginning at the specified key, to be monitored (of course it is possible to use this command multiple times). Valid key names must start with one of: HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, or HKEY_USERS. The Windows path separator ('\') must be used.

[Note]Escaping the path separator

The following two directives (StopAtKey, IgnoreKey) take a (POSIX) regular expression as argument. This implies that the path separator must be escaped by doubling it, i.e. you need to write '\\' instead of '\', because the '\' is a metacharacter in regular expressions (see example below).

StopAtKey= regex means that the check of a hierarchy will stop at the specified key, i.e. nothing below this key will be checked or monitored (but the key itself where the check stops will). It is allowed to use a regular expression for the key. Valid key names must start with one of: HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, or HKEY_USERS. The Windows path separator ('\') must be used.

IgnoreKey= regex differs from the StopAtKey option only insofar as the key where the check stops is not itself checked.

17.2.Example configuration

	  [Registry]
	  
	  #
	  # Switch on the module
	  #
	  RegistryCheckActive = yes
	  
	  # Check every 60 second
	  #
	  RegistryCheckInterval = 1
	  
	  # Check this and everything below
	  #
	  Hierarchy = HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft
	  
	  # Exclude this and anything below
	  # IgnoreKey and StopAtKey have a regex as argument, hence
	  # the path separator '\' must be escaped by doubling it.
	  #
	  IgnoreKey = HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion
	  
	  # Check this key
	  #
	  SingleKey = HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
	
MANUAL-2_4/usage.html0000664000175000017500000001241312703400301013722 0ustar rainerrainerChapter3.General usage notes

Chapter3.General usage notes

1.How to invoke

From the command line

  • samhain -t init [more options] — To initialize the database

  • samhain -t check [more options] — To check against the database

By default, samhain will not become a daemon, but stay in the foreground. Daemon mode must be set in the configuration file or on the command line. Also by default, samhain will neither initialize its file system database nor check the file system against it. The desired mode must be set in the configuration file or on the command line. A complete list of command line options is given in the appendix.

To start as daemon during the boot sequence

For Linux (Debian, Redhat, Gentoo, and SuSE), *BSD, Solaris, HP-UX, AIX, IRIX make install-boot will setup your system for starting the daemon upon system boot (if the correct OS/distribution cannot be determined, nothing will be done).

For any other system, you need to figure out by yourself how to start samhain during the boot sequence.

MANUAL-2_4/enabling-logging-to-the-server.html0000664000175000017500000000603212703400301020523 0ustar rainerrainer4.Enabling logging to the server

4.Enabling logging to the server

If the client is properly registered with the server, all you need to do is to set an appropriate threshold for remote logging in the client's configuration file, and give the IP address of the server (if not already compiled in). Of course, the client must be compiled with the --enable-network=client switch.

Example for client configuration:

	[Log] 
	# 
	# Threshold for forwarding to the log server 
	# 
	ExportSeverity=crit 
	[Misc]
	SetLogServer=IP address
      

Example for server configuration:

	[Clients] 
	# 
	# Register a client to allow it to connect 
	#
	Client=client.mydomain.com@salt@verifier
      
MANUAL-2_4/native-packages.html0000664000175000017500000003222312703400302015662 0ustar rainerrainer2.Method B: The native package manager

2.Method B: The native package manager

Samhain provides an easy method to create custom binary packages with the native package manager of your operating system. Basically, this works like:

        bash$ ./configure [your preferred options]
        bash$ make rpm|deb|tbz2|depot|solaris-pkg
      

I.e. the binary package will be built with the compile options chosen in the preceding ./configure command. Supported package formats are: rpm (e.g. Redhat, SuSE, ...), deb (Debian), tbz2 (Gentoo Linux), depot (HP-UX), and solaris-pkg (Solaris).

[Tip]Customization

The binary package will use the OS-specific samhainrc.OS configuration file from the source directory, thus if you customize this, your package will contain your customized version.

[Tip]Baseline initialization

Upon installation, the package will not automatically initialize the baseline database, and not start the daemon (though it will install the runlevel script to start upon boot).

[Tip]Client packages

Samhain uses a password embedded in the binary for client/server authentication (for details see Section3 ). To avoid the need for changing the binary after installation (to set the password), it is possible to compile it in during package building (for RPM and DEB packages only). To do so, export the password in the PASSWORD environment variable before running the command make rpm or make deb .

[Note]Note

For reasons explained in Section2 , we do not recommend to distribute binary packages to third parties. On the other hand, it is perfectly ok to use a self-built binary package to install/distribute samhain on your machine/within your own network.

2.1.Building an RPM

2.1.1.Custom RPM

If you run ./configure in the source directory, a spec file samhain.spec will be created from samhain.spec.in. You can then use make rpm to create source and binary RPMs, or make srpm to create just the source RPM.

The RPM will be located in /usr/src/(distribution-specific)/RPMS/i386. Installing the RPM will not initialize the database automatically.

If anything fails during the build (and after installation has begun), just cd into the build directory and do a make uninstall && make uninstall-boot . If building for a non-RedHat system, the error messages will tell you which file paths in the spec file were incorrect.

2.1.2.Single-host

If you want to create an RPM for a single-host version of samhain without any fancy options, you can just run

            bash$ rpmbuild -ta samhain-version.tar.gz
          

on the tarball (there is a default spec file in there).

The RPM will be located in /usr/src/(distribution-specific)/RPMS/i386. Installing the RPM will not initialize the baseline database automatically.

2.2.Building an HP-UX package

First run ./configure in the source directory with your preferred options, then do a make depot . The result should be a package named samhain.depot, that can be installed with swinstall . Installing the package will not initialize the baseline database automatically.

2.3.Building a Solaris package

[Note]Note

This is experimental and not well tested. Constructive feedback from experienced Solaris administrators is welcome.

First run ./configure in the source directory with your preferred options, then do a make solaris-pkg . The result should be a package named samhain.pkg.

2.4.Building a Gentoo Linux package

First run ./configure [your preferred options] in the source directory (reminder: use ./configure --prefix=USR , NOT ./configure --prefix=/usr for standard paths), then do a make tbz2 . The .tbz2 package will be in /usr/portage/packages/All(this is just how Gentoo package building works).

The Gentoo package thus created will not initialize the database automatically upon installation. The .tbz2 package file will be in /usr/portage/packages/All(this is just how Gentoo package building works).

[Note]Note

If you just want to install on your own system, rather than building a package for other machines, you can use the command make emerge (after running ./configure , of course).

2.5.Building a Debian package

First run ./configure in the source directory (reminder: use ./configure --prefix=USR , NOT ./configure --prefix=/usr for standard paths), then do a make deb . The .deb package and the corresponding .dsc file will be in the directory above the source directory (this is just how Debian package building works).

You will need the following additional Debian packages in order to build a Debian packages: apt-get fakeroot , apt-get debmake , apt-get debhelper , apt-get devscripts , and apt-get cpio .

The Debian package thus created will not initialize the database automatically upon installation. It will be located in the parent directory of the source directory (that's just the way the Debian build system works).

MANUAL-2_4/installation-configure.html0000664000175000017500000002600512703400300017277 0ustar rainerrainer4.Configuring the source

4.Configuring the source

Before you can start to compile, it is neccessary to configure the source for your particular platform and your personal requirements. This is done by running the ./configure command in the source directory. If you type ./configure with no options, the source will get configured with the default options. In particular, a standalone version of samhain will get built which uses the Filesystem Hierarchy Standard (FHS) for file/directory layout. This is not the standard GNU layout of 'everything under /usr/local'.

[Tip]Paths

(A) samhain is a Filesystem Hierarchy Standard (FHS) compliant application. Thus the default directory layout is not the standard GNU layout (see Section10 ).

(B) samhain has a concept of trusted users, and will refuse to run if the path to critical files is writeable by users not in its list of trusted users (default: root, and the user who has started samhain ). Please read Section10.1 for details.

To change the defaults, ./configure accepts a variety of command-line options and environment variables (use ./configure --help for a complete list). The available command line options are listed and explained in AppendixA .

To configure a standalone version of samhain :

        sh$ ./configure [more options]
      

[Note]Important remark on client/server use

Please read Chapter6 if you intend to use samhain as a client/server system. Things will not work automagically just because you compiled a client and a server version of samhain. In particular, clients need to authenticate themselves to the server, and special configure options are required if you want to keep the configuration file(s) and the baseline database(s) on the central server.

To configure a client version of samhain that can connect to a central server:

        sh$ ./configure --enable-network=client [more options]
      

To configure a server version of samhain that will act as a central log server:

        sh$ ./configure --enable-network=server [more options]
      

4.1.Some more configuration options

If you want to use any options/modules that are not enabled by default (e.g. because the majority of users do not require them, or because they require additional programs and/or libraries), at this point you need to specify such options:

  • To compile in the module to check for SUID files (see Section9 ) use ./configure --enable-suidcheck

  • To compile in the module to monitor login/logout events (see Section11 ) use ./configure --enable-login-watch

  • To compile in the module to check mount options for mounted filesystems (see Section12 ) use ./configure --enable-mounts-check

  • To compile in the module to specify files relative to user home directories (see Section13 ) use ./configure --enable-userfiles

  • To compile in code for logging to an RDMS, (see Section12 ) use ./configure --enable-xml-log --with-database= oracle/mysql/postgresql

  • To compile in code for logging to the Prelude IDS, (see Section9 ) use ./configure --with-prelude

  • To use PGP-signed configuration files, (see Chapter9 ) use ./configure --with-gpg= /path/to/gpg . Please review Chapter9 for further information and additional options to compile in the key fingerprint and/or the checksum of the gpg executable.

  • To compile samhain for use of the 'stealth' options to hide its presence, please review Chapter10 for the available options.

  • To configure a server version of samhain that will act as a central log server, use ./configure --enable-network=server

  • To configure a client version of samhain that can connect to a central server, use ./configure --enable-network=client . Please refer to the chapter Chapter6 for an explanation of the client/server setup, in particular further options that you need if you want to store configuration files and baseline databases on the server(see Section5 ).

MANUAL-2_4/openpgp-signatures.html0000664000175000017500000000724212703400302016455 0ustar rainerrainer3.OpenPGP Signatures on Configuration/Database Files

3.OpenPGP Signatures on Configuration/Database Files

--with-gpg=PATH

Use GnuPG to verify database/configuration file. The public key of the effective user, usually root, (in ~/.gnupg/pubring.gpg) will be used.

--with-keyid=0x<hex KeyID>

This optional argument allows to specify a key ID, if there is more than one key in your keyring. This is only used for the installation routine, and for configuring the samhainadmin.pl convenience script.

--with-checksum=CHECKSUM

Compile in TIGER checksum of the gpg binary. CHECKSUM must be the full line output by samhain or gpg when computing the checksum.

--with-fp=FINGERPRINT

Compile in the fingerprint of the key used to sign the configuration/database file. If used, samhain will verify the fingerprint, but still report on the used public key.

MANUAL-2_4/database-fields.html0000664000175000017500000001525012703400302015631 0ustar rainerrainerAppendixD.List of database fields

AppendixD.List of database fields

The database may hold (i) internal message from yule, the log server, and (ii) client messages. The latter result in two rows: one for the client message, and one for the server message recording the arrival of the client message, the originating remote host, and the timestamp. The different message types can be recognized by the log_ref field (see below).

Many database fields record details of files (see man stat ), before (_old) and after (_new) a detected modification. For some items, both numeric (iXXX) and string values are reported, because the translation between both is host-specific. This allows to perform updates of the file signature database(s) on the server side. Other fields are listed below. Basically, most of the fields supply additional information for log_msg if relevant.

1.General

log_index

Unique index of the message (primary key).

log_ref

Zero for internal server messages, NULL for messages received from a client, log_index(client_message) for server timestamp of client message.

log_host

The host where the message originates.

log_time

The timestamp of the message.

log_sev

The severity/priority of the message.

log_msg

The message itself.

log_hash

A checksum over the union of user-defineable fields.

entry_status

NEW for new entries. Used by the Beltane frontend to track the status of a message.

path

Path of a file (whenever a message refers to a file).

userid

UID of the current user if relevant (e.g. if access to a file fails).

grp

Name of a group (for messages reporting problems with a GID, e.g. no entry in /etc/group).

program

Name of the current process (startup message).

subroutine

Name of an internal subroutine (in messages reporting failure of a subroutine).

status

Exit status value of samhain.

hash

Checksum of configuration file (if gpg not used). Startup message.

path_data, hash_data

Path and checksum of data file (if gpg not used). Startup message.

key_uid, key_id

User ID and key id of GPG key used to sign the configuration file. Startup message.

key_uid_data

User ID of GPG key used to sign the data file (different keys for configuration and data file cause program abort). Startup failure message.

peer

Address of a connecting host.

obj

Generic field to hold additional information. Occasionally used.

interface

Name of a library routine/interface (error messages).

dir

Name of a directory, if relevant.

linked_path

In reports about dangling symlinks.

port

Port number (in reports about connections errors).

service

Logging facility or remote service (failure reports).

MANUAL-2_4/index.html0000664000175000017500000006217012703400302013733 0ustar rainerrainerThe Samhain Host Integrity Monitoring System

The Samhain Host Integrity Monitoring System

This is version 2.4.0 of the Samhain manual.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a copy of the GNU Free Documentation Licensefrom the Free Software Foundation by visiting their Web site or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

This manual refers to version 4.0.0 of Samhain.


Table of Contents

1. Introduction
1. Backward compatibility
2. Compiling and installing
1. Overview
2. Requirements
3. Download and extract
4. Configuring the source
4.1. Some more configuration options
5. Build
6. Install
6.1. Important make targets
7. Customize
8. Initialize the baseline database
9. Run samhain
10. Files and directory layout
10.1. Trusted users and trusted paths
10.2. Directory layout
10.3. Runtime files
10.4. Installed files
11. The testsuite
3. General usage notes
1. How to invoke
2. Using daemontool (or similar utilities)
3. Controlling the daemon
4. Signals
5. PID file
6. Wait on file check
7. Log file rotation
8. Updating the file signature database
9. Improving the signal-to-noise ratio
10. Runtime options: command-line & configuration file
11. Remarks on the dnmalloc allocator
12. Support / Bugs / Problems
12.1. If samhain appears to hang indefinitely
4. Configuration of logging facilities
1. General
1.1. Severity levels
1.2. Classes
1.3. Error message customization
2. Available logging facilities
3. Activating logging facilities and filtering messages
4. E-mail
4.1. E-mail reports and their integrity
5. Log file
5.1. The log file and its integrity
6. Log server
6.1. Details
7. External facilities
8. Console
9. Prelude
9.1. Prelude-specific command-line options
9.2. Registering to a Prelude manager
10. Using samhain with nagios
11. Syslog
12. SQL Database
12.1. Upgrade to samhain 2.3
12.2. Upgrade to samhain 2.4.4
12.3. Upgrade to samhain 2.8.0+
12.4. Upgrade to samhain 4.0
12.5. MySQL configuration details
5. Configuring samhain, the host integrity monitor
1. Usage overview
2. Available checksum functions
3. File signatures
4. Defining file check policies: what, and how, to monitor
4.1. Monitoring policies
4.2. File/directory specification
4.3. Suppress messages about new/deleted/modified files
4.4. Dynamic database update (modified/disappeared/new files)
4.5. Recursion depth(s)
4.6. Hardlink check
4.7. Check for weird filenames
4.8. Support for prelink
4.9. SELinux attributes and Posix ACLs
4.10. Codes in messages about reported files
4.11. Loose directory checking
4.12. Storing the full content of a file
4.13. Who made changes to a file?
4.14. Skip checksumming for particular files
4.15. Graceful handling of log rotation
5. Excluding files and/or subdirectories (All except...)
6. Timing file checks
6.1. Using a second schedule
7. Initializing, updating, or checking
8. The file signature database
9. Checking the file system for SUID/SGID binaries
9.1. Quarantine SUID/SGID files
9.2. Configuration
10. Detecting Kernel rootkits
11. Monitoring login/logout events
12. Checking mounted filesystem policies
13. Checking sensitive files owned by users
14. Checking for hidden/fake/missing processes
14.1. Example configuration
15. Checking for open ports
15.1. Options
15.2. Example configuration
16. Logfile monitoring/analysis
16.1. Event Correlation
16.2. Reporting non-occurence of an event
16.3. Reporting bursts of similar, repeated events
16.4. Options
16.5. Example configuration
17. Checking the Windows registry
17.1. Options
17.2. Example configuration
18. Modules
19. Performance tuning
20. Storing the full content of a file (aka: WHAT has changed?)
20.1. Example configuration
20.2. Implementation details
21. Inotify support on Linux (instantaneous reports, no I/O load)
21.1. Example configuration
6. Configuring yule, the log server
1. General
2. Important installation notes
3. Registering a client
4. Enabling logging to the server
5. Enabling baseline database / configuration file download from the server
5.1. Configuration file
5.2. Database file
6. Rules for logging of client messages
7. Detecting 'dead' clients
8. The HTML server status page
9. Chroot
10. Restrict access with libwrap (tcp wrappers)
11. Sending commands to clients
11.1. Communicating with the server
11.2. Authenticating to the server
12. Syslog logging
13. Server-to-server relay
14. Performance tuning
7. Hooks for External Programs
1. Pipes
2. System V message queue
3. Calling external programs
3.1. Example setup for paging
8. Change Control Process Integration
1. Use cases
1.1. Case I: Machine taken offline for a large patch
1.2. Case II: Installation of a new package
1.3. Case III: Configuration change / Package upgrade
2. Limitations
9. Additional Features — Signed Configuration/Database Files
1. Compiling with support for signatures
2. Installation
3. The samhainadmin script
10. Additional Features — Stealth
1. Hiding the executable
1.1. Using kernel modules to hide samhain (Linux/ix86 only)
2. Packing the executable
11. Deployment to remote hosts
1. Method A: The deployment system
1.1. Requirements
1.2. Layout of the deployment system
1.3. Customizing the system
1.4. Using the deploy.sh script
1.5. deploy.sh info
1.6. deploy.sh clean
1.7. deploy.sh download
1.8. deploy.sh checksrc
1.9. deploy.sh build
1.10. deploy.sh install
1.11. deploy.sh uninstall
1.12. Usage notes
2. Method B: The native package manager
2.1. Building an RPM
2.2. Building an HP-UX package
2.3. Building a Solaris package
2.4. Building a Gentoo Linux package
2.5. Building a Debian package
12. Security Design
1. Usage
1.1. Client security in a client/server system
2. Integrity of the samhain executable
3. Client executable integrity
4. The server
5. General
A. List of options for the configure script
1. General
2. Optional modules to perform additional checks
3. OpenPGP Signatures on Configuration/Database Files
4. Client/Server Connectivity
5. Paths
B. List of command line options
1. General
2. samhain
3. yule
C. Configuration file syntax and options
1. General
1.1. Shell expansion
1.2. Conditionals
2. Files to check
3. Severity of events
4. Logging thresholds
5. Watching login/logout events
6. Checking for SUID/SGID files
7. Checking for mount options
8. Checking for user files
9. Checking for hidden/fake/required processes
10. Checking for open ports
11. Logfile monitoring/analysis
12. Database
13. Miscellaneous
14. External
15. Clients
D. List of database fields
1. General
2. Modules
3. Syslog
E. List of recognized file types
MANUAL-2_4/syslogdetails.html0000664000175000017500000000716712703400301015516 0ustar rainerrainer11.Syslog

11.Syslog

samhain will translate its own severities into syslog priorities as follows:

SeveritySyslog priority
debugLOG_DEBUG
infoLOG_INFO
noticeLOG_NOTICE
warnLOG_WARNING
markLOG_ERR
errLOG_ERR
critLOG_CRIT
alertLOG_ALERT

Messages larger than 959 chars will be split into several messages. By default, samhain will use the identity 'samhain', the syslog facility LOG_AUTHPRIV, and will log its PID (process identification number) in addition to the message.

The syslog facility can be modified via the directive SyslogFacility= LOG_xxx in the Misc section of the configuration file.

The syslog priority to be used for heartbeat messages (timestamps) can be selected with the directive SyslogMapStampTo= LOG_xxx in the Misc section of the configuration file. The default is LOG_ERR.

MANUAL-2_4/wait-on-check.html0000664000175000017500000001011112703400301015240 0ustar rainerrainer6.Wait on file check

6.Wait on file check

As of version 4.0, samhain allows to perform a wait on check operation which waits on the end of the current filesystem scan and indicates the result via the exit status:

samhain -w seconds

The argument for this option is the timeout. The maximum timeout value is 86400 (one day). A timeout of zero is interpreted as no timeout. A negative timeout is interpreted in the following way:

  1. First, wait until the Samhain daemon has initalized.

  2. Then, wait for the end of the filesystem scan with a timeout of (abs(seconds) - 1). I.e. a timeout of -1 will become 0, a timeout of -601 seconds will become 600 seconds.

The exit status has the following meaning:

0

The deamon currently performs no file system scan, and no issues have been reported in the last scan.

1

The deamon currently performs no file system scan, and one or more issues have been reported in the preceding scan.

2

The wait operation has timed out while the deamon was performing a file system scan.

3

An error has occured. Usually this would be either an access error (the wait operation needs at least group privilege), or a non-negative argument has been given and the deamon has not yet initialized (or isn't running).

MANUAL-2_4/udp.html0000664000175000017500000000665312703400302013420 0ustar rainerrainer12.Syslog logging

12.Syslog logging

yule (version 1.2.8+) can listen on port 514/udp to collect reports from syslog clients. This must be enabled by using the --enable-udp configure option when compiling. In addition, in the Misc section of the configuration file, you must set the option SetUDPActive= yes .

This option requires to run yule either as root, or as SUID root. For security, yule will drop root privileges irrevocably immediately after binding to port 514/udp. It will assume the credentials of some compiled-in user. The default is 'yule', 'daemon', or 'nobody' (i.e. the first of these that exists on your system). You can override this with the --enable-identity= USER option. Note that each daemon should have its own user/group, such that an exploit will not give write access to files owned by other daemons.

MANUAL-2_4/packing-the-executable.html0000664000175000017500000001016512703400302017132 0ustar rainerrainer2.Packing the executable

2.Packing the executable

For even more stealthyness, it is possible to pack and encrypt the samhain executable. The packer is just moderately effective, but portable. Note that the encryption key of course must be present in the packed executable, thus this is no secure encryption, but rather is intended for obfuscation of the executable. There is a make target for packing the samhain executable:

make samhain.pk

On execution, samhain.pk will unpack into a temporary file and execute this, passing along all command line arguments. The temporary file is created in /tmp, if the sticky bit is set on this directory, and in /usr/bin otherwise. The filename is chosen at random, and the file is only opened if it does not exist already (otherwise a new random filename will be tried). The file permission is set to 700.

The directory entry for the unpacked executable will be deleted after executing it, but on systems with a /proc filesystem, the deleted entry may show up there. In particular, this is the case for Linux. You should be aware that this may raise suspicion.

On Linux, the /proc filesystem is used to call the unpacked executable without a race condition, by executing /proc/self/fd/NN, where NN is the file descriptor to which the unpacked executable has been written. On other systems, the filename of the unpacked executable must be used, which creates a race condition (the file may be modified between creation and execution).

The packed executable will not honour the SUID bit.

MANUAL-2_4/support.html0000664000175000017500000001555312703400301014342 0ustar rainerrainer12.Support / Bugs / Problems

12.Support / Bugs / Problems

If you have problems getting samhain to run, or think that you have encountered a bug, then please check the FAQ first.

If your problem is not anwered there, you can visit the user forum(which is searchable, by the way) and ask there for help (recommended for questions of probably general interest), or send email to .

Please remember that a useful problem report should at least include the following three items:

  • What did you do?

  • What result did you expect?

  • What result did you obtain instead?

Please be sure to provide relevant details, such as:

  • your operating system, its release version, and the machine ( uname -srm ).

  • your operating system, its release version, and the machine ( uname -srm ).

  • the version of samhain that you are using, and the options that you have supplied to configure ,

  • the command line options used to start samhain, and

  • the samhainrc runtime configuration file.

  • If you think you have encountered a bug, it is usually very helpful if you run samhain in the foreground(i.e. not as daemon) with the command line switch -p debug to get some more information about the problem.

    It would be even more helpful if you first re-compile samhain with configure --enable-debug , and then run it with the command line switch -p debug (again, not as daemon, but in the foreground).

    Please compress the output using gzip , and send it as attachment to .

12.1.If samhain appears to hang indefinitely

If you have the impression that samhain hangs indefinitely, this could be due to a deadlock caused by some rare circumstance (it is not possible to fully test all possible configurations of samhain ).

The most useful thing to do then is to recompile samhain with --enable-debug=gdb , start it in the foreground under the control of the gdb debugger, and get a backtrace as soon as it seems to hang:

        bash$ gdb ./samhain
        (gdb) run -t check -p info --foreground --forever
	(samhain output) 
	[Ctrl-C]
        (gdb) thread apply all
        (gdb) backtrace
MANUAL-2_4/compilation-checks.html0000664000175000017500000000636612703400302016405 0ustar rainerrainer2.Optional modules to perform additional checks

2.Optional modules to perform additional checks

These are all client-only options, as the server does not perform any checks (if you want to run checks on the log server host, you need to run a client there as well).

--enable-login-watch

[CLIENT ONLY] Compile in the module to watch for login/logout events.

--enable-mounts-check

[CLIENT ONLY] Compile in the module to check for correct mount options.

--enable-userfiles

[CLIENT ONLY] Compile in the module to check for files in user home directories (i.e. with paths relative to $HOME for all users).

--enable-suidcheck

[CLIENT ONLY] Compile in the module to check file system for SUID/SGID binaries not in the database.

MANUAL-2_4/kerneldef.html0000664000175000017500000000447612703400301014567 0ustar rainerrainer10.Detecting Kernel rootkits

10.Detecting Kernel rootkits

This option has been removed as of samhain 4.0 because it has been obsoleted by modern kernel developments.

MANUAL-2_4/sys-db-fields.html0000664000175000017500000000510612703400302015265 0ustar rainerrainer3.Syslog

3.Syslog

ip

IP of remote host received syslog reports. Also used in the login/logout watch module (see above).

facility

Syslog facility for received syslog reports.

priority

Syslog priority for received syslog reports.

syslog_msg

Syslog message for received syslog reports.

MANUAL-2_4/layout.html0000664000175000017500000003461112703400301014137 0ustar rainerrainer10.Files and directory layout

10.Files and directory layout

[Tip]Tip

samhain has its own set of trusted users. Paths to critical files (e.g. the configuration file) must be writeable by trusted users only. Failure to ensure this (e.g. by compiling in an appropriate set of trusted users) is one of the most frequent reasons for problems. See below for details.

10.1.Trusted users and trusted paths

  • Trusted users are root and the effective user of the process (usually, the effective user will be root herself). Additional trusted users can be defined in the configuration file (see Sect. Section5 for an example), or at compile time, with the option

                  bash$ ./configure --with-trusted=0,...
                
  • A trusted path is a path with all elements writeable only by trusted users. samhain requires the paths to the configuration and log file to be trusted paths, as well as the path to the pid file.

If a path element is group writeable, all group members must be trusted. If the path to the configuration file itself is writeable by other users than root and the effective user these must be defined as trusted already at compile time.

[Note]Note

The list of group members in /etc/group may be incomplete or even empty. samhain will check /etc/passwd(where each user has a GID field) in addition to /etc/group to find all members of a group.

10.2.Directory layout

samhain conforms to the FHS, which mandates a directory layout that is different from the default GNU layout (everything in subdirectories under /etc/local).

[Tip]Tip

There is an option ./configure --enable-install-name= NAME . When this option is used, not only the executable is installed as NAME, but also in all the paths, samhain is replaced with NAME.

[Note]Note

For the yule server, replace samhain with yule in the paths explained below.

The following table explains which directory layout results from ./configure --prefix= PREFIX

sbindirmandirsysconfdirlocalstatedir
PREFIX(none)
/usr/local/sbin/usr/local/man/etc/var
PREFIXUSR (all capital)
/usr/sbin/usr/share/man/etc/var
PREFIXOPT (all capital)
/opt/samhain/bin/opt/samhain/man/etc/opt/var/opt/samhain
PREFIX/other
/other/sbin/other/share/man/other/etc/other/var

The file signature database will be written to localstatedir/lib/samhain/samhain_file, the pid file to localstatedir/run/samhain.pid, and the log file to localstatedir/log/samhain_log. In addition, yule writes an HTML status file to localstatedir/log/yule/yule.html

To get a more fine-grained control on the layout, the following configure options are provided

  • --with-config-file=FILE — The path of the configuration file.

  • --with-log-file=FILE — The path of the log file.

  • --with-pid-file=FILE — The path of the pid file.

  • --with-data-file=FILE — The path of the file signature database file.

  • --with-html-file=FILE — The path of the HTML status file (server only).

10.3.Runtime files

10.3.1.Standalone or client

PurposeDirectory
Logfiles localstatedir/log/
Data files localstatedir/lib/samhain/
Pid file localstatedir/run/

10.3.2.Server

[Note]Note

The server will drop root privileges after startup. I does not need write access to the data files, thus the data file directory is chmod 555 on installation. It does need write access to the log file directory. As the system logfile directory usually is owned by root, the install script will by default create a subdirectory and chown it to the unprivileged yule user. The PID file is written before dropping root.

PurposeDirectory
Logfiles localstatedir/log/yule/
Data files localstatedir/lib/yule/
Pid file localstatedir/run/

10.4.Installed files

10.4.1.Standalone or client

FileInstalled toMode
samhain sbindir/samhain700
samhainrc sysconfdir/samhainrc600
samhain.8 mandir/man8/samhain.8644
samhainrc.5 mandir/man5/samhainrc.5644
(samhain_setpwd) sbindir/samhain_setpwd700
(samhain_stealth) sbindir/samhain_stealth700

10.4.2.Server

FileInstalled toMode
yule sbindir/yule700
yulectl sbindir/yulectl700
yulerc sysconfdir/yulerc600
samhain.8 mandir/man8/yule.8644
samhainrc.5 mandir/man5/yulerc.5644
samhain_setpwd sbindir/yule_setpwd700
MANUAL-2_4/trustedexample.html0000664000175000017500000002305712703400301015672 0ustar rainerrainer5.Log file

5.Log file

Trusted users

TrustedUser= username

If some element in the path to the log file is writeable by someone else than root or the effective user of the process, you have to include that user in the list of trusted users(unless their UIDs are already compiled in).

Separate log files for clients

UseSeparateLogs= yes/no

Only relevant on the server. Use a separate log file for (reports from) each client. The root name of these log files will be the same as the main log file, with the client name appended.

5.1.The log file and its integrity

The log file is named samhain_log by default, and placed into /var/log by default (name and location can be configured at compile time). If samhain has been compiled with the ./configure --enable-xml-log option, it will be written in XML format.

[Note]Note

If you have compiled for stealth ( Chapter10 ), you won't see much, because if obfuscated, then both a 'normal' and an XML logfile look, well ... obfuscated. Use samhain -jL /path/to/logfile to view the logfile.

The log file is created if it does not exist, and locked by creating a lock file, which has the same path as the logfile, with a ".lock" appended. The lock file holds the PID of the process, which allows samhain to recognize and remove a stale lock if there is no process with that PID.

On the log server, it is possible to use separate log files for individual clients. This can be enabled with UseSeparateLogs= yes/no in the Misc section of the server configuration file. No locking will be performed for client files (only one instance of the server can listen on the TCP port, thus there will be no concurrent access).

The directory where the logfile and its lock file are located must be writeable only by trusted users (see Section10.1 ). This requirement refers to the complete path, i.e. all directories therein. By default, only root and the effective user of the process are trusted.

Audit trails (sequences of messages from individual runs of samhain ) in the log file start with a [SOF] marker. Each message is followed by a signature, that is formed by hashing the message with a key.

The first key is generated at random, and sent by e-mail, encrypted with a one-time pad as described in the previous section on e-mail. Further keys are generated by a hash chain (i.e. the key is hashed to generate the next key). Thus, only by knowing the initial key the integrity of the log file can be assured.

The mail with the key looks like:

	  -----BEGIN MESSAGE-----  
	  message    
	  -----BEGIN LOGKEY----- 
	  Key(48 chars)[timestamp]     
	  -----BEGIN SIGNATURE----- 
	  signature
	  ID TRAIL_ID:hostname 
	  -----END MESSAGE-----  
	
[Tip]Integrity verification

To verify the log file's integrity, a convenience function is provided:

samhain -L /log/file/path

When encountering the start of an audit trail, you will then be asked for the key (as sent to you by e-mail). You can then: (i) hit return to skip signature verification, (ii) enter the key (without the appended timestamp), or (iii) enter the path to a file that contains the key (e.g. the mail box).

If you use option (iii), the path must be an absolute path (starting with a '/', not longer than 48 chars. For each audit trail, the file must contain a two-line block with the -----BEGIN LOGKEY----- line followed by the line ( Key(48 chars)[timestamp]) from the mail. Additional lines before/after any such two-line block are ignored (in particular, if you collect all e-mails from samhain in a mailbox file, you can simply specify the path to that mailbox file).

[Warning]CAVEATS

Verification will fail, if the compiled-in key of the verifying executable is different from the one that generated the message(s) (see Section2 ).

If you use a pre-compiled executable from some binary distribution, be sure to read Section2 carefully.

MANUAL-2_4/gcm.html0000664000175000017500000000551112703400301013365 0ustar rainerrainer7.Detecting 'dead' clients

7.Detecting 'dead' clients

It is possible to set a time limit for the maximum time between two consecutive messages of a client (option SetClientTimeLimit in the [Misc] section of the configuration file). If the time limit is exceeded without a message from the client, the server will issue a warning. The default is 86400 seconds (one day); specifying a value of 0 will switch off this option.

You may want to set ExportSeverity = mark (or any lower threshold) in the client configuration file in order to log timestamp ('heartbeat') messages to the server.

MANUAL-2_4/installation-running.html0000664000175000017500000000620712703400301017001 0ustar rainerrainer9.Run samhain

9.Run samhain

After successful initialization of the baseline database, you can run samhain in 'check' mode by typing:

        sh$ samhain -t check
      

To run samhain as a daemon, you can either use the command line option '-D', or set daemon mode in the configuration file with the option 'Daemon=yes'.

[Tip]Tip

When testing samhain for the first time, you may want to use the command line option --foreground to run samhain in the foreground rather than as daemon. This allows to spot the reason for eventual problems much easier.

MANUAL-2_4/checking-userfiles.html0000664000175000017500000000615412703400302016376 0ustar rainerrainer8.Checking for user files

8.Checking for user files

Section heading:

[UserFiles]

Entries:

UserfilesActive= boolean — '1' to switch on, '0' to switch off.

UserfilesName= filename policy — Files to check for under each $HOME. Allowed values for 'policy' are: allignore, attributes, logfiles, loggrow, noignore (default), readonly, user0, user1, user2, user3, and user4.

UserfilesCheckUids= uid list — A list of UIDs where we want to check. The default is all. Ranges (e.g. 100-500) are allowed. If there is an open range (e.g. 1000-), it must be last in the list.

MANUAL-2_4/samhain-command-line.html0000664000175000017500000001073412703400302016604 0ustar rainerrainer2. samhain

2. samhain

  1. -t <arg>, --set-checksum-test=<arg> Set file checking to init, update, or check. Use init to create the database, update to update it, and check to check files against the database.

    [Tip]Tip

    Yes, it is normal that update takes much more time than init.

  2. -i, --interactive Use interactive mode for update(ask before updating an entry).

  3. --listfile=<path> Use a text file comprising a list of files to update(one file per line).

  4. -e <arg>, --set-export-severity=<arg> Set the severity threshold for forwarding messages to the log server. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  5. -r <arg>, --recursion=<arg> Set the default recursion level for directories (0 -- 99).

  6. --init2stdout Write the database to stdout when performing the initialization.

MANUAL-2_4/watching-login-logout-events.html0000664000175000017500000000622012703400302020341 0ustar rainerrainer5.Watching login/logout events

5.Watching login/logout events

Section heading:

[Utmp]

Entries:

LoginCheckActive= boolean — '1' to switch on, '0' to switch off.

LoginCheckInterval= seconds — Interval between checks.

SeverityLogin= severity — Severity for login events.

SeverityLoginMulti= severity — Severity for multiple logins by same user.

SeverityLogout= severity — Severity for logout events.

MANUAL-2_4/mountcheck.html0000664000175000017500000000700012703400301014752 0ustar rainerrainer12.Checking mounted filesystem policies

12.Checking mounted filesystem policies

To compile with support for this option, use the configure option

./configure --enable-mounts-check

samhain can be compiled to check if certain filesystems are mounted, and if they are mounted with the appropriate options. This module currently supports Linux, Solaris, HP-UX (mount options as in /etc/mnttab), and FreeBSD. The configuration of the module is done in the Mounts section of the configuration file:

	[Mounts]
	#
	# Activate (default is no).
	#
	MountCheckActive = yes
	#
	# Interval between checks (default = one day).
	#
	MountCheckInterval=7200
	#
	# Logging severities. We have two checks: 
	# 1) to see if a mount is there (default = err), and 
	# 2) to see if it is mounted with the correct options (default = err).
	#
	SeverityMountMissing=warn
	SeverityOptionMissing=warn
	#
	# Mounts to check for, (optionally) followed by lists of 
	# mount options to check on them.
	#
	checkmount=/
	checkmount=/var
	checkmount=/usr
	checkmount=/tmp noexec,nosuid,nodev 
	checkmount=/home noexec,nosuid,nodev
      

This module by the eircom.net Computer Incident Response Team.

MANUAL-2_4/files-to-check.html0000664000175000017500000000723412703400302015421 0ustar rainerrainer2.Files to check

2.Files to check

Allowed section headings (see Section4.1 for more details) are:

[Attributes] , [LogFiles] , [GrowingLogFiles] , [IgnoreAll] , [IgnoreNone] , [ReadOnly] , [User0] , [User1] , and [User2] , and [User3] , and [User4] , and [Prelink]

Placing an entry under one of these headings will select the respective policy for that entry (see Section4.1 ). Entries under the above section headings must be of the form:

dir= [optional numerical recursion depth]path

file= path

MANUAL-2_4/yule.html0000664000175000017500000002112212703400302013572 0ustar rainerrainerChapter6.Configuring yule, the log server

Chapter6.Configuring yule, the log server

yule is the log server within the samhain file integrity monitoring system. yule is part of the distribution package. It is only required if you intend to use the client/server capability of the samhain system for centralized logging to yule.

[Warning]Important

Client and server are distict applications, and must be built seperately. By default, installation names and paths (e.g. the configuration file) are different. Do not blame us if you abuse './configure' options to cause name clashes, if you install both on the same host.

To compile yule, you must use ./configure --enable-network=server . To compile a samhain client, you must use ./configure --enable-network=client .

1.General

yule is a non-forking server. Instead of forking a new process for each incoming logging request, it multiplexes connections internally. Apart from samhain client reports (see below), yule (version 1.2.8+) can also collect syslog reports by listening on port 514/udp, if compiled with this option enabled (see also man syslogd .

Each potential client must be registered with yule to make a connection (see Section1 and the example below). The client tells its host name to the server, and the server verifies it against the peer of the connecting socket. On the first connection made by a client, an authentication protocol is performed. This protocol provides mutual authentication of client and server, as well as a fresh session key.

By default, all messages are encrypted using Rijndael (selected as the Advanced Encryption Standard (AES) algorithm). The 192-bit key version of the algorithm is used. There is a compile-time option to switch off encryption, if your local lawmakers don't allow to use it (see Appendix).

yule keeps track of all clients and their session keys. As connections are dropped after successful completion of message delivery, there is no limit on the total number of clients. There is, however, a limit on the maximum number of simultaneous connections. This limit depends on the operating system, but may be of order 1000.

Session key expire after two hours. If its session key is expired, the client is forced to repeat the authentication protocol to set up a fresh session key.

Incoming messages are signed by the client. On receipt, yule will:

  1. check the signature,

  2. accept the message if the signature can be verified, otherwise discard it and issue an error message,

  3. discard the clients signature,

  4. log the message, and the client's hostname, to the console and the log file, and

  5. add its own signature to the log file entry.

MANUAL-2_4/server-security.html0000664000175000017500000000552212703400302015775 0ustar rainerrainer4.The server

4.The server

The server does not need root privileges. Therefore, if it is started with root privileges, it will drop them irrevocably after startup. If a privileged port (below 1024) must be opened, the server will first open it, then drop root, and only thereafter accept any connection on the port.

The server can be chrooted, and actually has a config file option to do so by itself (which means that you don't need to copy shared libraries into the chroot environment).

(If your clients are configured to download baseline databases and configuration files from the server:) The server does not need write access to the directory where client baseline databases and configuration files are stored, and it would be wise to deny such access (chown to some other user, and allow group read access for the server).

MANUAL-2_4/mondef.html0000664000175000017500000001613512703400301014073 0ustar rainerrainer11.Monitoring login/logout events

11.Monitoring login/logout events

To compile with support for this option, use the configure option

./configure --enable-login-watch

samhain can be compiled to monitor login/logout events of system users. For initialization, the system utmp file is searched for users currently logged in. To recognize changes (i.e. logouts or logins), the system wtmp file is then used.

Optionally, it is possible to perform further checks for login events. All these additional checks are off by default. The following checks are provided:

First login

Report on the first login from a host or a domain / subnet. This option is configured with the directive:

LoginCheckFirst = no|yes|domain

If set to yes, samhain will issue a report when a user logs in from some host they haven't logged in from before. If set to domain, the domain (or C-class subnet, if the host cannot be resolved) is checked instead of the host.

Statistical outlier

Report unusual login times. This option will only take effect once a user has logged in several times, and a database of login times has been built which can be analyzed for statistical outlier detection. Since this is based on statistics, it will inevitably cause false positives (legitimate logins reported as outliers). This option is configured with the directive:

LoginCheckOutlier = no|yes|paranoid

If set to yes, samhain will issue a report when a login time is found to be an outlier with 99 per cent probability. If set to paranoid, the required outlier probability is lowered to 95 per cent, resulting in more reports and more false positives (legitimate logins reported as outliers).

Login date (global)

Report login events occuring outside some given date restrictions. This option is configured with the directive:

LoginCheckDate = date

Possible values for dateare: always, never, and workdays|saturday|sunday(list of time ranges), e.g. workdays(8:00-10:00,13:00-16:00) or saturday(08:10-17:20). To set date restriction for workdays (Mo-Fr) and saturday and/or sunday, use LoginCheckDate multiple times. The internal time resolution is ten minutes, i.e. 8:09 will be interpreted as 8:00.

Login date (individual)

Report login events occuring outside some date restrictions defined for the given individual user. This option, if defined for a given user, overrides the global setting above, and is configured with the directive:

LoginCheckUserDate = user:date

Here, usermust be the login name for a user, and datehas to be given as in the global option.

This facility is configured in the Utmp section of the configuration file:

	[Utmp]  
	#  
	# activate (0 for switching off) 
	# 
	LoginCheckActive=1 
	#  
	# interval between checks (in seconds)
	# 
	LoginCheckInterval=600 
	#  
	# these are the severities (see section Section1.1) 
	# 
	SeverityLogin=info 
	SeverityLogout=info 
	#  
	# multiple logins by same user 
	# 
	SeverityLoginMulti=crit
      
MANUAL-2_4/pid-file.html0000664000175000017500000000450212703400301014307 0ustar rainerrainer5.PID file

5.PID file

samhain generates a PID file if it is run as a daemon process. You can configure the path to the PID file at compile time, either explicitely using the ./configure --with-pid-file=FILE option, or via the ./configure --prefix=PREFIX option.

MANUAL-2_4/installation.html0000664000175000017500000001500412703400301015316 0ustar rainerrainerChapter2.Compiling and installing

Chapter2.Compiling and installing

[Note]Samhain as a client/server system

This chapter focuses on building a standalone samhain executable. For a client/server system, client and server executable are built from the same source, but with different options for the 'configure' script (see Section4 ).

Please refer to the chapter Chapter6 for an explanation of the client/server setup.

1.Overview

Download:

        sh$ wget http://la-samhna.de/samhain/samhain-current.tar.gz
      

Extract (and verify PGP signature):

        sh$ gunzip -c samhain-current.tar.gz | tar xvf -
        sh$ gpg --verify samhain-N.N.N.tar.gz.asc samhain-N.N.N.tar
        sh$ gunzip -c samhain-N.N.N.tar.gz | tar xvf -
        sh$ cd samhain-N.N.N

Configure:

        sh$ ./configure
      

Compile:

        sh$ make
      

Install:

        sh$ make install
      

Customize:

        sh$ vi /etc/samhainrc
      

Initialize the baseline database:

        sh$ samhain -t init
      

Start the samhain daemon:

        sh$ samhain -t check -D
      
MANUAL-2_4/external.html0000664000175000017500000001073512703400302014446 0ustar rainerrainer14.External

14.External

Definition of an arbitrary number of external programs/scripts (see Chapter7 ). Section heading:

[External]

Entries:

OpenCommand= /full/path/to/program — Starts new command definition.

CloseCommand — Ends new command definition (optional syntactic sugar).

SetType= log/srv — Type/purpose of the program.

SetCommandline= list — The command line.

SetEnviron= KEY=value — Environment variable (can be repeated).

SetChecksum= TIGER checksum — Checksum of the program.

SetCredentials= username — User whose credentials shall be used.

SetFilterNot= list — Regular expression patterns not allowed in message.

SetFilterAnd= list — Regular expression patterns required (ALL) in message.

SetFilterOr= list — Regular expression patterns required (at least one) in message.

SetDeadtime= seconds — Deadtime between consecutive calls.

SetDefault= boolean — Set default environment (HOME from /etc/passwd, SHELL=/bin/sh, PATH=/sbin:/usr/sbin:/bin:/usr/bin).

MANUAL-2_4/server-status-information.html0000664000175000017500000001411712703400302017774 0ustar rainerrainer8.The HTML server status page

8.The HTML server status page

yule writes the current status to a HTML file. The default name of this file is samhain.html, and by default it is placed in /var/log.

The file contains a header with the current status of the server (starting time, current time, open connections, total connections since start), and a table that lists the status of all registered clients.

There are a number of pre-defined events that may occur for a client:

Inactive

The client has not connected since server startup.

Started

The client has started. This message may be missing if the client was already running at server startup.

Exited

The client has exited.

Message

The client has sent a message.

File transfer

The client has fetched a file from the server.

ILLEGAL

Startup without prior exit. May indicate a preceding abnormal termination.

PANIC

The client has encountered a fatal error condition.

FAILED

An unsuccessful attempt to set up a session key or transfer a message.

POLICY

The client has discovered a policy violation.

TIME_EXCEEDED

No message (e.g. timestamp) has been received from the client for a defined amount of time (default 1 day, option SetClientTimeLimit).

For each client, the latest event of each given type is listed. Events are sorted by time. Events that have not occurred (yet) are not listed.

It is possible to specify templates for (i) the file header, (ii) a single table entry, and (iii) the file end. Templates must be named head.html, entry.html, and foot.html, respectively, and must be located in the data directory (i.e. localstatedir/lib/yule/, see Section5 ). The distribution package includes two sample files head.html and foot.html.

The following replacements will be made in the head template:

PlaceholderSignificance
%TCurrent time.
%SStartup time.
%LTime of last connection.
%OOpen connections.
%ATotal connections since startup.
%MMaximum simultaneous connections.

The following replacements will be made in the entry template:

PlaceholderSignificance
%HHost name.
%SEvent.
%TTime of event.
[Tip]Tip

A literal '%' in the HTML output must be represented by a '% ' ('%' followed by space) in the template.

MANUAL-2_4/installation-install.html0000664000175000017500000001402212703400300016760 0ustar rainerrainer6.Install

6.Install

After successful compilation, you can install samhain by typing:

        sh$ make install
      

The installation routine will not overwrite your configuration file from a previous installation.

Executables will be stripped upon installation. On Linux i386 and FreeBSD i386, the sstrip utility (copyright 1999 by Brian Raiter, under the GNU GPL) will be used to strip the executable even more, to prevent debugging with the GNU gdb debugger.

After installation, you will be offered to run make install-boot in order to install the init scripts that are required to start samhain automatically when your system (re-)boots. For many operating systems (Linux, *BSD, Solaris, HP-UX, IRIX), configure will generate init scripts, and make install-boot will figure out which of them to install, and where (if the correct distribution cannot be determined, none of them will be installed).

        sh$ make install-boot
      

6.1.Important make targets

          sh$ make install
        

Create the required directories (if not existing already), and install the compiled executable and the configuration file.

          bash$ make DESTDIR=/somedir install
        

Install as if /somedir is the root directory. Useful for creating packages or installing for chroot (server).

          sh$ make install-boot
        

Install runlevel start/stop scripts or create inittab entry (AIX) in order to start the daemon upon system boot. Supported on Linux, *BSD, Solaris, HP-UX, AIX(*), IRIX(*) [(*) untested].

          sh$ make uninstall
        

Uninstall the executable and remove directories if empty. Does not uninstall the configuration file.

          sh$ make purge
        

As make uninstall , but also remove the the configuration file.

 
	  sh$ make uninstall-boot
        

Uninstall the runlevel start/stop scripts.

[Tip]Tip

You can save the script samhain-install.sh and use it for uninstalling if you ever want to remove samhain:

            sh$ samhain-install.sh purge
            sh$ samhain-install.sh uninstall-boot
          
MANUAL-2_4/deployment.html0000664000175000017500000012625112703400302015005 0ustar rainerrainerChapter11.Deployment to remote hosts

Chapter11.Deployment to remote hosts

1.Method A: The deployment system

samhain includes a system to facilitate deployment of the client to remote hosts. This system enables you to: build and store binary packages for different operating systems, install them, create baseline databases upon installation, update the server configuration, and maintain the client database required by the beltane web-based console.

The system comprises a shell script deploy.sh that will be installed in the same directory as the samhain/yule (by default, /usr/local/sbin), and a directory tree that will be installed below the samhain/yule data directory (see Section1.2 ). The script and the directory tree can be relocated freely. There is a configuration file ~/.deploy.conf that is created in the home directory of the user when deploy.sh is run for the first time, where you can specify the default for the top level directory of the system.

[Note]Note

In the following, an architecture is just a label for some group of hosts, typically a particular operating system (or some particular installation thereof). As long as you know what the label means, you can choose it freely (alphanumeric + underscore).

The architecture for a build/install host (i.e. the association between a host and the architecture-specific configuration data) is currently specified via a command-line option.

The system allows to use per-architecture customized build options, as well as per-host customized runtime configuration files.

By default, the system will search for a sufficiently advanced incarnation of dialog to provide a nice user interface. You can switch this off in favour of a plain console interface, if you prefer (or if you want to run the script non-interactively).

To use this system, you must first install it with the command:

        sh$ make install-deploy
      
[Tip]Installation tip

This system is somewhat tied to the server (yule). While you can safely install it later, installing it together with the server will take care that the defaults are already correct. Upon first invocation a configuration file ~/.deploy.conf will be written, where you can modify the defaults settings.

[Warning]Backward compatibility

The deployment system has been completely revised in version 2.0 of samhain. It will not work with samhain versions below 2.0 (i.e. you cannot install them using this system). However, the default location and format of the client database (used by the beltane web-based console) has not changed.

Installing the new version of the deploy system will not overwrite the old version (deploy.sh will be installed as deploy2.sh, if an old version is detected).

1.1.Requirements

  1. You must have compiled and installed the server ( yule ) on the local host where you use the deploy system.

  2. You must have installed the deployment system by using make deploy-install . This will install the script deploy.sh into the sbindir(default /usr/local/sbin, but depends on your configure options), and the deployment system into localstatedir/install_name/profiles(default /var/lib/yule/profiles, but depends on your configure options).

    If you already have installed the deprecated version 1 deployment system, the script will be installed as deploy2.sh.

  3. For each architecture that you define, there must be (at least) one build host where development tools (C compiler, make, strip) are available to build the client executable.

  4. On each remote where you want to build or install, you should be able to login as root with ssh using RSA authentication, such that ssh-agent can be used.

[Tip]Tip

To use RSA-based authentication in a secure way, you may proceed as follows:

Use ssh-keygen to create a public/private key pair. Don't forget to set a passphrase for the private key ( ssh-keygen will ask for it).

Copy the public key ( HOME/.ssh/identity.pub for the ssh protocol version 1, HOME/.ssh/id_rsa.pub for ssh protocol version 2) to HOME/.ssh/authorized_keys on any remote host where you want to log in. Do not copy the private key HOME/.ssh/identity(ssh protocol version 1) or HOME/.ssh/id_rsa(ssh protocol version 2) to any untrusted host !

On your central host, execute the commands (use "ssh-agent -c" if you are using a csh-style shell):

            bash$ eval `ssh-agent -s`
            bash$ ssh-add
          

You can then ssh/scp without typing the passphrase again, until you exit the current shell.

1.2.Layout of the deployment system

(localstatedir)/(install_name)/profiles/
                      |
                      |
                      |-- source ------------> (tarballs)
                      |
                      |-- configs -----------> (default configs)
                      |
                      |-- archpkg
                      |    | 
                      |    |-- architecture -> (compiled package, setup script)
                      |
                      |-- hosts
                      |    |
                      |    |-- hostname -----> (optional host-specific config)
                      |
                      |-- libexec -----------> (scripts)
                      |
                      |-- private -----------> (gpg key)
                      |
                      |-- tmp
	

1.2.1.The configs subdirectory

The configs subdirectory holds for each architecture at least two files (example files will be placed there upon installation of the deployment system):

<architecture>.configure (required)

The configure options for this architecture; one option per line, each enclosed in single quotes.

If this file does not exist, it will be copied from generic.configure, which is created upon installation, and holds (only) some minimum options.

<architecture>.samhainrc (required)

The default runtime configuration file for a client running on this architecture. It is possible to override this on installation with a file hosts/<hostname>/samhainrc.

<architecture>.preinstall (optional)

The shell script to run before installing a client. Typically this script would shutdown the running client, if there is one.

Defaults to libexec/preinstall.

<architecture>.postinstall (optional)

The shell script to run after installing a client. This script receives the client password as first (and only) argument, and typically would set the password in the client binary.

Defaults to libexec/postinstall.

<architecture>.initscript (optional)

The shell script to initialize/update the baseline database file installing a client.

Defaults to libexec/initscript.

1.2.2.The archpkg subdirectory

The archpkg directory holds for each architecture a subdirectory archpkg/<architecture>, where compiled binary installer packages are stored.

For each build, up to four files will be stored: (a) the binary installer package samhain-<version>.<format>, (b) the configure options used ( configure-<version>.<format>), (c) the samhain-install.sh script generated during the build ( install-<version>.<format>), and (only for packed executables) the client password set in the executable ( PASSWD-<version>.<format>).

1.3.Customizing the system

1.3.1.Setting default options

If you want to change the default options, you can set some of them via a configuration file ~/.deploy.conf, which is created upon the first invocation of deploy.sh .

1.3.2.Adding support for an architecture

To add support for another architecture <arch>, just create the two files <arch>.configure(configure options) and <arch>.samhainrc(runtime configuration) in the configs directory of the deployment system (see Section1.2 ).

Upon installation of the system, a template file generic.configure is created, which contains the minimum options for a client.

1.3.3.Per-architecture pre-/postinstallation scripts

The default scripts for preinstallation (shutting down the running client) and postinstallation (setting the client password, fixing the local configuration file), and the script for database initialization are located in the libexec directory. You can override them for some (or all) architectures by storing architecture-specific files <arch>.preinstall, <arch>.postinstall, <arch>.initscrip in the configs directory.

1.3.4.Per-host runtime configuration

If you want to override the runtime configuration file configs/<arch>.samhainrc on a per-host basis, you need to store a host-specific runtime configuration file as hosts/<hostname>/samhainrc, before you run deploy.sh install .

1.4.Using the deploy.sh script

[Tip]Tip

When run for the first time, deploy.sh will create a configuration file ~/.deploy.conf with some default configuration options. You may want to review this file. Note that you can override all options there with command-line options; the configuration file is just for convenience, if you don't like the defaults and don't want to type the corresponding option on the command line every time.

deploy.sh can be invoked in three ways:

        bash$ deploy.sh --help
	This will provide a general overview. 
        bash$ deploy.sh --help command
	This will provide help on a specific command 
	(where command can be any of: 'clean', 'download', 'checksrc', 
	'build', or 'install'. 
        bash$ deploy.sh [options] command
	This will run 'command' with the specified options.
	

A log of the last run will be kept in tmp/logfile.lastrun

command can be any of the following:

info

Provides information on installed clients, or available installer packages.

clean

Removes source tarballs from the source subdirectory of the deploy system. Removes unused installer packages from the archpkg/<arch> subdirectories of the deploy system.

download

Download a source tarball from the distribution site, verify the GnuPG signature (gpg must be installed), and install it into the source subdirectory of the deploy system. Requires one of: wget , curl , links , lynx , fetch , or lwp-request .

checksrc

Check the GnuPG signatures of available source tarballs in the source subdirectory of the deploy system (gpg must be installed). Optionally delete tarballs with no/invalid signature.

build

Build a binary installer package for the chosen architecture from one of the tarballs in the source subdirectory, and store it in the archpkg/<architecture> subdirectory (which will be created if it does not exist yet). Requires a file <architecture>.configure and a file <architecture>.samhainrc in the configs subdirectory.

install

Copy a pre-built binary package (built with deploy.sh build ) to a remote host, stop the client running there (if any), install the (new) client, update the server configuration file and reload the server, initialize the file signature database and fetch it from the remote host.

uninstall

Remove a samhain client that was previously installed with deploy.sh install .

1.4.1.General options

-q | --quiet | --quiet=2 Produce output suitable for logging. Note that --quiet=2 implies --yes (see below).

-s | --simulate Print what would be done, but do not actually change the system.

-y | --yes Assume yes as answer to all prompts and run non-interactively.

-o <file> | --logfile=<file> Specify an output file for messages that would go to stdout otherwise. Has no effect on stderr (error messages).

-d <dialog> | --dialog=<dialog> Specify your preferred "dialog" clone (e.g. Xdialog). Use "no" to force plain text.

1.5.deploy.sh info

This command will show information for hosts in the client database (default), or for available binary installer packages.

1.5.1.Specific options

--packages Show information for available installer packages rather than for clients.

1.6.deploy.sh clean

This command will clean unused files: source tarballs in the source subdirectory, and unused installer packages in the archpkg/>arch> subdirectories.

1.6.1.Specific options

There are no specific options for this command.

1.7.deploy.sh download

This command will download a source tarball from the distribution website, verify its GnuPG signature, and install it into the source subdirectory. This command requires that either wget or lynx is in your PATH.

[Note]Manual installation of source

This note applies if you want to download source manually instead. Samhain distribution tarballs contain exactly two files: first, a source tarball with the source code, and second, its GnuPG signature. For installation into the source subdirectory, the distribution tarball must be unpacked, and both the source source tarball and its GnuPG signature moved into the source subdirectory.

1.7.1.Specific options

--version=<version> The version of samhain to download. The default is "current" to download the current version.

1.8.deploy.sh checksrc

This command will check the GnuPG signatures of source tarballs in the source subdirectory.

1.8.1.Specific options

--delete Delete source tarballs if PGP signature cannot be verified.

1.9.deploy.sh build

This command will create a temporary directory on a remote build host, copy the selected version of the source there, build the selected format of the binary installer package, retrieve and store the package into the archpkg/>architecture> subdirectory, and remove the temporary build directory.

For each build, up to four files will be stored: (a) the binary installer package samhain-<version>.<format>, (b) the configure options used ( configure-<version>.<format>), (c) the samhain-install.sh script generated during the build ( install-<version>.<format>), and (only for packed executables) the client password set in the executable ( PASSWD-<version>.<format>).

[Note]Package formats

Note that the build host must provide the required tools if you want to build a package for the native package manager (i.e. deb, rpm, tbz2, depot (HP-UX), or solaris pkg). On RPM-based Linux distributions and Gentoo Linux, building of RPMs and tbz2s, respectively, should just work. Debian requires additional packages for building debs.

The "run" binary package format does not require additional tools (it is a self-extracting tar package based on the makeself application, which is included in the samhain distribution). Use /bin/sh <package> --help for details.

1.9.1.Specific options

--host=<hostname> The build host.

--arch=<arch> The architecture to build for. This is used to get the "./configure" options from the file configs/<arch>.configure, and to store the binary package into the directory archpkg/<arch>.

--version=<version> The version of samhain you want to build. Must be in the source subdirectory.

--format=<run|rpm|deb|tbz2|depot|solaris-pkg> The format of the binary installer package. "run" is a portable (Unix) package based on makeself, "deb" is a Debian package, "tbz2" is a binary Gentoo Linux package, "rpm" is an RPM package, "depot" is an HP-UX binary package, and "solaris-pkg" for Sun Solaris.

--packed=<password> Build a packed executable, and set the client password before packing.

--user=<username> Login as <username> on the build host (defaults to root).

--add-path=<path> Append <path> to the PATH variable on the build host.

--tmpdir=<path> Temporary directory to use on the build host (defaults to /tmp).

1.10.deploy.sh install

This command will create a temporary directory on a remote host, copy the selected version of the installer package, its corresponding samhain-install.sh script, the runtime configuration file, and the preinstall, postinstall, initscripts scripts there. It will then:

(A) run the preinstall script on the client, which shuts down the running samhain daemon (if there is any).

(B) install the binary installer package on the client.

(C) run the postinstall script on the client, which sets the client password (unless the binary is packed), and replaces the default runtime configuration file with the proper one. The latter step is required, because deploy.sh build builds from the pristine source, so the runtime configuration file in the installer package is just the default one.

(D) copy the proper client runtime configuration file to the server data directory (as rc.<client_name>), fix the server configuration file, and restart the server (which will fail non-fatally if the server is not running).

(E) run the initscript script on the client, which initializes (or updates) the baseline database.

(F) retrieve the baseline database, copy it to the server data directory (as file.<client_name>), and remove the temporary directory on the client.

[Note]The runtime configuration file

If hosts/<hostname>/<arch>.samhainrc or hosts/<hostname>/samhainrc exists, this will be used (in this order of preference), otherwise configs/<arch>.samhainrc will be used. If the latter does not exist, the command will fail.

[Note]Transparent handling of particular build options

The build options '--enable-stealth=..' is handled by determining the argument from the configure options that were used for the build, and preparing the runtime configuration file appropriately. I.e., you should provide a 'normal', plain-text configuration file.

The build option '--with-nocl=..' is handled by determining the argument (which is required for database initialization) from the configure options that were used for the build, and passing it to the initscript script.

1.10.1.Specific options

--host=<hostname> The host on which to install.

--group=<foobar> The group to which you want to assign that client (default: none). This is used by the beltane web console to restrict access to users which are members of that group.

--arch=<arch> The architecture to install. This is used to get the installer package from the directory archpkg/<arch>/.

--version=<version> The version of samhain you want to install. An installer package for this version must exist in the archpkg/<arch>/ subdirectory.

--format=<run|rpm|deb|tbz2|depot|solaris-pkg> The format of the binary installer package. "run" is a portable (Unix) package based on makeself, "deb" is a Debian package, "tbz2" is a binary Gentoo Linux package, "rpm" is an RPM package, "depot" is an HP-UX binary package, and "solaris-pkg" for Sun Solaris.

--yule_exec=<path> Path to the yule executable.

--yule_conf=<path> Path to the yule configuration file.

--yule_data=<path> Path to the yule data directory.

--no-init Do not initialize the file signature (baseline) database (and consequentially, do not replace the file.<host> file on server.

--no-rcfile Do not replace the rc.<host> file on server.

--no-start Do not start up the client after installation.

--local=<command> An optional command executed locally (i.e. on the server) twice (with the last argument set to 'first' and 'second', respectively. First is after client config file installation (i.e. before baseline database initialisation on the client), second is just before client startup. The script will be called with the following five arguments:

  1. hostname, i.e. the host on which to install,

  2. arch, the architecture to install,

  3. the directory where the deployment system is installed (default is /var/lib/yule/profiles, but depends on your configure options),

  4. the server data directory where client configuration files and baseline databases are stored (default is /var/lib/yule, but depends on your configure options),

  5. the literal word 'first' if the script is called the first time during client installation, the literal word 'second' otherwise.

--tmpdir=<path> Temporary directory to use on the installation host (defaults to /tmp).

1.11.deploy.sh uninstall

This command will remove a samhain client that was previously installed by using deploy.sh install .

1.11.1.Specific options

--host=<hostname> The host on which to uninstall.

--tmpdir=<path> Temporary directory to use on this host (defaults to /tmp).

1.12.Usage notes

[Warning]Warning

On Solaris, the PATH environment variable on the remote host (where you build or deploy) may get set according to /etc/default/su, which may be different from what you would expect (noted by S. Bailey).

MANUAL-2_4/options-configuration-file.html0000664000175000017500000000635412703400301020102 0ustar rainerrainer10.Runtime options: command-line & configuration file

10.Runtime options: command-line & configuration file

All command line options are described in AppendixB . Note that depending on the ./configure options used for compiling, not all options may be available. You can get a list of valid options with samhain --help .

All settings in the configuration file, are described in AppendixC . Note that depending on the ./configure options used for compiling, not all options may be available. If you are using unsupported options, samhain will log warning messages upon startup, including the line number of the offending line in the configuration file.

MANUAL-2_4/stylesheet-images/0000755000175000017500000000000012545202252015372 5ustar rainerrainerMANUAL-2_4/stylesheet-images/tip.gif0000644000175000017500000000112612121421267016654 0ustar rainerrainerGIF89a !!!999ZZZccckkksss{{{!, EQEQEEQEEQEQEQE9,<EQEQEQ(FR$E<EQEQ) 4M4M8MPEQEIJ#M4M4M- CQEQL4MSD4MӤ4E,4M$!M4MQ-N4M4M4= EQ3M4M8A 4M4MD@4M4%L4M4MCE4M4M@Q4M4)TH4M4)eH4M4E FK4M4MTP4M4MSP"M8M4IeH4M4E -4M4MTP4M4MPL4M$!4M4-EA4M4MRA4MNQ<4M$!M4MSPHQM4M! 4M,EQ,4M4A3M4MCQEQD44M4MOPEQEQH4MN8EQEQEAJ@Q=DHQEQEQEE(DEQEQ!;MANUAL-2_4/stylesheet-images/important.gif0000644000175000017500000000175312121421267020103 0ustar rainerrainerGIF89aC)))999BB1ZZ)ccBBBRRRkkBccRssRccckkk{{{9!9Z{c{JRZck{!19)11!ZRsckBc{!K,KKKKKKKKKKHHHHHKKKKKKKKKKKKKKKKHD?8???8?EJKKKKKKKKKKKJC79"&&&&&>7EKKKKKKKKKH84'''''''''/?JKKKKKKJ8=&'''''''''''&BKKKKKJ8='''''% ''''''BKKKKE&'''''&'''''&GKKH<4'''''' "''''''/@KKE:'''''''6 ,'''''''HK?#''''''')''''''':EH?&'''''''''''''''$8H?&''''''' ''''''''$8H?&'''''''!''''''''$8H?&'''''''*1''''''''$8H?&'''''''375''''''''$?KB"'''''''+ )''''''':EKF9''''''' +''''''3;HKJ ]> MANUAL-2_4/stylesheet-images/next.png0000644000175000017500000000042112150576765017072 0ustar rainerrainerPNG  IHDR#Yi&BPLTE!!))11BBJJRRcckkƌΔΥ֭޵twIDATxڽ 0bFBaLP8Ak k_*)HURm3;z&ƙԬ9c^;%898!KZJanXmՊRo柳+,̣z:l&BR2AIENDB`MANUAL-2_4/stylesheet-images/home.png0000644000175000017500000000041712150576764017050 0ustar rainerrainerPNG  IHDR#Yi&9PLTE!!))11BBJJccssƌΔΥ޵IDATxڽ 0E[]4;;6 t/co"A'|??d|`ŕ$b+X+#  N*ؗx3j Z C걞r!;?ҌOP3T">\32p >7A|W$M|a-nCķ>|Ç>|Ç>|Ç>|Ç>|'Ç>|Ç>|Ç\5߿ѧhP@;MANUAL-2_4/stylesheet-images/home.gif0000644000175000017500000000050112121421267017004 0ustar rainerrainerGIF87a((```,((pH+ ͻ`)fh؆pY)0M6 =@v3R|g2v@g u?`̕tUSŒ_ҾoФԥԿǾVV@Gu0 e K,h+BII ;MANUAL-2_4/stylesheet-images/prev.svg0000644000175000017500000000202012121421267017060 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/warning.tif0000644000175000017500000000370612121421267017550 0ustar rainerrainerII* P1aBHd R10l9 Aa="+JG"b) J%R@f\<IAxU, c Hb &>@`C@ c3ȘSdb6$fv*d ^u(_fb0mRUtE 2JCUZ0 ʅ1CEZ8 𒑦^:ncxBol+"go=1}΁>wA !)1BJRZks{{RZ{9J1)))!{RZ{9J1)))!KK=@MANUAL-2_4/stylesheet-images/next.gif0000644000175000017500000000207312121421267017040 0ustar rainerrainerGIF87a&%@@@ʦ@@@𠠤,&%H*\P #JHA2jȱI!Gfl_ʂ2d%Ag.gs :0#LA#z@Fc #T3QxfC|[u{_Xh;u!bm >uoә aƂ/xb{\0B|flrƙg E-j^';)Ç>|Ç>|Ç>|G>|Ç>|!Ç>|Ç>|1mZ}Yf:h@;MANUAL-2_4/stylesheet-images/tip.png0000644000175000017500000000070012121421267016670 0ustar rainerrainerPNG  IHDR* bKGD#2IDAT(u0 DUµ2.L ”`hLU,.{F~4ODD N=GFf'IԥK':\}ԃ8\g&G:%Ѡ9!4uAe1b/ʟrSNL?Lw ~#J&)_˚}9q^={\E>_R_H>4+|݂)CtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignatureee9d877396ce267aeb0179d35f81b2ac3'tEXtPage25x24+0+0 IENDB`MANUAL-2_4/stylesheet-images/warning.svg0000644000175000017500000000217512121421267017564 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/up.svg0000644000175000017500000000202012121421267016530 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/prev.png0000644000175000017500000000037212150576765017075 0ustar rainerrainerPNG  IHDR#Yi&?PLTE!!))11BBJJRRkkssƌΔΥ֭>-vIDATxڵQ 1 g[܋P|&c޵ʩ٫;!sƎHȾiUQ %tQ+jr @2W^c3Q69:'$;X %s-IENDB`MANUAL-2_4/stylesheet-images/warning.gif0000644000175000017500000000134712121421267017532 0ustar rainerrainerGIF89a5!)1BJRZks{9911))RRZZ{{{{JJ))))!!!6,@fl3L&d2fl6fbbX.ˊfl6f8t: l6f*t:NJl6feLt:Nth6Mt:M t:@)Nt t:Nm1NttN%Nt:It:NI#Nt:ut:NI#N ]> MANUAL-2_4/stylesheet-images/colorsvg/prev.svg0000644000175000017500000007436612121421267020744 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/warning.svg0000644000175000017500000004132212121421267021417 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/up.svg0000644000175000017500000007472012121421267020406 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/next.svg0000644000175000017500000007466012121421267020743 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/tip.svg0000644000175000017500000010111612121421267020544 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/note.svg0000644000175000017500000004327112121421267020724 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/home.svg0000644000175000017500000014747112121421267020716 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/colorsvg/caution.svg0000644000175000017500000002610712121421267021420 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/note.png0000644000175000017500000000074412121421267017051 0ustar rainerrainerPNG  IHDRb$bKGD#2IDATa0 @aaiaსZA#  zw0VFfF`9:r0prɅŠ6 P 5\r{~̌Y#fO}1:huŚs=c|;qct9tW{\9̗<'gݻ7 l@10pV]`s=y޽+`슈:dMCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature3bd747c5e45807006b090dd3e7a26c44ӓtEXtPage24x24+0+0r[ 1IENDB`MANUAL-2_4/stylesheet-images/note.gif0000644000175000017500000000110412121421267017021 0ustar rainerrainerGIF89a JJJRRRZZZccckkksss{{{!,`UUUUUUUI$IUUUUUUUUUUUU,ʲ,TUUUUUUUUMN@N(SUUUUUUIQEQEQ0UUUUUM CQEQEQ5-MUU`UMJCQEQEQEQTUU= EEQEQEQ5-UUUKDQEQREQEQRUBQE9 0M$I(IHM$AO,˲(ȢslZOd#(!-^IT y`Wjc Uz-CE[l&J#Ӱh//D,}51 hc2oxZ ӱ(,ŀ1!Zڈ51)#lQl-*m%~#E*F0gv:(YoR#xyKuL F,F,ŀb41*Z 䢘15(&EQ!䢘lc*F0b4b`,F0b4b4b4b41v"51nZH.iE1H-#h*lj#E1E1HQF0bfxE1F,F,F,7b4Q`IYR1\ZܬXX]hH. XhIF,X>#o,w5ZFX,eX<$K`|Ź+;IYT*E0>Т$-?|iT!BL24F,JhZ3sQB6ci"FKE0>bic,Q i<lsQF0>ۢRA*0gb9X/H,m(`L&WVb&"YT a(bH"/7iir,1YYc#ik,1Moѽ#uSKc 456t5.Zcz8h0&1^`LMcƥZcZcE01\cR (@c\odcm4E01`LDc (ΞJ"8'a)h{)iv"k<6F)dc:$lgcJ%}:`\$`1{Fꦖzb[ FlLei]rjmZc0oTYccx[,19Zcj#4lii"E01r`Q?"-1l"SјE0&1`L:0RB4 )4~cH6B#F6q`D#CSl#F0lFU7FFRexL6ߢRJ5h*SU9`#"wDcT^eylf{fw<ݮ PM)Oqg4`Sˆm(GuG_6=_u|15xJ\h :E75J};_c:6ӓO"-q_;?<:bh;gjUގZ3D|ϵӾ~N|_o9L&`<\9o9ggȣ ]D0v ,Wez04M؋BZ7@>F4us,Sy^m7. 5=;j"]^VU7o=e͂ŇcnW6ToǷlfn>Raѷ2X|0F4ptC[X|.7|x;Ua=wuf8XL;VLus/d`1ev8pphJr,:PT XE{e]}.F3[U湽`t-É ؕA6O*W*̱&1Chkb<BRb@8fu?c J Rg1T~Ia;7X|,69PۖS1T~zĢL,f6++bLKH(ʺ*Bm{ŧ==X| ټji1Zcyj=o\6:cq{VU5h_iblQ|yھ:_XqbZӗoꓫjZPYޮնZw'lmgc$\l7w-6Ig k'ͼlѻ㻦טvuͦZ# ߎr[bW,j^Ɵox0Ѻ>^k?T0bvz2טƕ\,]Ϻ8۷n`\ŝ7ј Ɛ.OokA/kLZqŕ+v|kK1\KQWM|7S<1/~a6L>=+,Ә+{31^bѻ&;1^c9&F5F* te;='NG2x!Ϋ,%"xE+kmg ,Ċ1ˏa˶4 л[3) s.cn﬍'k-zCL8gw|W1b0 3br BW[$ciGˍ͊=C:\0-~ f "xW5oѬ0ސξI~޼,g]5y~tp1ҸnrUZrI6q*v^YF*4ƥƞt,FO }z^ȘqO= Ѣ qjN꬛`c{z1h㩚P?6 1J+.4KkU,ε ];٠= \̶]ܺ jd'o-6UkzƖQ [,,c?lL㻱Ko }A6R0r1k~Ohd777F1bĭ6Ӗh`cqK9v6h d# ڝ3l8]h;!nz0Zu߱{xqt![^B1b%v~N[Z0bǠGs kk }JX0FwkdGYܻͲrD1~X#-|^޷1~{zr1~shԒ1~Ңsc~tpV^1bvGwOio[bh|[tn,V[jH1J,:gH1ʰ\~_c(Y] vZF)>GXqb~EgV{yV#aV`j5M7G>XQw'Xp( ]i\QiĢ0r9lx_#a\GwvΧH(3sv펲ЈEa%jY6\Ql.:NkjĢ0R_5 ^[#a9_ևW~iĢ0\tʵg4bQU+WvMF, 85oZgeaCjzYqiU M 𞏘& D?јN  a|q*;9ӗ(4zwj0&\Fo4tA6Z\cx:1h >cbk\y07>[J.F8Qb1: Qz6`q֯$S([1zI0;rW#F}{ldLdƳ>ƝT1 u[>df^clbs'PE3.F_ɘhLT3kQp:4FM#(R3'bі{QFO3i(o-ƼLFnzFqh (-_7Ӫ0 e2fp 4NY|g`s$O^}=2<QiB?y@ņQLK9S2 BZj߁,> lMQFϔ7]ƧaR4Wk9<Y{g<F#1~T5/0>G5z^%31~PbF{KS'ss`tX |85% Ƈc_q,0ޭ>|;߻_xƩ5 xƩQ1QF㵨X{_P* [5-jj[d8 8U?˞xƩ_ӤbPEm`aaaaVcMO9IENDB`MANUAL-2_4/stylesheet-images/next.svg0000644000175000017500000000202012121421267017062 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/warning.png0000644000175000017500000000073112150576765017565 0ustar rainerrainerPNG  IHDRשPLTE!)1BJRZks{{{RRZZ{{99JJ11))))))!!1VIDATxm Yz׻h5*&JM.JM|PXe% >%v%l%5*/dD6 2~;]U-&3hv`EBq:Oː;& .l@eڗ, oqg zB{=bjö ns_ wUzz¾;#dz9nz |0n!IENDB`MANUAL-2_4/stylesheet-images/important.png0000644000175000017500000000107412150576765020136 0ustar rainerrainerPNG  IHDRשPLTE)))999BB1ZZ)ccBBBRRRkkBccRssRccckkk{{{9!9Z{c{JRZck{!19)11!ZRsckBc{IDATxmR0wPm`jj%Vl0P~pf2'_dU:<'ZA/7 MZgnt |1q=:I^(~K 霕 ]> MANUAL-2_4/stylesheet-images/caution.gif0000644000175000017500000000134712121421267017527 0ustar rainerrainerGIF89a-!!11BBZZcckkss{{ss{{Zcc9191Bス!.,@r\.r\.r\.r\.b\.r\.r\.˵-r\.r\.˵,r\.r\.%!y>Tr\.r].k%y<r\.r\.jx8ǒj\.r\e@dZ.r\DxYN-r\, x|0rVx<Ax< rVx<@x<%r$$x<x<xQZ)x<x<gCY\-x<΁x<Ohr\V x< Px<Or\.<0x ]> MANUAL-2_4/stylesheet-images/toc-minus.png0000644000175000017500000000040312121421267020012 0ustar rainerrainerPNG  IHDR )bKGD#2IDATxch`g  I׏j?}-pZECtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignatureecf413ef47524404f90c44d8c7d12a2e݈ tEXtPage15x9+0+07vIENDB`MANUAL-2_4/stylesheet-images/draft.svg0000644000175000017500000000073712121421267017221 0ustar rainerrainer Draft MANUAL-2_4/stylesheet-images/callouts/0000755000175000017500000000000012544464531017231 5ustar rainerrainerMANUAL-2_4/stylesheet-images/callouts/23.svg0000644000175000017500000000260312121421267020165 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/9.gif0000644000175000017500000000163312121421267020061 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, x l%%E)* s(TA+kJEתo0ҐE:@ ٫aȆz;wM6 FaBP/GCFhݚ)ư@ o QA ;MANUAL-2_4/stylesheet-images/callouts/5.svg0000644000175000017500000000170712121421267020111 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/9.png0000644000175000017500000000053612121421267020101 0ustar rainerrainerPNG  IHDR s;bKGD#2xIDAT0b1 {ŽB1W.j18{H}]v EN Pm9^`8\*8Ȑ ]> MANUAL-2_4/stylesheet-images/callouts/3.png0000644000175000017500000000052712121421267020073 0ustar rainerrainerPNG  IHDR s;bKGD#2qIDAT@E'Wn/HdZ\L H@"'+f{6"4ML|fW(^A> ƻWQPE{s4ݥHmmQ5c@0CtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature80bbda2726ddace8ab8a01f59de2ebdbutEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/27.svg0000644000175000017500000000207312121421267020172 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/11.png0000644000175000017500000000065412121421267020153 0ustar rainerrainerPNG  IHDR s; pHYsttfxtIME-'Kp"!;MANUAL-2_4/stylesheet-images/callouts/25.svg0000644000175000017500000000243212121421267020167 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/4.gif0000644000175000017500000000161312121421267020052 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, h l%%E %*Ta r,l@ɿ9 %E6lUƆ104r½ a2=F*c2gR(R"#9z[PaҡR()1 ;MANUAL-2_4/stylesheet-images/callouts/3.gif0000644000175000017500000000162212121421267020051 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, o *AX7kޜAs!oGF +Xc:g &sgaJ-82(w1r#tCkq cZUrd J ;MANUAL-2_4/stylesheet-images/callouts/14.svg0000644000175000017500000000161212121421267020164 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/12.png0000644000175000017500000000066612121421267020157 0ustar rainerrainerPNG  IHDR s; pHYsttfxtIME.UF/tEXtAuthorH tEXtDescription !# tEXtCopyright:tEXtCreation time5 tEXtSoftware]p: tEXtDisclaimertEXtWarningtEXtSourcetEXtComment̖tEXtTitle'IDATce? @s_/!@?#za8<3<``ؕC@΄[0c6Z6؞_\ A,E~Z0IENDB`MANUAL-2_4/stylesheet-images/callouts/10.svg0000644000175000017500000000202612121421267020160 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/11.svg0000644000175000017500000000147312121421267020166 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/22.svg0000644000175000017500000000237212121421267020167 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/5.png0000644000175000017500000000052612121421267020074 0ustar rainerrainerPNG  IHDR s;bKGD#2pIDAT!E'W"H$r[ԃD""JJ\A9 ZKvWDtetp}à5 FBcCS/gD#Nԋ y?#[7/BCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignaturefe690463379eb25e562fcc8cc9b3c7e0߲9tEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/30.svg0000644000175000017500000000255312121421267020167 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/1.png0000644000175000017500000000051112121421267020062 0ustar rainerrainerPNG  IHDR s;bKGD#2cIDATxU 0.)Bft6#dH('XW 9cAM-!d>0(*?/c}֮5uƌ:x,TCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature58a072e070da22f6135cbd3e414546f9hj!tEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/15.svg0000644000175000017500000000207612121421267020172 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/10.png0000644000175000017500000000054412121421267020150 0ustar rainerrainerPNG  IHDR s;bKGD#2~IDAT E'Hl$-D^ )!-DFƦĞD" . McBhO^<۔s*;{Rt_IH}l2ء{bJ7^vǶޒCH,|-ݢCbCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature386e83bb9bdfba3227f58bb897e2c8a5+ tEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/4.svg0000644000175000017500000000141712121421267020106 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/15.gif0000644000175000017500000000032212121421267020130 0ustar rainerrainerGIF89a  333999AAANNNTTTeeekkksss}}}!, O'~4U,߀$@,,4l" 4(FqXQ" ʨX&pDhr" 5F} ;MANUAL-2_4/stylesheet-images/callouts/11.gif0000644000175000017500000000031212121421267020123 0ustar rainerrainerGIF89a  $$$)))222;;;CCCSSSeeeiii{{{!, G'ht&ñ&@4B% a,*>CPJdB4pB ]>j0Uc4|;MANUAL-2_4/stylesheet-images/callouts/1.gif0000644000175000017500000000157112121421267020052 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, V * c,l35TrER,1"8txJD6|Q˕dT B(HT/$9() ;MANUAL-2_4/stylesheet-images/callouts/2.svg0000644000175000017500000000163612121421267020107 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/8.gif0000644000175000017500000000162612121421267020062 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, s l%%E)*T s(Ұ7k TC%4ӐCBB"xa :wAC0h'E ˛'KjjF3xPIP:MO QaG%!BI(0 ;MANUAL-2_4/stylesheet-images/callouts/29.svg0000644000175000017500000000260712121421267020177 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/9.svg0000644000175000017500000000206212121421267020110 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/10.gif0000644000175000017500000000164112121421267020130 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, ~ *) XVz_Y`761-RCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature298368142ac43cebd2586d8d1137c8df&9tEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/8.png0000644000175000017500000000053512121421267020077 0ustar rainerrainerPNG  IHDR s;bKGD#2wIDAT0j{bGF }-KBa lCϝqBǠ͜$H, ạpZ:j>'DaVJsI9e"UCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature57be19505c03f92f3847f535e9b114e94kCtEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/21.svg0000644000175000017500000000203512121421267020162 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/17.svg0000644000175000017500000000154212121421267020171 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/26.svg0000644000175000017500000000266312121421267020176 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/28.svg0000644000175000017500000000303212121421267020167 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/16.svg0000644000175000017500000000232412121421267020167 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/2.png0000644000175000017500000000052512121421267020070 0ustar rainerrainerPNG  IHDR s;bKGD#2oIDAT@ /+ȮH$+D2+0 w-vT*Q&Ϗ&S0w/Qw| V׈S#3s3]3T5`bCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature80eae529c94a7f47deccfada28acb9dfo tEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/3.svg0000644000175000017500000000205312121421267020102 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/7.svg0000644000175000017500000000134212121421267020106 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/4.png0000644000175000017500000000052212121421267020067 0ustar rainerrainerPNG  IHDR s;bKGD#2lIDAT@`0Z\ Ç{`̕_g$9#TGmWg󕁷V kqV¤KPO+7}#:O^6SCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature9f82fcac9e039cbdb72380a4591324f5vtEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/12.gif0000644000175000017500000000032212121421267020125 0ustar rainerrainerGIF89a  +++222:::DDDOOOSSS^^^cccmmmttt!, O'ZMHb9@P eLD 4@"<-bLp  j .O0(40~ ;MANUAL-2_4/stylesheet-images/callouts/5.gif0000644000175000017500000000162412121421267020055 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, q *́ E)X ǿwH|H#VGK!}dIZ>R:1GFi W F% ;MANUAL-2_4/stylesheet-images/callouts/2.gif0000644000175000017500000000161312121421267020050 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, h *@ c,ڹw Ȩa)ku!= Պ4Dҥsj"0Iʗ##1t9|P`I9() ;MANUAL-2_4/stylesheet-images/callouts/18.svg0000644000175000017500000000247312121421267020176 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/24.svg0000644000175000017500000000215112121421267020164 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/20.svg0000644000175000017500000000234112121421267020161 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/6.png0000644000175000017500000000053512121421267020075 0ustar rainerrainerPNG  IHDR s;bKGD#2wIDAT0OEFF ]Hdm$#"3ytkC?BF< kQ݀F'/0 sƀO,KvI#s(̠Bʯ=?s83baCtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignatured25d7176d67a038afc1c56558e3dfb1atEXtPage12x12+0+0m}IENDB`MANUAL-2_4/stylesheet-images/callouts/13.png0000644000175000017500000000067012121421267020153 0ustar rainerrainerPNG  IHDR s; pHYsttfxtIME.1 tEXtAuthorH tEXtDescription !# tEXtCopyright:tEXtCreation time5 tEXtSoftware]p: tEXtDisclaimertEXtWarningtEXtSourcetEXtComment̖tEXtTitle'IDATcߎO4DqZ.ؼ|i~ۯlBwv1c?[~Aw6gx L>qc  >胍f%g l)@|}Z_IENDB`MANUAL-2_4/stylesheet-images/callouts/1.svg0000644000175000017500000000127712121421267020107 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/7.gif0000644000175000017500000000161312121421267020055 0ustar rainerrainerGIF89a   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, h %%E %*CCr(տ1I<~$)Z~D Z.O8?2%#J> 1B!.*)) ;MANUAL-2_4/stylesheet-images/callouts/8.svg0000644000175000017500000000230012121421267020102 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/14.png0000644000175000017500000000036612121421267020156 0ustar rainerrainerPNG  IHDR s; pHYsss"tIME x8bKGD̿IDATc[j ̹%o6m`O%p_]Ͱ?u #+ӴE I|o `0les Sr m8_wZ]IENDB`MANUAL-2_4/stylesheet-images/callouts/19.svg0000644000175000017500000000225512121421267020175 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/callouts/13.gif0000644000175000017500000000032112121421267020125 0ustar rainerrainerGIF89a  ///555<< ]> MANUAL-2_4/stylesheet-images/callouts/6.svg0000644000175000017500000000213612121421267020107 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/tip.tif0000644000175000017500000000064412121421267016675 0ustar rainerrainerII*?P8# BaP';JRb .^x5(gE=ҋجRaR*`J,,=Ms*K R s@J*3([z Q*aT-d3 B7:R_=6\Pm{ޭWtޱ R_lvdfxRk^)ݮyx›l-RS;_"}]J#(yx >x_A|Px|zlU࿂[Xv࿂&lK_A|rQX 4W` ῂ_A| S >!W` +0?  cA|X9>G>|Ç>|DÇ>|Ç>|Ç>|Ç>|>>>TQi$ᄈ)r;MANUAL-2_4/stylesheet-images/caution.tif0000644000175000017500000000367212121421267017547 0ustar rainerrainerII* P8$  0dH ᰁ HV ĢpAx4V2Ñ ]> MANUAL-2_4/stylesheet-images/caution.svg0000644000175000017500000000233412121421267017556 0ustar rainerrainer ]> MANUAL-2_4/stylesheet-images/caution.png0000644000175000017500000000073312150576764017563 0ustar rainerrainerPNG  IHDRשPLTE!!11BBZZcckkss{{sss{s{cZcc19B191brxIDATxu0 D-ZXH/4,q %ɼxfgZf~5ٛ_@-bmmRcSf< n9#;6Rn WB#%r?7e[ah.'=S'dwɊ=u49Ude]. &+y53ŭN$a c6Q|JH7dg.@A Nl;vGIENDB`MANUAL-2_4/stylesheet-images/annot-close.png0000644000175000017500000000016012150576765020336 0ustar rainerrainerPNG  IHDR O"PLTE$Y%IDATxMA 0M᝼GZpb) WKDIENDB`MANUAL-2_4/processcheck.html0000664000175000017500000001474112703400301015300 0ustar rainerrainer14.Checking for hidden/fake/missing processes

14.Checking for hidden/fake/missing processes

To compile with support for this option, use the configure option

./configure --enable-process-check

This module enables samhain to check for processes that are:

(a) hidden from ps, i.e. running processes that are not listed by ps,

(b) fake, i.e. listed by ps although they don't exist, and

(c) missing, i.e. processes that are required to run (as specified by the user), but are actually not running.

The module works by searching the complete range of possible PIDs for processes, and comparing the list of processes thus found against the output of ps. Note that the range of possible PIDs is OS-specific, and in general must be configured by the user (except for Linux, where it is determined automatically).

[Note]Threads

Threads (including kernel threads) may be detected as well; thus ps must be called with the proper argument such that threads are listed as well, otherwise they will be reported as hidden. On Linux, this is handled automatically by the code, for other operating systems, you can use the configuration option ProcessCheckPSArg= arg to set the argument to ps .

E.g. OpenBSD needs ProcessCheckPSArg= axk such that kernel threads are listed as well.

[Note]OpenVZ

The OpenVZ virtualisation has one hidden process for each visible process (within the container). If you run samhain within an OpenVZ container, use ProcessCheckIsOpenVZ= true to automatically avoid false positives.

14.1.Example configuration

	  [ProcessCheck]
	  #
	  # Activate (default is on)
	  #
	  ProcessCheckActive = yes
	  
	  # The severity of reports: debug/info/notice/warn/err/crit/alert
	  # (default is crit)
	  #
	  SeverityProcessCheck = crit
	  
	  # The PID range (default is 0 to 32767)
	  #
	  ProcessCheckMinPID = 0
	  ProcessCheckMaxPID = 32767
	  
	  # The interval (in seconds) for process checks (default is 300 sec)
	  #
	  ProcessCheckInterval = 300
	  
	  # Specify a process that is required to run. The argument
	  # must be a POSIX regular expression that matches the
	  # output of ps (samhain will check whether the PID in the
	  # output of 'ps' actually runs). You can use this option 
	  # multiple times. Note that each matching substring in a line
	  # from the 'ps' output is considered a successful match.
	  #
	  ProcessCheckExists = syslogd
	  
	  # The 'configure' script determines automatically
	  # the location of 'ps' as well as whether it is 
	  # Posix or BSD style. Therefore, these options may
	  # not be required. For 'ProcesscheckPSArg', note
	  # that the first column must be the PID, except on
	  # Linux, where the format 'PID SPID ...' is expected
	  # (spid = thread id), as shown by 'ps -eT'
	  #
	  # ProcessCheckPSPath = /usr/bin/ps
	  # ProcessCheckPSArg = -e
	
MANUAL-2_4/command-line-yule.html0000664000175000017500000000645712703400302016151 0ustar rainerrainer3. yule

3. yule

  1. -S, --server Run as server. Only required if the binary is dual-purpose.

  2. -q, --qualified Log received messages with the fully qualified name of client host.

  3. --chroot=<arg> Chroot to to the directory arg(should be an absolute path.

  4. -G, --gen-password Generate a random password suitable for use in the following option (16 hexadecimal digits).

  5. -P <arg>, --password=<arg> Compute a client registry entry. arg is the chosen password (16 hexadecimal digits).

MANUAL-2_4/ccp-limitations.html0000664000175000017500000000760712703400302015727 0ustar rainerrainer2.Limitations

2.Limitations

The --verify-database requires that the policy under which a file is checked is stored in the baseline database. (Note that this affects only this command. For the normal file system monitoring, the checking policy is taken from the configuratiion file, not from the baseline database.) For this reason, the format of the baseline database has changed in samhain 4.0. However, it is possible that the information about the check policy becomes incorrect:

Added files
If files are added to the filesystem after baseline initialisation and reported by the client, the correct policy should be set. To ensure this, the option ReportCheckflags = yes should be set in the client configuration (for backward compatibility, this option is off by default.)
Merging a DeltaDB
The DeltaDB is generated with the policy set to ReadOnly, to collect a complete set of checksum and metadata. However, if the actual policy should be less restrictive because some of that data is allowed to change, a later --verify-database may result in spurious failures.
Client configuration change
If the configuration file for the client is changed to alter the checking policy for the monitored files, it is recommended to re-initialize the baseline.
MANUAL-2_4/preludedetails.html0000664000175000017500000002171112703400301015625 0ustar rainerrainer9.Prelude

9.Prelude

[Note]REQUIREMENTS

This facility requires that you have compiled with the --with-prelude option to include support for prelude. Of course you need the libprelude client library for this to work.

[Note]Note

The following configuration options can only be used. They should be placed the [Misc] section of the configuration file, if you use them. The 'PreludeMapTo...' options do not affect in any way whether a message is reported by samhain to the prelude manager (for this there is 'PreludeSeverity' in the [Log] section); they only affect the 'Impact severity' shown on the prelude side.

PreludeProfile

PreludeProfile= profile_name

Specify the profile to use. The default is 'samhain'.

PreludeMapToInfo

PreludeMapToInfo= list of samhain severities

The severities that should be mapped to impact severity 'info' for prelude. (default: none).

PreludeMapToLow

PreludeMapToInfo= list of samhain severities

The severities that should be mapped to impact severity 'low' for prelude. (default: debug, info).

PreludeMapToMedium

PreludeMapToMedium= list of samhain severities

The severities that should be mapped to impact severity 'medium' for prelude. (default: notice, warn, err).

PreludeMapToHigh

PreludeMapToHigh= list of samhain severities

The severities that should be mapped to impact severity 'high' for prelude. (default: crit, alert).

9.1.Prelude-specific command-line options

The following prelude-specific command-line options are accepted:

  1. --prelude Prelude generic options are following. This option must be given before the following options are used.

  2. --profile <arg> Profile to use for this analyzer

  3. --heartbeat-interval <arg> Number of seconds between two heartbeats

  4. --server-addr <arg> Address where this sensor should report to (addr:port)

  5. --analyzer-name <arg> Name for this analyzer

9.2.Registering to a Prelude manager

[Tip]Sensor name/profile

The default sensor name/profile is 'samhain'. However, version 2.0.6 of samhain still had 'Samhain' For versions of samhain later than 2.0.6, there is an option PreludeProfile= profile (in the [Misc] section) to set a user-defined name/profile.

In order to register samhain as a Prelude sensor, you need to run on the sensor host and on the manager host the prelude-admin command.

	  sensor # prelude-admin register samhain "idmef:w admin:r" <manager host> \
	  --uid=prelude --gid=prelude

	  You now need to start "prelude-admin" registration-server on 127.0.0.1:
	  example: "prelude-admin registration-server prelude-manager"

	  Enter the one-shot password provided on 127.0.0.1:
	
	  manager # prelude-admin registration-server prelude-manager

	  The "76g4h8au" password will be requested by "prelude-admin register"
	  in order to connect. Please remove the quotes before using it.

	  Generating 1024 bits Diffie-Hellman key for anonymous authentication...
	  Waiting for peers install request on 0.0.0.0:5553...
	  Waiting for peers install request on :::5553...

	

You now have to type in the one-shot password generated on "manager" at the password prompt on "sensor", (twice, for confirmation). Then on "manager" you will be asked to approve the registration. Type 'y', and you are finished.

The configuration file for the samhain sensor is /etc/prelude/profile/samhain/config

MANUAL-2_4/log-file-rotation.html0000664000175000017500000000733112703400301016154 0ustar rainerrainer7.Log file rotation

7.Log file rotation

samhain locks the logfile using a lock file. This lock file has the same path as the log file, with .lock appended. After sending SIGTTIN or SIGABRT to the samhain daemon, it will first finish its current tast (this may take some time), then unlock the log file (i.e. remove the logfile.lock file), wait three seconds, then proceed. Thus, to rotate the log file, you should use something like the following script:

	#! /bin/sh 

	if test -f /usr/local/var/run/samhain.pid; then \
	  PIN=`cat /usr/local/var/run/samhain.pid`; \
	  /bin/kill -TTIN $PIN; \
	  sleep 1; \
	  AA=0; \
	  while test "x$AA" != "x120"; do \
	    AA=$(( AA + 1 )); \
	    if test -f /usr/local/var/log/samhain_log.lock; then \
	      sleep 1; \
	    else \
	      break; \
	    fi \
	  done; \
	fi 
	mv /usr/local/var/log/samhain_log /usr/local/var/log/oldlog
      

If you use the 'logrotate' tool, you could use the following (untested):

	/usr/local/var/log/samhain_log { 
	weekly 
	rotate 52 
	nocreate
	missingok 
	compress 
	prerotate 
	if test -f /usr/local/var/run/samhain.pid; then \
	  PIN=`cat /usr/local/var/run/samhain.pid`; \
	  /bin/kill -TTIN $PIN; \
	  sleep 1; \
	  AA=0; \ 
	  while test "x$AA" != "x120"; do \
	    AA=$(( AA + 1 )); \
	    if test -f /usr/local/var/log/samhain_log.lock; then \
	      sleep 1; \
	    else \
	      break; \
	    fi \
	  done; \
	fi 
	endscript
        }
MANUAL-2_4/file-monitor.html0000664000175000017500000003176412703400301015234 0ustar rainerrainerChapter5.Configuring samhain, the host integrity monitor

Chapter5.Configuring samhain, the host integrity monitor

Table of Contents

1. Usage overview
2. Available checksum functions
3. File signatures
4. Defining file check policies: what, and how, to monitor
4.1. Monitoring policies
4.2. File/directory specification
4.3. Suppress messages about new/deleted/modified files
4.4. Dynamic database update (modified/disappeared/new files)
4.5. Recursion depth(s)
4.6. Hardlink check
4.7. Check for weird filenames
4.8. Support for prelink
4.9. SELinux attributes and Posix ACLs
4.10. Codes in messages about reported files
4.11. Loose directory checking
4.12. Storing the full content of a file
4.13. Who made changes to a file?
4.14. Skip checksumming for particular files
4.15. Graceful handling of log rotation
5. Excluding files and/or subdirectories (All except...)
6. Timing file checks
6.1. Using a second schedule
7. Initializing, updating, or checking
8. The file signature database
9. Checking the file system for SUID/SGID binaries
9.1. Quarantine SUID/SGID files
9.2. Configuration
10. Detecting Kernel rootkits
11. Monitoring login/logout events
12. Checking mounted filesystem policies
13. Checking sensitive files owned by users
14. Checking for hidden/fake/missing processes
14.1. Example configuration
15. Checking for open ports
15.1. Options
15.2. Example configuration
16. Logfile monitoring/analysis
16.1. Event Correlation
16.2. Reporting non-occurence of an event
16.3. Reporting bursts of similar, repeated events
16.4. Options
16.5. Example configuration
17. Checking the Windows registry
17.1. Options
17.2. Example configuration
18. Modules
19. Performance tuning
20. Storing the full content of a file (aka: WHAT has changed?)
20.1. Example configuration
20.2. Implementation details
21. Inotify support on Linux (instantaneous reports, no I/O load)
21.1. Example configuration

The samhain file monitor checks the integrity of files by comparing them against a database of file signatures, and notify the user of inconsistencies. The level of logging is configurable, and several logging facilities are provided.

samhain can be used as a client that forwards messages to the server part ( yule ) of the samhain system, or as a standalone program (for single hosts).

samhain can be run as a background process (i.e. a daemon), or it can be started at regular intervals by cron.

[Tip]Tip

It is recommended to run samhain as daemon, because

  • samhain can remember file changes, thus while running as a a daemon, it will not bother you with repetitive messages about the same problem, and

  • using cron opens up a security hole, because between consecutive invocations the executable could get modified or replaced by a rogue program.

1.Usage overview

To use samhain, the following steps must be followed:

  1. The configuration file must be prepared ( Section4 , Section1 , and Section11 for details).

    • All files and directories that you want to monitor must be listed. Wildcard patterns are supported.

    • The policies for monitoring them (i.e. which modifications are allowed and which not) must be chosen.

    • Optionally, the severity of a policy violation can be selected.

    • The logging facilities must be chosen, and the threshold level of logging should be defined To activate a logging facility, its threshold level must be different from none.

    • Eventually, the address of the e-mail recepient and/or the IP address of the log server must be given.

  2. The database must be initialized. If it already exists, it should be deleted ( samhain will not overwrite, but append), or update instead of init should be used:

    samhain -t init|update

  3. Start samhain in check mode. Either select this mode in the configuration file, or use the command line option:

    samhain -t check

    To run samhain as a background process, use the command line option

    samhain -D -t check

MANUAL-2_4/logging-thresholds.html0000664000175000017500000001055312703400302016425 0ustar rainerrainer4.Logging thresholds

4.Logging thresholds

Section heading (see Section3 for more details):

[Log]

Entries:

MailSeverity= list of [optional specifier]threshold

PrintSeverity= list of [optional specifier]threshold

LogSeverity= list of [optional specifier]threshold

SyslogSeverity= list of [optional specifier]threshold

PreludeSeverity= list of [optional specifier]threshold

ExportSeverity= list of [optional specifier]threshold

ExternalSeverity= list of [optional specifier]threshold

DatabaseSeverity= list of [optional specifier]threshold

threshold may be one of none, debug, info, notice, warn, mark, err, crit, alert .

The optional specifier may be one of '*', '!', or '=', which are interpreted as 'all', 'excluding', and 'only', respectively. Examples: specifying '*' is equal to specify 'debug'; specifying '!*' is equal to specifying 'none'; 'info,!alert' is the range from 'info' to 'crit'; and 'info,!=mark' is info and above, but excluding 'mark'.

MANUAL-2_4/libwrap.html0000664000175000017500000000672212703400302014265 0ustar rainerrainer10.Restrict access with libwrap (tcp wrappers)

10.Restrict access with libwrap (tcp wrappers)

As of version 1.8.0, yule can be build with support for libwrap, i.e. Wietse Venema's tcp wrappers libraries. To enable this, use the configure option --with-libwrap.

You can then restrict access to yule with appropriate entries in the /etc/hosts.allow and/or /etc/hosts.deny files.

[Note]Note

If you use the configure option --enable-install-name=NAME, then yule will be installed as 'NAME', and this is what you then need to use as the daemons name in the /etc/hosts.allow and/or /etc/hosts.deny files.

MANUAL-2_4/server-logging.html0000664000175000017500000000752112703400301015554 0ustar rainerrainer6.Rules for logging of client messages

6.Rules for logging of client messages

As the log server may receive quite a large number of log messages from clients (depending on the number of clients and their threshold settings), client messages are treated specially and by default are only logged to facilities suitable for bulk logging: console, log file, relational database (if enabled), and external (if enabled).

To override this behavior, you can set the option UseClientSeverity= yes in the [Misc] section of the configuration file. In that case, the client message severity is used, and client messages are treated just like local messages (i.e. like those from the server itself).

If you also want to filter by message class, there is also an option UseClientClass= yes

All client messages are recorded in the main log file by default. However, it is possible to use separate log files for individual clients. This can be enabled with UseSeparateLogs= yes/no in the Misc section of the server configuration file. No locking will be performed for such separate client log files (only one instance of the server can listen on the TCP port, thus there will be no concurrent access).

MANUAL-2_4/samhainadmin.html0000664000175000017500000001112012703400302015242 0ustar rainerrainer3.The samhainadmin script

3.The samhainadmin script

In the subdirectory scripts/ of the source directory you will find a Perl script samhainadmin.pl to facilitate some tasks related to the administration of signed configuration and database files (e.g. examine/create/remove signatures). By default, this script is not installed.

bash$ samhainadmin.pl --help
  samhainadmin.pl { -m F | --create-cfgfile }      [options] [in.cfgfile]
    Sign the configuration file. If in.cfgfile is given, sign it
    and install it as configuration file.

  samhainadmin.pl { -m f | --print-cfgfile }     [options] 
    Print the configuration file to stdout. Signatures are removed.

  samhainadmin.pl { -m D | --create-datafile }     [options] [in.datafile]
    Sign the database file. If in.datafile is given, sign it
    and install it as database file.

  samhainadmin.pl { -m d | --print-datafile }    [options] 
    Print the database file to stdout. Signatures are removed. Use
    option --list to list files in database rather than printing the raw file.

  samhainadmin.pl { -m R | --remove-signature }  [options] file1 [file2 ...]
    Remove cleartext signature from input file(s). The file
    is replaced by the non-signed file.

  samhainadmin.pl { -m E | --sign }              [options] file1 [file2 ...]
    Sign file(s) with a cleartext signature. The file
    is replaced by the signed file.

  samhainadmin.pl { -m e | --examine }           [options] file1 [file2 ...]
    Report signature status of file(s).

  samhainadmin.pl { -m G | --generate-keys }     [options] 
    Generate a PGP keypair to use for signing.

Options:
  -c cfgfile    --cfgfile cfgfile
    Select an alternate configuration file.

  -d datafile   --datafile datafile
    Select an alternate database file.

  -p passphrase --passphrase passphrase
    Set the passphrase for gpg. By default, gpg will ask.

  -s gnupg_homedir --secretkeyring gnupg_homedir
    Select an alternate gpg homedirectory to locate the secret keyring.
    Will use '/home/rainer/.gnupg/' by default.

  -k keyid      --keyid keyid
   Select the keyid to use for signing.

  -l            --list
    List the files in database rather than printing the raw file.

  -v            --verbose
    Verbose output.
      
MANUAL-2_4/basic-configuration.html0000664000175000017500000003247612703400301016557 0ustar rainerrainerChapter4.Configuration of logging facilities

Chapter4.Configuration of logging facilities

The configuration file for samhain is named samhainrc by default. Also by default, it is placed in /etc. (Name and location is configurable at compile time). The distribution package comes with a commented sample configuration file. The layout of the configuration file is described in more details in Section1 .

1.General

Events(e.g. unauthorized modifications of files monitored by samhain ) will generate messages of some severity. These messages will be logged to all logging facilities, whose threshold is equal to, or lower than, the severity of the message.

1.1.Severity levels

The following severity levels are defined:

LevelSignificance
noneKeyword to switch off a looging facility (*).
debugDebugging-level messages.
infoInformational message.
noticeNormal conditions.
warnWarning conditions.
markTimestamps.
errError conditions.
critCritical conditions.
alertProgram startup/normal exit, or fatal error, causing abnormal program termination.
inetIncoming messages from clients (server only).

(*) the keyword 'none' can only be used as a threshold for logging facilities, to indicate that no messages shall be logged via that facility.

Most events (e.g. timestamps, internal errors, program startup/exit) have fixed severities. The following events have configurable severities: (*) the keyword 'none' can only be used as a threshold for logging facilities, to indicate that no messages shall be logged via that facility.

  • (server only) failure to resolve a client address (section [Misc], option SeverityLookup)

  • policy violations (for monitored files)

  • access errors for files

  • access errors for directories

  • obscure file names (with non-printable characters) and/or invalid UIDs/GIDs (no such user/group)

  • login/logout events (if samhain is configured to monitor them)

Severity levels for events (see Section1.1 ) are set in the EventSeverity and (for login/logout events) the Utmp sections of the configuration file.

In the configuration file, these can be set as follows:

	  [EventSeverity] 
	  # 
	  # these are policies 
	  # 
	  SeverityReadOnly=crit
	  SeverityLogFiles=crit 
	  SeverityGrowingLogs=warn
	  SeverityIgnoreNone=crit 
	  SeverityIgnoreAll=info 
	  # 
	  # these are access errors 
	  # 
	  SeverityFiles=err 
	  SeverityDirs=err 
	  # 
	  # these are obscure file names 
	  # and/or invalid UIDs/GIDs (no such user/group) 
	  # 
	  SeverityNames=info 
	  # 
	  # This is the section for login/logout monitoring 
	  # 
	  [Utmp]
	  SeverityLogin=notice 
	  SeverityLogout=notice 
	  # multiple logins by same user 
	  SeverityLoginMulti=err
	

1.2.Classes

Events of related type are grouped into classes. For each logging facility, it is possible to restrict logging to a subset of these classes (see Section3 ). The available classes are:

ClassSignificance
EVENTEvents to be reported (i.e. policy violations, login/logout).
STARTStartup/stop messages.
STAMPTimestamp (heartbeat) messages.
LOGKEYThe key to verify the signed log file.
ERRORError messages.
OTHEREverything else (e.g. informational messages).
AUDSystem calls (for debugging).

The aforementioned classes represent a new, simplified classification scheme since version 1.8.2. The previous scheme (listed below) will still work, and both can be mixed.

ClassSignificance
AUDSystem calls.
RUNNormal run messages (e.g. startup, exit, ...)
STAMPTimestamps and alike.
FILMessages related to file integrity checking.
TCPMessages from the client/server subsystem.
PANICFatal errors, leading to program termination.
ERRError messages (general).
ENETError messages (network).
EINPUTError messages (input, e.g. configuration file).

1.3.Error message customization

It is possible to customize the initial part (the header of messages via the MessageHeader= "format" directive. Enclosing quotes are only required to protect leading/trailing space, and there is no need to escape quotes within the format string. The following placeholders are recognized:

%S

Severity of the message.

%T

Timestamp of the message.

%C

Class of the message.

%F

Source file where the message originates from.

%L

Line number (in the source file) where the message originates from.

%E

An error code that may provide additional information in case of internal errors.

In the configuration file, these can be set as follows:

	  [Misc] 
	  # 
	  # This is the default without XML 
	  # 
	  MessageHeader="%S %T " 
	  # 
	  # Default for XML-style messages. 
	  # Note that quotes within the format strings are NOT escaped in any way. 
	  # 
	  # MessageHeader="<log sev="%S" tstamp="%T"
        
MANUAL-2_4/daemontool.html0000664000175000017500000000542312703400301014762 0ustar rainerrainer2.Using daemontool (or similar utilities)

2.Using daemontool (or similar utilities)

samhain does not auto-background itself (to become a daemon) unless explicitely specified in the config file or on the command line. However, normally it runs in single-shot mode if not used as daemon. To cause samhain to enter the main loop while running in the foreground (as required if you want to use daemontool ), you need to start with the option -f or --forever. Note that yule, the server, will always loop.

MANUAL-2_4/installation-customize.html0000664000175000017500000000762512703400301017350 0ustar rainerrainer7.Customize

7.Customize

samhain comes with default configuration files for several operating systems: samhainrc.linux, samhainrc.solaris, samhainrc.freebsd, samhainrc.aix5.2.0(and yulerc for the server). The installation routine will choose the one matching closest your system, or fall back to samhainrc.linux, if no good match could be found. However, all these configuration files are kept very general, and most probably you want to adjust settings like:

  • which files/directories should be checked

  • which logging facilities should be used

The default location of the configuration file is /etc/samhainrc(see Section10 ). To customize, type:

        sh$ vi /etc/samhainrc
      

The default configuration file is heavily commented to help you. For a list of all runtime configuration directives, please have a look at AppendixC .

If you have any typos or other errors in your configuration file, samhain will log warning messages upon startup including the corresponding line number of the configuration file.

MANUAL-2_4/keypad.html0000664000175000017500000001457512703400302014107 0ustar rainerrainer2.Integrity of the samhain executable

2.Integrity of the samhain executable

Each samhain executable contains a compiled-in key, that is used when the signatures of emails and/or logfile entries are verified. By default, a cryptographically strong random key is generated by the configure script at compile time. Thus, each build is unique, and signature verification will fail if a different build is used, except if the compiled-in key was set to a common value for both builds.

To set a user-defined key, there is an option

./configure --enable-base= B1,B2

where B1,B2 should be two integers in the range 0...2147483647.

The key generated by configure is printed in the configure script's output. It is recommended that you save this key and use it for further builds.

Whenever you try to verify the integrity of e-mails or log file entries, this compiled-in key is used (to be more specific: the signature key is encrypted with a one-time pad generated from the message itself and the compiled-in key). As a result, if executable B is used to verify the integrity of e-mails sent by executable A, integrity verification will fail if the compiled-in keys of A and B do not match. This can be used to check the integrity of A in a straightforward way (check e-mails on another host, using a different executable compiled with the same key).

Obviously, this scheme can be broken, but it requires an intruder to disassemble/decompile and analyze the existing samhain executable, rather than simply replace it with a precompiled trojan.

However, if you use a precompiled samhain executable (e.g. from a binary distribution), in principle a prospective intruder could easily obtain a copy of the executable and analyze it in advance. This will enable her/him to generate fake audit trails and/or generate a trojan for this particular binary distribution.

For this reason, it is possible for the user to add more key material into the binary executable. This is done with the command:

samhain --add-key= key@/path/to/samhain_executable

This will read the file /path/to/samhain_executable, add the key key, which can be a string of arbitrary length, except that it should not contain a '@' (because it has a special meaning, separating key from path), and write the new binary to the location /path/to/executable.out(i.e. with .out appended).

[Note]For Clarification

Please note that --add-key does not replace a compiled-in key but only adds to it. Integrity verification depends on both the compiled-in and any added key material, and integrity verification using different binaries will therefore only work if all were compiled with the same key and had the same extra key material (if any) added in.

[Warning]WARNING

Using a precompiled samhain executable from a binary package distribution is not recommended unless you add in key material as described above.

MANUAL-2_4/installation-initialize.html0000664000175000017500000001007612703400301017461 0ustar rainerrainer8.Initialize the baseline database

8.Initialize the baseline database

samhain works by comparing the present state of the filesystem agains a baseline database. Of course, this baseline database must be initialized first (and preferably from a known good state !). To perform the initialization (i.e. create the baseline database), type:

        sh$ samhain -t init -p
        info
      

(with -p info, messages of severity 'info' or higher will be printed to your terminal/console).

If the database file already exists, samhain -t init will append to it. This is a feature that is intended to help you operating samhain in a slightly more stealthy way: you can append the database e.g. to a JPEG picture (and the picture will still display normally - JPEG ignores appended 'garbage').

[Note]Note:

It is usually an error to run samhain -t init twice, because (a) it will append a second baseline database to the existing one, and (b) only the first baseline database will be used. Use samhain -t update for updating the baseline database. Delete or rename the baseline database file if you really want to run samhain -t init a second time.

MANUAL-2_4/stealthmode.html0000664000175000017500000002352012703400302015131 0ustar rainerrainerChapter10.Additional Features — Stealth

Chapter10.Additional Features — Stealth

If an intruder does not know that samhain is running, s/he will make no attempt to subvert it. Hence, you may consider to run samhain in stealth mode, using some of the options discussed in this section.

1.Hiding the executable

samhain may be compiled with support for a stealth mode of operation, meaning that the program can be run without any obvious trace of its presence on disk. The following compile-time options are provided:

--enable-stealth= xor_val provides the following measures:

  1. All embedded strings are obfuscated by XORing them with some value xor_val chosen at compile time. The allowed range for xor_val is 128 to 255.

  2. The messages in the log file are obfuscated by XORing them with xor_val. The built-in routine for validating the log file ( samhain -L /path/to/logfile ) will handle this transparently. You may specify as path an already existing binary file (e.g. an executable, or a JPEG image), to which the log will get appended.

    [Tip]Tip

    Use samhain -jL /path/to/logfile if you just want to view rather than verify the logfile.

  3. Strings in the database file are obfuscated by XORing them with xor_val. You may append the database file to some binary file (e.g. an executable, or a JPEG image), if you like.

  4. The configuration file must be steganographically hidden in a postscript image file (the image data must be uncompressed). To create such a file from an existing image, you may use e.g. the program convert , which is part of the ImageMagick package, such as convert +compress ima.jpg ima.ps .

    [Tip]Tip

    make install will do this automatically before installation.

    To hide/extract the configuration data within/from the postscript file, a utility program samhain_stealth is provided. Use it without options to get help.

    [Note]Note

    If --enable-stealth is used together with --with-gpg , then the config file must be signed before hiding it (rather than signing the PS image file afterwards).

--enable-micro-stealth= xor_val is like --enable-stealth , but uses a 'normal' configuration file (not hidden steganographically).

--enable-nocl[=ARG] will disables command line parsing. The optional argument is a 'magic' word that will enable reading command-line arguments from stdin. If the first command-line argument is not the 'magic' word, all command line arguments will be ignored. This allows to start the program with completely arbitrary command-line arguments.

--enable-install-name= NAME will rename every installed file from samhain to NAME when doing a make install (standalone/client installation), and likewise rename installed files from yule to NAME when doing a make install (server installation). Also, the boot scripts will be updated accordingly. Files created by samhain (e.g. the database) will also have samhain replaced by NAME in their filenames.

[Tip]Tip

The man pages have far too much specific information enabling an intruder to infer the presence of samhain. There is no point in changing samhain to NAME there — this would rather help an intruder to find out what NAME is. You probably want to avoid installing man8/samhain.8 and man5/samhainrc.5.

1.1.Using kernel modules to hide samhain (Linux/ix86 only)

This feature has been removed as of samhain version 4.0, because it does not work anymore on modern kernels due to enhanced kernel hardening.

MANUAL-2_4/mod-db-fields.html0000664000175000017500000000602212703400302015224 0ustar rainerrainer2.Modules

2.Modules

module

Name of a samhain module (e.g. the module to watch login/logout events). Used in initialization/error reports for a module.

return_code

Return code from a module. Used in initialization/error reports for a module.

syscall

ID of bad syscall. Formerly used by kernel checking module.

ip

IP address. Login/logout watch. Also used in received syslog messages (see below).

tty

Terminal used. Login/logout watch.

time

Login/logout time. Also used in some other messages (e.g. time to complete file check).

fromhost

Host from which user is logged in. Login/logout watch.

MANUAL-2_4/server-to-server.html0000664000175000017500000000505612703400302016056 0ustar rainerrainer13.Server-to-server relay

13.Server-to-server relay

As of version 2.2.0, it is possible to relay messages from one yule server to another. This is implemented in the same way as client-to-server connectivity, i.e. the relaying server and the endpoint server must be set up in the same way as a samhain client and a server, respectively (see Section3 ).

MANUAL-2_4/finotify.html0000664000175000017500000001510012703400301014441 0ustar rainerrainer21.Inotify support on Linux (instantaneous reports, no I/O load)

21.Inotify support on Linux (instantaneous reports, no I/O load)

The Linux kernel offers an interface — called inotify— which allows an application to obtain change notifications for files and directories, if the application has registered watches for the files and directories it is interested in.

As of version 3.0, samhain optionally can use the inotify interface. The advantage of this is twofold: First, it is not neccessary to perform regular filesystem scans to detect file changes, i.e. the I/O load is drastically reduced. And second, changes can be reported immediately, thus allowing faster responses.

[Note]Please note

Your system may be configured with a too low default for the maximum inotify watches per user. You can see the default with:

cat /proc/sys/fs/inotify/max_user_watches

You can change the default temporarily (i.e. until reboot) with:

echo 1048576 /proc/sys/fs/inotify/max_user_watches

You can change the default permanently by placing the following line in /etc/sysctl.conf(this will take effect at the next reboot):

fs.inotify.max_user_watches=1048576

Alternatively, samhain can be configured to reset the value by itself on startup (see example configuration below).

[Note]Full scans

(1) On startup, samhain will perform a full scan, first to set the inotify watches, and second to recover changes that happened after initialisation of the baseline database, but before starting the file check.

(2) The kernel will queue inotify events. If the queue overflows because there are too many events in too short a time, the application will be notified. In this case, samhain will automatically trigger a full scan to recover lost file system changes.

(3) Finally, even if inotify is enabled, samhain will still honour the configured intervals or schedules for full scans. If you want to rely only on inotify, you may want to configure a very large interval for filesystem checks, e.g. 'SetFilecheckTime = 315360000' (10 years).

Note that currently, directories specified via wildcard patterns can only be detected in a full scan if they appear newly in the filesystem (unless of course the parent directory is monitored anyway). Wildcard patterns for files are checked every 10 seconds.

21.1.Example configuration

	  [Inotify]
	  #
	  # Activate (default is off)
	  #
	  InotifyActive = yes
	  
	  # Optionally set the maximum number of watches allowed per user.
	  # (default is leave as is). To see the default, use:
	  # cat /proc/sys/fs/inotify/max_user_watches
	  #
	  InotifyWatches = 1048576
	
MANUAL-2_4/nagios.html0000664000175000017500000001062712703400301014103 0ustar rainerrainer10.Using samhain with nagios

10.Using samhain with nagios

After running ./configure , you will find the script check_samhain.pl in the subdirectory scripts/ of the samhain distribution, which you can copy to the nagios libexec/ directory. Before doing so, you may want to edit the script to set the correct path to the libexec/ directory in the following line:

      use lib "/usr/local/nagios/libexec";
      

The following recipe to use this script has been kindly provided by kiarna:

Nagios runs as user 'nagios'. However, in order to check the filesystem, you typically want to run samhain as 'root'. You can use sudo to fix this problem. In your /etc/sudoers file, add the line:

	nagios ALL = NOPASSWD:/path/to/check_samhain
      

Next, add the service to the nagios file objects/commands.cfg:

	# 'check_samhain' command definition 
	define command{ 
	command_name check_samhain
	command_line /usr/bin/sudo -u root $USER1$/check_samhain -t 100 
      }

Another option would be to install the check_samhain script with SUID permissions instead of using sudo (this requires that the suidperl package is installed and that samhain has been compiled with ./configure --enable-suid ...

	# 'check_samhain' command definition 
	define command{ 
	command_name check_samhain
	command_line $USER1$/check_samhain -t 100 
	}
      

Checking the filesystem may take some time, so you may want to increase the nagios plugin timeout by changing the following line in nagios.cfg from 60 to 600:

      service_check_timeout=600

Then add the service to the appropriate section in the nagios service.cfg file.

MANUAL-2_4/performance-tuning.html0000664000175000017500000001245412703400301016426 0ustar rainerrainer19.Performance tuning

19.Performance tuning

File checking is basically I/O-limited, i.e. typically most of the time the application waits for data from the disk. Most of the application runtime is spent in the checksum algorithm, but as the application is I/O-limited, using a faster algorithm does not neccessarily result in any noticable speed improvement.

Logging can be very expensive, so you should avoid enabling many different logging facilities. You should also avoid low logging thresholds (info/debug) on production systems — it tends to drown real problems in the noise of purely informational messages, and reduces performance quite noticably.

Other things you can do are:

  • Build a static binary (use the --enable-static switch for configure). Static binaries are faster, and also more secure, because they cannot be subverted via libraries they depend on.

    [Note]Note

    Some functionality may not be available with static binaries, in particular some name services (NIS, LDAP), the portmap service (used for the port check), and the support for the Linux audit daemon. On some operating systems (e.g. Solaris) static compiling may not be possible at all.

  • Change the compiler switches to optimize more aggressively.

  • If on a commercial UNIX, check whether the native compiler produces faster code (you need an ANSI C compiler). The ./configure script honours CC (compiler) and CFLAGS environment variables.

On the other side, if you want to reduce the load caused by file checking, you can change the scheduling priority (see man nice ), and/or limit the I/O:

	[Misc] 
	# low priority (positive argument means lower priority) 
	SetNiceLevel=19 
	# kilobytes per second 
	SetIOLimit=1000
      

If you want to avoid thrashing the file cache, you can tell samhain to drop checksummed files from the cache (unless they were already cached). For performance reasons, this defaults to 'false'.

	[Misc] 
	# drop checksummed files from cache 
	SetDropCache = True
      

Similarly, for the SUID check, you can limit the files per seconds:

	[SuidCheck] 
	# limit on files per seconds 
	SuidCheckFps=250
      
MANUAL-2_4/paths.html0000664000175000017500000001404212703400302013736 0ustar rainerrainer5.Paths

5.Paths

Compiled-in paths may be as long as 255 chars. If the --with-stealth option is used, the limit is 127 chars. The paths to the database, log file, and pid/lock file can be overridden in the configuration file (see Section1 ).

[Tip]Tip

If using NFS with clients on different hosts accesing the same files, you can set the database, log file, and pid/lock file names to "AUTO" in the configuration file to simply tack on the hostname on the compiled-in path. The same length limits apply.

--prefix=PREFIX

The install prefix. Default is none, and using the Filesystem Hierarchy Standard 2.2 directory layout. If you prefer the GNU layout (everything under /usr/local), use --prefix=/usr/local. See Section10 for details.

--sbindir=DIR

The binary directory (default is /usr/local/sbin)

--localstatedir=DPFX

The state data directory prefix (default is /var). Data will be written to DPFX/lib/ install_name.

--with-state-dir=DIR

The state data directory (default is DPFX/lib/install_name). Data will be written to this directory.

--mandir=MPREFIX

The man directory directory prefix (default is /usr/local/share/man).

--with-tmp-dir=TPFX

The directory where tmp files are created (config/database downloads from server, extracted PGP-signed parts of config/database files) (default is HOME).

--with-config-file=FILE

The full path of the configuration file (default is /etc/(install_name)rc).

--with-log-file=FILE

The path of the log file (default is DPFX/log/samhain_log).

--with-pid-file=FILE

The path of the PID file (default is DPFX/run/(install_name).pid).

--with-html-file=FILE

[SERVER ONLY] The path of the HTML status file where the current status of clients is displayed (default is DPFX/log/(install_name).html).

--with-console=PATH

The path of the console (default is /dev/console). This may be a FIFO.

--with-altconsole=PATH

The path of a second console (default is none). This may be a FIFO. If defined, console output will always go to both console devices (but note that console devices are only used when running as daemon).

MANUAL-2_4/database-configuration-file-download.html0000664000175000017500000002456312703400301021762 0ustar rainerrainer5.Enabling baseline database / configuration file download from the server

5.Enabling baseline database / configuration file download from the server

A significant advantage of samhain is the option to store baseline databases and configuration files on the central log server ( yule ), from where they can be downloaded by clients upons startup. In order to use this option, clients must be configured to retrieve these files from the server rather than from the local filesystem.

[Tip]Tip

Obviously, retrieving the configuration file from the log server requires that the IP address of the log server is compiled in, using the option ./configure --with-logserver=HOST .

Downloaded files are written to a temporary file that is created in the home directory of the effective user (usually root. The filename is chosen at random, the file is opened for writing after checking that it does not exist already, and immediately thereafter unlinked. Thus the name of the file will be deleted from the filesystem, but the file itself will remain in existence until the file descriptor referring it is closed (see man unlink ), or the process exits (on exit, all open file descriptors belonging to the process are closed).

5.1.Configuration file

If the compiled-in path to the configuration file begins with the special value ``REQ_FROM_SERVER'', the client will request to download the configuration file from yule (i.e. from the server).

If ``REQ_FROM_SERVER'' is followed by a path, the client will use the path following ``REQ_FROM_SERVER'' as a fallback if ( and only if) it is initializing the database. This is a convenience feature to allow initializing the database(s) before the client is registered with the server.

Example: ./configure --with-config-file=REQ_FROM_SERVER/etc/conf.samhain In this case, the client will request to download the configuration file from the server. If the connection to the server fails, it will exit on error if run in 'check' mode, but fallback to /etc/conf.samhain as its configuration file, if run in 'init' mode.

[Note]Note

For obvious security reasons, the client cannot specify the path to the configuration file on the server side. The server will lookup the configuration file using only the hostname of the client and the compiled-in path for the 'localstatedir' (see below). The default for 'localstatedir' is /var.

The server will search for the configuration file to send in the following order of priority (paths are explained in Section5 ). CLIENTNAME is the hostname of the client's host, as listed in the server's config file in the Clients section:

  1. localstatedir/lib/yule/rc.CLIENTNAME

  2. localstatedir/lib/yule/rc

5.2.Database file

If the compiled-in path to the database file begins with the special value ``REQ_FROM_SERVER'', the client will request to download the database file from yule (i.e. from the server).

[Warning]CAVEAT

``REQ_FROM_SERVER'' must be followed by a path that will be used for writing the database file when initializing. Upon initialization, the database is always written to a local file, and must be copied with scp to the server (the client cannot upload the database file to the server, as this would open a security hole).

Example: --with-data-file=REQ_FROM_SERVER/var/lib/samhain/data.samhain In this case, the client will request to download the database file from the server if checking, and will create a local database file /var/lib/samhain/data.samhain if initializing. You have to use scp to copy the file signature database to the server then.

[Note]Note

For obvious security reasons, the client cannot specify the path to the database file on the server side. The server will lookup the databse file using only the hostname of the client and the compiled-in path for the 'localstatedir' (see below). The default for 'localstatedir' is /var.

The server will search for the database file to send in the following order of priority (see Section5 ). CLIENTNAME is the hostname of the client's host, as listed in the server's config file in the Clients section:

  1. localstatedir/lib/yule/file.CLIENTNAME

  2. localstatedir/lib/yule/file

MANUAL-2_4/signed-installation.html0000664000175000017500000000752312703400302016575 0ustar rainerrainer2.Installation

2.Installation

make install will gpg sign the configuration file before installation.

      bash$ ./configure --with-gpg=/usr/bin/gpg \
      --with-fp=EF6CEF54701A0AFDB86AF4C31AAD26C80F571F6C
      bash$ make
      bash$ su
      bash$ make install
      bash$ samhain -t init
      bash$ gpg -a --clearsign /var/lib/samhain/samhain_file
      bash$ mv /var/lib/samhain/samhain_file.asc \
      /var/lib/samhain/samhain_file
    

samhain will report the signature key owner and the key fingerprint as obtained from gpg . If both files are present and checked (i.e. when checking files against the database), both must be signed with the same key. If the verification is successful, samhain will only report the signature on the configuration file. If the verification fails, or the key for the configuration file is different from that of the database file, an error message will result.

MANUAL-2_4/calling-external-programs.html0000664000175000017500000002631412703400302017705 0ustar rainerrainer3.Calling external programs

3.Calling external programs

samhain may invoke external programs or scripts in order to implement logging capabilities that are not supported by samhain itself (e.g. pager support). This section provides an overview of this capability.

External programs/scripts invoked for logging will receive the formatted log message on stdin. The program should expect that stdout and stderr are closed, and that the working directory is the root directory.

Each external program must be defined in the configuration file, in a section starting with the header [External] . In addition, ExternalSeverity must be set to an appropriate threshold in the section [Log] .

Each program definition starts with the line

OpenCommand= /full/path

Options for the program may follow. The definition of an external program is ended (a) when explicitely terminated with the line CloseCommand , (b) when the section ends, or (c) when another OpenCommand= /full/path line for the next command is encountered.

[Note]Environment variables

By default, the environment is limited to the TZ (timezone) variable. If you need other variables (e.g. LD_LIBRARY_PATH), you can set them using the Setenviron= KEY=value option (see below).

  • There are several places in samhain where external programs may be called. Each such place is identified by a type. Currently, valid types are:

    • log— An external logging facility, which is handled like other logging facilities. The program will receive the logged message on stdin, followed by a newline, followed by the string [EOF] and another newline.

    • srv— Executed by the server, whenever the status of a client, as displayed in the HTML status table, has changed. The program will receive the client hostname, the timestamp, and the new status, followed by a newline, followed by [EOF] and another newline.

  • Any number of external programs may be defined in the configuration file. Each external program has a type, which is log by default. Whenever external programs are called, all programs of the appropriate type are executed. The type can be set with SetType= type

  • External programs must be on a trusted path (see Section10.1 ), i.e. must not be writeable by untrusted users.

  • For enhanced security, the (192-bit TIGER) checksum of the external program/script may be specified in the configuration file: SetChecksum= checksum (one string, no blanks in checksum)

  • Command line arguments and environment variables for each external program are configurable (the default is no command line arguments, and a clean environment containing only the TZ (timezone) variable:

    SetCommandline= full_command_line (full command line starting with the name of the program)

    Setenviron= KEY=value

  • The user whose credentials shall be used, can be specified: SetCredentials= username

  • Some filters are available to make the execution of an external program dependent on the message content:

    SetFilterNot= list If any regular expression in 'list' matches the message, the program is not executed, else

    SetFilterAnd= list if any regular expression in 'list' is not matching the message, the program is not executed, else

    SetFilterOr= list if none of the regular expressions in 'list' matches the message, the program is not executed.

    For all filters, list items can be quoted with single or double quotes. It is also possible to use each filter option multiple times, although this does not affect the order (not, and, or) in which filters are evaluated. A maximum of 32 filter patterns for each of (not, and. or) are supported per defined external program. Any filter not defined is not evaluated.

  • It is possible to set a 'deadtime'. Within that 'deadtime', the respective external program will be executed only once (if triggered): SetDeadtime= seconds

3.1.Example setup for paging

The distribution contains two example perl scripts for paging and SMS messages (example_pager.pl, example_sms.pl). The paging script will page via a web CGI script at www.pagemart.com (obviously will work only for their pagers), the SMS script is for any German 'free SMS' web site that outsources free SMS to pitcom (with a suitable query on Google you can find such sites; you can then inspect the HTML form to set proper values for the required form variables.)

If you know some Perl, both scripts can be adapted fairly easily to other providers. Below is an example setup for calling example_pager.pl as an external logging facility.

	  [External]
	  # start definition of first external program
	  OpenCommand=/usr/local/bin/example_pager.pl 
	    SetType=log 
	    # arguments
	    SetCommandline=example_pager.pl pager_id 
	    # environment 
	    SetEnviron=HOME=/home/moses 
	    SetEnviron=PATH=/bin:/usr/bin:/usr/local/bin 
	    # checksum 
	    SetChecksum=FCBD3377B65F92F1701AFEEF3B5E8A80ED4936FD0D172C84 
	    # credentials 
	    SetCredentials=moses 
	    # filter 
	    SetFilterOr=POLICY 
	    # deadtime 
	    SetDeadtime=3600
	  #Optional
	  CloseCommand 

	
MANUAL-2_4/performance-tuning-server.html0000664000175000017500000001435412703400302017734 0ustar rainerrainer14.Performance tuning

14.Performance tuning

If connections time out because of slow network, you can raise the timeout with SetConnectionTimeout= seconds (the default is 900 seconds).

Even without tweaking, the server can probably handle some 100 connections per second on a 500Mhz i686. Depending on the verbosity of the logging that you wish, this should suffice even for some thousand clients.

Almost all time is spent (i) in the HMAC function that computes the message signatures, and (ii) if you do not have the gmp (GNU MP) multiple precision library, in the multiple precision arithmetic library (for SRP authentication).

The reason for (ii) is that samhain / yule will use a simple, portable, but not very efficient MP library that is included in the source code, if gmp is not present on your system.

To improve performance, you can:

  • install gmp, remove the file config.cache in the source directory (if you have run configure before), and then run configure and make again. The configure script should automatically detect the gmp library and link against it.

  • use a simple keyed hash (HASH-TIGER), which will compute signatures as HASH(message key) instead of the HMAC (HMAC-TIGER). This will save two of the three hash computations required for a HMAC signature.

    [Warning]CAVEAT

    Make sure you use the same signature type on server and client !

    	      [Misc] 
    	      # 
    	      # use simple keyed hash for message signatures 
    	      # Make sure you set this both for client and server 
    	      #
                  MACType=HASH-TIGER
    	    
  • build a static binary (use the --enable-static switch for configure). Static binaries are faster, and also more secure, because they cannot be subverted via libraries.

    [Note]Note

    Some functionality may not be available with static binaries, in particular some name services (NIS, LDAP), the portmap service (used for the port check), and the support for the Linux audit daemon. On some operating systems (e.g. Solaris) static compiling may not be possible at all.

  • change the compiler switches to optimize more aggressively.

  • if on a commercial UNIX, check whether the native compiler produces faster code than gcc (you need an ANSI C compiler). The configure script honours CC (compiler) and CFLAGS environment variables.

MANUAL-2_4/clients.html0000664000175000017500000001566612703400301014274 0ustar rainerrainer3.Registering a client

3.Registering a client

Clients must be registered with yule to make a connection. Connection attempts by unknown clients will be rejected. The respective section in the server configuration file looks like:

	[Clients] 
	# 
	# A client
	# 
	Client=HOSTNAME_CLIENT1@salt1@verifier1 
	# 
	# another one 
	#
	Client=HOSTNAME_CLIENT2@salt2@verifier2 
	#
      

These entries have to be computed in the following way:

  1. Choose a password(16 chars hexadecimal, i.e. only 0 - 9, a - f, A - F allowed. To generate a random password, you may use:

                  sh$ yule --gen-password
                
  2. Use the program samhain_setpwd to reset the password in the compiled client binary (that is, samhain, not yule ) to the one you have chosen. samhain_setpwd takes three arguments: (1) the binary name, (2) an extension to append to the new binary, and (3) the password. It will read the executable binary (argument 1), insert the password (argument 3), and write a modified binary with the specified extension (argument 2). Run samhain_setpwd without arguments for usage information. Example:

                  sh$ samhain_setpwd samhain EXT 0123456789ABCDEF
                
  3. Use the server's convenience function '-P' to create a registration entry. Example:

                  sh$ yule -P 0123456789ABCDEF
                
  4. The output will look like:

    Client=HOSTNAME@salt@verifier

    You now have to replace HOSTNAME with the fully qualified domain name of the host on which the client should run ( exception: if the server cannot determine the fully qualified hostname, you may need to use the numerical address instead. You will see the problem in a 'Connection refused' message from the server).

  5. Put the registration entry into the servers's configuration file, under the section heading [Clients](see Section3 ). You need to send SIGHUP to the server for the new entry to take effect.

  6. Repeat steps (1) -- (5) for any number of clients you need (actually, you need a registration entry for each client's host, but you don't neccesarily need different passwords for each client. I.e. you may skip steps (1) -- (3)).

If you have a default directory layout, a [Clients] section right at the end of the server config file, and your client is client.mydomain.com, then you could e.g. do:

          bash$ PASSWD=`yule --gen-password`
          bash$ samhain_setpwd samhain new $PASSWD
          bash$ scp samhain.new root@client.mydomain.com:/usr/local/sbin/samhain
          bash$ ENTRY=`yule -P $PASSWD | sed s%HOSTNAME%client.mydomain.com%`
          bash$ echo $ENTRY >>/etc/yulerc
          bash$ kill -HUP `cat /var/run/yule.pid`
        

MANUAL-2_4/filedef.html0000664000175000017500000015542412703400301014226 0ustar rainerrainer4.Defining file check policies: what, and how, to monitor

4.Defining file check policies: what, and how, to monitor

This section explains how to specify in the configuration file, which files or directories should be monitored, and which monitoring policy should be used.

4.1.Monitoring policies

samhain offers several pre-defined monitoring policies. Each of these policies has its own section in the configuration file. Placing a file in one of these sections will select the respective policy for that file.

The available policies (section headings) are:

ReadOnly

All modifications except access times will be reported for these files.

Checked: owner, group, permissions, file type, device number, hardlinks, links, inode, checksum, size, mtime, ctime.

LogFiles

Modifications of timestamps, file size, and signature will be ignored.

Checked: owner, group, permissions, file type, device number, hardlinks, links, inode.

GrowingLogFiles

Modifications of timestamps, and signature will be ignored. Modification of the file size will only be ignored if the file size has increased.

Checked: owner, group, permissions, file type, device number, hardlinks, links, inode, size >= previous_size, checksum(file start up to previous size) equals previous checksum.

If the size has shrunk (e.g. because of log rotation), samhain will look for a file with the same inode as before and check whether it has a size >= previous_size, and checksum(file start up to previous size) equals previous checksum. No report will be issued if this check succeeds. Thus log rotation will be handled gracefully as long as the inode is kept (i.e. the old file is moved rather than copied) and the first rotated file is not compressed (the logrotate tool can be told to compress only after the second cycle, and on Debian this seems to be standard anyway).

Attributes

Only modifications of ownership, access permissions, and device number will be checked.

Checked: owner, group, permissions, file type, device number.

IgnoreAll

No modifications will be reported. However, the existence of the specified file or directory will still be checked.

IgnoreNone

All modifications, including access time, but excluding ctime, will be reported - checking atime and ctime would require to play with the system clock.

Checked: owner, group, permissions, file type, device number, hardlinks, links, inode, checksum, size, mtime, atime.

User0

Initialized to: report all modifications.

User1

Initialized to: report all modifications.

User2

Initialized to: report all modifications.

User3

Initialized to: report all modifications.

User4

Initialized to: report all modifications.

Prelink

Modifications of timestamps, size, and inode will be ignored Checksums will be verified by calling /usr/sbin/prelink --verify . This policy is intended for verification of prelinked executables/libraries and/or directories containing such files. For details and further configuration options see Section4.8 .

Checked: owner, group, permissions, file type, device number, hardlinks, links, checksum.

[Note]Note

Each policy can be modified in the config file section Misc with entries like RedefReadOnly= +XXX[,...] or RedefReadOnly= -XXX[,...] to add (+XXX) or remove (-XXX) a (a comma-separated list of) tests XXX, where XXX can be any of CHK (checksum), TXT (store file content in database), LNK (link), HLN (hardlink), INO (inode), USR (user), GRP (group), MTM (mtime), ATM (atime), CTM (ctime), SIZ (size), RDEV (device numbers), MOD (file mode), PRE (Linux; prelinked binary), SGROW (file size is allowed to grow), and/or AUDIT (Linux; report who changed the file)

This must come before any file policies are used in the config file.

4.2.File/directory specification

Entries for files have the following syntax:

file= /full/path/to/the/file

Entries for directories have the following syntax:

dir= [recursion depth]/full/path/to/the/directory

The specification of a (numerical) recursion depth is optional (see Section4.5 ). (Do not put the recursion depth in brackets — they just indicate that this is an optional argument!).

Wildcard patterns ('*', '?', '[...]') as in shell globbing are supported for paths. The leading '/' is mandatory. Since version 2.7.1, it is allowed to enclose the value of the directive (i.e. the path for files, the optional recursion depth and the path for directories) within matching single or double quotes, which allows to have trailing blanks ( note: it is not neccessary to escape quotes in between - the algorithm does not scan forward to find the matching quote, rather it uses the last character). Also since version 2.7.1, C quoting style is supported ('\a' [bell], '\b' [backspace], '\f' [form feed], '\n' [newline], '\r' [carriage return], '\t' [horizontal tab], '\v' [vertical tab], '\\' [backslash], '\'' [single quote], '\"' [double quote], '\nnn' [dree digit octal value], \xNN' [two digit hexadecimal value]). Example:

	  [ReadOnly]
	  # valid examples
	  dir = /u01/oracle/archive00
	  dir = 7/u01/oracle/archive02
	  dir = "7/u01/oracle/archive03  "
	  dir = "7/u01/oracle/archi"ve"
	  dir = /u01/oracle/archive\v04
	  dir = /u01/oracle/archive\\04
	  dir = /u01/oracle/archive\076
	  file = '/u01/oracle/archive\x0a'
	  
	  # valid (no quote at start, thus quote at end
	  #        is considered part of filename)
	  file = /u01/oracle/archive_0"
	  
	  #invalid (no matching quote at end)
	  file = "/u01/oracle/archive_0
	  
	  #invalid (\03 is bad, must be 3 digits [octal]
	  #         or \x03 for hexadecimal)
	  file = /u01/oracle/archive_\03
	  
	  #invalid (\g is undefined escape sequence)
	  file = /u01/oracle/archive_\g
	
[Note]Note on directories

A directory is (a) a collection of files, with (b) a directory special file where a listing of all files in the directories is kept. This directory special file will be modified in case of a file addition, removal, or renaming. Depending on the chosen policy, samhain will report on such modifications of the directory special file.

The addition and/or deletion of files from a directory modifies the directory special file (mtime/ctime). The addition/deletion of subdirectories will also modify the number of hardlinks of the directory special file. A modification of a file may modify a directory special file (mtime/ctime), if this modification is done by first creating a temporary file, followed by renaming this temporary file to the original one.

4.2.1.Rules

  1. For the file check, samhain does not follow symlinks. If the argument for a file=... directive is a symlink, then the symlink itself is checked, not the location it points to.

  2. The argument for a dir=... directive must be a directory. Using a symlink to a directory as argument is incorrect.

  3. Precedence is given to the most specific location in the filesystem regardless of the order listed in the config file. I.e.,

    • a policy for a specific file overrides the policy for its directory

    • a policy for a subdirectory overrides the policy for its parent directory

    • if a directory or file path are explicitly listed twice in two different policy sections, Samhain will print a warning and honor only the first stanza processed. "First matching rule wins." Note however that it is perfectly ok to list a directory both as file=/path and dir=/path (see next rules).

  4. Checking a directory with dir=... will check both the content of the directory as well as the directory special file itself, honoring a local and global recursion depth, giving local preference.

  5. Using a directory as argument for both a file=... and a dir=... directive will have the effect that

    • the file=... directive will override the dir=... directive for the directory special file itself,

    • while the dir=... directive remains in effect for the directory content.

  6. The presence of a file= /parent/subdir , which is more specific of a path entry than that of the parent directory in another policy section with a "deeper" recursion depth as dir= N/parent will not prevent Samhain from descending into /parent/subdir and applying the higher level directory with the "deeper" recursion policy to the contents of /parent/subdir The more-specific rule will only apply to the directory special file and does not "truncate" the higher level policy in any way.

  7. To determine if you config file syntax is working as expected, increase the verbosity of debugging when running samhain with "-t init" using "-p info" or even "-p debug".

Example 1: If you only want to check files in a directory, but not the directory inode itself, use:

	    [ReadOnly]
	    dir = /u01/oracle/archive00
	    [IgnoreAll]
	    file = /u01/oracle/archive00
	    
	    # Note: /u01/oracle/archive00/archive01.dbf -> archive99.dbf *should* be
	    # mounted in the DB as a read-only tablespace and should never be
	    # changed, however, the DBA thinks he's God and does not need to consult
	    # with the Admin, so he may be adding new, deleting, or renaming the
	    # DBFs using SQLPlus without consulting with the admin, so tell me about
	    # changes to the files inside that we know about at Samhain INIT but
	    # such as when he adds a file.
	  

Example 2: If you want to monitor a directory, but not the dynamic contents inside it:

	    [Attributes] 
	    file = /var/spool/mqueue 
	    file = /tmp 
	    [IgnoreAll]
	    dir=-1/var/spool/mqueue 
	    dir=-1/tmp
	  

Example 3: If you want to monitor a directory special file, while ensuring no files within are removed but not the actual attributes of those files:

	    [Attributes] 
	    file = /root 
	    [IgnoreAll] 
	    dir=0/root
	  

Thanks to Brian A. Seklecki for his effort to clarify these rules and provide examples.

4.3.Suppress messages about new/deleted/modified files

If you want to suppress messages about the creation of certain files (e.g. rotated log files), you can use the options IgnoreAdded=/fullpath/with_some_regex_inside and/or IgnoreMissing=/fullpath/with_some_regex_inside (to be placed in the [Misc] section of the configuration files. If you want to add more regular expressions, you can use these options multiple times. Since transient files might get modified during their lifetime, there is also the option IgnoreModified=/fullpath/with_some_regex_inside

[Tip]Note

The argument to IgnoreAdded , IgnoreMissing , and IgnoreModified must be a regular expression that matches the full path. In particular, it has to start with a forward slash.. To test your regex before putting in samhain, you do something like this:

	    # This regex matches all files added by logrotate 
	    # (e.g: messages.1 or messages.2.gz, etc.) 
	    cd /var/log 
	    for file in *; do 
	      echo $file| \
	      egrep "(cron|messages|rpmpkgs|secure|up2date|wmtp)\.[0-9](\.gz)?$"; 
	    done
	  

Once it's work this way, you can add it to your samhainrc file, but don't forget to add the full path. e.g:

	    IgnoreAdded = your_tested_regex
	  

This tip has been provided by jim at aegis hyphen corp dot org.

[Tip]Alternative

If a directory is added to [Attributes] as a file=/dir, then only the directory special file is monitored for permissions/ownership. The advantage is that additions/removals of files to that subdirectory can happen without recourse, but the integrity of that directory is defended. Assuming the administrator doesn't want to get granular level of detail.

Good for such directories as: /var/mail /var/cron/tabs /var/tmp /tmp

This tip has been provided by Brian A. Seklecki

4.4.Dynamic database update (modified/disappeared/new files)

samhain reads the file signature database at startup and creates an in-memory copy. This in-memory copy is then dynamically updated to reflect changes in the file system.

I.e. for each modified/disappeared/new file you will receive an alarm, then the in-memory copy of the file signature database is updated, and you will only receive another alarm for that file if it is modified again (or disappears/appears again).

Note that the on-disk file signature database is not updated (if you have signed it, the daemon could not do that anyway). However, as long as the machine is not rebooted, there should be no need to update the on-disk file signature database.

If files disappear after initialization, you will get an error message with the severity specified for file access errors ( except if the file is placed under the IgnoreAll policy, in which case a message of SeverityIgnoreAll— see Section1.1 — is generated).

If new files appear in a monitored directory after initialization, you will get an error message with the severity specified for that directory's file policy ( except if the file is placed under the IgnoreAll policy, in which case a message of SeverityIgnoreAll— see Section1.1 — is generated).

The special treatment of files under the IgnoreAll policy allows to handle cases where a file might be deleted and/or recreated by the system more or less frequently.

4.5.Recursion depth(s)

Directories can be monitored up to a maximum recursion depth of 99 (i.e. 99 levels of subdirectories. The recursion depth actually used is defined in the following order of priority:

  1. The recursion depth specified for that individual directory ( Section4 ). As a special case, for directories with the policy IgnoreAll, the recursion depth should be set to 0, if you want to monitor (the existence of) the files within that directory, but to -1, if you do not want samhain to look into that directory.

  2. The global default recursion depth specified in the configuration file. This is done in the configuration file section Misc with the entry SetRecursionLevel= number

  3. The default recursion depth, which is zero.

4.6.Hardlink check

As of version 1.8.4, samhain will by default compare the number of hardlinks of a directory to the number of its subdirectories (including "." and ".."). Normally, these numbers should be equal. The idea here is that a (kernel) rootkit may hide a directory, but fail to "fix" the parent directory hardlink count (actually, I am not aware of any kernel rootkit that would care to fix the hardlink count of the parent directory). This is an experimental feature; if there are any problems, it can be disabled with the option UseHardlinkCheck= no in the [Misc] section of the configuration file.

Errors will be reported at the same severity as directory access errors option SeverityDirs= severity in section [EventSeverity]).

[Note]MacOS X

This feature is not supported on MacOS X (because the resource fork is implemented as an invisible directory, it modifies the parent directory hardlink count.)

4.6.1.Specify exceptions for the hardlink check

Some filesystems do not always follow the rule mentioned above (directory hardlink equals number of subdirectories). E.g. the root directory of reiserfs partitions generally seems to have two additional hardlinks. To account for such exceptions, you can specify exceptions with the option HardlinkOffset= N: /path in the [Misc] section of the configuration file. Here, N is the numerical offset (actual - expected hardlinks) for /path. For multiple exceptions, use this options multiple times (note that '/path N:/path2' would itself be a valid path, so using the option only once with multiple exceptions on the same line would be ambiguous).

[Note]Note

Please note that samhain will not check for an exception if the standard rule (offset = 0) is true for a directory. Thus it will not warn if a directory that once was exceptional is not anymore.

4.7.Check for weird filenames

Samhain checks for weird filenames (containing control/nonprintable characters, newlines or tabs) and warns about them at a severity level that is set with SeverityNames= severity in section [EventSeverity]. The rationale is: most of the time, such names are either the result of user errors, buggy scripts, or questionable activity.

If you want to add characters to the set of 'good' ones, you can do so with the option: AddOKChars= N1, N2, ... in the [Misc] section of the configuration file. Nn should be the unsigned byte value of the character(s) in hex (leading '0x': 0xNN), octal (leading zero: 0NNN), or decimal.

[Tip]UTF-8 filenames

To specify that filenames are UTF-8 rather than ASCII, use FileNamesAreUTF8=yes . Samhain will check for invalid UTF-8 sequences, and for filenames ending with invisible characters.

[Tip]Tip

This check will not be performed for files under the IgnoreAll policy. To completely disable this check, use AddOKChars=all .

4.8.Support for prelink

prelink is a tool available on modern Linux systems that can significantly reduce the startup time of applications. It does this by performing some of the work of the dynamic linker in advance. As this changes both executables and shared libraries, file integrity verification will fail unless prelink is supported, in particular as prelinking has to be redone if libraries are updated (so initializing the checksum database after prelinking may not be good enough).

The disadvantage is that prelinking modifies libraries and executables, and may need to be redone (potentially modifying all or many executables again) if a library is updated. This is a major problem for file integrity checkers.

Version 2.0 of samhain and later support prelink. To use this support, you need to place prelinked executables and libraries (or directories holding them) under the [Prelink] policy rather than under the (e.g.) [ReadOnly] policy. For all files under the [Prelink] policy, inode, size, and timestamps will be ignored (prelinking changes them). In addition, for ELF binaries under the [Prelink] policy, /usr/sbin/prelink --verify will be used to compute checksums (i.e. the checksum will be computed on the output of this command). For other files, checksums are computed as usual.

[Note]Speed

Obviously, invoking prelink results in a significant overhead, and slows down file integrity checking (tests indicate a factor of three - your mileage may vary).

[Note]Verification failures (zero checksum)

It seems that prelink --verify fails if the dependencies of a prelinked binary have changed. This results in a zero checksum, and can be fixed by re-prelinking the affected binary.

There are two configuration options in the [Misc] section that can are relevant for prelink support:

SetPrelinkPath= fullpath sets the path to the prelink executable. The default is /usr/sbin/prelink.

SetPrelinkChecksum= checksum sets the TIGER192 checksum for the prelink executable. You can compute this with samhain -H /usr/sbin/prelink (remove whitespace from the computed checksum). If the checksum is set, samhain will verify the prelink executable immediately before using it, otherwise prelink will be used without this special precaution.

4.9.SELinux attributes and Posix ACLs

[Note]Note for users of SQL database logging

You need to update the database scheme before using this feature, if you are upgrading from a version below 2.3.0. See Section12.1 for details.

As of version 2.3, samhain supports checking and verifying of SELinux attributes and/or Posix ACLs, if the operating system supports these features. SELinux attributes are a Linux-specific feature, while Posix ACLs are supported by multiple operating systems.

These features will only get compiled if the required development environment is available on the host where samhain is compiled (e.g. on Debian Linux, packages libattr1-dev and libacl1-dev).

For backward compatibility, these features are disabled by default, even if they are compiled in. To enable them, use the configuration directives:

	  [Misc] 
	  UseACLCheck = yes 
	  UseSelinuxCheck = yes
	

4.10.Codes in messages about reported files

As of version 1.8.2, reports about modified files include a short code in the message field to describe which properties have been modified. The codes are: 'C' for 'checksum', 'L' for (soft) 'link', 'D' for 'device number', 'I' for 'inode', 'H' for (number of) 'hardlinks', 'M' for 'mode', 'U' for 'user' (owner), 'G' for 'group' (owner), 'T' for 'time' (any), and finally 'S' for 'size'.

As an example, 'C--I----TS' would indicate that a file has been replaced by one with different checksum, inode, timestamp, and size, but (e.g.) same mode (type and access permissions) and same ownership.

4.11.Loose directory checking

If files are added to, or removed from a directory, or modified by writing a temporary file and renaming it to the original, samhain will report the changed file as well as the changed directory inode. If you regard the report on the directory inode as redundant, you can suppress it with the option: LooseDirCheck= true in the [Misc] section of the configuration file. This will cause samhain to ignore modified directory inodes if nothing else but size and timestamps has changed.

4.12.Storing the full content of a file

This is discussed in Section20 .

4.13.Who made changes to a file?

First of all, the UID of the user who changed or created a file is not stored in the file metadata, and hence in general not available. However, some operating systems may have non-standard security enhancements to log such information.

In particular, sufficiently recent versions of the Linux kernel provide an audit subsystem that can be used to gather such information if the required userspace tools are installed and the system is properly configured.

It should be noted that the Linux audit subsystem does NOT audit every file access by default. Rather, files are only audited if a watch is placed on them. What Samhain can do is making sure that watches are indeed placed on all files of interest for you (as defined in the Samhain configuration file), and collecting relevant information in case of an event.

Samhain supports the Linux audit system insofar as it can automatically mark files of interest for logging, and automatically collects and reports the log information after a change has been detected. This implies that you don't need to maintain two separate configurations (one for Samhain and one for the audit daemon).

4.13.1.Compiling

If you compile a Samhain standalone or client executable on a Linux system, support for the Linux audit system will be compiled in automatically if the required development packages for libaudit and libauparse are present (Debian: libaudit-dev, RedHat: audit-libs-devel).

To verify that the compiled executable has audit support, use samhain --version, which should list "optionally report auditd record of changed file".

[Note]Not supported with static compiling

This extension is incompatible with static compiling, i.e. it is not available if '--enable-static' has been used for compiling.

4.13.2.Audit System Configuration

(1) If you want Samhain to report who changed a file, you need to have the Linux audit daemon (Debian: auditd, RedHat: audit) installed. You also need to have the libaudit and libauparse libraries installed.

The audit daemon must be running. You can check that with the command auditctl -s , which should show a non-zero PID for the audit daemon. If it says 'pid=0', you need to enable the audit daemon. First, make sure the daemon will autostart on boot: on RedHat/CentOS use chkconfig auditd on , on Debian/Ubuntu use update-rc.d auditd defaults . Second, start the daemon with /etc/init.d/auditd start .

(2) You are most likely interested in the auid, i.e. the audit UID which tracks the login user. This UID is only set correctly if you are using the pam_loginuid PAM module, and in a correct way even. Please read the man page for pam_loginuid carefully, and add the line

session required pam_loginuid.so

to the files /etc/pam.d/gdm, /etc/pam.d/login, /etc/pam.d/atd, /etc/pam.d/cron, /etc/pam.d/sshd.

Do NOT add this line to /etc/pam.d/su or /etc/pam.d/sudo, as that will set auid=0 and hence erase the track of the login user. If your system has a /etc/pam.d/common-session file, don't add it there if that file is included by the /etc/pam.d/su or /etc/pam.d/sudo file(s).

(3) The audit daemon enables the audit system in the kernel. Therefore all processes starting earlier than the audit daemon itself may get an auid=4294967295 (unknown). To avoid this problem, add audit=1 to the kernel boot parameters.

(4) Because Samhain needs to fetch the audit information from the audit log, this log needs to be current. I.e. in the audit deamon configuration (/etc/audit/auditd.conf on Ubuntu), the parameter 'flush' must be set to DATA or SYNC, otherwise it might happen that the log entry has not been written yet when Samhain tries to fetch it.

4.13.3.Usage

In order to activate this feature for some particular file or directory, you have to add the AUDIT flag to the policy under which you place the file or directory (see Section4.1 ). Note that placing an audit rule on a directory will cause the whole file hierarchy under that directory to be audited. Also note that you cannot place an audit rule on the root directory itself. This is a limitation of the Linux audit system itself, not of Samhain. You have to place audit rules on the individual directories in the root directory.

	    [Misc]
	    RedefReadOnly = +AUDIT 
	    # 
	    [ReadOnly] 
	    file = /etc/login.defs 
	    dir = /bin 
	  

The rules set by Samhain are flagged with samhain, i.e. you can check them with auditctl -l -k samhain, and delete them manually with auditctl -D -k samhain. See the man page of the auditctl command for further reference.

If you want to verify that the audit system works properly, you can e.g. use ausearch -k samhain to see all audit log entries generated by rules flagged with 'samhain', i.e. inserted by Samhain.

[Note]Persistance of audit rules

If Samhain runs in the foreground, it will not delete the inserted rules upon exit. This is to ensure that file changes are still audited as desired when Samhain is run only occasionally or at fixed intervals (e.g. as a cron job). If you want to delete the rules, use the command auditctl -D -k samhain .

4.14.Skip checksumming for particular files

Checksumming can put a high I/O load on a machine, and in some cases one might want to skip this for particular files. As of version 2.8.2, Samhain allows to specify certain conditions for which checksumming of a file should be skipped. These are:

match_prefix( string )

Skip checksumming if the full path of the file starts with the given string (e.g.: /home/someuser).

match_regex( regular_expression )

Skip checksumming if the full path of the file matches the given POSIX regular expression (e.g.: .*\.mpg$).

size_exceeds( bytes )

Skip checksumming if the filesize exceeds the given size (in bytes).

match_permission( octal_perm )

Skip checksumming if the file permissions exactly match the given one (as octal number, e.g. 0755 for rwxr-xr-x, or 4755 for rwsr-xr-x).

have_permission( octal_perm )

Skip checksumming if the file permissions include the given one (as octal number, e.g. 0100 for execute by owner).

match_filetype( filetype )

Skip checksumming if the file is of some particular type. See appendix for a list of supported file types.

Files that should not be checksummed are specified with SkipChecksum= list of conditions in the [Misc] section of the configuration file. The following rules apply:

  1. To negate a condition, place an exclamation mark ('!') in front of it.

  2. All conditions in the given list are and ed, i.e. checksumming for a file is skipped only if all conditions in the list are true. E.g. you can place a match_prefix(string) condition at the start of the list to avoid evaluation of the following condition(s) for files that should not be skipped.

  3. If more than one SkipChecksum=... directives are given, then they are or ed, i.e. checksumming for a file is skipped if one of the directives matches.

4.14.1.User-defined file types

It is possible to add (at most 16) user-defined filetype descriptions to the compiled-in list. This can be done with the directive FileType= description where the format of description is 8 fields, separated by ':'.

The 8 fields are offset:type:length:G1:G2:G3:Name:Teststring, which describe:

  1. An optional offset into the file, can be at most 3072-length. Counting starts at 0, thus '6' would mean the 7th byte of the file.

  2. Type is 0 for a C string, 1 if binary, i.e. if the teststring contains NULL bytes,

  3. Length should be 0 if the type is 0, othewise the length of the teststring if it is of type 1 (binary).

  4. G1, G2, G2 give the filetype as GENERIC:MORE_SPECIFIC:EXACT, e.g. IMAGE:COMPRESSED:JPG

  5. The name field is currently unused and should hold a human-understandable description, e.g. 'Jpeg image'

  6. The teststring is a string or yte pattern that is found at the given offset in files of this type. You can use quoted-printable (qp) encoding (which is often used for e-mail) for arbitrary binary patterns. A qp-encoded character (byte) consists of 3 characters: a "=" followed by the two-digit hexadecimal value if the byte. Please note that NULL bytes MUST be qp-encoded as '=00', and the equal sign ('=') MUST be qp-encoded as '=3D'.

A valid example would be FileType= 6:0:0:IMAGE:COMPRESSED:JPG:JFIF Jpeg:JFIF (this one is already compiled in). This would recognize any file with the string 'JFIF' starting at the 7th byte (counting starts at '0') as a Jpeg image.

4.15.Graceful handling of log rotation

Growing log files should be placed under the [GrowingLogFiles] policy which (as of 3.0.11+) uses the following logic to handle log rotation:

If the size has shrunk (e.g. because of log rotation), samhain will look for a file with the same inode as before and check whether it has a size >= previous_size, and checksum(file start up to previous size) equal to the previous checksum. No report will be issued if this check succeeds. Thus log rotation will be handled gracefully as long as the inode is kept (i.e. the old file is moved rather than copied) and the first rotated file is not compressed (the logrotate tool can be told to compress only after the second cycle, and on Debian this seems to be standard anyway).

MANUAL-2_4/client-server-connectivity.html0000664000175000017500000001060312703400302020114 0ustar rainerrainer4.Client/Server Connectivity

4.Client/Server Connectivity

--enable-network=client/server

Compile a client or server, rather than a standalone version.

--disable-encrypt

Disable encryption for client/server communication.

--disable-srp

Disable the use of the zero-knowledge SRP protocol to authenticate to log server, and use a (faster, but less secure) challenge-response protocol. This must be set to the same value for client and server, i.e. either disabled for client and server, or for none of both.

--with-libwrap[=PATH]

[SERVER ONLY] Build the server with support for libwrap (Wietse Venema's TCP wrappers library). In /etc/hosts.allow and/or /etc/hosts.deny, use 'yule' or the name defined with --enable-install-name=NAME for the name of the daemon.

--with-port=PORT

The port on which the server will listen (default is 49777), or to which the client will connect, respectively. This must be set to the same value for client and server. Only needed if this port is already used by some other application. Port numbers below 1024 require root privileges for the server.

--with-logserver=HOST

[CLIENT ONLY] The host address of the log server. This can be set in the configuration file. A compiled-in address is only required if you want to fetch the configuration file from the log server. An address in the configuration file will take precedence.

--with-altlogserver=HOST

[CLIENT ONLY] The host address of an alternative (backup) log server.

MANUAL-2_4/sqldetails.html0000664000175000017500000003503212703400301014765 0ustar rainerrainer12.SQL Database

12.SQL Database

[Note]Requirements

This facility requires that you have compiled with the --enable-xml-log option to format log messages in XML ( also for the client, even if you do SQL logging on the server), and of course with the --with-database=XXX option (where 'XXX' may be any of: mysql, postgresql, oracle, or odbc).

If you are using the MessageHeader directive in the configuration file for a user-defined message header, make sure that the log messages are still valid XML, and that all the default entities are still present.

Currently MySQL, PostgreSQL, and Oracle are implemented and tested. Support for unixODBC is implemented, but not fully tested. If the header file 'mysql.h' ('libpq-fe.h') is not found during compilation ('mysql.h: No such file or directory'), you can use the option --with-cflags=-I/dir/where/mysql.h/is. If the library libmysqlclient.a (libpq.a) is not found ('/usr/bin/ld: cannot find -lmysqlclient'), you can use the option --with-libs=-L/dir/where/libmysqlclient.a/is.

[Note]Note

PostgreSQL may fail with --enable-static. This is a postgresql bug.

By default, the database server is assumed to be on localhost, the db name is 'samhain', the db table is 'log', and inserting is possible for any user without password. To create the database/table with the required columns, the distribution includes the scripts 'samhain.mysql.init', 'samhain.postgres.init', and 'samhain.oracle.init'. E.g., for PostgreSQL you would setup the database like:

      $ su postgres
      $ createdb samhain
      $ createuser -P samhain
      Enter password for new role: 
      Enter it again: 
      Shall the new role be a superuser? (y/n) n
      Shall the new role be allowed to create databases? (y/n) n
      Shall the new role be allowed to create more new roles? (y/n) n
      $ psql -d samhain < samhain.postgres.init
      $ exit
      

... and for MySQL:

      $ mysql -p -u root < samhain.mysql.init
      $ mysql -p -u root
      > GRANT SELECT,INSERT ON samhain.log TO 'samhain'@'localhost';
      > SET PASSWORD for 'samhain'@'localhost' = PASSWORD('...');
      > FLUSH PRIVILEGES;
      
[Note]Permissions

The PostgreSQL init script will grant INSERT permission only to a user 'samhain'. Please take note that for PostgreSQL, inserting also requires SELECT and UPDATE permission for the sequence 'log_log_index_seq' (see bottom of init script). The MySQL init script will create the database, but not the user, and will not grant any permissions.

As with all logging facilities, logging to the SQL database must be enabled in the configuration file by setting an appropriate threshold, e.g.:

	[Log]
	DatabaseSeverity=warn
      

In the Database section of the configuration file, you can modify the defaults via the following directives:

	[Database]
	SetDBName=db_name 
	SetDBTable=db_table
	SetDBHost=db_host 
	SetDBUser=db_user 
	SetDBPassword=db_password
	UsePersistent=yes/no
      

The default is to use a persistent connection to the database. You can change this with UsePersistent=no

[Note]Note re. PostgreSQL

For PostgreSQL, db_host must be a numerical IP address.

When logging client messages, yule will wrap them into a server <log sev=''RCVT'' tstamp=[...] > [...] </log> message. The parser will then create a separate database entry for this server timestamp. If you don't like this, you can use the option SetDBServerTstamp= false .

The table field 'log_ref' is NULL for client messages, 0 for server messages, and equal to 'log_index' of the client message for the aforementioned server timestamp of a client message.

Log records can be tagged via a special (indexed) table field 'log_hash', which is the MD5 checksum of (the concatenation of) any fields registered with AddToDBHash= field . The beltane web-based console can use these tags to filter messages. There is no default set of fields over which the MD5 hash is computed, so by default the tag is equal for all rows.

[Tip]Tip

For security, you may want to set up a user/password for insertion into the db. However, as the password is in cleartext in the config file (and the connection to the db server is not encrypted), for remote logging this facility is less secure than samhain's own client/server system (it is recommended to run the db server on the log host and have the log server, i.e. yule, log to the db).

12.1.Upgrade to samhain 2.3

Version 2.3 of Samhain supports checking of SELinux attributes and/or Posix ACLs. For backward compatibility, this is off by default. If you upgrade Samhain and enable this option, you need to update the database scheme as follows:

Mysql:

	  ALTER TABLE samhain.log ADD COLUMN acl_old BLOB; 
	  ALTER TABLE samhain.log ADD COLUMN acl_new BLOB;
	

PostgreSQL:

	  ALTER TABLE samhain.log ADD COLUMN acl_old TEXT; 
	  ALTER TABLE samhain.log ADD COLUMN acl_new TEXT;
	

Oracle:

	  ALTER TABLE samhain.log ADD acl_old VARCHAR2(4000); 
	  ALTER TABLE samhain.log ADD acl_new VARCHAR2(4000); 
	  DROP TRIGGER trigger_on_log;
	

12.2.Upgrade to samhain 2.4.4

Version 2.4.4 of Samhain supports storing the content of files. If you have created your Oracle database using the database scheme from a previous version, you need to change at least the 'link_old' and 'link_new' columns from VARCHAR2 to CLOB:

	  ALTER TABLE samhain.log ADD tmp_name CLOB;
	  UPDATE samhain.log SET tmp_name=link_old;
	  ALTER TABLE samhain.log DROP COLUMN link_old;
	  ALTER TABLE samhain.log RENAME COLUMN tmp_name to link_old;
	  
	  ALTER TABLE samhain.log ADD tmp_name CLOB;
	  UPDATE samhain.log SET tmp_name=link_new;
	  ALTER TABLE samhain.log DROP COLUMN link_new;
	  ALTER TABLE samhain.log RENAME COLUMN tmp_name to link_new;
        

12.3.Upgrade to samhain 2.8.0+

As of version 2.8.0, Samhain supports IPv6 now, which means that the size of the 'ip' column in the database must be increased from VARCHAR(16) to VARCHAR(46).

Mysql:

 
          ALTER TABLE samhain.log MODIFY ip VARCHAR(46);
	

PostgreSQL:

 
          ALTER TABLE samhain.log ALTER COLUMN ip TYPE VARCHAR(46);
	

Oracle:

 
          ALTER TABLE samhain.log MODIFY ip VARCHAR(46);
	

12.4.Upgrade to samhain 4.0

As of version 4.0, Samhain optionally logs the checking policy for a file if the option ReportCheckflags is set in the configuration file. If you enable this option, you need to update your database scheme as follows:

Mysql:

	  ALTER TABLE samhain.log ADD COLUMN checkflags_old BIGINT UNSIGNED;
	  ALTER TABLE samhain.log ADD COLUMN checkflags_new BIGINT UNSIGNED;
	

PostgreSQL:

	  ALTER TABLE samhain.log ADD COLUMN checkflags_old NUMERIC(20); 
	  ALTER TABLE samhain.log ADD COLUMN checkflags_new NUMERIC(20);
	

Oracle:

	  ALTER TABLE samhain.log ADD checkflags_old NUMBER(20); 
	  ALTER TABLE samhain.log ADD checkflags_new NUMBER(20); 
	

12.5.MySQL configuration details

To pass the location of the MySQL Unix domain socket (for connections on localhost) to samhain, you can use the environment variable MYSQL_UNIX_PORT (the value must be the path of the socket).

Alternatively, as of samhain version 2.2, you can set options for the group "samhain" in my.cnf. See the MySQL manual for the proper syntax of the my.cnf file, as well as for possible options.

[Note]Note

It is not possible for an application (like e.g. samhain ) to detect whether my.cnf is readable (because the application does not know where the file resides). Interesting errors may result...

MANUAL-2_4/databasefile.html0000664000175000017500000000622212703400301015223 0ustar rainerrainer8.The file signature database

8.The file signature database

The database file is named samhain_file by default, and placed into /usr/local/var/lib/samhain by default (name and location can be configured at compile time).

The database is a binary file. For security reasons, it is recommended to store a backup copy of the database on read-only media, otherwise you will not be able to recognize file modifications after its deletion (by accident or by some malicious person).

samhain will compute the checksum of the database at startup and verify it at each access. samhain will first open() the database, compute the checksum, rewind the file, and then read it. Thus it is not possible to modify the file between checksumming and reading.

MANUAL-2_4/configfacility.html0000664000175000017500000001171212703400301015611 0ustar rainerrainer2.Available logging facilities

2.Available logging facilities

samhain supports the following facilities for logging:

  • e-mailsamhain uses built-in SMTP code, rather than an external mailer program. E-mails are signed to prevent forging.

  • syslog — The system logging utility.

  • console — If running as daemon, /dev/console is used, otherwise stderr. /dev/console can be replaced by other devices, including a FIFO.

  • log file — Entries are signed to provide tamper-resistance.

  • log serversamhain uses TCP/IP with strong authentication and signed and encrypted messages.

  • externalsamhain can be configured to invoke external programs for logging and/or taking some action upon certain conditions.

  • SQL db — Currently samhain supports MySQL, PostgreSQL, Oracle, and unixODBC.

  • Preludesamhain can be compiled with support for the Prelude IDS, i.e. it can be used as a Prelude sensor.

Each of these logging facilities has to be activated by setting an appropriate threshold on the messages to be logged by this facility.

[Note]Note

In addition, some of these facilities require proper settings in the configuration file (see next sections).

MANUAL-2_4/system-v-message-queue.html0000664000175000017500000000765712703400302017170 0ustar rainerrainer2.System V message queue

2.System V message queue

It is possible to have a SystemV IPC message queue (which is definitely more elegant than named pipes) as additional 'console' device. You need to compile with --enable-message-queue= MODE and use the option MessageQueueActive= T/F .

The default mode is 0700 (rwx------), but this is a compile option (message queues are kernel-resident, but have access permissions like files).

In your code, to get the System V IPC key for the message queue, use ftok("localstatedir/lib/samhain", '#'); (since Samhain Version 4.0) or ftok("/tmp", '#'); (previous versions). Here, localstatedir/lib/samhain is the directory where samhain writes the database upon initialisation, i.e. /var/lib/samhain by default.

[Note]Messages logged / Queue full

The message queue is treated as an additional 'console' device, i.e. the same messages go there that go to the console.

(Since version 4.0) If the queue is full, the oldest message(s) will get deleted until there is enough free space for the current message. I.e. the queue will behave like a ring buffer.

MANUAL-2_4/security-design.html0000664000175000017500000001613112703400302015736 0ustar rainerrainerChapter12.Security Design

Chapter12.Security Design

1.Usage

It is recommended to:

  • compile a static binary(not linked to shared libraries), using the configure option --enable-static if possible. Some functionality may not be available with static binaries, in particular some name services (NIS, LDAP), the portmap service (used for the port check), and the support for the Linux audit daemon. On some operating systems (e.g. Solaris) static compiling may not be possible at all.

  • strip the binary(on i386 Linux/FreeBSD, also use the provided sstrip utility: strip samhain && sstrip samhain ). This will help somewhat against intruders that try to run it under a debugger ...

    [Note]Note

    make install will always strip the excutables. Trying to strip again by hand may corrupt the executable.

  • use signed database/configuration files using the configure option --with-gpg=PATH_TO_GPG , and compile in the fingerprint of the signing key ( --with-fp=... )

  • take a look at the stealth options- while 'security by obscurity' only is a very bad idea, it certainly helps if an intruder does not know what defenses you have in place

  • read the next chapter to understand how the integrity of the samhain executable can be verified.

1.1.Client security in a client/server system

In a client/server Samhain system, if an intruder has obtained root privileges on the server he may modify configuration files that are stored on the server and downloaded by the clients. Thus, if the client executes shell commands given in the configuration file (via the shell expansion option, or by logging events to external commands specified in the configuration file), this may allow the intruder to take over the clients as well.

As of version 2.8.5, there are two ways to protect against this scenario:

first, you can use the option --with-gpg=PATH to use signed configuration (and baseline database) files. The signature is checked on the client, after downloading the configuration file from the server. It is thus not possible to make the client perform any actions if the configuration file is not signed correctly (note that in versions before 2.8.5, the signature would be checked too late to prevent the attack).

second, you can just forego any execution of external programs by compiling with the options --disable-shellexpand --disable-external-scripts . No shell expansion will be performed on configuration file directives, and no logging to external programs will be supported.

MANUAL-2_4/signed-files.html0000664000175000017500000002454712703400302015203 0ustar rainerrainerChapter9.Additional Features — Signed Configuration/Database Files

Chapter9.Additional Features — Signed Configuration/Database Files

Both the configuration file (see Section1) and the database of file signatures ( Section8) may always be cleartext signed by GnuGP (gpg). The recommended options are:

gpg -a --clearsign --not-dash-escaped FILE

1.Compiling with support for signatures

If compiled with support for signatures, samhain will invoke gpg to verify the signature. To compile with gpg support, use the option:

./configure --with-gpg=/full/path/to/gpg --with-fp=FINGERPRINT [--with-keyid=0x<hex KeyID>]

  • Note that gpg --fingerprint will only list the fingerprint of primary keys. If you are signing with a secondary key, you need to repeat the '--fingerprint' option (i.e. run gpg gpg --fingerprint --fingerprint ) in order to obtain the fingerprint for the signing (secondary) key. (If you don't know what a secondary key is, then this note is probably irrelevant for you.)

    Example(spaces in FINGERPRINT do not matter): --with-fp="EF6C EF54 701A 0AFD B86A F4C3 1AAD 26C8 0F57 1F6C"

  • The optional argument --with-keyid=0x<hex KeyID> allows to specify a key ID, if there is more than one key in your keyring. This is only used for the installation routine, and for configuring the samhainadmin.pl convenience script (see below).

    The installation routine ("[sudo] make install") will use the keyring of the user running it (in ~/.gnupg) for signing. At runtime, samhain will use the keyring of the runtime user (usually root) for verification.

  • samhain will check that the path to the gpg executable is writeable only by trusted users(see Section10.1 ).

  • The gpg program will be called without using the shell, with its full path (as compiled in), and with an environment that is limited to the HOME variable.

    If you need LD_LIBRARY_PATH, because your gpg executable relies on libraries that are not in the search path of the loader, you can either (i) use a wrapper script to set the environment and exec gpg (take care not to mess with file descriptors), (ii) update the system loader configuration file, or (iii) recompile with loader paths (-Wl,-r<path> or -Wl,-R<path>).

  • The public key must be in in the subdirectory HOME/.gnupg, where HOME is the home directory of the effective user (usually root).

  • From the command line, the signature must verify correctly with /path/to/gpg --status-fd 1 --verify FILE when invoked by the effective user of samhain (usually root).

[Tip]Tip

There is a Perl script samhainadmin.pl to facilitate some tasks related to the administration of signed configuration and database files (see Section3).

When signing, the option --not-dash-escaped is recommended, because otherwise the database might get corrupted. However, this implies that after a database update, you must remove the old signature first, before re-signing the database. Without 'dash escaping', gpg will not properly handle the old signature. See the tip just above.

As signatures on files are only useful as long as you can trust the gpg executable, the configure script will determine the TIGER192 checksum of the gpg executable, which will be compiled into samhain. In case of an error, you can specify the checksum by hand with:

--with-checksum=" CHECKSUM" — or — --without-checksum

CHECKSUM should be the checksum as printed by

gpg --load-extension tiger --print-md TIGER192 /path/to/gpg — or — samhain -H /path/to/gpg (the full line of output, with spaces).

Example: --with-checksum="/usr/bin/gpg: 1C739B6A F768C949 FABEF313 5F0B37F5 22ED4A27 60D59664"

[Warning]WARNING

Compiling in the GnuPG checksum will tie the samhain executable to the gpg executable. If you upgrade GnuPG, you will need to re-compile samhain. If you don't like this, use '--with-checksum=no' (or '--without-checksum' , which is equivalent).

MANUAL-2_4/filetypes-defined.html0000664000175000017500000000675712703400302016235 0ustar rainerrainerAppendixE.List of recognized file types

AppendixE.List of recognized file types

Filetypes have hierarchical names of the form G1:G2:G3, and in the "match(filetype)" condition you can specify filetypes as G1:G2:G3, or G1:G2 (less specific), or G1 (generic). The list of currently (version 2.8.2) recognized filetypes comprises:

IMAGE:COMPRESSED:JPG
    IMAGE:COMPRESSED:PNG IMAGE:COMPRESSED:JPG IMAGE:COMPRESSED:GIF
    IMAGE:COMPRESSED:TIFF IMAGE:COMPRESSED:PCX IMAGE:RAW:BMP
    IMAGE:RAW:XPM IMAGE:SPECIAL:AUTOCAD IMAGE:SPECIAL:COREL
    IMAGE:SPECIAL:FITS IMAGE:SPECIAL:VISIO IMAGE:SPECIAL:DICM
    IMAGE:SPECIAL:PHS IMAGE:SPECIAL:XCF MOVIE:COMPRESSED:RIFF
    MOVIE:RAW:MOV MOVIE:COMPRESSED:MPG MOVIE:COMPRESSED:QT
    MOVIE:COMPRESSED:FLI MOVIE:COMPRESSED:FLASH
    MOVIE:COMPRESSED:WMV AUDIO:RAW:SND AUDIO:RAW:EMOD AUDIO:RAW:MOD
    AUDIO:RAW:WAVE AUDIO:RAW:DEC AUDIO:STANDARD:MIDI
    AUDIO:COMPRESSED:REAL AUDIO:COMPRESSED:OGG
    AUDIO:COMPRESSED:FLAC AUDIO:COMPRESSED:MP3
    ARCHIVE:COMPRESSED:LHA ARCHIVE:COMPRESSED:RAR
    ARCHIVE:COMPRESSED:ZIP ARCHIVE:COMPRESSED:7Z
    ARCHIVE:COMPRESSED:COMPRESS ARCHIVE:COMPRESSED:GZIP
    ARCHIVE:COMPRESSED:BZIP2 ARCHIVE:COMPRESSED:ARJ
    ARCHIVE:COMPRESSED:HPAK ARCHIVE:COMPRESSED:JAM
    ARCHIVE:COMPRESSED:SQUISH ARCHIVE:COMPRESSED:CAB
    ARCHIVE:COMPRESSED:ZOO ARCHIVE:COMPRESSED:XPK
    ARCHIVE:PACKAGE:RPM ARCHIVE:PACKAGE:DEB ARCHIVE:UNIX:AR
    ARCHIVE:UNIX:TAR LIBRARY:JAVA:CLASS DOCUMENT:OFFICE:WORD
    DOCUMENT:OFFICE:EXCEL DOCUMENT:OFFICE:WORD DOCUMENT:OFFICE:ALL
    DOCUMENT:ADOBE:PDF DOCUMENT:ADOBE:EPS DOCUMENT:STANDARD:RTF
    DOCUMENT:ID:VCARD EXECUTABLE:DOS:EXE EXECUTABLE:DOS:COM
    EXECUTABLE:UNIX:SHELL EXECUTABLE:UNIX:ELF EXECUTABLE:DOS:COM
    EXECUTABLE:AMIGAOS:EXECUTABLE DATABASE:ANY:ACCESS
    DATABASE:ANY:MYSQL
MANUAL-2_4/configfile-clients.html0000664000175000017500000001022412703400302016361 0ustar rainerrainer15.Clients

15.Clients

This section is relevant for yule only. Section heading:

[Clients]

Entries must be of the form:

Client= hostname@salt@verifier

See Section3 on how to compute a valid entry.

The hostname must be the same name that the client retrieves from the host on which it runs. Usually, this will be a fully qualified hostname, no numerical address. However, there is no method that guarantees to yield the fully qualified hostname (it is not even guaranteed that a host has one ...). The only way to know for sure is to set up the client, and check whether the connection is refused by the server with a message like Connection attempt from unregistered host hostname In that case, hostname is what you should use.

[Warning]CAVEAT

Problems and oddities encountered in client/server setups (like client messages from 127.0.0.1, server warnings about unknown/unresolved peer, etc. are always(at least so far) due to incorrect configuration of the DNS or the /etc/hosts file.

A surprisingly large number of hosts are not able to determine the own hostname, or reverse lookup adresses on the own local network. Don't bother asking about such problems — fix your DNS.

MANUAL-2_4/intro.html0000664000175000017500000000775412703400300013764 0ustar rainerrainerChapter1.Introduction

Chapter1.Introduction

Table of Contents

1. Backward compatibility

samhain is a file and host integrity and intrusion alert system suitable for single hosts as well as for large, UNIX-based networks. samhain offers advanced features to support and facilitate centralized monitoring.

In particular, samhain can optionally be used as a client/server system with monitoring clients on individual hosts, and a central log server that collects the messages of all clients.

The configuration and database files for each client can be stored centrally and downloaded by clients from the log server. Using conditionals (based on hostname, machine type, OS, and OS release, all with regular expresions) a single configuration file for all hosts on the network can be constructed.

The client (or standalone) part is called samhain, while the server is referred to as yule. Both can run as daemon processes.

1.Backward compatibility

Samhain version 4.0 introduces a change in the baseline database format. This does not affect the client/server communication, i.e. it is possible to mix pre-4.0 and 4.0+ clients and server.

If you are using the Beltane II WebGUI, you need version 2.5+ to handle the new database format.

Finally, if you are planning to make use of the new features for integrating samhain into your change control process, you will need Samhain version 4.0+ for clients and sever, and Beltane II version 2.5+.

MANUAL-2_4/design.html0000664000175000017500000001202412703400302014066 0ustar rainerrainer5.General

5.General

Obviously, a security application should not open up security holes by itself. Therefore, an inportant aspect in the development of samhain has been the security of the program itself. While samhain comes with no warranty (see the license), much effort has been invested to identify security problems and avoid them.

As the client requires root privileges, while the server does not, the clients has no open socket to listen on the network. Consequently, all client/server connections are initiated by the client.

To avoid buffer overflows, only secure string handling functions are used to limit the amount of data copied into a buffer to the size of the respective buffer (unless it is known in advance that the data will fit into the buffer).

On startup, the timezone is saved, and all environment variables are set to zero thereafter. Signal handlers, timers, and file creation mask are reset, and the core dump size is set to zero. If started as daemon, all file descriptors are closed, and the first three streams are opened to /dev/null.

If external programs are used (in the entropy gatherer, if /dev/random is not available), they are invoked directly (without using the shell), with the full path, and with a limited environment (by default only the timezone). Privileged credentials are dropped before calling the external program.

With respect to its own files (configuration, database, the log file, and its lock), on access samhain checks the complete path for write access by untrusted users. Some care has been taken to avoid race conditions on file access as far as possible.

Critical information, including session keys and data read from files for computing checksums, is kept in memory for which paging is disabled (if the operating system supports this). This way it is avoided that such information is transfered to a persistent swap store medium, where it might be accessible to unauthorized users.

Random numbers are generated from a pseudo-random number generator (PRNG) with a period of 2^88 (actually by mixing the output from three instances of the PRNG). The internal state of the PRNG is seeded from a strong entropy source (if available, /dev/random is used, else lots of system statistics is pooled and mixed with a hash function). The PRNG is re-seeded from the entropy source at regular intervals (one hour).

Numbers generated from a PRNG can be predicted, if the internal state of the PRNG can be inferred. To avoid this, the internal state of the PRNG is hidden by hashing the output with a hash function.

MANUAL-2_4/client-integrity.html0000664000175000017500000000560712703400302016120 0ustar rainerrainer3.Client executable integrity

3.Client executable integrity

If you use samhain in a client/server setup, the client needs to authenticate to the server using a password that is located within the client executable, at one of several possible places (where the valid place for your particular build is chosen at random at compile time). If the password is set, the alternative places are filled with random values.

Upon authentication to the server, client and server negotiate ephemeral keys for signing and encrypting further communication.

This implies that an intruder needs to analyse the running process to obtain knowledge of the signing/encryption keys in order to successfully fake a valid communication with the server, or she needs to analyse/disassemble the executable in order to find the password.

MANUAL-2_4/configuration-email.html0000664000175000017500000004320412703400301016554 0ustar rainerrainer4.E-mail

4.E-mail

It is possible to define email recipients at compile-time, but it is also possible to define recipients, or aliases (lists of recipients) in the configuration file. Each recipient (list) definition starts with either:

SetMailAddress= recipient

or:

SetMailAlias= listname: addresslist

Filters and/or a threshold severity for the recipient (list) may follow. The definition of a recipient is ended (a) explicitely when terminated with the line CloseAddress , or (b) implicitely when another recipient (list) definition is started.

Items that can/must be configured are:

Recipients address

SetMailAddress= username@hostname

Each address must on a separate line in the configuration file.

[Tip]Tip

it is recommended to use numerical IP addresses instead of host names (to avoid DNS lookups).

Recipients address list

SetMailAlias= listname: addresslist

Define an alias for a list of (already defined) recipients. The format is listname":" addresslist, where addresses in addresslist can be separated by comma, tab, or space. Logging threshold and filters (see below) can be set for a list as for an individual recipient, but will take effect only for email that is specifically targeted at the list (e.g. via a per-queue rule in the logfile monitoring module).

Logging threshold

SetAddrSeverity= severity

This defines a logging threshold severity for the last defined recipient (list). The syntax is the same as for MailSeverity .

[Note]MailSeverity and SetAddrSeverity

The MailSeverity setting in the [Log] section defines an upper bound for all recipients. Messages not included by the MailSeverity setting will never be emailed.

NOT Filter

SetMailFilterNot= list_of_regexes

Defines a filtering condition for the last defined recipient (list). If there is no recipient (list) defined yet, it applies to the compiled-in recipients.

List items are POSIX regular expressions. As whitespace (blank or tab) is a valid separator in a list, strings with whitespace must be enclosed in single or double quotes. If a string begins with a double quote, enclose it in single quotes (and vice versa).

If used, then NONE of the regular expressions in list can occur in a message, otherwise it will not be sent by email.

AND Filter

SetMailFilterAnd= list

[Note]Order of evaluation

AND conditions are evaluated after all NOT conditions.

If used, then ALL strings in list must occur in a message, otherwise it will not be sent by email. The syntax is the same as for SetMailFilterNot .

OR Filter

SetMailFilterOr= list

[Note]Order of evaluation

OR conditions are evaluated after all AND conditions.

If used, then AT LEAST ONE of the strings in list must occur in a message, otherwise it will not be sent by email. The syntax is the same as for SetMailFilterNot .

Closing a recipient (list) definition

CloseAddress

This explicitely closes the definition of a recipient (list). However, this is optional syntactic sugar (i.e. not really required), since recipient (list) definitions are closed implicitely by the beginning of another recipient (list) definition (i.e. SetMailAddress or SetMailAlias ).

Relay host / Mail exchanger

SetMailRelay= mail.some_domain.com

You may need this option because some sites don't allow outbound e-mail connections from any arbitrary host. If the recipient is offsite, and your site uses a mail relay host to route outbound e-mails, you need to specify the relay host.

Maximum interval

SetMailTime= 86400

You may want to set a maximum interval between any two consecutive e-mails, to be sure that samhain is still 'alive'.

Maximum pending

SetMailNum= 10

Messages can be queued to send several messages in one e-mail. You may want to set the the maximum number of messages to queue. (Note: messages of highest priority (alert) are always sent immediately. At most 128 messages can be queued.

Multiple recipients

MailSingle= yes/no

If there are multiple recipients, whether to send a single mail with the recipient list, or send multiple mails. If all recipients are on same domain, a single mail may suffice, otherwise it depends on whether the mail server supports forwarding (for security, most don't).

Subject line

MailSubject= string

Here, string may contain the placeholders %T, %H, %S, and/or %M that will get replaced by the time, hostname, message severity and message text, respectively. The default subject line is equivalent to "%T %H". This option may be useful if you want to send emails to an email-to-sms gateway.

Sender

SetMailSender= string

Here, string is the address that is inserted in the From: field. If a name without domain is given (i.e. without '@xyz.tld'), the FQDN of the local host will be added automatically.

SMTP port

SetMailPort= port_number

This option allows to specify a custom port for SMTP (the default is 25).

Example:

	[Misc]  
	#
	# Do not send messages about added files, and startup messages.
	# We have no recipient defined yet, thus this applies to
	# compiled-in recipients only (if there are any).
	#
	SetMailFilterNot = 'POLICY ADDED', START
	# 
	# E-mail recipient (offsite in this case). 
	# 
	SetMailAddress=username@host.some_domain.com
	SetMailFilterNot = LOGKEY
	CloseAddress
	# 
	# Need a relay host for outgoing mail. 
	# 
	SetMailRelay=relay.mydomain.com 
	#  
	# Number of pending mails. 
	# 
	SetMailNum=10 
	#  
	# Maximum time between e-mails. 
	# Want a message every day, just to be sure that the 
	# program still runs. 
	# 
	SetMailTime=86400
	#
	# Do not send messages about added files, and startup messages
	#
	SetMailFilterNot = 'POLICY ADDED', START
	#
	# To all recipients in a single mail. 
	MailSingle=yes 
      

4.1.E-mail reports and their integrity

The subject line contains timestamp and local hostname, which are repeated in the message body. samhain uses its own built-in SMTP code rather than the system mailer, because in case of temporary connection failures, the system mailer (e.g. sendmail ) would queue the message on disk, where it may become visible to unauthorized persons.

During temporary connection failures, messages are stored in memory. The maximum number of stored messages is 128. samhain will re-try to mail every hour for at most 48 hours. In conformance with RFC 821, samhain will keep the responsibility for the message delivery until the recipient's mail server has confirmed receipt of the e-mail (except that, as noted above, after 48 hours it will assume a permanent connection failure, i.e. e-mailing will be switched off).

The body of the mail may consist of several messages that were pending on the internal queue (see Section2 ), followed by a signature that is computed from the message and a key. The key is initialized with a random number, and for each e-mail iterated by a hash chain.

The initial key is revealed in the first email sent (obviously, you have to believe that this first e-mail is authentic). This initial key is not transmitted in cleartext, but encrypted with a one-time pad ( Section2 ).

The signature is followed by a unique identification string. This is used to identify seperate audit trails (here, a trail is a sequence of e-mails from the same run of samhain ), and to enumerate individual e-mails within a trail.

The mail thus looks like:

	  -----BEGIN MESSAGE----- 
	first message 
	second message 
	... 
	-----BEGIN SIGNATURE----- 
	signature 
	ID TRAIL_ID:hostname 
	-----END MESSAGE-----
[Tip]Integrity verification

To verify the integrity of an e-mail audit trail, a convenience function is provided:

samhain -M /mailbox/file/path

The mailbox file may contain multiple and/or overlapping audit trails from different runs of samhain and/or different clients (hosts).

[Warning]CAVEATS

Verification will fail, if the compiled-in key of the verifying executable is different from the one that generated the message(s) (see Section2 ).

If you use a pre-compiled executable from some binary distribution, be sure to read Section2 carefully.

MANUAL-2_4/severity-of-events.html0000664000175000017500000001120312703400302016371 0ustar rainerrainer3.Severity of events

3.Severity of events

Section heading (see Section1.1 for more details):

[EventSeverity]

Entries:

SeverityReadOnly= severity

SeverityLogFiles= severity

SeverityGrowingLogs= severity

SeverityIgnoreNone= severity

SeverityIgnoreAll= severity

SeverityAttributes= severity

SeverityUser0= severity

SeverityUser1= severity

SeverityUser2= severity

SeverityUser3= severity

SeverityUser4= severity

SeverityPrelink= severity

SeverityFiles= severity

SeverityDirs= severity

SeverityNames= severity

severity may be one of none, debug, info, notice, warn, mark, err, crit, alert .

MANUAL-2_4/file-content-store.html0000664000175000017500000001565112703400301016346 0ustar rainerrainer20.Storing the full content of a file (aka: WHAT has changed?)

20.Storing the full content of a file (aka: WHAT has changed?)

[Note]Consider using a revision control system

One of the most frequently requested features is the ability to determine what has changed in a file. This is not really within the scope of a file integrity checker; rather it would be the task of a revision control system like GIT, SVN (subversion) or CVS.

While samhain, as of version 2.4.4, supports storing the full content of files in the baseline database, this feature is limited to small files (smaller than 9200 bytes after zlib compression). If you really think you need this feature, it is recommended to evaluate whether a revision control system does not fit your needs better.

As of version 2.4.4, samhain can optionally store the full literal content of regular files in the database, which allows to determine what has changed in a file. This feature will only get compiled if the required zlib development environment is available on the host where samhain is compiled (e.g. on Debian Linux, the package zlib1g-dev). This feature is subject to the following restrictions:

  • Only small files can be stored, where 'small' means less than 9200 bytes after zlib compression (and less than 92000 bytes before compression, i.e. files 10 times larger than the limit are assumed to not compress below the limit).

  • Only regular files can be stored; in particular, symlinks are not stored, since the content of a symlink inode actually is the target path (which is stored literally). It is safe to enable this for a directory, in the sense that it is silently ignored for file types where it does not apply.

  • The feature must be explicitely enabled in the runtime configuration file by adding the '+TXT' to the monitoring policy of a file or directory.

To enable this feature, modify a policy to include 'TXT', and place the desired files under this policy (see example below).

In order to show the stored content of a file, use the following command:

        sh$ samhain --list-file path -d database_path
      

20.1.Example configuration

	  [Misc]
	  #
	  # UserN policies default to ReadOnly + ATM (access time). This
	  # makes the default (intentionally ;-) more or less useless.
	  #
	  # Redefine to ReadOnly + TXT (store file content)
	  #
	  RedefUser0 = -ATM, +TXT
	  
	  [User0]
	  #
	  # Files for which we want to store the full content in the
	  # baseline database.
	  #
	  file=/etc/passwd
	  file=/etc/group
	  
	

20.2.Implementation details

File contents are zlib compressed (RFC 1950), and the compressed data are base64 encoded. To avoid internal conflicts, samhain uses the letters '(', ')' and '?' instead of the letters '+', '/', and '=' used in standard base64 encoding. E.g. in PHP the following will decode the data:

	  $tmp1 = strtr($data, "()?", "+/="); 
	  $tmp2 = base64_decode($tmp1); 
	  $tmp3 = gzuncompress($tmp2);
	
MANUAL-2_4/dnmalloc.html0000664000175000017500000001332212703400301014407 0ustar rainerrainer11.Remarks on the dnmalloc allocator

11.Remarks on the dnmalloc allocator

As a proactive security measure, since version 2.4.5, samhain ships with dnmalloc ( Dnmalloc Site), a safer allocator that isn't vulnerable by heap buffer overflows and/or double free errors. I.e. with dnmalloc, it's not possible to exploit such errors to run arbitrary code.

If you want to disable dnmalloc, you can do so at compile time with ./configure --disable-dnmalloc [more options] .

[Note]Unsupported operating systems

The dnmalloc allocator doesn't work on: OpenBSD (problems with pthread internals), Cygwin (also pthread internals), and 64bit FreeBSD. On 64bit AIX, you need to compile as a 32bit application, or to forego dnmalloc.

Speed and memory overhead of dnmalloc:

Speed

Dnmalloc is as fast, or sometimes faster than, the GNU libc allocator (which is based on ptmalloc).

Memory overhead

The actual memory overhead of dnmalloc is in the range of 20 per cent or less.

On top of that, dnmalloc allocates a huge (128MB/256MB for 32bit/64bit systems) table on startup. This is basically a non-issue, since this table is only sparsely used, and hence contributes very little to the "reserved memory", i.e. the actual resource usage of dnmalloc.

Both 'top' and 'ps' include this table in the 'virtual size' (columns VIRT/VSZ in top/ps) of an application using dnmalloc, thus giving the incorrect impression that physical swap storage would be required to back this table, if it's not resident in RAM (columns RES/RSS in top/ps). In fact, since most parts of this table are never used, no physical storage (neither RAM nor swap) is ever reserved for them. Note that this is not true anymore if (on Linux) you've switched off overcommiting completely ( echo 2 > /proc/sys/vm/overcommit_memory ).

[Tip]Reserved memory

"Reserved momory" is the amount of memory that the operating system has reserved for an application, is backed by physical reasources (RAM or swap), and hence is not available for other applications. In other words, "reserved momory" is the actual resource usage of an application.

Because of deferred memory allocation, reserved memory can be less than what an application has asked for, since memory is only reseved when it is used.

MANUAL-2_4/installation-requirements.html0000664000175000017500000001204212703400300020035 0ustar rainerrainer2.Requirements

2.Requirements

POSIX environment

Samhain will only compile and run in a POSIX operating system, or an emulation thereof (e.g. the free Cygwin POSIX emulation for Windows XP/2000).

ANSI C compiler and build system

You need an ANSI C compiler to compile samhain. The GNU C compiler (GCC) from the Free Software Foundation (FSF) is fine. If your vendor's compiler is ANSI compliant, you should give it a try, since it might produce faster code. Also you will need to have standard tools like make in your PATH (the make tool is part of the POSIX standard).

[OPTIONAL] GnuPG

If you want to use signed configuration and database files (this is an optional feature), GnuPG (gpg) must be installed.

[OPTIONAL] libacl/libattr

Samhain can check and verify POSIX ACLs (access control lists, on operating systems supporting them) and SELinux attributes (Linux). This feature is only compiled in if the required libraries and header files are present (e.g. on Linux the libacl/libattr development packages; in Debian these are named libacl1-dev, libattr1-dev).

[OPTIONAL] libz

Samhain can store the content of files in the baseline database (for files smaller than 9200 bytes after zlib compression). This feature is only available if the zlib library and header files are present (e.g. on Linux the libz development package; in Debian this is named zlib1g-dev).

[OPTIONAL] PCRE

Samhain can monitor logfiles of other applications, e.g. Syslog, Apache (or other webservers with similar log formats), Samba, or pacct (BSD-style process accounting). This extension requires the PCRE (Perl Compatible Regular Expressions) library, e.g. on linux the libpcre package (and for compiling, also the libpcre development package). In Debian, this would be libpcre3 and libpcre3-dev.

MANUAL-2_4/testsuite.html0000664000175000017500000001451212703400301014651 0ustar rainerrainer11.The testsuite

11.The testsuite

Samhain comes with a suite of verification/regression tests located in the test/ subdirectory of the source tree.

The driver script is test/test.sh. Calling it without arguments will provide some usage information. The script should be called as:

        bash$ test/test.sh [options] <test_number>
      

To get the list of possible tests, use:

        bash$ test/test.sh -h
      

The recognized options are as follows:

  1. -q|--quiet No output; success/failure is reported vi exit status only.

  2. -v|--verbose Report additional information.

  3. -s|--stoponerr Stop when a test fails.

  4. --no-cleanup Don't clean up generated test data (useful to investigate the reason for a failure).

  5. --srcdir=... Tell the script the location of the source tree (not necessary if run from the top source directory).

  6. --color=always|never|auto Whether to use colour for output. Default is 'auto' (no colour if stdout is not a terminal).

  7. --really-all This option enable additional test that are not run usually (see below).

[Note]The --really-all option

This option enables the following additional tests:

  1. clang/cppcheck As part of the compile test suite (test 1), the cppcheck checker will be used, and the source will be compiled twice, once with the default compiler and second with the clang compiler.

  2. prelude logging Logging to prelude will be tested as part of test 7. Requires prelude-manager, and requires that samhain is already registered as analyzer. This test is designed such that it should not interfere with an eventually running instance of prelude-manager.

  3. mysql/postgresql logging Logging to mysql and/or postgresql will be tested with tests 13/14. Requires a running database with an existing default setup (database/user/password = samhain/samhain/samhain, table = log).

[Warning]CAVEAT

The database tests (13/14) with --really-all will modify (i.e. log to) the database. These are the only tests that are not confined to the directory where the test is run.

MANUAL-2_4/improving-the-signal-to-noise-ratio.html0000664000175000017500000000560712703400301021537 0ustar rainerrainer9.Improving the signal-to-noise ratio

9.Improving the signal-to-noise ratio

To get a good signal-to-noise ratio (i.e. few false alerts), you need to know which files should be checked, and which not (looking at the 'last modified' timestamp may be helpful, if in doubt).

To see how to set recursion depths, implement 'check all but xxx' policies etc., have a look at Section4.1 .

As samhain runs a a daemon, it is capable to 'remember' all file system changes, thus you won't get bothered twice about the same problem.

MANUAL-2_4/thresholds.html0000664000175000017500000001771712703400301015011 0ustar rainerrainer3.Activating logging facilities and filtering messages

3.Activating logging facilities and filtering messages

All messages have a severity level (see Section1.1 ) and a class (see Section1.2 ), with somewhat orthogonal meaning:

The severity ranks messages with respect to their importance. Most events (e.g. timestamps, internal errors, program startup/exit) have fixed severities. However, as importance sometimes is a matter of taste, some events have configurable severities (see Section1 ).

Classes refer to the purpose/category of a message. As such, they should (ideally) be useful to exclude messages that are not interesting in some context (e.g. startup/stop messages may seem useless noise if samhain is run from cron).

Obviously, as severity is a rank, the most natural way to exclude unwanted messages is to set a threshold. On the other hand, as the message class is a category, the most natural way to exclude messages is to list those message classes that you want.

Messages are only logged to a log facility if their severity is at least as high as the threshold of that facility, and their class is one of those wanted (by default: all). Thresholds and class lists can be specified individually for each facility.

[Tip]Switching on/off

Most log facilities are off by default, and need to be enabled by setting an appropriate threshold.

A threshold of none switches off the respective facility.

[Tip]Logging of client messages by the server

By default, messages received by the server are treated specially, and are always logged to the logfile, and never to mail or syslog. If you don't like that, use the option UseClientSeverity=yes(section [Misc]).

Thresholds and class lists are set in the Log section of the configuration file. For each threshold option FacilitySeverity there is also a corresponding option FacilityClass to limit that facility to messages within a given set of class. The argument must be a list of valid message classes, separated by space or comma.

Actually, the FacilitySeverity can take a list of severities with optional specifiers '*', '!', or '=', which are interpreted as 'all', 'excluding', and 'only', respectively. Examples: specifying '*' is equal to specify 'debug'; specifying '!*' is equal to specifying 'none'; 'info,!crit' is the range from 'info' to 'err' (excluding crit and above); and 'info,!=err' is info and above, but excluding (only) 'err'. This is the same scheme as used by the Linux syslogd (see man 5 syslogd).

System calls: certain system calls (execve, utime, unlink, dup (+ dup2), chdir, open, kill, exit (+ _exit), fork, setuid, setgid, pipe) can be logged (only to console and syslog). You can determine the set of system calls to log via the option LogCalls= call1, call2, ... . By default, this is off (nothing is logged). The priority is notice, and the class is AUD.

Example:

	[Log] 
	# 
	# Threshold for E-mails (none = switched off) 
	# MailSeverity=none 
	# 
	# Threshold for log file 
	# 
	LogSeverity=err 
	LogClass=RUN FIL STAMP 
	# 
	# Threshold for console 
	# 
	PrintSeverity=info 
	# 
	# Threshold for syslog (none = switched off) 
	#
	SyslogSeverity=none 
	# 
	# Threshold for logging to Prelude (none = switched off) 
	# 
	PreludeSeverity=none 
	# 
	# Threshold for forwarding to the log server 
	# 
	ExportSeverity=crit 
	# 
	# Threshold for invoking an external program 
	#
	ExternalSeverity=crit 
	# 
	# Threshold for logging to a SQL database 
	# 
	DatabaseSeverity=err 
	# 
	# System calls to log 
	#
	LogCalls=open, kill
      
MANUAL-2_4/checking-mounts.html0000664000175000017500000000651312703400302015721 0ustar rainerrainer7.Checking for mount options

7.Checking for mount options

Section heading:

[Mounts]

Entries:

MountCheckActive= boolean — 'yes' to switch on, 'no' to switch off (default = no).

MountCheckInterval= seconds — Interval between checks (default one day).

SeverityMountMissing= severity — Severity for missing mounts (default = err).

SeverityOptionMissing= severity — Severity for missing mount options (default = err).

CheckMount= /path [mount options] — Mount point to check. Mount options must be given as comma-separated list, separated by a blank from the preceding mount point.

MANUAL-2_4/hash-function.html0000664000175000017500000001104412703400301015363 0ustar rainerrainer2.Available checksum functions

2.Available checksum functions

A cryptographic hash function is a one-way function H( foo) such that it is easy to compute H( foo) from foo, but infeasible to compute foo from H( foo) , or to find bar such that H( bar) = H( foo) (which would allow to replace foo with bar without changing the hash function).

One common usage of a such a hash function is the computation of checksums of files, such that any modification of a file can be noticed, as its checksum will change.

For computing checksums of files, and also for some other purposes, samhain uses the TIGER hash function developed by Ross Anderson and Eli Biham. The output of this function is 192 bits long, and the function can be implemented efficiently on 32-bit and 64-bit machines. Technical details can be found at this page.

As of version 1.2.10, also the MD5 and SHA-1 hash functions are available. (You need to set the option DigestAlgo=MD5 or DigestAlgo=SHA1 in the config file to enable this). Note that MD5 is somewhat faster, but because of security concerns it is not recommended anymore for new applications.

As of version 3.1.0, also the SHA2-256 hash function is available. (You need to set the option DigestAlgo=SHA256 in the config file to enable this).

MANUAL-2_4/suidchk.html0000664000175000017500000002472212703400301014256 0ustar rainerrainer9.Checking the file system for SUID/SGID binaries

9.Checking the file system for SUID/SGID binaries

To compile with support for this option, use the configure option

./configure --enable-suidcheck

If enabled, this will cause the samhain daemon to check the whole file system hierarchy for SUID/SGID files at user-defined intervals, and to report on any that are not included in the file database. Upon database initialization, all SUID/SGID files will automatically be included in the database. Excluded are nfs, proc, msdos, vfat, and iso9660 (CD-ROM) file systems, as well as file systems mounted with the 'nosuid' options (the latter is not supported on all OSes, but at least on Linux).

On Linux, files that are marked as candidates for mandatory locking (group-id bit set, group-execute bit cleared) will be ignored.

You can manually exclude one directory (see below); this should be used only for obscure problems (e.g.: /net/localhost on Solaris - the automounter will mirror the root directory twice, as '/net/localhost' and '/net/localhost/net/localhost', and any nfs file system in '/' will be labelled as ufs system in '/net/localhost/net/localhost' ...).

[Note]Note

The SUID check is very I/O expensive. Using 'nice' may not help, if the CPU is waiting for I/O all the time anyway. To limit the load, the following options are provided:

You can schedule execution at fixed times with SuidCheckSchedule= schedule .

You can limit I/O with the SuidCheckFps= fps option (fps: files per second).

As an alternative to the SuidCheckFps option, you can use SuidCheckYield= yes . This will cause the SuidCheck module to yield its time slice after each file. If SuidCheckYield is used, the SuidCheckFps option will not take effect.

The schedule should have the same syntax as a crontab entry (see crontab(5) and example below), with the following exceptions: (a) lists are not allowed, and (b) ranges of names are allowed. If a schedule is given, the SuidCheckInterval option will not take effect. You can specify a list of schedules with successive SuidCheckSchedule=... directives.

9.1.Quarantine SUID/SGID files

As of version 1.8.4, it is possible to quarantine new SUID/SGID files detected by samhain. To use this option, you must first enable it with SuidCheckQuarantineFiles= yes . This tells the SuidCheck module to quarantine any SUID/SGID files found after the initialization of the database using the method selected in SuidCheckQuarantineMethod (see next paragraph). If this is used, the file will be logged each time it is found and not added to the memory resident database.

You must also choose a method to be used to quarantine a SUID/SGID file: SuidCheckQuarantineMethod= 0/1/2 . Currently, there are 3 methods implemented: 0 - Delete the file from the system. 1 - Remove the SUID/SGID permissions from the file. 2 - Move the SUID/SGID file to a quarantine directory. The quarantine directory is DEFAULT_DATAROOT/.quarantine. Each file moved there has an additional file created that contains information about the SUID/SGID file. For example, if a file /foo is an unauthorized SUID/SGID file, then it will be removed and moved to /var/lib/samhain/.quarantine and another file, foo.info, will be created in /var/lib/samhain/.quarantine with information about /foo.

[Warning]Important remarks

Methods 0 and 2 will by default not remove the original file, but rather truncate to zero size and remove suid/sgid properties. If you really want to remove the original file rather than truncate, you need to set the option SuidCheckQuarantineDelete= yes

The rationale for this behaviour is that removing a file in an arbitrary directory is considered to be dangerous, because the object that is unlinked may not be the same object anymore that has been determined to be a suid/sgid file before. You have been warned.

For additional security, samhain will recursively chdir into the parent directory of the file to make sure there are no symlinks in the path. Also, a file will not be truncated if it is a hardlink to another one.

No quarantining will be done if samhain is run in 'update' mode, since it is assumed that the current filesystem state is ok, and the database should be updated to reflect the current state.

9.2.Configuration

This facility is configured in the SuidCheck section of the configuration file.

	    [SuidCheck]  
	    # activate (0 for switching off) 
	    SuidCheckActive=1 
	    # interval between checks (in seconds, default 7200)
	    # SuidCheckInterval=86400 
	    # scheduled check at 01:30 each night
	    SuidCheckSchedule=30 1 * * * 
	    # this is the severity (see Section1.1) 
	    SeveritySuidCheck=crit 
	    # you may manually exclude one directory 
	    SuidCheckExclude=/net/localhost
	    #
	    # limit on files per seconds
	    SuidCheckFps=250 
	    # alternatively yield time slice after each file
	    # SuidCheckYield=yes
	    #
	    # Quarantine detected SUID/SGID files
	    # SuidCheckQuarantineFiles=no
	    #
	    # Quarantine Method
	    # 0 - Delete the file from the system.
	    # 1 - Remove the SUID/SGID permissions from the file.
	    # 2 - Move the SUID/SGID file to a quarantine directory.  
	    #     The quarantine directory is DEFAULT_DATAROOT/.quarantine.
	    # SuidCheckQuarantineMethod = 1
	    #
	    # Really delete if using methods 0 or 2
	    # SuidCheckQuarantineDelete = no
          

MANUAL-2_4/controlling-the-daemon.html0000664000175000017500000001316312703400301017172 0ustar rainerrainer3.Controlling the daemon

3.Controlling the daemon

As part of their boot concept, some systems have individual start/stop scripts for each service (daemon). As a minimum, these scripts take either 'start' or 'stop' as argument, sometimes also e.g. 'reload' (to reload the configuration), 'restart', or 'status' (check whether the daemon is running). While this is convenient, there are also a number of problems:

  • Some systems do not have such start/stop scripts.

  • There is no standard for the location of these scripts.

  • There is no standard for the arguments such a script may take, neither for their interpretation (e.g.: on Linux distribution XYZ, do the start/stop scripts take 'status' as argument, and if, is the status reported by printing a message or by the exit status ?)

To provide a portable interface for controlling the samhain daemon, the executable itself can serve for this purpose ( only if invoked by the superuser) The supported actions, which must be given as first argument on the command line, are:

  • start Start samhain. Arguments after 'start' are passed to the process. Daemon mode will be enforced, as well as running in 'check' mode, irrespective of command line or config file settings.

  • stop Stop the daemon. On Linux and Solaris, actually all running instances of samhain are stopped, even if no pid file is available.

  • restart Stop and start.

  • reload or force-reload Reload the configuration file.

  • status Check whether the daemon is running.

Success/failure is reported via the exit status as follows: 0 Success. (On Linux/Solaris, stop will always be successful, on other systems only if the pid file is found.) 1 Unspecified error. 4 User had insufficient privilege. 5 Program is not installed. 7 Program is not running.

If the status command is given: 0 Program is running. 1 Program is dead and /var/run pid file exists. 3 Program is stopped. 4 Program status is unknown.

I.e., this interface behaves as mandated by the LSB Standard for init scripts.

MANUAL-2_4/compilation-options.html0000664000175000017500000002704112703400302016631 0ustar rainerrainerAppendixA.List of options for the configure script

AppendixA.List of options for the configure script

1.General

--with-rnd=egd/dev/unix/default

The entropy gatherer to use. 'egd' is the Entropy Gathering Daemon (EGD), 'dev' is /dev/random, 'unix' is the built-in Unix entropy gatherer (similar to EGD), and 'default' will check for /dev/random first, and use 'unix' as fallback.

--with-egd-socket=NAME

The path to the EGD socket. Default is localstatedir/lib/samhain/entropy(see Section5 ).

--enable-identity=USER

The username to use when dropping root privileges (default nobody).

--with-sender=SENDER

The username of the sender for e-mail, or a complete e-mail address. If only a username is given, SENDER@{FQDN_of_local_host} will be used for the sender. Default is daemon.

--with-recipient=ADDR

The recepient(s) for e-mail, seperated by whitespace (max. 8). You can add recepients in the configuration file as well.

--with-trusted=UID

Trusted users (must be a comma-separated list of numerical UIDs). Only required if the configuration file must be on a path writeable by others than root and the effective user.

--with-timeserver=HOST

Set host address for time server (default is to use own clock). You can set this in the configuration file as well. An address in the configuration file will take precedence. Note that the simple 'time' service (port 37/tcp) is used.

--with-alttimeserver=HOST

Set host address for an alternative (backup) time server.

--enable-stealth=XOR_VAL

Enable stealth mode, and set XOR_VAL. XOR_VAL must be decimal, in the range 127 -- 255, and will be used to obfuscate literal strings.

--enable-micro-stealth=XOR_VAL

As --with-stealth , but without steganographic hidden configuration file.

--enable-nocl=PW

Command line parsing is disabled, but command-line arguments will be read from STDIN if the first command line argument is PW. PW="" (empty string) will disable command line parsing completely. This option may be used as addition to --enable(-micro)-stealth to prevent interactive enforcement of telltale output.

--enable-install-name=NAME

Upon installation, rename every file from samhain(or yule for the server) to NAME. To be used in conjunction with --with-(micro-)stealth.

--enable-base=B1,B2

Set compiled-in key for email and logfile signature verification. ONE string (no space) made of TWO comma-separated integers in the range 0 -- 2147483647. See Section2 for details on this option.

--enable-db-reload

[CLIENT ONLY] Enable reload of file database on SIGHUP (otherwise, only the config file will be read again).

--enable-xml-log

Enable XML format for the log file.

--with-database=mysql/postgresql/oracle/odbc

Support logging to a relational database (MySQL, PostgreSQL, Oracle or unixODBC). Oracle and unixODBC are not fully tested.

--with-prelude

Support logging to the Prelude IDS system. Requires the libprelude library.

--with-libprelude-prefix=PFX

Prefix where libprelude is installed. This will be used to search libprelude-config in the PFX/bin/ directory.

--disable-ipv6

Disable IPv6 support.

--enable-debug[=gdb]

Enable debugging. Will slow down things, increase resource usage, and may leak information that should be kept secure. Will dump 'core' and 'samhain_backtrace' in the root directory on segfault. Do not use in production code.

If used as --enable-debug=gdb, will only compile in debugging symbols for the GNU gdb compiler. This is more suitable for debugging the code itself.

--enable-ptrace

Periodically check whether a debugger is attached, and abort if yes. Only takes effect if --enable-debug is not used. Only tested on Linux.

--with-cflags=FLAGS

Additional flags to pass to the compiler.

--with-libs=LIBS

Additional libraries to link with.

--disable-largefile

Disable support for large files (> 2GB). Large file support is enabled automatically if your system supports it.

--enable-posix-acl

Compile with support for checking posix ACLs of files. This is compiled in by default if the required libraries and header files are present, but using this option will turn the 'soft fail' into a 'hard fail' if it can't be compiled in.

--enable-selinux

Compile with support for checking SELINUX attributes of files. This is compiled in by default if the required libraries and header files are present, but using this option will turn the 'soft fail' into a 'hard fail' if it can't be compiled in.

--enable-udp

This options enables code to listen on port 514/upd, i.e. the syslog port. Thus the server can receive syslog reports from remote hosts (if they are configured to send), and log them to any of the log facilities supported by samhain. If you compile in support for this, you still need to enable it in the runtime configuration file.

--disable-dnmalloc

This options disables use of the dnmalloc allocator that is the default since samhain 2.4.5, and reverts to using the standard allocator provided by your system.

--disable-ssp

This options disables use of the GCC stack protector.

--enable-suid

With this option, samhain will honour the SUID bit instead of resetting all privileges to the real UID of the process. Required for Nagios if samhain is invoked by the Nagios plugin itself, unless you want to use sudo instead.

--disable-shellexpand

This options disables the expansion of shell commands in the configuration file.

--disable-external-scripts

This options disables the possibility to call an external program to log an event (or perform active response).

--enable-message-queue[=MODE]

This options enables logging to a POSIX message queue, where MODE should be the octal permission for the queue (default is 0700).

MANUAL-2_4/initializing-updating-checking.html0000664000175000017500000000722612703400301020700 0ustar rainerrainer7.Initializing, updating, or checking

7.Initializing, updating, or checking

In the Misc section of the configuration file, you can choose between initializing the database, updating it, or checking the files against the existing database:

ChecksumTest= init|update|check|none

If you use the mode none, you should specify on the command line one of init, update, or check, like: samhain -t check

As of version 1.8.1, there is a new command line flag --interactive to enable interactive updates. If you use this flag together with -t update, you will be asked if the database entry should be updated, whenever samhain encounters a modified file.

As of version 2.8.6, updates can also be done using a text file listing paths (one per line) of files to update, with the command line flag --listfile= path_to_listfile

MANUAL-2_4/consoledetails.html0000664000175000017500000000764612703400301015642 0ustar rainerrainer8.Console

8.Console

Up to two console devices are supported, both of which may also be named pipes. If running as daemon, samhain will use /dev/console for output, otherwise stdout. On Linux, _PATH_CONSOLE will be used instead of /dev/console, if it is defined in the file /usr/include/paths.h.

You can override this at compile time, or in the [Misc] section of the configuration file with the SetConsole= device option. Up to two console devices are supported, both of which may also be named pipes (use the SetConsole option twice to set both devices).

[Tip]Switching off

Invariably, some users set SetConsole= /dev/null to switch off console logging. This is highly ineffective, as the device will be opened, and the message written to it, for every log message. The correct way is to use PrintSeverity= none in the [Log] section of the configuration file (or the command line switch '-p none').

MANUAL-2_4/logmon.html0000664000175000017500000007117312703400301014121 0ustar rainerrainer16.Logfile monitoring/analysis

16.Logfile monitoring/analysis

This option is available with samhain version 2.5.0 and higher. To compile with support for this option, use the configure option

./configure --enable-logfile-monitor

[Note]PCRE library required

This option requires the PCRE (Perl Compatible Regular Expressions) library. Many Linux distributions split library packages into a runtime package (required to run a dependent executable) and a development package (required to compile an executable). At least on the build host where samhain is compiled, the development package is required if you use this option.

This module enables samhain to monitor/analyze logfiles of other applications. Currently ( samhain 2.5.0) the following logfile formats are supported:

  • Syslog

  • Apache (access and error log)

  • Samba

  • 'pacct' BSD-style process accounting (also available on Linux)

Logfile analysis will always start from the point the last one ended; the pointer into the file is stored persistently on disk. Logfile rotation is handled automatically as long as the rotated logfile remains in the same directory and is not compressed(usually log rotation tools can be configured to compress only after the second rotation, which is advisable for unrelated reasons - the logging application may still have an open file pointer after logfile rotation).

Logfile entries can be filtered with Perl-style regular expressions (filter rules). Regular expressions must match the whole logfile record. For efficiency, regular expressions can be grouped under a common regular expression, i.e. if the group expression fails to match, no RE in the group is tried. Furthermore, (groups of) regular expressions can be grouped by host, if the logfile(s) contain host information (such as host information in centralized syslog server logfiles, or virtual host information in Apache logfiles). Note that host->group->rule is supported (just as host->rule or group->rule), while group->host->rule isn't.

Each filtering rule (regular expression) is assigned to an output queue. Currently (samhain 2.5.0) queues only differ in the assigned severity of an event, but more options (per-queue mail addresses for alerts) are under development.

Filtering rules are processed in the order given in the configuration file, i.e. the first match wins.

[Note]Blacklisting vs. whitelisting, and the 'trash' output queue

Output queues are labelled. The label 'trash' is reserved and refers to the trash bin (no output, throw away log entries if the matching rule is assigned to the 'trash' queue).

If a logfile entry does not match any rule, it is reported (i.e. the default is whitelisting known-good entries). To turn this into a blacklisting policy, simply add a catch-all rule at the end and assign it to the 'trash' queue.

16.1.Event Correlation

Sometimes it is desirable to report on the fact that several events happend at a similar time, possibly in a particular order. As of version 2.6.1, samhain supports this in the following way:

16.1.1.Marking individual events to be correlated

First, individual events to be correlated need to be marked for keeping them, under an arbitrary user-defined label, for an arbitrary user-defined time. So the rule for matching an event has to be modified like this:

LogmonRule=KEEP( seconds,label): queue_label: (perl)regex matches a logfile entry against the provided regular expression, AND keeps it for the specified time in seconds, with the specified label. In other words, processing of this rule will be no different than other rules, except for the fact that also a memory of the event is kept for the specified amount of time. So if you e.g. don't want a separate report for this individual event, just assign it to the trash queue.

16.1.2.Correlating the marked events

To correlate events labelled label_one, label_two, etc., just build a regular expression that matches the labels, in the temporal order you want to check for. E.g. if the temporal order is irrelevant, you may want to match (label_one.*label_two)|(label_two.*label_one). Use this expression in a rule maked as CORRELATE( description), like this:

LogmonRule=CORRELATE( description): queue_label: (perl)regex

[Note]Old records in existing logfiles

Because the 'keep' timeout is relative to the current time, correlation of old entries in logfiles (i.e. when, at startup, an existing logfile with old entries is scanned) will only work if you specify 'keep' timeouts that are long enough to cover the whole timespan from the first logfile record until now.

16.2.Reporting non-occurence of an event

To check whether a given event occurs at least once within some given interval, the rule for matching an event can be modified like this:

LogmonRule=MARK( seconds,description): queue_label: (perl)regex matches a logfile entry against the provided regular expression, AND checks whether is occurs at least once within the specified interval (seconds).

Processing of this rule will be no different than other rules otherwise, so if you e.g. only want a report for this event if it is missing, just assign it to the trash queue. However, in the latter case the severity for reporting the messages must be set separately with the LogmonMarkSeverity directive, because the 'trash' queue has no severity assigned:

LogmonMarkSeverity= severity — Severity for reports on missing heartbeat messages if the messages themselves are assigned to the 'trash' queue (default: crit).

16.3.Reporting bursts of similar, repeated events

Samhain can automatically detect and report bursts of similar, repeated events in the monitored logfiles. Here similar, repeated events refers to events that differ (only) in details that can be expected to differ for events of the same kind: IP adresses, FQDNs, email adresses, and numbers. The event history goes back 12 minutes, and thus a report is triggered if the number of similar events within the last 12 minutes exceeds a given threshold (default: 24).

This feature is off by default. In order to switch it on, you need to set a reporting queue:

LogmonBurstQueue= queue — Set the reporting queue for reporting bursts of similar log messages (default: don't report).

In addition, there are two more configurable parameters, one to set the triggering threshold (i.e. the number of messages within 12 minutes that need to be exceeded to raise an alert), and another one to indicate whether messages from the cron daemon should be considered as well (default: no):

LogmonBurstThreshold= number — The number of repeated messages within 12 minutes that must be exceeded to report a burst of repeated messages (default: 24).

LogmonBurstCron= boolean — Whether to report also on bursts of repeated cron messages (default: false).

16.4.Options

LogmonActive= boolean switches this module on or off (default: off).

LogmonSaveDir= /absolute/path sets the directory where checkpoint data for logfiles is stored (default: same as for database file).

LogmonClean= boolean delete old checkpoint data unmodified for 30 days or more (default: off).

LogmonInterval= seconds sets the interval for logfile checking (default: 10 seconds).

LogmonMarkSeverity= severity — Severity for reports on missing heartbeat messages if the messages themselves are assigned to the 'trash' queue (default: crit).

LogmonBurstThreshold= number — The number of repeated messages within 12 minutes that must be exceeded to report a burst of repeated messages (default: 24).

LogmonBurstQueue= queue — Set the reporting queue for reporting bursts of similar log messages (default: don't report).

LogmonBurstCron= boolean — Whether to report also on bursts of repeated cron messages (defaul: false).

LogmonDeadtime= seconds — Do not report a correlated event again within the given time (default: 60 seconds).

LogmonWatch= TYPE:path[:format] advises the module to monitor the logfile with the specified path, which is of type 'TYPE' (logfile types are uppercase). Some logfile types (e.g. Apache access logs) can be customized, and hence some format information must be provided.

[Note]Do not quote the format

Please note that it's neither required nor supported to add quotes around the format string. Likewise, quotes within the format should not be escaped. Wrong:

LogmonWatch= APACHE:/var/log/apache/access.log:"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\""

Correct:

LogmonWatch= APACHE:/var/log/apache/access.log:%h %l %u %t "%r" %>s %b "%{Referer}i"

Currently ( samhain 2.6.4) the following logfile types are supported

SYSLOG

Standard UNIX style syslog files. Matching starts at the command (i.e. after the hostname). To select certain hostnames, place the rule under a LogmonHost directive (see below). If the LogmonHidePID option is used, the RE should not account for the process PID.

APACHE

Apache (or compatible) webserver access and/or error logs. Required format information: either one of combined, common, or error(error log), or the Apache custom log format specification used (also '%{X-Forwarded-For}i' is recognized). The whole log line is matched. If there are virtual hosts (%v), then the LogmonHost directive will match the virtual host.

In addition to the Apache format specifications, is possible to insert a literal regular expression as RE{ regex} ( samhain 2.8.4+).

SAMBA

Samba logfile format (multiline, timestamp and origin within samba source code on first line, log message on continuation lines). The RE will match the continuation line (with the log message) only.

PACCT

BSD style process accounting (also available on Linux). This is a binary logfile. The module will build a text line like the 'last' command does, and match it against the RE.

What is pacct good for? Note that pacct records contain only the executable name, not the arguments. This may look somewhat useless for shell accounts, but is quite useful for servers: how many different commands can e.g. postfix legitimately execute? Just a handful, indeed, and certainly none of them is /bin/sh! So if pacct says that the 'postfix' user has executed a shell, then this would be rather alarming...

SHELL

A shell command. The full output on stdout will be read and matched. The PATH environment variable will be set to /sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb, and the SHELL, IFS, and TZ variables will be defined. The command is executed via /bin/sh -c command .

LogmonHidePID= boolean is an option that only affects logfiles of type SYSLOG. It causes the PID to be stripped from the log line (before matching against the RE).

LogmonQueue= label:[interval]:(sum|report):severity[:alias] defines an output queue. Here, label is an arbitrary name which is used to assign rules to this queue; interval is the timespan over which messages are summarized if the queue is of type 'sum'; sum(summarize over some interval) or report(report each event seperately and immediately) are the two queue type supported, and severity is the severity assigned to an event. Furthermore, optionally it is possible to specify an alias(must be defined in the email configuration) to direct email for this rule to a specific list of recipients.

[Note]Email

If you spefify a list alias, email will still go to all defined email recipients unless filtered, e.g. with

	    SetMailFilterNot = \[Logfile\]
	  

I.e. you may want to define recipients, filter them as above, and then define list aliases to be used in an event queue. See Section4 for more information.

LogmonHost= (perl)regex causes the following rules to be applied only to entries for this host(s). It is ended implicitely by another LogmonHost directive, or explicitely by a LogmonEndHost directive.

LogmonEndHost explicitely ends a preceding LogmonHost directive.

LogmonGroup= (perl)regex causes the following rules to be applied only if the group regex matches (i.e. rules within the group are skipped if the group regex doesn't match. This can be used to improve speed/efficiency of matching, i.e. you can group regexes by a common prefix. A group is ended implicitely by another LogmonGroup directive, or explicitely by a LogmonEndGroup directive.

LogmonEndGroup explicitely ends a preceding LogmonGroup directive.

LogmonRule= queue_label:(perl)regex matches a logfile entry against the provided regular expression. If the expression matches, then captured subexpressions are replaced by '___', and the logfile entry is reported as specified for the queue referenced by queue_label. Non-captured subexpressions (i.e. subexpressions where the opening bracket is followed by '?:') are not replaced by '___', but reported literally.

LogmonRule=KEEP( seconds,label): queue_label:(perl)regex as above, but additionally keep the event label for seconds to perform event correlation.

LogmonRule=CORRELATE( description): queue_label: (perl)regex perform event correlation by matching the labels(as specified in KEEP rules) of a sequence of events against the given regular expression.

LogmonRule=MARK( seconds,description): queue_label: (perl)regex matches a logfile entry against the provided regular expression, AND checks whether is occurs at least once within the specified interval (seconds).

16.5.Example configuration

	  [Logmon]
	  
	  #
	  # Switch on the module
	  #
	  LogmonActive = yes
	  
	  # Check every second
	  #
	  LogmonInterval = 1
	  
	  # Strip PIDs from syslog messages
	  #
	  Logmonhidepid = true
	  
	  # Define a queue with severity 'crit'.
	  # This is a 'report' queue, hence 'interval' (10)
	  # will be ignored.
	  #
	  LogmonQueue = q1:10:report:crit
	  
	  # Define a second queue with severity 'alert'
	  # 
	  LogmonQueue = q2:10:report:alert
	  
	  # Monitor /var/log/messages, which is a syslog file
	  #
	  LogmonWatch = SYSLOG:/var/log/messages
	  
	  # Monitor /var/log/samba/log.nmbd, which is a samba
	  # logfile
	  #
	  LogmonWatch = SAMBA:/var/log/samba/log.nmbd
	  
	  # Monitor /var/log/apache2/access.log, which is
	  # an Apache logfile in 'combined' format
	  #
	  LogmonWatch = APACHE:/var/log/apache2/access.log:combined
	  
	  # Monitor disks to check for full /dev/sda1
	  #
	  LogmonWatch = SHELL:df -h
	  
	  # Syslog messages for the pppd deamon
	  #
	  LogmonGroup = g1:pppd.*
	    #
	    # Rules in this group
	    #
	    LogmonRule     = q1:pppd:\s+primary.*
	    LogmonRule     = q1:pppd:\s+secondary.*
	    #
	  LogmonEndGroup

	  # Warn about disk /dev/sda1 nearly full (80% or more. Use a 
	  # non-capturing subexpression [the (?:8|9)] for the percentage full.
	  #
	  LogmonRule = q1:/dev/sda1\s+[0-9GM.]+\s+[0-9GM.]+\s+[0-9GM.]+\s+(?:8|9).%.*

	  # Messages starting with WARNING (some samba stuff)
	  #
	  LogmonGroup = g2:WARNING.*
	  LogmonRule     = q2:.*interfaces.*
	  LogmonEndGroup

	  # Report on these events if happening within 120 seconds.
	  # Set LogmonDeadtime to 120 seconds to avoid multiple reports.
	  # Use the 'trash' queue for the keep rules to avoid reports on
	  #   the individual events.
	  #
	  LogmonRule = KEEP(120,event1):trash:sshd: Accepted publickey for root.*
	  LogmonRule = KEEP(120,event2):trash:sshd: pam_unix\(sshd:session\).*
	  LogmonRule = CORRELATE(root_login):q1:(event1.*event2)|(event2.*event1)

	  LogmonDeadtime = 120

	  # Throw away all non-matching entries. This amounts
	  # to a blacklist policy (only report known bad).
	  #
	  # Usually considered bad practice!!! Use whitelisting!
	  #
	  # 'trash' is a built in queue, no definition needed.
	  #
	  LogmonRule = trash:.*
	
MANUAL-2_4/command-line.html0000664000175000017500000003371012703400302015165 0ustar rainerrainerAppendixB.List of command line options

AppendixB.List of command line options

1.General

  1. -D, --daemon Run as daemon.

  2. --foreground Stay in the foreground, do not run as daemon.

  3. -f, --forever Loop forever, even if not daemon.

  4. --bind-address=<IP-Address> Use this IP address (i.e. interface) for outgoing connections (e.g. on multi-interface machines).

  5. --server-port=<port number> Connect to this port on the server (client-side option for client-server connection).

  6. --server-host=<hostname/IP address> Connect to this server host (client-side option for client-server connection). Using this option a second time will set the backup server host. Reloading the configuration with a server defined in the configuration file will overwrite the original CL values.

  7. -s <arg>, --set-syslog-severity=<arg> Set the severity threshold for syslog. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  8. -l <arg>, --set-log-severity=<arg> Set the severity threshold for logfile. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  9. -m <arg>, --set-mail-severity=<arg> Set the severity threshold for e-mail. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  10. --set-database-severity=<arg> Set the severity threshold for logging to a RDBMS. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  11. --set-prelude-severity=<arg> Set the severity threshold for logging to the Prelude IDS system. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  12. -p <arg>, --set-print-severity=<arg> Set the severity threshold for terminal/console. arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  13. -x <arg>, --set-extern-severity=<arg> Set the severity threshold for external program(s). arg may be one of none, debug, info, notice, warn, mark, err, crit, alert .

  14. -L <arg>, --verify-log=<arg> Verify the integrity of the log file and print the entries ( arg is the path of the log file).

  15. -j, --just-list Modify -L to just list the logfile, rather than verify (to de-obfuscate the logfile if you have compiled for stealth mode). Order matters: this must come before -L.

  16. -M <arg>, --verify-mail=<arg> Verify the integrity of e-mailed messages ( arg is the path of the mail box).

  17. -V <arg>, --add-key=<arg> Add key material to the compiled-in key (see Section2 ). arg must be of the form key@/path/to/executable. Output will be written to /path/to/executable.out.

  18. -H <arg>, --hash-string=<arg> Print the hash of a string / the checksum of a file, and exit. If arg starts with a '/', it is assumed to be a file, otherwise a string. This function is useful to test the hash algorithm.

  19. -z <arg>, --tracelevel=<arg> If compiled with --enable-debug: arg > 0 to switch on debug output. If compiled with --enable-trace: arg > 0 max. level for call tracing.

  20. -i <arg>, --milestone=<arg> If compiled with --enable-trace: trace from milestone arg to arg+1. If arg = -1, trace all.

  21. -o <arg>, --outfile=<filename> Pathname for the output filename (relevant for the options --list-database and --create-database).

  22. -d <arg>, --list-database=<arg> List the database file arg(use ``default'' for the compiled-in path). The listing can be modified in various ways by prepending some other options (see next).

  23. --list-file=<path> Modify --list-database to list the literal content of a file, if this has been stored. Order matters: this must come before --list-database.

  24. -a, --full-detail Modify --list-database to list full details (numeric mode, owner, group, all three timestamps (ctime, mtime, atime), and the checksum. Order matters: this must come before --list-database.

  25. --delimited Same as --full-detail, but with comma-delimited fields. Order matters: this must come before --list-database.

  26. --binary This will list the database in the binary format of the database, i.e. it will output another database. Intended to be used together with --list-filter to create a partial database. Order matters: this must come before --list-database.

  27. --list-filter=<filename> Modify --list-database to list only those files listed in the text file <filename> (one path per line). Together with the --binary option this allows to create a partial database. Order matters: this must come before --list-database.

  28. --verify-database=<arg> Verify (the integrity of the files in) the database given as argument, and exit with a status of success or failure. The configuration file will NOT be read, the policy recorded in the baseline database will be used instead. For more verbosity, the option --set-print-severity=<arg>> can be prepended. Intended to be used with a partial database created by --binary --list-filter=<filter_filename> --list-database=<database_filename>

  29. --create-database=<arg> Create a baseline database for the files listed in the textfile arg(one path per line). The configuration file will NOT be read, the policy recorded in the baseline database will be ReadOnly, and the content of files will optionally be stored if the path in the list is preceded by a '+' (plus) sign. For choosing the output pathname, the option --outfile=<filename> should be prepended. For more verbosity, the option --set-print-severity=<arg> can be prepended.

  30. -c, --copyright Print copyright information and exit.

  31. -v, --version Show version information and compiled-in options.

  32. -h, --help Print a short help on command line options and exit.

  33. --trace-enable Print a trace of the execution flow.

  34. --trace-logfile=<arg> Use file arg to log the trace.

MANUAL-2_4/usercheck.html0000664000175000017500000000702412703400301014574 0ustar rainerrainer13.Checking sensitive files owned by users

13.Checking sensitive files owned by users

To compile with support for this option, use the configure option

./configure --enable-userfiles

samhain can be compiled to support checking of files that are specified as being relative to the a user's home directory. It is intended to detect interference with files that influence process behaviour such as .profile It simply adds the appropriate file entries to the main samhain list, at the specified alerting level.

	[UserFiles]
	#
	# Activate (0 is off).
	#
	UserfilesActive=1
	
	#
	# Files to check for under each $HOME
	# A specific level can be specified.
	# The allowed values are:
	# allignore
	# attributes
	# logfiles
	# loggrow
	# noignore
	# readonly
	# user0
	# user1
	# user2
	# user3
	# user4
	# 
	# The default is noignore
	#
	UserfilesName=.login noignore
	UserfilesName=.profile readonly
	UserfilesName=.ssh/authorized_keys
	#
	# A list of UIDs where we want to check. 
	# The default is all.
	# IF THERE IS AN OPEN RANGE, IT MUST BE LAST
	#
	UserfilesCheckUids=0,100-500,1000-
      

This module by the eircom.net Computer Incident Response Team.

MANUAL-2_4/installation-download.html0000664000175000017500000001175512703400300017133 0ustar rainerrainer3.Download and extract

3.Download and extract

The current version of samhain can be downloaded from http://www.la-samhna.de/samhain/samhain-current.tar.gz. Older versions of samhain are available from the online archive. You should always make sure that you have a complete and unmodified version of samhain. This can be done by verifying the PGP signature (see below).

The downloaded tarball will contain exactly two files:

  1. A tarball named samhain-N.N.N.tar.gz (N.N.N is the version number) containing the source tree, and

  2. the PGP signature for this tarball, i.e. a file named samhain-N.N.N.tar.gz.asc. use of the dnmalloc allocator that is the default since samhain 2.4.5, and reverts to using the standard allocator provided by your system.

      sh$ wget http://la-samhna.de/samhain/samhain-current.tar.gz
      sh$ gunzip -c samhain-current.tar.gz | tar tvf -
      -rw-r--r-- 500/100 920753 2004-05-24
      19:57:55 samhain-1.8.8.tar.gz -rw-r--r-- 500/100 189
      2004-05-24 19:58:29 samhain-1.8.8.tar.gz.asc

You might wish to verify the PGP signature now, in order to make sure that you have received a complete and unmodified version of samhain. All samhain releases are signed with the key 0F571F6C (Rainer Wichmann).

Key fingerprint = EF6C EF54 701A 0AFD B86A F4C3 1AAD 26C8 0F57 1F6C

        sh$ gpg --keyserver pgp.mit.edu --recv-keys 0F571F6C
        sh$ gpg --verify samhain-N.N.N.tar.gz.asc samhain-N.N.N.tar.gz
      

Now you can proceed to extract the source tarball:

        sh$ gunzip -c samhain-N.N.N.tar.gz | tar tvf -
      

This will create a new subdirectory samhain-N.N.N under your current directory. You should cd into this subdirectory to proceed with configuring the source:

        sh$ cd samhain-N.N.N
      
samhain-4.1.4/docs/README.win2K0000644000175000017500000000265012615253277012677 00000000000000 Using SAMHAIN on Win2K ---------------------- samhain builds and runs on Win2K (and maybe other M$ products) with the (free, GPL) Cygwin environment. Fabio Paracchini writes: (UPDATE: note that some configure options have changed since this has been written. Check the manual and/or run './configure --help' for available options.) The configuration I'm testing now is a server on OpenBSD 2.8 and a client on W2K, using the latest Cygwin. I was able to compile the client on a W2K Cygwin development machine using those configuration flags: --enable-static --enable-network --with-tmp-dir=/tmp --with-data-file=REQ_FROM_SERVER/samhain.db --with-config-file=REQ_FROM_SERVER/etc/samhainrc --with-logserver=x.x.x.x --with-lock-file=/cygdrive/c/samhain.lck --with-log-file=/cygdrive/c/samhain.log I was able to successfully compile and sign the executable, upload to the production server with the cygwin1.dll in the same directory and run both samhain -t init and samhain -t check. If you need a stealthy configuration you could change lock & log file to something more obscure, only pay attention that in Cygwin if you need to access drive C: you have to prefix your path with /cygdrive/c. The configuration is kept on the server where Yule runs; I registered the client and I'm in the process of tuning the exceptions for the files modified by Windows. samhain-4.1.4/docs/HOWTO-samhain+GnuPG.html0000644000175000017500000002757612615253277015224 00000000000000 HOWTO samhain+GnuPG

samhain file integrity scanner | online documentation


Using samhain with GnuPG



This document aims to explain how to use samhain with signed configuration and database files which are checked by invoking GnuPG.

Introduction

Samhain can be compiled to recognize PGP signatures on configuration and database files and to invoke GnuPG in order to check such signatures. (Note: while the application usually is referred to as GnuPG, the executable itself is called gpg).

If samhain is compiled with this option, then

  1. both the configuration file and the file signature database must be signed, and
  2. for both files the signatures must verify correctly,
  3. otherwise samhain will abort.

Prerequisites

  • Obviously you need gpg (GnuPG), and you must have created a key pair with:

       gpg --gen-key

    (it does not really matter which type of key, the defaults are ok).

    GnuPG uses a public-key algorithm: the key pair consists of

    • a secret key that is used for signing and stored in ~user/.gnupg/secring.gpg, and
    • a public key used for verifying the signature, and stored in ~user/.gnupg/pubring.gpg.

    The secret key obviously should be kept secret, while the public key can be published.

  • You need to compile samhain with support for GnuPG:

       ./configure --with-gpg=/path/to/gpg [more options]

Note 1: If compiled with support for GnuPG, the TIGER192 checksum of the gpg executable will be compiled into samhain, and the gpg executable will be checksummed (to verify its integrity) before invoking it. If you don't like this, you should add the configure option:

   --with-checksum=no

Compiling in the GnuPG checksum will tie the samhain executable to the gpg executable. If you upgrade GnuPG, you will need to re-compile samhain. If you don't like this, use '--with-checksum=no'.

Note 2: The mere fact that the signature is correct does not prove that it has been signed by you with your key - it just proves that it has been signed by somebody. Samhain can optionally check the fingerprint of the key that has been used to sign the files, to verify that your key has been used to sign the file(s). To enable this, use the configure option

   --with-fingerprint=FINGERPRINT

where FINGERPRINT is the hexadecimal fingerprint of the key as listed with

   gpg --fingerprint

Example


rainer$ gpg --fingerprint rainer
pub  1024D/0F571F6C 1999-10-31 Rainer Wichmann
     Key fingerprint = EF6C EF54 701A 0AFD B86A  F4C3 1AAD 26C8 0F57 1F6C
uid                            Rainer Wichmann
sub  1024g/9DACAC30 1999-10-31

rainer$ which gpg
/usr/bin/gpg

rainer$ ./configure --with-gpg=/usr/bin/gpg --with-fingerprint=EF6CEF54701A0AFDB86AF4C31AAD26C80F571F6C

Signing the files

The configuration file and the file signature database (created by running samhain -t init) must be signed manually using the command:

   gpg -a --clearsign --not-dash-escaped /etc/samhainrc
   mv /etc/samhainrc.asc /etc/samhainrc

Gpg will create a signed copy of the file, named file.asc. You need to rename (cp/mv) this signed copy to the original filename. After signing the configuration file, you can initialize the database and sign it likewise.

Note 1: The installation script will ask you to sign the configuration file upon installation.

Note 2: The gpg option --not-dash-escaped does not harm if used with the configuration file, but is only required for the file signature database.

TIP

In the subdirectory scripts/ of the source directory you will find a Perl script samhainadmin.pl to facilitate some tasks related to the administration of signed configuration and database files (e.g. examine/create/remove signatures). Use with --help to get usage information.

CAVEAT

When signing, the option --not-dash-escaped is recommended, because otherwise the database might get corrupted. However, this implies that after a database update, you must remove the old signature first, before re-signing the database. Without 'dash escaping', gpg will not properly handle the old signature. See the tip just above.

Example


root# gpg -a --clearsign --not-dash-escaped /etc/samhainrc

You need a passphrase to unlock the secret key for
user: "Rainer Wichmann"
1024-bit DSA key, ID 0F571F6C, created 1999-10-31

root# mv  /etc/samhainrc.asc /etc/samhainrc
root# samhain -t init
root# gpg -a --clearsign --not-dash-escaped /var/lib/samhain/samhain_file

You need a passphrase to unlock the secret key for
user: "Rainer Wichmann"
1024-bit DSA key, ID 0F571F6C, created 1999-10-31

root# mv /var/lib/samhain/samhain_file.asc /var/lib/samhain/samhain_file
root# samhain -D -t check

Make samhain verify the signature

This is the part where some people run into problems. The point is, when gpg is invoked by samhain, it must find the public key needed for verification. Gpg expects public keys in a file located at ~user/.gnupg/pubring.gpg where ~user is the home directory of the user as that gpg is running.

It is therefore crucial to include the public key corresponding to te secret key used for signing into the correct pubring.gpg file (this file can hold many public keys, e.g. of people sending you emails signed by them).

So which is the correct file? Here we have to consider two seperate cases:

  1. The client (or standalone) samhain daemon runs with UID 0 (i.e. root), thus the public key must be in ~root/.gnupg/pubring.gpg
  2. The server (yule) always drops root privileges (if started with), and runs as a non-root user. The username to use is compiled in, either with the configure option --enable-identity=USER, or by default as determined by configure (the first existing user out of the list yule, daemon, nobody). Thus, the public key must be in ~root/.gnupg/pubring.gpg (for startup) and in ~non_root_user/.gnupg/pubring.gpg (for reload with SIGHUP).

To import a public key into the public keyring (pubring.gpg) of another user, you can do:

   gpg --export KEY-ID > filename
   su another_user
   gpg --import filename

Note: samhain will invoke gpg with the options:

   --status-fd 1 --verify --homedir /homedir/.gnupg --no-tty -

and pipe the configuration/database file into gpg, similar to:

cat filename | /usr/bin/gpg --status-fd 1 --verify --homedir /root/.gnupg --no-tty -

(of course samhain does not invoke cat, or the shell; the example above just shows how to do the same from the shell command prompt).

Example for signature check

If you want to check the signature the same way samhain does, it should look like (note the GOODSIG and VALIDSIG keywords in the output):


root# cat /etc/samhainrc | gpg --status-fd 1 --verify --homedir /root/.gnupg --no-tty -
gpg: Signature made Sat Mar 15 16:08:21 2003 CET using DSA key ID 0F571F6C
[GNUPG:] SIG_ID 9hQvRhgjWLqyFzVOHi2b0uDmBFo 2003-03-15 1047740901
[GNUPG:] GOODSIG 1AAD26C80F571F6C Rainer Wichmann
gpg: Good signature from "Rainer Wichmann"
gpg:                 aka "Rainer Wichmann"
[GNUPG:] VALIDSIG EF6CEF54701A0AFDB86AF4C31AAD26C80F571F6C 2003-03-15 1047740901
[GNUPG:] TRUST_ULTIMATE

Troubleshooting

First and foremost, run samhain (or yule) from the command line, in non-daemon mode, and with the command-line option -p debug for debug-level output. This will print descriptive information on setup errors and/or relevant output from the GnuPG subprocess.

Output from the GnuPG subprocess is marked by [GNUPG:], and may show the following errors:

  • ERRSIG and/or NO_PUBKEY indicates that gpg did not find the public key to verify the signature. You should import that key into the keyrings of root and (for yule additionaly) the yule user.
  • BADSIG indicates that the public key was found by gpg, but the signature is invalid. Either the file has been modified after signing, or a previous signature has not been removed.
  • NODATA indicates that there is no signed data, i.e. the configuration or database file is not signed at all.
samhain-4.1.4/docs/#Changelog#0000644000175000017500000032515212724016577012754 000000000000004.1.4: * fix problems with wildcard pattern re-evaluation: - not stored if no match at startup - only one (the first) stored if same pattern for file and dir * fix problems with directory creation in inotify watched tree - recursive depth not decreased - watched as directory even when recursion depth should drop below zero 4.1.3: * on Cygwin, the AvoidBlock function is now off by default (problem reported by Fred C) * tighter sanity checks in sh_static.c * fix regression with '--enable-static' in sh_static.c (reported by amaiket). 4.1.2: * add options --enable-selinux and --enable-posix-acl for "hard fail" if libraries aren't found (requested feature) * fix wrong policy assignment when inotify is active and change occurs during a reload (reported by Bond) * fix failure to detect open UDP port for some daemons (reported by James) * fix broken 'rpm' and 'rpm-light' makefile targets (reported by Bond) * fix message for self-check 4.1.1: * fix problem with timezone calculation on month rollover for negative timezones (west of GMT; reported by Bond) * fix problem with rotated logfiles when content is always constant, i.e. checksum does not change (reported by Bond). * fix problem with baseline update on FreeBSD and probably other non-GNU/Linux systems (reported by L.Vasiliev) * fix bad check_libwrap() call in sh_xfer_server.c (reported by L.Vasiliev) 4.1.0: * fix quirks with Linux audit support * implement 'silent check' (requested feature) * fix call of self_check for exit on sigterm * fix safe_logger() - uses the logger utility with a non-posix option * fix missing reporting on shell expansion capability in --version * fix missing error message on invalid list for skipchecksum (reported by Bond) * fix missing definition for a sh_dummy_ var on BSD et al. (reported by Andrew) 4.0.0: * fix and document default settings for mounts check * new -w CL option to wait on scan completion * new option ReportCheckflags * enhance testsuite to cover new functionality * implement draft for change control integration: * new database format to store change flags * refactoring of db I/O and client/server code * option StartupLoadDelay * --create-database CL option * --outfile CL option * --binary, --list-filter CL options * --verify-database CL option * yulectl -c DELTA: command * option SetDeltaRetryCount * option SetDeltaRetryInterval * update documentation * remove old/unused code * fix compiler warnings with gcc 5.1.0 * update config.sub, config.guess 3.1.6 (08-06-2015): * Modify testcompile.sh to remove 'smatch' and use 'clang' instead. * Fix compile problems with clang. * Modify testcompile.sh to remove 'uno' and use 'cppcheck' for static checking * Move AC_CHECK_FUNCS( getnameinfo getaddrinfo ) behind the check for libsocket to have them found on Solaris * Fix IPv4-only bug in bind_addr use in retry_connect() * Add more debug code in connect_port() 3.1.5 (26-03-2015): * Fix IPv6 issue with portcheck (need to be able to specify IPv6 interfaces). * Fix minor issues with bugs in testing code * Add command line option '--server-host' to set the log server * In samhain.startLinux.in start script template, add code to read options from /etc/sysconfig/${NAME} for RedHat 3.1.4 (17-02-2015): * Add non-existent file to the regression test config * Fix erroneous call to sh_hash_init when a missing file is specified in the configuration * Fix buffer allocation for getgrnam_r for large groups (problem reported by Sergio B) * Search RPM in $HOME/rpmbuild if test -d _topdir fails (CentOS recommends '%(echo $HOME)/topdir', reported by E. Taft) 3.1.3 (01-11-2014): * Remove initgroups() from the popen call in unix entropy gatherer * Add error message for update mode if local baseline cannot be found 3.1.2 (07-08-2014): * Fixed incorrect memset in sh_checksum.c (sha256) * Circumvent a gcc compiler bug with inline asm (gcc 4.8) * Allow multiple exclusions for SUID check * Use calloc instead of malloc * Add overflow check in minilzo.c (but the potential integer overflow [CVE-2014-4607,LMS-2014-06-16-1] is irrelevant anyway because the function is never used on external data). * Fixed a minor bug in exepack_fill.c that was unearthed by the minilzo overflow check (the required buffer length information for the check wasn't provided) * Fixed incorrect logic in setting the ALLIGNORE flag (more specific directory / file directives were ignored) * Fix for tickets #358 (repetitive lstat warning about deleted directory) and #359 (reporting of deleted/added top level directory) * Fix a free() on NULL (harmless but avoids spurious warning) 3.1.1 (01-05-2014): * Disable inline asm on Cygwin (issue reported by Erik) * Fix sh_ipvx_is_ipv4 such that numeric hostnames are not incorrectly recognised as IP address (reported by A. Hofland) * Fix sh_ipvx_is_ipv6 3.1.0 (31-10-2013): * Add support for SHA2-256 checksum function * Drop support for --enable-khide on kernel version 3.x and above * Fix IgnoreAdded to anchor regex at beginning of path (reported by R.Lindner) * Add check to detect availability of pmap_getmaps() (missing in static library on recent Linux systems as reported by Ian Baldwin) * Fixes for Ubuntu 13.4: - no error msg for failing stat on /run/user/Username/gvfs in suidcheck - no error message for failing hardlink check on /run/user/Username - eliminate compiler warnings * Add option '--disable-asm' to work around a gcc issue in Debian unstable (reported by micah) * Remove option '-i' from mkitab in samhain-install.sh.in (reported by N. Kerski) 3.0.13 (11-06-2013): * Fix detection of nonfunctional /dev/kmem * Fix race condition in GrowingLogfiles policy that causes spurious reports (problem noticed by J. Daubert) 3.0.12 (16-05-2013): * Fix compiler warning in bignum.c (unused parameter) * Detect if /var/run is a symlink and /run exists * Fix for broken support for audit subsystem (reported by isquish) * Fix for incorrect use of sh_inotify_add_watch_later which causes a steady increase in memory usage (issue reported by Maxime V) * Fix for potential minor memory leak * Fix for bug in negated conditionals for config file (reported by M. Ward) 3.0.11 (08-04-2013): * Fix for compile error on HP-UX (reported by P. Alves) * Propagate ERANGE error from getgrxxx_r (issue raised by C. Feikes) * Fix reconnecting to database for Oracle * Add better logrotate handling for the GrowingLogs policy (search rotated log and verify it, don't report if this succeeds) * Add ability to create debian packages with preset password (use env var PASSWORD) * Add option KernelCheckProc (bool) to suppress kernel /proc test * Add option IgnoreModified to cover transient files that not only get added/deleted but also modified 3.0.10 (13-01-2013): * Revert to previous logic in samhain.c because it will block otherwise (reported by Alexandr Sabitov) 3.0.9 (21-12-2012): * Fixed a Cygwin compile warning * Change logic in samhain.c to make sure inotify doesn't cause excessive full scans * Add option IgnoreTimestampsOnly in Windows registry check (ignore changes if only timestamp has changed) * Fix the probe command (misses clients if their startup message has been missed) * Fix the RPM spec file for --enable-network=client and no password (reported by Mitch St Martin) * Fix build error with Linux audit (reported by Andy Jack) * Fix detection of utmpx.h (reported by D. Thiel) 3.0.8 (01-11-2012): * rename to 3.0.8 for release * useful exit status for samhainadmin.pl --examine 3.0.7a (25-12-2012): * add ability to create RPM with preset password (use env var PASSWORD) * fix the rpm-light makefile target * fix minor bug in samhain_setpwd.c (incorrect error message) 3.0.7 (25-10-2012): * update documentation for prelude * fix configure to properly search for Oracle Instantclient SDK * pass through TNS_ADMIN environment variable for Oracle * optimize audit rules automatically * zero out the html status file at server exit * don't check for assembly optimization unless linux or *BSD 3.0.6 (01-09-2012): * install logrotate script if /etc/logrotate.d is detected * new option --enable-suid for nagios * fix for --enable-ptrace: make the save_tv variable thread specific * fix bug in inotify code which made it follow symlinks (by [anonymous]) * fix two missing SH_MUTEX_LOCK(mutex_thread_nolog) (by [anonymous]) * fix for 'no such process' message from sh_fInotify_init_internal() (by [anonymous]) * fix for --enable-ptrace with threads (by [anonymous]) * option SetReportFile for writing out summary after file check 3.0.5 (11-07-2012): * fix xml format templates for registry check * fix database download on registry check init (reported by ldieu) 3.0.4 (01-05-2012): * fix verbosity of message for alerts on already deleted watches (set it to debug - suggested by xrx) * fix extraneous error messages about file not found from sh_fInotify_init_internal() (bug reports by xrx and aj) 3.0.3 (28-03-2012): * fix potential deadlock in sh_ext_popen() * make sure sh_processes_readps cannot hang forever * fix for deadlock if sh_processes_readps hangs * fix for deadlock if suid check and inotify are used together (reported by A. Jack) * fixed problem with samhain_stealth.c (handle input config files that don't end with a newline) * fixed compiler warnings for yulectl.c with stealth * fixed lacking support for O_NOATIME on 64bit linux 3.0.2a (23-02-2012): * Fix compile error on Solaris 10 3.0.2 (16-02-2012): * change sql init scripts to make bigint fields unsigned (problem reported by A. Sabitov) * patch by Andy Jack for issue with the --with-gpg option (hangs with high cpu load at startup) * call ./samhain-install.sh as /bin/sh ./samhain-install.sh in the RPM spec file, because /var might be mounted noexec (reported by GC) * fixed configure.ac for the case that --with-gpg and --enable-nocl are used (./samhain for gpg checksum; problem report by Andy Jack) * fixed a potential NULL pointer dereference in sh_inotify.c on systems where inotify is not available (reported by ) * fixed: the config file template mentions (in a comment) the non-existent directive SetLockPath instead of the correct SetLockfilePath (reported by Curtis). * fixed: the definition of O_NOATIME isn't seen in sh_files.c. 3.0.1 (07-12-2011): * fix a memory leak (reported by C. Westlake) * fix an uninitialized variable in the suidcheck code (problem reports by T- Luettgert and Kai) * fix a bug in the port check with --disable-ipv6 (reported by C. Westlake) * fix potential deadlock in sh_files.c (reported by S. Mirolo) * change Makefile.in to stop on compile error rather than at link stage (suggested by S. Mirolo) * fix compile errors caused by missing #define (pthread disabled) and wrong function call (OSX specific code), reported by S. Mirolo * fix warning by the llvm/clang static checker * fix compile issues on freebsd * handle (ignore) SIGPIPE more thoroughly * update config.guess, config.sub 3.0.0a (06-10-2011): * Fix compile-time issues on RHEL5 (reported by Thomas) 3.0.0 (01-11-2011): * Add support for the inotify API * If --disable-shellexpand is used, also disable setting the prelink/ps paths * Fix missing check_mask storage for glob pattern * Add support for integer keys in zAVL * Fix compiler warnings with gcc 4.6.1 (variables that get set but then remain unused) * Add more server-side debugging for IPv6 * Make kern_head compile with 3.x kernels 2.8.6 (20-09-2011): * Manual updated. * Added an option LogmonDeadtime to avoid repetitive reporting on correlated events. * Fix problems with timestamp handling in logfile correlation (problem reported by D. Dearmore) * List the policy under which a directory/file is checked * Option to use a textfile with a list of files for update * Fix --enable-db-reload option (reported by David L.) * Fix samhain_kmem compilation, need to compile under chosen name if --enable-install-name is used (reported by David L.) * Fix uninitialized string in error message (reported by mimox) 2.8.5a (16-06-2011): * Fix autolocal.m4 for new configure option 2.8.5 (15-06-2011): * Detect non-working /dev/kmem in configure script, and fix a bug in the samhain_kmem kernel module. * Fix wrong handler for LogmonMarkSeverity (reported by S. Chittenden) * Better protection against the 'intruder on server' scenario pointed out by xrx. Add option to disable shell expansion in configuration files, and check gpg signature earlier. * Support /opt/local/bin in the Unix entropy gatherer (suggestion by Sean Chittenden) * Cache timeserver response for one second (suggestion by Sean Chittenden) 2.8.4a (11-05-2011): * Fix for compile error with --with-prelude (reported by Sean Chittenden), missing regression test added * Fix for compile error with --enable-udp (reported by Sean Chittenden), missing regression test added 2.8.4 (30-04-2011): * Fix another reload bug in the log monitoring module * Add unit tests for IgnoreAdded/IgnoreDeleted configuration directives * Fix deadlock after reload when compiled with --enable-login-watch (reported by M. Teege and O. Cobanoglu) * Fix compile error for samhain_hide.ko with recent kernel * Include patch by J. Graumann to specify the location of the secret keyring with samhainadmin.pl * Fix potential timeout problem in sh_sub_stat_int() and propagate the error (issue reported by mtg) * Add support for X-Forwarded-For in apache logfile parser, add option 'RE{regex}' to insert arbitrary regex * New options PortcheckMinPort, PortcheckMaxPort for the open ports check 2.8.3a (23-03-2011): * Fix two 'label at end of compound statement' errors on FreeBSD (reported by David E. Thiel) 2.8.3 (22-03-2011): * init scripts: load samhain_kmem.ko before samhain starts * slib.c: eliminate mutex from sl_create_ticket() * sh_entropy.c: move pthread usage out of child * sh_hash.c, sh_pthread.c, sh_pthread.h: sh_hash_hashdelete() needs deadlock detection, may be called from within sh_hash_init() via atexit handler on error condition * sh_suidchk.c, sh_calls.c, sh_calls.h: need a nosub version of lstat() to use with relative path after chdir() * samhain.c, sh_calls.c, sh_calls.h: only run (l)stat() in subprocess after reading config file (to allow disabling) * sh_unix.c: run sh_sub_kill() in parent after forking the daemon * fix zeroing of result from getnameinfo() (problem reported by Richard) * fix spurious warnings about unsupported address family (reported by N Silverman) * option to run lstat/stat in subprocess to avoid hanging on NFS mounts (off by default) * fix Windows/Cygwin compile error (reported by A. Schmidt) 2.8.2 (16-02-2011): * add function to skip checksumming * Fix missing check for recursion depth >= 0 if not IgnoreAll * Fix hardcoded path for temp directory in deployment scripts * Fix bad compile on CentOS 4.8 with gcc 4.1.2 * Fix minor bug in check_samhain.pl (pointed out by J.-S. Eon long ago) 2.8.1 (17-11-2010): * Document handling of missing files with secondary schedule * Fix incorrect handling of missing files when secondary schedule is used (reported by Sergey) * Fix null pointer dereference in config parse handler for SetMailAlias (reported by Sergey) * Fix incorrect memset() in sh_kern.c (passed struct by value...), reported by Roman and Stefan * Fix 'make install' to create user-defined directory * fix minor issues noticed by T. Luettgert (test code assumes port 0/tcp is unused, wrong ifdef order (without impact on compilation)) * fix compile error on AIX 5.3 with --enable-login-watch, reported by M. El Nahass (time.h missing in src/sh_login_track.c) 2.8.0 (01-11-2010): * Support IPv6 * Add registry checking * Use auditd records to find out who did it 2.7.2c (23-09-2010): * Fix uppercase hostname problem in client/server communication 2.7.2b (05-09-2010): * Fix compile errors on Solaris 10 (reported by A. Saheba) 2.7.2a (23-08-2010): * rewrote rijndaelKeySched() in a more conservative way to fix compile problem on SLES 11. 2.7.2 (16-08-2010): * sh_utils.c: fixed an endianess issue that prevented cross-verification of email signatures (reported by A. Zangerl) * sh_login_track.c: fix compiler warning (ignored return value of fwrite) * sh_readconf.c: fix comparison of SeverityUserX string (reported by max__) * sh_processcheck.c: sh_prochk_set_maxpid: set retval on success (reported by max__) * fixed some compiler warnings on cygwin * sh_extern.c: As reported by T. Luettgert, gcc 4.4.4 on Fedora 13 will throw a warning if execve is called with a NULL argv pointer. Need to provide a dummy argp[]. 2.7.1 (07-06-2010): * samhain_kmem.c: fix compile problems * fix problems with config file parser: increase max. line length, support quoting/escaping of filenames (as in 'ls --quoting-style=c') * check for pcre_dfa_exec (not available in old versions of libpcre, reported by Shinoj) * patch to allow server to log client reports to prelude (by J. Ventura) 2.7.0a (09-05-2010): * fix /dev/kmem detection (reported by S. Clormann) 2.7.0 (01-05-2010): * sh_utmp.c, sh_login_track.c: additional login checks * sh_unix.c: use SIGTTIN as alternative for SIGABRT (SIGABRT seems not to work on AIX, reported by Peter) * sh_utmp.c: fix compile error without pthreads (inotify_watch used) * sh_kern.c, kern_head.c: fix some 64bit issues * dnmalloc.c: fix compiler warning (ignored ret value) * Fix LSB init script for kernel module * samhain_kmem kernel module for /proc/kmem added 2.6.4 (22-03-2010): * Don't read proc_root_iops in sh_kern.c (Problem report by H. R.) * Logfile check can check output of shell commands * Use data directory as default for logfile checkpoints * Fix broken checkpoint save/restore for logfiles 2.6.3 (10-03-2010): * Fix bug in mail module, recipients incorrectly flagged as aliases, which breaks immediate mail for 'alert' (reported by Jesse) 2.6.2 (28-01-2010): * Makefile.in: fix problem in deploy system caused by adding build number for debs in 2.5.9 (reported by roman) * add option for per-rule email alias in log monitoring module * sh_readconf.c: make keywords case-independent * sh_mail.c: on error, report full reply of mail server * sh_mail.c: report smtp transcript at debug level * make sure mail aliases are not emailed twice, and recipients cannot be defined after aliasing them * handle named pipes in log monitoring module (open in nonblocking mode, ignore read error if empty) * fix bug in the server function to probe for necessity of configuration reload for client 2.6.1b (23-12-2009): * fix missing include for sh_inotify.h in sh_inotify.c (reported by Ack) 2.6.1a (22-12-2009): * fix typo in code for older inotify versions without inotify_init1(), reported by Forll 2.6.1 (21-12-2009): * add a routine to log monitoring module to guess the proper year for timestamps without year (standard syslog) * add feature to automatically detect and report bursts of similar messages in log monitoring module * add feature to check for missing heartbeat messages in log monitoring module * cache UIDs/GIDs to reduce the number of lookups * use inotify to track login/logout (sh_inotify.c, sh_utmp.c) * support event correlation in log monitoring module * make sure host matching is done in a case insensitive way (reported by Tracy) * fix invalid use of mutex_mlock in src/sh_unix.c, function sh_unix_count_mlock() (reported by Remco Landegge). 2.6.0 (01-11-2009): * don't use statvfs() for process checking on FreeBSD * fix bug with parallel compilation of cutest in Makefile * sh_mem.c: fix deadlock in debug-only code * Evaluate glob patterns for each run of file check * Add compile option to disable compiling with SSP * Run SUID check in seperate thread * By default disable scanning ..namedfork/rsrc (deprecated by Apple) 2.5.10 (12-10-2009): * sh_suidchk.c: handle $HOME/.gvfs mount gracefully * slib.c: fix race condition caused by closing a stream and the fd 2.5.9c (01-10-2009): * move stale file record error message closer to problem zone * sh_port2proc.c: fix flawed logic for interpreting /proc/net/udp,tcp 2.5.9b (22-09-2009): * remove stale file record when creating handle, and raise diagnostic error to find origin of stale record * sh_port2proc.c: check /proc/net/upd6 for IPv6-only UDP sockets 2.5.9a (17-09-2009): * fixed a race condition in closing of file handles 2.5.9 (11-09-2009): * added code to generate directory for pid file, since it would get cleaned if /var/run is a tmpfs mount (problem reported by M. Athanasiou) * fixed a bug that prevented reporting of user/executable path for open UDP ports (issue reported by N. Rath) * added more debugging code 2.5.8a (18-08-2009): * fixed a bug in sh_files.c that would prevent samhain from running on MacOS X (reported by David) 2.5.8 (06-08-2009): * fixed a bug in the MX resolver routine which causes it to fail sometimes (issue reported by N. Rath). * fixed deadlock with mutex_listall in sh_nmail_test_recipients() if error occurs within sh_nmail_flush (problem reported by N. Rath) 2.5.7 (21-07-2009): * sh_userfiles.c: set userUids = NULL at reconfiguration (issue reported by U. Melzer) * if available, use %z to print timezone as hour offset from GMT in email date headers (problem reported by NP, solution suggested by TimB). * eliminate C99-style comments (problem reported by venkat) * fix bad variable name for AC_CACHE_CHECK * fix potential deadlock when external programm is called (problem reported by A. Dunkel) 2.5.6 (09-06-2009): * recognize fdesc filesystem on MacOS X for suid check (Problem reported by David) 2.5.5 (01-05-2009): * fix some warnings from gcc 4.4 (strict aliasing) * fix minor memory leak in process check * t-test1.c: change function names because of clashes with an AIX system header file * fix warnings with -fstack-check (too large stack frames) * fix for incorrect handling of hostnames in database insertion (reported by byron) 2.5.4 (04-03-2009): * fix for incorrect input check in SRP implementation (discovered by Thomas Ptacek) * option KernelCheckPCI to switch off check of PCI expansion ROMs 2.5.3 (25-02-2009): * disable dnmalloc on MacOS X, doesn't work properly * stat -> lstat in sh_unix_file_exists (OS X nameforks, report by David) * Fix problem in standalone trustfile, does not work correctly on group-writeable files (reported by David). * Option SetThrottle to throttle throughput for db download * Option SetConnectionTimeout to configure the client connection timeout configurable * Provide getrpcbynumber, getservbyname implementations to avoid dependencies with static linkage * Fix missing sh.host.(system|release|machine) on FreeBSD, reported by D.Lowry * New option SetMailPort to allow setting of SMTP port (patch by lucas sizzo org) * allow POSIX regexes for filters * consolidate filtering code from sh_extern.c, sh_(n)mail.c * rewrite mail subsystem to allow individual filtering for recipients * allow shell expansion for values of config file options * allow list as value for option PortCheckInterface * fix bug in trustfile.c (with slapping on "/../" for symlinks) * lock baseline database upon writing 2.5.2b (29-01-2009): * turn warnings into errors in the compile test suite * fix missing define in sh_portcheck.c to eliminate compiler warning (reported by joerg) 2.5.2a (26-01-2009): * fix problem building deb package (bit rot; reported by joerg) 2.5.2 (22-01-2009): * samhain.c: report module failure with positive offset * sh_database.c: parse numerical fields into ulong * fix regression test script for postgresql * fix regression test script for SELinux/ACL test * fix reporting of user for open ports to prelude * report process pid for open ports * replace _exit() by raise(SIGKILL) b/o pthread problem * new option LooseDirCheck ([false]/true), request by Alexander * improved help output of samhain_stealth (as suggested by Michael Athanasiou) * new option ProcessCheckIsOpenVZ ([false]/true) 2.5.1 (07-12-2008): * workaround for freebsd7 amd64 lossage (compiler toolchain, no mmap to 32bit address space) * samhain-install.sh: check for presence of stealth_template.ps before trying to create it * use -Wno-empty-body if supported to suppress warnings about glibc pthread_cleanup_pop implementation * fix text relocations for i386 in src/sh_tiger1.s * implement server->client SCAN command to initiate file check * implement @if / @else conditionals with more tests in config file * new option SetDropCache to drop checksummed files from cache * report process/user for open ports on FreeBSD (code lifted from FreeBSD sockstat.c) * fix for config reload issue with stealth mode (reported by siim) * add -fstack-protector flags to LDFLAGS * cygwin fix: don't use dnmalloc, doesn't work with pthreads * cygwin fix: make trust check in samhain-install.sh return zero * improved diagnostics for file read errors * fixed script permissions (754 -> 755), reported by Christoph * constness patch by Joe MacDonald * GnuPG key ID patch by Jim Dutton * sh_kern.c: more error checking for reads from kernel 2.5.0 (01-11-2008): * dnmalloc.c: fix inconsistent chunksize on 64bit systems * fix improved error reporting for failed fstat in checksumming * report process/user for open ports (Linux only currently) * fix deadlock on exit in sh_hash_init() * fix --enable-mounts-check for FreeBSD 7.0 (no MNT_NODEV anymore) * log monitoring support * fixed constness in trustfile interface * remove libprelude 0.8 support (obsolete) * sh_forward.c: increase TIME_OUT_DEF to 900 secs * dnmalloc.c: initialize rc in dnmalloc_fork_child(), reported by B. Podlipnik 2.4.6a (09-10-2008): * fix compile problem on Fedora 9 (reported by pierpaolo), 'struct ucred' in sh_socket.c requires _GNU_SOURCE 2.4.6 (27-08-2008): * fix compile failure on win2k/cygwin (sh_unix_mlock prototype), reported by jhamilton * fix potential deadlock with dnmalloc upon fork() * fix non-portable use of 'hostname -f' in regression test suite (reported by Borut Podlipnik) 2.4.5a (18-08-2008): * fix compile problem in dnmalloc.c (remove prototypes for memset/memcpy), problem reported by Juergen Daubert 2.4.5 (07-08-2008): * testscripts: 'chmod -R' -> 'chmod -f -R', since Solaris 10 bails out on a chmod on a dangling link * fix bug in check_samhain.pl nagios script (J.-S. Eon) * use the UNO static checker * compile as position independent executable (PIE) * handle EINPROGRESS error (Windows/cygwin issue) * make sure every function uses less than one page of stack (proactive security against gap jumping, Gael Delalleau) * use dnmalloc instead of system malloc (proactive security against heap buffer overflows) * fix dnmalloc bugs and portability problems * check for compressBound, since older zlibs don't have it 2.4.4 (30-04-2008): * sh_database.c: fix maximum size of sql query string, maximum size of strings in struct dbins_ * sh_hash.c: fix maximum size of message string * fix typo in the base64 decoder * fix 'make cutest' for parallel compiling * fix compile warnings with -Wstrict-prototypes * sh_static.c: override getgrgid, getpwuid for libacl * fix more warnings about variables clobbered by 'longjmp' or 'vfork' (due to library internal handling of mutexes) * fix configure warning about unused datarootdir * configure.ac: warn, but accept nonexistent tmp dir (Problem reported by Brian) * sh_unix.c: undef P_ALL, P_PID, P_PGID before including sys/wait.h (compile problem reported by Reputation) * syslog function tested ok with Syslog Fuzzer v0.1 by Jaime Blasco (c) 2008 * slib.c: call fflush when writing trace to file * sh_readconf.c: don't set OnlyStderr to false if gpg (problem reported by Irene Reed) * fix unconditional removal of pid file in atexit handler (bug reported by Brian) * fix invalid free() in sh_unix_checksum_size() * sh_processcheck.c: workaround for stupid OpenBSD bug (returns ENODEV instead of EAGAIN, because fgetc does fcntl(0,F_SETFL,O_NONBLOCK) [ENODEV] internally), problem reported by Roman R. * fix buf that cause incomplete reporting of modified symlink if symlink has changed and both old and new paths are >48 bytes * fix bug that prevented mount check from running in one-shot mode * enable mount check for openbsd * fix processcheck default options and test script for openbsd * option --list-file to list content of file (if saved) * sh_tools.c: use strcasecmp in reverse lookup since DNS is case insensitive (bug reported by Phil) * fill content if MODI_TXT, zlib compress, base64 encode and add as link_path in sh_unix.c; add to report in sh_hash.c * testsuite: add test for gpg fingerprint option * sh_extern.c: add 'CloseCommand' for syntactic sugar, add in testsuite 2.4.3a (12-02-2008): * fix compile error caused by open() with O_CREAT and no third argument (reported by J.-S. Eon) 2.4.3 (31-01-2008): * sh_kern.c: don't require asm/segment.h for kernel check module * use global var with pid of initial thread instead of getpid(), since LinuxThreads returns different value in each thread (problem reported by Steffen Mueller) * sh_kern.c: no inode check for pci rom (creates spurious messages) * slib.c: eliminate prototype for vsnprintf (compile problem reported by eddy_cs) * Makefile.in: fix missing dependency on 'encode' for $(OBJECTS) (reported by Matthias Ehrmann) 2.4.2 (17-01-2008): * fix broken option --with-checksum (reported by halosfan), regression test added * change HP-UX default optimization to +O2 since +O3 breaks cutest unit testing framework * put result vector of rng in skey struct * fix more compiler warnings, and a potential (compiler-dependent) NULL dereference in the unix entropy collector * fix some compiler warnings * use -D_FORTIFY_SOURCE=1 -fstack-protector-all instead of -fstack-protector * always add PTHREAD_CFLAGS to LDFLAGS * sh_tiger0.c: checksum functions return length of file hashed, needed to fix GrowingLogfile bug (researched by siim at p6drad dash teel dot net) * sh_static.c: fix more 'label at end of compound statement' (SH_MUTEX_UNLOCK closing brace; reported anonymously) * make sh_hash.c thread-safe * remove plenty of tiny allocations * improve sh_mem_dump * modify port check to run as thread * new option PortCheckSkip to skip ports * fix unsetting of sh_thread_pause_flag (was too early) 2.4.1a (28-11-2007): * fix overwrite of ErrFlags (functionality bug) 2.4.1 (26-11-2007): * security fix: regression in the seeding routine for the PRNG (detected by C. Mueller) * regression test added for PRNG seeding routine * fix problem with PCI ROM check (spurious messages about modified timestamps, reported by S. Clormann) 2.4.0a (08-11-2007): * fix compile failure with --enable-static (reported by S. Clormann) * fix potential deadlock if SIGHUP is received while suspended 2.4.0 (01-11-2007): * eliminate alarm() for I/O timeout (replaced by select) * use getgrgid_r, getpwnam_r, getpwuid_r, gmtime_r, localtime_r, rand_r, strtok_r if available * protect readdir(), getpwent(), gethostname() with mutexes (readdir_r considered harmful) * make checksum/hash, entropy, rng functions reentrant * use thread-specific conversion buffer for globber() * fixed compile problems and problems with test suite * modify login watch to run as thread * modify process check to run as thread 2.3.8 (03-10-2007): * new option PortCheckIgnore = interface:portlist 2.3.7 (13-09-2007): * Makefile.in: fix 'make deb' target, wrong name of config file written to debian/conffiles (reported by marc) * configure.ac: fix incorrect order of with-prelude, enable-static (libprelude test was always without -static) 2.3.6 (06-09-2007): * added yuleadmin.pl script contributed by Riccardo Murri * fix compile error with -f-stack-protector on some systems (reported by marc); we now check for libssp * fix local DoS attack on BSD systems lacking getpeereid() (reported by Rob Holland). * fix yulectl password reading from $HOME/.yulectl_cred, erroneously rejected passwords with exactly 14 chars (reported by Jerry Brown) * introduce 'fflags' flag for suid files to detect new files already found in regular file check (problem reported by J. Crutchfield); also add regression test to ascertain that files in baseline database are not quarantined erroneously * sh_hash.c: replace check for prefix 'K' with check for not prefix'/' to allow for arbitrary module-specific store/lookup in db * replace 'visited', 'reported', 'allignore' with generic 'fflags' field * sh_cat.c: reduce priority of MSG_TCP_RESET to avoid spamming if port checking is used on same host as server (reported by kadafax) * Install.sh: don't use --separate-output with non-checklist widgets (problem discovered by D. Denton) * sh_gpg.c, sh_userfiles.c: use sh_getpwnam et al. wrappers 2.3.5 (20-06-2007): * sh_portcheck.c: try to tear down connections more gracefully (request by S. Petersen) * fix incorrect handling of files with zero size in GrowingLogFiles (problem reported by S. Petersen) * fix incorrect encoding of null checksums in stealth mode * sh_hash.c: fix repeated printing of acl/attributes in database dump * sh_unix.c: fix option useaclcheck ignored if both useaclcheck and useselinuxcheck are supported 2.3.4 (01-05-2007): * sh_processcheck.c: fix missing init of sh_prochk_res array before check (leads to degrading functionality over time and 'fake pid' warnings; reported by D. Ossenbrueggen and soren dot petersen at musiker dot nu) * sh_processcheck.c: fix memory leak * sh_kern.c: for 2.6.21+ don't check proc_root_lookup (not possible anymore? proc_root_inode.lookup != proc_root_lookup) * sh_extern.c: flush streams before forking (problem if [Prelink] used together with prelude logging, reported by M. deJong) * fixed compilation of kern_head (regression cause by cross-compiling fix; problem reported by S. Clormann) * more typos fixed (reported by John Horne) 2.3.3 (27-03-2007): * fixed typos in configure.ac and manual (reported by John Horne) * don't use mysql_options on x86_64, since libmysql is broken * fixed cross-compiling (patch by Joe MacDonald) * refactor sh_kern.c, sh_suidchk.c * fix bug with leading slashes in linked path of symlinks within the root directory * sh_kern.c: check PCI ROM (Linux), refactor code * move file descriptor closing more towards program startup * kernel check: support OpenBSD 4.0 (wishlist) * fix samhain_hide module (in-)compatibility with recent kernels (reported by Jonny Halfmoon) 2.3.2 (29-01-2007): * fix regression in full stealth mode (incorrect comparison of bytes read vs. maximum capacity), reported by B. Fleming 2.3.1a (21-01-2007): * fix incorrect use of sh_gpg_fill_startup if option --with-fp is used (reported by zeroXten) 2.3.1 (21-01-2007): * fix bug that may cause accidental closure of yule TCP socket (problem reported by B. Masuda) * fix sh_kern.c for kernel 2.6.19 (reported by S. Clormann) * don't use sstrip in 'make deb', since dh_shlibdeps uses objdump (reported by B. Masuda) * rm report.pl from rules.deb.in (reported by B. Masuda) * samhainctl(): longer timeout (bad status reporting at startup, reported by Phil and by Dan Track) * sh_portcheck.c: make connect errors more descriptive * sh_portcheck.c: fix ignored setting of PortCheckActive * sh_processcheck.c: add statvfs, and wrap for EINTR * sh_portcheck.c: add wrappers for EINTR * report user and executable for hidden processes * fix update failure if reportonlyonce = false (reported by D. Strine) * fix compile error in sh_portcheck.c (problem on cygwin reported by J. D. Fiori) * check filenames ending in space (also for utf8 spaces) * check and escape csv formatted db listing * cache results of sl_trustfile_euid() * trustfile: use 4096 for MAXFILENAME, switch to strncpy * CL option -v|--version for info on version and compiled-in options 2.3.0a (01-11-2006): * fix compile failure with portcheck + stealth (reported by lucas) 2.3.0 (01-11-2006): * fix concurrency for inserts in oracle db * add acl_(new|old) to database schema * check for selix attributes and/or posix acl * new option UseSelinuxCheck (bool) * new option UseAclCheck (bool) * regression tests for above * add module to check for open ports * add module to check processes (hidden/fake/missing) * use const char* for argument of module configuration callbacks 2.2.6 (31-10-2006): * fix missing support for MacOX X init script (reported by Daniel Kowalewski) * fix error about non-readable file with no checksum required * fix server warning about 'no server name known' * fix 'make deb' makefile target * fix default export severity for server 2.2.5 (05-10-2006): * fix broken Install.sh, reported by Alexander Kraemer * workaround for glob(3) sillyness on MacOS X (reported by David) * fix for broken resorce fork check (reported by David) * fix for broken compilation on cygwin (reported by Elias) 2.2.4 (03-09-2006): * add regression test for the GrowingLogFiles issue to test suite * fixed sh_unix.c: bug in database init if GrowingLogFiles used with signed database (reported by Timothy Stotts) * bug in manual fixed (incorrect documentation of --enable-user, noticed by M. Brown) * rc.subr compatible init script for FreeBSD/NetBSD * improve routine to find rpm after build * add netbsd rc file from Brian Seklecki (taken from pkgsrc-wip) * fix error in manual (location of lock file) * fix bug with SuidExclude (files in directory were still checked) 2.2.3 (31-07-2006): * fix samhainadmin.pl: check for gpg-agent running if use-agent is set (ticket #28 by anonymous) * fix stealth mode (regression in parser), problem reported by Joschi Kuphal * fix minor typo in sh_database.c (compile problem reported by Joschi Kuphal) 2.2.2 (17-07-2006) * minor fixes for regression test scripts * minor updates to the manual (suggested by Brian A. Seklecki) * fix sh_kern.c, kern_head.c: kernel rootkit detection for 2.6.17+ (problem reported by Leonhard Maylein) * fix samhain_hide.c for 2.6.17+: use module_param() if MODULE_PARM is not defined 2.2.1c (11-07-2006) * fix sh_extern.c: sh_ext_add_default() cast to (void) was too early (Solaris 8 build failure reported by Jesse) * fix sh_unix.c: wrong prototype for sh_unix_mlock() if HAVE_BROKEN_MLOCK (AIX 5.2 build failure reported by Jonathan Kaufman) 2.2.1b (20-06-2006): * fix compile error on SuSE 10.1 (reported by Leonhard Maylein) 2.2.1a (15-06-2006): * fix compile error on i686/MacOS X (reported by Andreas Neth) 2.2.1 (13-06-2006): * fix gcc 4 warnings and build failure on x86_64 (debian bug #370808) * fix compiling with Oracle (noticed by Colapinto Giovanni) * fix configure.ac for most recent autoconf version (debian bug #369503) * fix a regression that would make impossible local updates w/clients * fix a few missing '\n' in sh_getopt.c * sh_kern.c: fall back on mmap() if read() fails on /dev/kmem * fix Solaris package creation * recognize Solaris doors and event ports * fix the idmef_inode_t patch: provide required info to avoid stat() * fix bug on database update: fill in dev and rdev fields * fix get_file_infos() in sh_prelude.c: avoid premature return * GCC_STACK_PROTECT_CC: AC_TRY_COMPILE -> AC_TRY_LINK * deploy.sh: allow to set a group for hosts upon installation * patch by Yoann: fix an issue when setting the idmef_inode_t object * fix memory leaks in error paths in sh_prelude.c * fix concurrent inserts with postgres in sh_database.c * code cleanup * fix manual version in spec file, first noticed by Imre Gergely 2.2.0 (01-05-2006): * patch by Jim Simmons for samhainadmin.pl.in * fix testsuite portability problems * fix md5 endianess problem detected on HP-UX 11i / PA-RISC 8700 * fix potential NULL dereference in sh_utmp_endutent() * patch by Neil Gorsuch for suidchk.c (do not scan lustre, afs, mmfs) * fix sh_ext_popen (OpenBSD needs non-null argv[0] in execve) * fix make_tests.sh portability (echo '"\n"' does not work on OpenBSD) * fix bug in sh_utils_obscurename (check isascii) * scan h_aliases for FQDN if h_name is not * add copyright/license info to test scripts * add copyright/license info to deployment system scripts * support server-to-server relay * new CL option --server-port * minor improvements in manual * patch by Yoann Vandoorselaere for sh_prelude.c * allow --longopt arg as well as --longopt=arg * verify checksum of growing log files (up to previous size) * rewrite of the test suite * added a bit of unit testing * minor optimizations in various places * optimized implementation of tiger checksum algorithm * read in 64k blocks (faster than 4k) * sh_unix.c, sh_hash.c: support file flags on *BSD, update Linux file attribute code * kern_head: fix compilation of kernel check module on OpenBSD * updated samhainrc.linux, samhainrc.freebsd * sh_unix.c: fix setrlimit (RLIMIT_NOFILE, ..) * sh_files.c: fix missing use of flag_err_info * sh_tiger0.c: remove repetitive use of mlock * slib.c: remove fcntl's from sl_read_timeout (caller sets O_NONBLOCK), add function sl_read_timeout_prep 2.1.3 (13-03-2006): * fix compile problem in slib.c (reported by Lawrence Bowie) * fix bug with combination of one-shot update mode and file check schedule (reportedby Dan Track) * improved the windows howto according to suggestions by Jorge Morgado * fix samhain_hide kernel module for new linux kernel versions * fix minor problem with dead client detection (problem reported by Michal Kustosik) 2.1.2 (10-01-2006): * fix startup error with combination of gpg+prelude 2.1.1a (22-12-2005): * fixed a stupid bug in sh_files.c (break if file = dir) 2.1.1 (21-12-2005): * sh_calls.c: protect sh_calls_set_bind_addr against overriding * comINSTALL, updateDB: use locking * samhainadmin.pl: use locking * fix typos in samhainrc.solaris (noticed by Robby Cauwerts) * improve zAVLSearch (remove redundant strcmp) * use AVL tree in sh_files.c instead of linked list (better scaling) * fix bug with suidcheck (no update/check in one-shot mode with schedule instead of check interval; noticed by R. Rati) * fix for problem with '-t update -i' if daemon mode (problem report by Peter van der Does) * fix for bug in sh_util_ask_update (two returns were required ...) 2.1.0 (31-10-2005): * minor fix for cross-compiling with --with-kcheck * sh_forward.c: handle bad fds in the select() fd sets (reported by hmy) * sh_extern.c: fix debugging code * slib.c, sh_calls.c, sh_calls.h: improve handling of O_NOATIME (reported by Gabor Kiss) * makefile.in: fix for solaris package creation * sh_mail.c, sh_readconf.c: mail filtering options * sh_database.c: Oracle reconnect on connection failure (bug report by Alexander A. Sobyanin) * sh_unix.c: don't purge MYSQL_UNIX_PORT environment variable (problem reported by Peter) * sh_calls.c: fix for a HP-UX accept() problem caused by the gcc4 fix * fixes for gcc 4.0.2 compiler warnings * ability to use daemon mode together with update (wishlist Yoan Vandoorselaere) * fixes for debugging 2.0.10a (22-08-2005): * fix for overlapping directory check specification (reported by Bub) 2.0.10 (21-08-2005): * fix for segfault (free() on a constant string) with libprelude (problem reported by Grae Noble) * upgrade FreeBSD kernel check to 5.4, minor fixes * useful script for users of Linux kernel check (contributed by marc heisterkamp) * documentation improvements (suggested by Brian Seklecki and Robby) 2.0.9 (25-08-2005): * samhain_erase.c: add #define for NULL * sh_suidchk.c: fix incorrect use of escaped filename * sh_prelude.[ch], sh_readconf.c: configurable mapping from samhain severity to prelude severity * sh_unix.h: second arg of gettimeofday should be NULL * sh_files.c: fix checking of directory special file (use specified policy, not that of parent dir, problem found by Brian A. Seklecki) * sh_entropy.c: longer timeout for entropy collector * sh_socket.c, sh_forward.c: allow probing of clients for necessity of configuration reload * yulectl: minor fixes, option -v (verbose), new command PROBE * fix 'File not found' messages for files flagged with IgnoreMissing * sh_database.c: strip newline from oracle error messages * sh_files.c: fix rsrc fork issue with MacOS X Tiger (reported by A. Koren) * never compute checksum if not checked (problem report by D.Hughes) * sh_prelude.c: cleanup and bugfix by Yoann * sh_hash.c: for prelude, make sure mode is supplied with user/group and vice versa * sh_prelude.c: provide proper FileAccess objects (bug report by Mihai Ilinca) 2.0.8 (03-07-2005): * configure.ac: use $LIBPRELUDE_PTHREAD_CFLAGS rather than $LIBPRELUDE_CFLAGS (bugfix by Yoann) * samhain.spec.in: remove support for chkconfig (it's too buggy). Strangely, if invoked as install_initd it behaves sanely ... * src/sh_err_log.c: fix key input (this time for real) * fix --with-altlogserver (bug from 2.0.7b) * remove server socket in start/stop script 2.0.7e (not released): * Makefile.in: introduce a total of 6 sec delay for 'make' utilities that use 1 sec resolution, and consider target out-of-date if timestamp(target) = timestamp(dependency) ... * src/sh_err_log.c: fix key input * another fix for yulectl (use pwent->pw_dir) * dsys/comINSTALL, dsys/comUNINSTALL, dsys/comBUILD: fix PATH 2.0.7d (not released): * one more fix for the spec file (stupid rpm finds tags in comments!!!) 2.0.7c (not released): * test/testrun_1b.sh, test/testrun_2b.sh: use $GPG_PATH * dsys/comINSTALL, dsys/funcDB, dsys/funcINSTALL: some bugfixes * samhain-install.sh.in: fix test -z $verbose * sh_hash.c: speedup database reading * Makefile.in: fix the problem that BSD make would make too much * deploy: yulerc.clients -> yulerc.install.db, provide $defdatabase for backward compatibility * deploy: allow for comma in client_install_date 2.0.7b (not released): * hp_ux.psf.in: fix psf file * dsys/comINSTALL: fix $yule_date -> $yule_data * Makefile.in: fix 'make depot' * sh_tools.c, sh_unix.c: fix detection of open file limit * sh_readconf.c: reset read_mode after reading conf file * yulectl.c: better error messages, use homedir from getpwuid(geteuid) * init/samhain.startLSB.in: fix misleading message in lsb init script * sh_forward.c: better display for nonce u in debug mode * sh_tiger*.c: fix checksum for HP-UX 64bit * samhain.c: don't fetch database twice * configure.ac: accept nodename for --with-logserver=... * samhain_setpwd.c: return proper exit status for samhain_setpwd * respond to SIGTERM on initializing * fix problems with samhainadmin.pl * sh_utils.c: fix bug with AddOKChars (found by Karol) 2.0.7a (not released): * remove 'df' from entropy gatherer (NFS may hang) * modify va_copy check (doesn't work with HP-UX PA64 compiler) * fix compile warnings in sh_database.c * samhain-install.sh.in: check for /usr/bin/false in /etc/shells * fix install-boot on HP-UX * aclocal.m4: fix configure CL parsing to recognize VAR=VALUE 2.0.7 (11-06-2005): * yet another fix for the spec file (use internal dependency generator) * sh_error.c, sh_prelude.c: init libprelude after open fds are closed * error message if queue is full * fix two compiler warnings on HP-UX * fix sh_mail.c for Interix (no resolver routines) * fix sh_unix_initgroups2() if no initgroups() function (bug reported by Geries Handal) * remove references to 'struct timezone' (Interix; problem reported by Geries Handal) * init/stop for prelude on SIGHUP * sh_cat.h: fix a stupid bug with messages classes * manual: new section on nagios (with help from kiarna), more on prelude * sh_prelude.c: cleanup and improvements (Yoann Vandorselaere) * default prelude profile name now is 'samhain' (lowercase) * sh_readconf.c: new option PreludeProfile (by Yoann Vandorselaere) * remove obsolete check for linux/module.h, linux/unistd.h * remove dependency on virtual/glibc in gentoo ebuild (problem reported by Willis Sarka) 2.0.6 (01-03-2005): * sh_prelude.c, configure.ac, aclocal.m4: support for libprelude 0.9 (Yoann Vandoorselaere) * sh_html.c: fix bug with entry.html template (reported by Stephane Sanchez) * Install.sh: fix mandir option (reported by Rodney Smith) * Fixed Linux/64bit bug in definition of EUIDSLOT * New targets 'make depot', 'make depot-light' (HP-UX, untested) * Use sstrip for RPMs and DEBs (automatic stripping disabled) * Fix aclocal.m4 for autoconf 2.59 (missing $ac_cr_alnum et al., problem noticed by Yoann Vandoorselaere) * Modify samhain.spec.in to disable automatic stripping upon install * Fix deploy.sh + '--enable-gpg', and fix 'make rpm' and 'make deb' for '--with-khide' (problems reported by Mark) * Fix compile error in sh_tools.c on HP-UX 10.20 (problem reported by Dennis Boylan) * Runtime configuration of server listening port (wishlist) * Runtime configuration of server listening interface (wishlist) * Ignore SIGTTIN (consistency) * Use SIGTTOU to force file check (wishlist) 2.0.5b (01-04-2005): * Fix build problem b/o timestamp on stamp file 2.0.5a (16-03-2005): * Fix problem with 'make rpm' (reported by Dirk Brümmer) 2.0.5 (02-03-2005): * Fix bug with partial reads from clients in server (bug report by Brian) * Support gpg checksum bootstrap with yule * Support mount option check on HP-UX * For MAIL FROM, use 'example.com' as domain part if hostname is numeric (problem reported by Eric Raymond) * The HOWTO-write-modules has been updated. * Convenience functions to insert data in database have been added. * Use int0x03 only on i386 in sh_derr() (portability problem reported by John Mandeville) 2.0.4 (09-02-2005): * Fixed broken 'make deb' (problem report by olfi) * Fixed minor bug in test scripts (detection of gmake vs. make) * Fixed Tru64/OSF compile warnings (reported by B. Terp) * Normalize list parsing to allow comma, space, and tab as separators * Some more descriptive error messages in kern_head.c * Absolute path to utilities in init/samhain.startLinux.in * Fixed is_root variable in deploy.sh * Fixed 'deploy.sh info' * Fixed 'deploy.sh install' client startup * Fixed 'make tbz': don't remove ebuild scripts in 'make dist' (issue reported by W. Sarky) 2.0.3 (14-12-2004): * Fix CPPFLAGS with mysql/postgresql (repoted by P. Smith) * Fix missing sys/time.h include in slib.c (reported by Jonas) * Workaround for file closing problem with Prelude+GPG * Fixed memory leak with Prelude. * Fixed bug in samhain_stealth (PGP signature not correctly retrieved from hidden configuration; report and patch by V. Tuska) * Added Perl script to concatenate file signature database files * Fix compile error with combination of --enable-nocl and --enable-stealth (reported by Zdenek Polach) * Fix bug in dsys/initscript with --enable-nocl * Fix declaration of sh_kern_timer() * Fix missing Mounts+Userfiles options in appendix of manual * Updated the README (bug report by H. Franzke) * Fix some compiler warnings 2.0.2a (09-11-2004): * Fixed OoM condition when client rc file not found (reported by Eilko) 2.0.2 (08-11-2004): * Fixed buffer overflow in sh_hash_compdata() (only in 'update' code) * Fixed uninitialized variable in sh_mail_msg() (problem reported by Michael Milvich) * Fixed potential NULL pointer dereference in sh_hash_compdata() 2.0.1 (01-11-2004): * Fixed compilation bug reported by jue (--with-kcheck broken). * Fixed start option (bug reported by sanek). Behaviour wrt. environment variables depended on the way the daemon was started. 2.0.0 (31-10-2004): * The deployment system has been rewritten from scratch in a cleaner and more modular and extensible way. Deployment of native packages is supported now. * The build system has been revised. Building outside the source directory is supported now. * Support for checksumming of prelinked executables / libraries has been added. * The configure script now checks for the SSP/ProPolice patch in GCC, and enables it if present. * The install-boot option in samhain-install.sh has been fixed (use absolute paths for sbin utilities). * A nagios plugin (scripts/check_samhain.pl) has been added. * The LSB (Linux Standard Base) init script has been fixed (the output was incorrect). * Fetching of built binary packages has been fixed ($(PACKAGE)->@install_name@). * For files in proc, the timeout has been reduced, and no error messages are issued upon timeout. * A function has been added to print out full details for missing files if encountered while in sh_files(). * The reporting for SuidCheck has been fixed (incorrect policy noticed by JiM). * On Linux, SuidCheck does not report on files marked as candidates for mandatory locking (group-id bit set, group-execute bit cleared). * Fix for oracle init script (by Matt Warner) 1.8.12b (11-10-2004): * fix bug in MSG_MSTAMP (%ld -> %lu) * fix bugs in sh_suidchk.c (%ld -> %lu), check fopen for NULL, mkdir mode for quarantine directory * fix the fix for modlist_lock search in System.map 1.8.12a (01-10-2004): * fix bug in samhain-install.sh.in (only occurs on Solaris), reported by J. Roland 1.8.12 (27-09-2004): * fix compile bug with --enable-static + --with-database=postgresql * fix search for modlist_lock in System.map * password auth for yule command socket (request by D. Kocic) * more info about pending/sent commands to clients 1.8.11 (30-08-2004): * fix static linking on Linux by use of replacement routines from uClib - however, this means, there is no NIS support anymore * new option AddOKChars=... to modify the set of characters for filenames considered 'obscure' * new option HardlinkOffset=... to specify an offset from the canonical hardlink count for a directory * fix some warning with HP 11.23 native compiler * fix minor OpenBSD portability problems (EIDRM, compiler warning) * samhainrc.5, samhain.8: updated the man pages * sh_unix.c, sh_files.c: ignore 'no user/group' and 'obscure name' for AllIgnore * sh_kern.c: fix 'update' to display modifications * sh_kern.c: fix bug with IDT check (spurious alerts b/o uninitialized fields) * stealth kernel modules: fix for linux 2.6, fix redefine of KERNEL_VERSION * warn about stealth kernel module problem with 2.6 in manual * sh_unix.c: remove some cruft * fix a typo in the manual (noticed by J. Rubin) * configure.ac: re-order output from libprelude-config (required for static linking - problem reported by E. Neber) * kern_head.h, kern_head.c: fixes for Linux 2.6 kernel 1.8.10b (13-07-2004): * fix incorrect usage of 'retry_msleep()' in sh_kern.c (reported by Pat Smith) 1.8.10a (13-07-2004): * depend-gen.c: fix for FreeBSD 'make' which does not understand the dependencies ... (problem reported by David Thiel) 1.8.10 (13-07-2004): * sh_unix.c/sh_unix.h: fix defaults for 'GrowingLogFiles' policy (bug report by VZoubkov) * fix some warnings (unreachable statement) with HP-UX native compiler * kern_check.c: silence warning about 'sendfile' for 4.10 (noticed by Ryan Beasley) * modify depend-gen.c to ignore sh_gpg_chksum.h * add a non-plaintext version of GPG_HASH (sh_gpg_chksum.h) * .. and for fingerprint * sh_suidchk.c: fix some compiler warnings on solaris * allow commas to separate multiple entries in a RedefXXX= directive * replace sleep/usleep with nanosleep wrapper function * replace alarm() for read timeout with select() in sl_read_timeout (should fix bug reported by Scott Kelley) * increase lstat/open timeout to 6 sec 1.8.9 (16-06-2004): * made 'no action specified' error message more informative (suggested by Stephen Gill) * fix memory leak in mysql sh_database_query() (bug report by Dejan) * remove some cruft from the code * sh_files.c: check MacOS X resource forks (idea from Osiris) * sh_files.c: no hardlink check for MacOS X * sh_util_ask_update: fix bug with no terminal in non-interactive mode (report and debug data by Kris Dom) * manual refactored * fix redundant messages when updating with suidcheck * allow interactive update for suid files * don't remove the TZ environment variable to guard against misconfigured hosts * also use gethostname if uname returns possibly truncated name * fix improper file descriptor handling in sh_mail.c (bug report by Alex Weiss) * cleanup MBLK cruft * use SH_ALLOC/SH_FREE in sh_prelude.c * update sstrip to Version 2.0 1.8.8 (25-05-2004): * fix compilation problem on AIX 5.2 (nameser_compat.h; report by Tim Evans and Ian McCulloch) * don't check for trusted paths on Cygwin * add Windows HOWTO written by Kris Dom * kern_check.h: extend FreeBSD syscall table for 5.x 1.8.7a (03-05-2004): * sh_mail.c: fix subject length * sh_mail.c: fix the sh.mailNum.alarm_last fix (report by Kris Dom) * sh_utils.c: sh_util_ask_update(): fix ISO C conformance bug (compile problem reported by Kris Dom) 1.8.7 (01-05-2004): * sh_mail.c: fix incorrect count of sh.mailNum.alarm_last, causing empty mails (introduced with segfault fix in 1.8.6, report by Kris Dom) * sh_utils.c: sh_util_ask_update(): check whether stdin is a terminal, try to reopen on controlling terminal if not * sh_utmp.c: fix order of options (problem report by Uri) * sh_files.c: sh_files_chk(): set tmp = NULL at end of loop (may cause segfault on null dereference for missing files) * sh_unix.c: patch by Marc Schütz (order of sh_unix_getinfo_type, sh_unix_getinfo_attr) * don't use dh_installmanpages in 'make deb' (samhain/yule conflict reported by xavier) * on HP-UX, define _XOPEN_SOURCE_EXTENDED in sh_mail.c and sh_tools.c (suggested by Kris) * include nameser_compat.h in sh_mail.c (for MacOS X, suggestion by jna) * sh_utmp.c: fix time for logout events (reported by Erich van der Velde) 1.8.6 (15-04-2004): * add CL option to set threshold for prelude and RDBMS * sh_mail.c: fix bug with MailSubject option (segfault on NULL pointer dereference; reported by Micha Silver) * fix compiling with --disable-encrypt (reported by Pat Smith) * fix minor problem in scheduler (don't return before all schedules are tested, to set last_exec correctly) 1.8.5 (05-04-2004): * fix bugs in sh_utmp.c (unlinking of list head); may fix an OpenBSD problem (endless loop; report and debugging aid by Joe MacDonald) * fix hardlink check (null dereference in error message, segfaults on solaris - noticed by Bob Bloom) * sh_suidcheck: don't truncate quarantined file if nlink > 1 * fix Install.sh (no --seperate-output with --radiolist); patch by Greg Kimberly 1.8.4 (17-03-2004): * add Prelude patch by Patrice Bourgin * add license statement to sh_mounts.c, sh_userfiles.c after receiving a clarifying e-mail from Cian Synnott * support UsePersistent = no for Oracle (problem spotted and fix tested by Michael Somers) * fix bug in samhainadmin.pl * sh_gpg.c: describe type of gpg error (if any) * fix persistent connections with postgresql (reported by Erwin Van de Velde) * prelude: local 'meaning' shadows global in sh_prelude_alert (spotted by David Maciejak) * uname: workaround for cases where nodename would be a possibly truncated FQDN (problem reported by Cian Synnott) * re-write parts of sh_kern.c, store kernel info in baseline database -> no need to recompile after kernel upgrade * modify timeouts in sh_unix_getinfo, add timeout warning * change handling of dangling symlinks (store in db) * fix typo with MSG_FI_OBSC2 (double slash) * remove redundant operation in sh_utils_safe_name * fix occasional random start bytes of long messages in sh_error_string (sl_strlcat -> sl_strlcpy) * provide details for missing files (as for added files) * remove duplicate message for no such group/user * add fixes for samhain.oracle.init (supplied by Michael Somers) * fix date insertion for Oracle (fix by Michael Somers) * manual: fix incorrect statement about RPM (noticed by Lars Kellogg-Stedman) 1.8.3 (02-02-2004): * add a HOWTO-client+server-troubleshooting document * fix another bug with SIGUSR2 (suspend mode) * new option SetBindAddress (--bind-address=...) to force interface for outgoing connections on multi-interface box * don't link against libgmp if not required (i.e. standalone) * test for ext2fs/ext2_fs.h or linux/ext2_fs.h * new make targets 'emerge' and 'tbz2' for gentoo * update rules.deb.in based on the Debian package by Javier Fernandez-Sanguino * updated config.guess, config.sub to version 2002-09-05 * external command: report failure only once * console: reset failure status after success * README.UPGRADE: explain 1.7.x <-> 1.8.x client/server compatibility * use persistent connection to database by default * option UsePersistent=no to switch off persistent connection 1.8.2 (19-01-2004): * sh_userfiles.c: new option UserfilesCheckUids (requested) * sh_error.c: server: don't log to logfile before dropping root * new script scripts/samhainadmin.pl (administrative tasks for signed config/database files) * add changes code to log_msg for reports on modified files * change default log threshold to 'mark', as 'none' tends to confuse new users * faster response time for SIGUSR2 * revised (mostly backward-compatible) message classes * fix missing check of mailTime in server select loop * add support for libprelude (version 0.8.10) * fix format for MSG_E_GRNULL (reported by Stefan Hudson) * fix Bourne shell incompatibility (export) in samhain-install.sh (first reported by David Thiel) * fix typo in spec file (first reported by Christian Vanguers) * remove some cruft (signal handler, memory handling) * return from sigterm handler, rather than exit directly (re-entrancy problem causes more problems than it's worth) 1.8.1 (03-12-2003): * fix gmp detection (problem pointed out by Nix) * fix/improve the error message if test compiling with mysql fails * new CL option --interactive for interactive db update * fix some compiler warnings from IRIX MIPS compiler * kern_head.h, kern_head.c: option to disable IDT check * kern_head.h, kern_head.c: update kernel syscall table (2.4.20,2.6) * sh_utmp.c: count number of logins (request by Erwin Van De Velde) * change username -> userid, remove (long) userid (bug noticed by Erwin Van De Velde) * emit ADDED message for new SUID/SGID files * add trailing slash to excluded directory if there is none 1.8.0a (04-11-2003): * sh_error.c: remove two debug printf's 1.8.0 (31-10-2003): * manual: make ps file fit on both a4 and letter paper * sh_socket.c, sh_socket.h, sh_forward.c: socket interface to send (quit/reload) commands to clients * sh_forward.c, configure.ac: enable build with libwrap (Wietse Venema's TCP Wrappers library) * sh_ignore.c, sh_ignore.h, sh_files.c, sh_hash.c, sh_readconf.c: new option to suppress messages for new and/or deleted files * samhainrc.aix5.2.0: contributed by Christoph Kiefer * samhain.c: fix compile warning on solaris (noticed by Ian Hunt) * sh_database.c: undef debug code for oracle * samhain.oracle.init: contributed by Joern Michael Krueger * configure.ac, sh_utils.ac, Makefile.in, sh_modules.c, sh_cat.c, sh_cat.h, sh_mounts.c/h, sh_userfiles.c/h: check-mounts and userfiles modules contributed by eircom.net * sh_utils.c: fix off-by-one bug in sh_util_compress() * sh_forward.c, sh_tools.c, configure.ac: version 2 client/server protocol * sh_mail.c: add %S to include severity in subject (user request) * sh_suidchk.c, 1093: fix warning about unused var 'flags' on FreeBSD * samhain.h, sh_unix.h, sh_unix.c: extern inline -> static inline for --enable-ptrace * samhain.c: lower priority for 'uninitialized module' message * sh_entropy.c: lower priority for message if /dev/random blocks and /dev/urandom is available * improved error messages in sh_readconf.c * print system error message for getpwuid, getgrgid * fix missing module init after SIGHUP (noticed by Cian Synnott) 1.7.12 (13-10-2003): * sh_mail.c: fix buffer overflow in mail handler (introduced in 1.7.10) thanks to bug reports by Jason Martin and Matthew P. Cox 1.7.11 (01-09-2003): * samhain.c, samhain.h, sh_unix.c, sh_forward.c, sh_html.h: - change SIG_USR1 to switch between dbg on/off - change SIG_USR2 to switch between suspend on/off - fix CLT_ILLEGAL to actually work - introduce new state CLT_SUSPEND - force reauthentication after suspend * slib.c: change MAXFD from FOPEN_MAX (16) -> 1024 * sh_suidchk.c: better AIX fs detection (Christoph) * sh_entropy.c: increase buffer size for unix entropy gatherer (problem reported by D. Danielson) * default config files: add lots of comments, list more options * sh_error.c: set default severities to 'crit' * sh_readconf.c, sh_cat.c, sh_cat.h: stricter check on config file syntax, issue warnings (triggered by C. Kiefer) * Makefile.in: handle depend-gen errors more gracefully * sh_err_console.c: fix bug in enable_msgq (reported by F. Behrens) * configure.ac: workaround for mysql_config weird output (reported by G. Faron) * sh_unix.c, sh_tiger0.c: check IO limit during read of large files * depend-gen.c: close streams before attempting to rename (Cygwin) * Makefile.in: fail gracefully if depend-gen fails * sh_database.c: sh_database_query(postgresql): fixed missing SL_ENTER 1.7.10 (27-07-2003): * FreeBSD init script: define $pidfile (reported by D. Thiel) * sh_unix.c, sh_unix.h: fix compile error on AIX 4.2 * sh_schedule.c: fix bad array size * samhain.c: fix pid_t <> int casts * sh_kern.c: fix repetitive messages * configure.ac: try to bootstrap if TIGER192 not supported by gpg, provide a detailed error message * configure.ac: try harder to locate mysql * docs/Changelog: retroactively add release dates, if known * sh_mail.c: fix potential message truncation in mailer * sh_unix.c, samhain.c, samhain.h: make --enable-ptrace more portable * sh_readconf.c: fix segfault (dereference of uninitialized pointer) if --with-gpg and --enable-stealth are used together (reported by Anthony Caetano) * sh_unix.c, samhain.c, sh_calls.c: fix problems with descriptive error messages (larger GLOB_LEN, stat fills aud_err_message) 1.7.9 (30-06-2003): * sh_err_log.c: fix segfault on SIGABRT (dereference of freed memory), problems with SIGABRT noticed by Brian and Alf B Lervåg * deploy.sh.in: fix some bugs (found by Alf B Lervåg) * scripts/chroot.sh: fix typo (found by Alf B Lervåg) * configure.ac (khide): search also for 'd sys_call_table' (noted by cuek_saja) * strip whitespace before checking gpg checksum (noted by D. Thiel) * manual (faq section): explain how to stop console output * Makefile.in: fix re-naming of yule with --enable-install-name * HOWTO-client+server.html: fix typo (noted by xavier renaut) * configure.ac: escape '-' in awk regex (required by GNU awk 3.1.1) 1.7.8 (28-05-2003): * sh_unix.c: new mlock implementation with reference count and page alignment (fix for solaris problem) * kern_head.c: search also for 'xxxxxxxx d sys_call_table' * sh_html.c: write status comment (for Beltane 2) * add CL option --delimited for comma-delimited signature database dump * sh_mail.c: check exit status of push_list to fix counting bug (bug reported by Alan Moore) * configure.ac: add error message to --with-libs * fix spelling of $DAEMON in init script (noted by C. Grigoriu) * fix missing initgroups() 1.7.7 (06-05-2003): * sh_forward.c: fix bug if compiled with --enable-udp, but disabled in config file (found by Andy OBrien) * sh_database.c: sh_database_entry(): size -> c_size (two places) to fix writing of '\0' to arbitrary places :( (problem pointed out by Stefan Giesen) * profiles/*/configopts: fix --with-base -> --enable-base 1.7.6 (24-04-2003): * sh_forward.c, entry.html, head.html: fix/additions by Stefan Giesen * fix samhain_hide for the O(1) scheduler used by RedHat: configure.ac, acconfig.h: check for next_task in struct task_struct samhain_hide.c: use find_task_by_pid if no next_task in task_struct * samhain_erase.c: add MODULE_LICENSE("GPL") to fix warning 1.7.5 (15-04-2003): * sh_cat.c, sh_forward.c, sh_hash.c: fix double 'msg' tag * manual: point out the bmaxdata problem on AIX in faq section * trustfile.c: don't check symlinks (permissions of directory count) * sh_schedule.c: fix problem with daylight saving switchover * sh_samhain.c: close all open fd's >2 before reading the conf file * sh_unix.c: fix dereferenced NULL pointer when exiting on non-existing user * sh_forward.c: fix dereferenced NULL pointer when exiting on udp error * sh_forward.c: place timestamp code before select() timeout handler * fix incorrect class of timestamp messages (conflict with manual) * sh_readconf.c, sh_forward.c: new config option SetStripDomain * configure.ac: add warning if /lib/modules/`uname -r`/build/include not found * samhain_hide.c: adapt for RedHat 2.4 kernel (fetch sys_call_table address from System.map) * sh_err_syslog.c: fix for Solaris * samhain.spec.in: strip REQ_FROM_SERVER from config file install path 1.7.4 (21-03-2003): * configure.ac: fix bug in defargs (--with-base > --enable-base) * aclocal.ac: detect unsupported options * kern_check: add syscalls, skip unused syscalls * fix Manual (--enable.../--with... inconsistency) * add two HOWTOs (signed files, server/client) * moved manual into new subdirectory docs/ * add admin scripts by S.Bailey/M.Redinger * option to have a version string in db file 1.7.3 (23-02-2003): * samhain-install.sh: use yule user key for signing on install * fix a bug in sh_err_console.c (attempted write to const char) * sh_gpg.c: if server, always use ~unprivileged_user/.gnupg * Makefile.in: make target 'trustfile' depend on config.h * configure.ac: don't use install_name before it is defined ... * sh_tiger0.c: fix bug in checksum computation introduced in 1.7.2 * samhain.c: make sure daemon cannot be forced into 'update' mode * sh_hash.c: remove AIX workaround (AIX has been fixed meanwhile) 1.7.2 (04-02-2003): * sh_kern.c: use sys_call_table address from System.map * fix for reserved SQL keyword 'group' * add AC_SYS_LARGEFILE to configure.ac * allow separate client-specific log files for server * sstrip.c: compile sstrip code only for i386 * sh_unix.c: closeall: don't close trace file * slib.c: don't trace sl_is_suid (leads to recursion in trace handler) * samhain-install.sh.in: fix detection of LSB compliant systems * sh_tools.c: get_client_*_file: lstat -> stat to allow symlinks * sh_forward.c: sh_forward_do_write: set O_NONBLOCK for fd (may block otherwise, for no good reason apparently ...) * samhain.spec.in: replace %configure with ./configure * sh_unix.c: re-write signal handling (use __malloc_hook et al. to check whether we are in the middle of a free/malloc/realloc/memalign) * sh_unix.c: use new safe_logger() function to log from signal handler * sh_err_log.c: fix xml * * fix Makefile.in to exit non-zero on compile failure * database init: create index on log_host, entry_status * sh_suidchk.c: fix path building * sh_tiger0.c: read larger blocks * sh_hash.c: cast inode to UINT32 * sh_tools.c: check that config/database files size fits in uint * sh_error.c: export flag_err_debug to avoid unnecessary calls * sh_unix.c: save the open() call in sh_unix_getinfo_attr() * profiles/redhat_i386/bootscript: add # description field * deploy.sh.in: set owner + permissions for files in yule_filedir * profiles/debianlinux_i386: fix bootscript * Makefile.in: fix deploy file lists and targets (include init+scripts) * MLOCK GOOD/BAD -> SL_FALSE/SL_TRUE * sh_mail.c: GOOD/BAD -> SL_FALSE/SL_TRUE (AIX sys/param.h) * sh_err_syslog.c: split long messages rather than truncating * sh_error.c: allocate msg to fix truncation limit * sh_unix.c: closeall fd's >= 3 in non-daemon mode (inherited filedescriptors may exceed FOPEN_MAX, causing problems in sl_open_file) * sh_err_console.c: avoid stdio * trustfile: dirz: make swp[] static * slib.c: speed up sl_strlcat * clean up some bad heap allocation (PATH_MAX+(1|2) -> PATH_MAX) * remove some unused code * slib.c: support long long int in the snprintf replacement * configure.ac: new configure macro to check whether sa_sigaction works * Makefile.in: make sstrip, encode dependent on config.h 1.7.1a (08-01-2003): * fix a syntax error in samhain-install.sh.in 1.7.1 (07-01-2003): * search runlevel scripts in ./init or ./ * handle all distro-specific Linux runlevel script issues within a single script * support install-boot on Yellow Dog Linux and Slackware * samhain-install.sh: fix a bug for unknown Linux ('"' not closed, DVER not set) * samhain-install.sh: check for /etc/yellowdog-release * sh_database.c: fix missing entry for 'userid' in attr_tab[] * fix debian.rules.in (disable sstrip) * update make targets: 'srpm', 'srpm-dist', 'rpm' * check for zlib if mysql is used * workaround for NetBSD bug with libresolve * fixed problems with spec files 1.7.0 (22-12-2002): * improved spec files (Andre Oliveira da Costa ) * sh_unix.c: fix a dereferenced static pointer in tf_trust_check * runlevel scripts: remove pid file after stop * make the data directory read-only for the daemon * treat 'localhost' specially in MX resolver * sh_err_log.c: set sh.flag.log_start == TRUE after writing * deploy.sh.in: fix quoting (fix by Simon Bailey) * slib.c: make sl_get_euid et al. behave well if uids not stored * trustfile.c: use euid = uid(SH_IDENT) if server * sh_mail.c: include an MX resolver * Makefile.in: install-user routine for user installation * have yule drop root * sh_tools.c: open_temp use logdir if server * unified options for runlevel script * HP-UX, IRIX runlevel scripts * AIX inittab entry 1.6.6 (13-12-2002): * configure.ac: solaris cc -O2 -> -xO2 * sstrip.c: avoid alpha architecture * profiles/solaris/configopts: no --enable-static * sh_forward.c: sh_forward_req_file: copy argument to local array 1.6.5 (04-12-2002): * sh_utmp.c: set userlist = NULL in sh_utmp_end () * sh_unix.c: do not assume that environ is sane * exit handler: write * sh_log_file(NULL): test sh.flag.log_start != S_TRUE * FreeBSD rc script does not blindly accept content of pid file * configure.ac: allow 'localhost' for log server * sh_calls.c: retry_connect: ntohs (port) * testrun_2[abc].sh: --with-logserver=localhost for client 1.6.4 (12-11-2002): * sh_tools.c: fix error when escaping '=<' * fix the 'make srpm' target * deploy.sh.in: avoid that client is named 'yule' * define memset to sl_memset * fix type cast of uid_t, gid_t 1.6.3 (31-10-2002): * fix options for Sun/Solaris native compiler * sh_unix.c: MSG_FI_LIST (line 2333): cast theFile->size to fix error * test sstrip on freebsd * default config file for freebsd * make target to build .deb packages * sh_readconf.c: fix bug in error message * samhain.c, sh_suidchk.c: fix initialization of suidchk * samhain-install.sh.in: don't remove config file by default * samhain-install.sh.in: support complete de-installation * samhain-install.sh.in: add support for Gentoo, FreeBSD, and Solaris * samhain-install.sh.in: check more paths * sh_unix.c: fix sys_siglist declaration [NetBSD portability issue] * sh_calls.c: save error message in retry_lstat() 1.6.2 (04-10-2002): * make target to build rpms * update samhain.spec.in, samhain.startRedHat * support DESTDIR, as in 'make DESTDIR=/what/ever install' * explicitely set -fno-omit-frame-pointer b/o gcc bug * mv configure.in to configure.ac to benefit from autoconf wrapper * sh_modules.c, sh_modules.h: add mod_reconf() to run at SIGHUP * slib.c: fix debug messages (no msgs for dlogActive <= 1) * sh_schedule.c, samhain.c, sh_suidchk.c: scheduler may accept multiple schedules 1.6.1 (04-09-2002): * sh_schedule.c: bugfix (executes only after first day) * rm obsolete WITH_TRACE stuff * new dlog() function for debug logging * some more descriptive error messages 1.6.0 (27-08-2002): * omit the -fomit-frame-pointer option (bugs in some gcc versions ?) * sh_error.c: fix escape mode when logging to database * sh_forward.c: fix error (twice escape) in recv_syslog_socket * sh_tools.c: change escape mode for server-received data * sh_mem.c: change ulong -> size_t in sh_mem_malloc() * configure.in: fix localstatedir if --prefix=USR * sh_hash.c: snprintf() -> sl_snprintf() 1.5.5 (07-08-2002): * sh_err_log.c: fix incorrect xml syntax for client messages logged by server * sh_err_log.c: fix incorrect '' entries on client EXIT * sh_files.c: introduce file_class_next this fixes the problem that a policy for the directory inode erroneously becomes a policy for the directory itself. 1.5.4 (17-07-2002): * sh_hash.c: fix buffer overflow with (micro-)stealth * sh_database.c: set path[] 1024 -> 12288 * sh_database.c: set query[] 2048 -> 16383 * sh_database.c: set values[] 1024 -> 16383 * sh_forward.c: larger limit for message size (16 kB) * trustfile.c: set MAXFILENAME 2048 -> 4096 * fixed a bug in the handling of filenames with embedded newlines * sh_files.c: fix missing sh_util_safe_name() in debug output * --with-sender can specify a full address * fix xml log in a backwards compatible way 1.5.3 (03-07-2002): * fix combination of stealth and sql logging * fix some more places where invalid UIDs/GIDs trigger errors 1.5.2 (01-07-2002): * include solaris config file from (sean [at] boran d.o.t com) * test for files/dirz defined twice in the configuration file * option to disable reverse lookup on outbound connections * option to use socket peer as client name (with name resolving) * sh_html.c: fix an HTML bug (twice ) * sh_suidchk.c: fix warning on AIX b/o dirname() * allow logging server -> syslog if yule is NOT configured to receive syslog messages * define PRIi64 to "lld" if undefined * invalid UIDs: use gid/uid as name, error level SeverityNames * minor fixes for connect_port * sh_hash.c: flush output of db listing before _exit() * configure.in: fix incorrect default ${install_name} for server * configure.in: try harder to find mysql.h / libpq-fe.h * sh_files.c: sh_files_checkdir: closedir() early to not exhaust OPEN_MAX 1.5.1a (30-05-2002): * fix missing LSB init script 1.5.1 (27-05-2002): * fix '-t update' option 1.5.0a (23-05-2002): * fix configure.in 1.5.0 (22-05-2002): * include solaris nosuid patch from (nathoo [at] co d.o.t ru) * similar fix for bsd nosuid * speed up -t update * convert manual to DocBook, distribute html and ps * fix some more problems with configure.in, Makefile.in * fix testsuite, add tests for udp, mysql * MSG_TCP_MSG: host -> remote_host * convert to autoconf 2.53 * make c_bits.sh exit with status 0 * sh_database.c #include "mysql.h" --> , ditto libpq-fe.h to avoid dependency tracking problems * samhain.c remove *YULE* #ifdefs * acconfig.h remove *YULE* #undefs * samhain.c: procdirSamhain: lstat --> stat (allow symlink) * configure.in: add checks for correct user input * Makefile.in: add automatic dependency tracking * depend-gen: tool to figure out dependencies * chkconfig comments in redhat start scripts 1.4.8: * sh_database.c: fix missing attr_old, attr_new, (from)host columns * configure.in, Makefile.in: fix an error in the configfile definition with REQ_FROM_SERVER * sh_err_console, sh_err_log: avoid recurrent failure messages * timeout on read from files (/proc) * fix errrors with setjmp/longjmp/alarm * fix memory leak in server (~20 byte/file download in sh_tools, 930) * check gpg signature for files downloaded from server, add a regression test * fix chown in solaris bootscript * provide second scheduler for file check * provide scheduler for file check * provide scheduler for SUID check 1.4.7 (08-04-2002): * make daemon control LSB-compliant (arguments, exit status) * set log_ref = 0 for server messages * boolean option SetDBServerTstamp to disable entering server timestamps for received client messages into database * sh_suidcheck: check for "nosuid" mount option if getmntent is used * fix logrotate script in manual (reported by Scott Worthington) * don't strip numerical IP addresses * check item->status_now != CLT_TOOLONG in client_time_check() * set log_host to client in db client message 1.4.6a (20-03-2002): * define prefix in deploy.sh 1.4.6 (19-03-2002): * modify samhain_hide.c to hide processes on new Linux kernels * better error diagnostics in kern_head.c * fix compile error in all_items () * check length of install-name in enable-khide (max is 15) * define exec_prefix in deploy.sh.in * make configure a bit more cross-compiler friendly 1.4.5 (07-03-2002): * Make sure missing file is reported even if ptr->reported == S_TRUE because the file has been added. * propagate 'reported' flag from sh_files_checkdir() into file list * close checkfd in sh_gpg_check_file_sign() * sh_derr(): kill(parent, SIGCONT) after ptrace(PT_DETACH,...) * use sh.srvcons.name in dbg() to get debugging info from daemon * option to log file timestamps with localtime instead of GMT * comment out MSG_FI_ADD in sh_dirs_chk () - obsoleted by mandatory sh_files_filecheck(directory) that triggers MSG_FI_ADD in sh_hash.c * set ptr->reported = S_FALSE; for reappeared files in sh_files_chk() to make sure re-disappearing will get reported * new function sh_hash_set_missing() to remove file record without (duplicate) 'missing' message * make sure all items are reported for added files * fix stealth mode with sh_kern (encode sh_ks.h -> sh_ks_xor.h) * clarify in the documentation which gpg options to use for signing 1.4.4 (11-02-2002): * check that parent process has exited before writing PID file * promote MGG_W_CHDIR to SH_ERR_ERR * add error message to sh_unix_testlock * fix missing _() macro in sh_aud_set_functions 1.4.3 (05-02-2002): * don't check attributes for symlinks (may cause device access) * add USE mysql; USE samhain; to samhain.mysql.init * point out the MessageHeader/mysql problem in manual * add -lz to LIBS for mysql * strip after install, avoid double strip 1.4.2 (27-01-2002): * support for EGD * fix some more problems with install-deploy / deploy.sh * fix a bug in profiles/suselinux_i386/bootscript (INSTALL_NAME_) * fixed the 'external logging' test (init rather than none in rc file) 1.4.1: * SuSE: include run level 4+5 * install location of hiding kernel modules changed - some insmod variants do not test for /lib/modules/$(uname -r)/module_name.o * new make targets 'install-deploy', 'uninstall-deploy' * fixed make targets 'deploydir', 'deploydirfast' * bail on unsupported CL option in deploy.sh * fix various bugs in deploy.sh 1.4.0 (16-01-2002): * fixed missing 'dirname' on Mac OS X * fixed && tested for/with postgres * 'user=' -> 'userid=' (reserved word in sql) * fix the endianess + size of file database; this changes db format for any non-Linux OS * --enable-old-format for old (V1.3) database format * getopt, samhain.c, samhain.h: option -f to loop if not daemon * sh_hash: list numeric + char data to allow file db update on server side * sh_database: modify handling of integer (long) data * sh_database: datetime in database * sh_database: hash field in database * sh_database: rewrite database insert string construction [use INSERT INTO log (fields) VALUES (values);] * makefile suse 7.x runlevel entries 1.3.7 (06-01-2002): * fix incorrect escape in sh_tools_safe_name * fix sh_error_handle (4. argument) in sh_extern.c 1.3.6c: * fix segfault in sh_database (mysql logging) on solaris 1.3.6b (03-01-2002): * fix syntax error ('==') in Makefile.in * fix configure.in (path for /lib/modules/$(uname -r)/build/include) * fix sh_kern.c (redeclaration of 'j') 1.3.6 (03-01-2002): * sh_kern.c: check integrity of int 80h vector (SucKIT rootkit - Phrack 58) * make sure childs in sh_kern are wait()'ed for * provide start/stop/restart/reload/status interface * fix a potential segfault (dereferenced NULL pointer) in the server * use sh_util_flagval for sh_unix_setdaemon * documentation for logging to SQL database * configure.in: check for -I/lib/modules/$(uname -r)/build/include * fix trustfile.c to ignore invalid users * separate 'make install-samhain' and 'make install-yule' * separate default log/pid/config files for server/client - less problems running server and client on same host * rewrite deploy.sh(.in): - don't use (make|install) if deploying - use command line options - better integrate into server environment - write install db * always write a pidfile if daemon * don't use server's config file as fallback for downloading client * don't overwrite config file when doing 'make install' 1.3.5 (28-12-2001): * fix --enable-message-queue for newer glibc versions * log to SQL database: implemented, but undocumented yet, needs to be tested further * xml: escape received syslog messages * xml: rename 'time' to 'tstamp' * make targets: make [un]install-[boot-]yule (for server-only installation) * fix samhain_hide.c for 2.4 kernel * fix sh_kern for updated samhain_hide.c * new option -j to just list the logfile * sh_getopt.c: recognize -Dt check for -D -t check * sh_tiger0.c: fix compiler warning (memmove) on Solaris 1.3.4 (12-12-2001): * sh_suidchk.c: option to limit files per second * sh_unix.c: option to limit (kilo)bytes per second * sh_hash.c: fix potential problem with '\n' in filename (not backward compatible if there are filenames with '=') 1.3.3 (03-12-2001): * sh_readconf.c, samhain.h, samhain.c, sh_suidchk.c: option SetNiceLevel to set scheduling priority * sh_hash.c: bugfix for database listing on Solaris * taus_seed: bugfix for emergency backup rng seed * sh_util_safe_name: fix for XML * sh_utmp_set_login_activate: use sh_util_flagval * sh_utils.c: sh_util_obscurename: rm 'space' from list * more backtrace macros * sh_util_flagval: fix bug to recognize 1/0 * fix test scripts testtimesrv.sh, testext.sh (test.sh 6/5) * rm stray debug fprintf in sh_srp.c 1.3.2 (27-11-2001): * sh_hash.c: fix an error introduced in 1.3.1 * set RLIMIT_CORE to RLIM_INFINITY if --enable-debug 1.3.1 (25-11-2001): * slib.c: get backtrace with --enable-debug * sh_unix.c: allow core dumps when --enable-debug * configure.in: fix default message queue permissions * sh_suidchk.c: automatically include suid/sgid files in database * sh_suidchk.c: check all suid/sgid files * sh_hash.c: don't insert duplicates when reading the database * sh_utmp, sh_kern, samhain: fix 1sec offset in timer * sh_unix.c: don't require /dev/random to be non-world-writeable * server: fix segfault in zAVLTree.c if avltree == NULL (no clients) * client: fix segfault on Solaris if path_conf == NULL * testrun_1b.sh: \(^/.*\) -> \(/.*\) for Solaris sed 1.3.0 (31-10-2001): * support compiling with GNU gmp library * set 3 sec timer on client_time_check to avoid excessive (and unnecessary) calls under heavy load * replace sl_strlen with a macro * store client_t structure in AVL tree * database format incompatible with previous format, up the magic# * sh_html.c: cache entry template for speedup * slib.c: reset islong(double) in sl_printf_count * sh_hash.c: report on rdev change * sh_hash.c: print size in 64 bit * sh_hash.c: save in absolute size types * sh_unix.c: get values as appropriate type (time_t, dev_t, ...) 1.2.10: * update MANUAL * sh_unix.c: tiger_hash -> tiger_generic_hash * sh_readcon.c: DigestAlgo option * sh_tiger0.c: add MD5 and SHA1 * sh_unix.c: fix minor problem with win2k/cygwin 1.2.9 (17-10-2001): * fix problem with entry template/empty hostname * fix MASK_USER_ (MTM -> ATM) * typo fixed in configure.in (${install_name} -> {install_name}) * bugfix group_old -> size_old in XML code * skip armor header in signed files 1.2.8 (29-09-2001): * Mac OS X: in sh_getopt.c, rename table[] to op_table[] to avoid obscure compiler warning * Mac OS X: fix test scripts * Mac OS X: import newest config.guess, config.sub from ftp.gnu.org * implement deadtime in syslog recv code to protect against flooding * sh_err_log: sl_close(fd) if lock|forward fails * compliance with Filesystem Hierarchy Standard -- Version 2.2 final * add policies User0, User1 * fix compile problem (FreeBSD) in sh_suidchk.c * macro to check for debugger breakpoints (linux/i386) * check for solaris (does not work) in sh_derr (--enable-ptrace) * option to listen on 514/udp for syslog, drop root irrevocably if compiled thus * use (check_mask & MODI_ATM) to decide whether to reset utime * reset the policy masks on sighup * option to write XML log messages * cleanup of message catalog * modified error messages for BADCONN * error messages for Rijndael * block recursive error messages within sh_error_handler() - would hang the machine ... - 1.2.7: * sh_files, sh_utils: check top level directory * sh_kern, sh_cat, kern_head: check syscall code, fork subprocess for reading from /dev/kmem * include /boot in default samhainrc * change source distribution signing/packaging system * Makefile, README, MANUAL: adhere to file system standard, document new locations * fix a bug in samhain_hide.c 1.2.6: * reset list of trusted users before config file re-read * TrustedUser=... can be a list * fix severity for files missing from IgnoreAll 1.2.5: * include example_pager.pl, example_sms.pl scripts * explain paging/sms setup in docs * allow manual exclusion of a directory in suidcheck * automatically track all file changes * remove missing files from in-memory database * add $(KERN) to DEPLOYFILES 1.2.4: * log IP address for login/logout events, if supported by the OS * release block in globerr (callback) ------------- 1.2.3: * fix problem with reading stealth configuration * fix a few formats in sh_cat.c * always use strncmp for file system type check in sh_suidchk.c (trailing 'fs' may be system specific for some types) * no bare LF in messages (RFC 2822) * no lines longer than 998 chars (RFC 2822) * fix error in testrc_1 1.2.2: * make tmp file directory a compile time option * fix minor bugs in tmp file allocator (potential memory leak, double slash if root directory) * obsolete testpipe script removed 1.2.1: * fix memory alignment in rijndael-api-fst.c: blockEncrypt() * fix byte order in HMAC code (compatibility fix for Linux/HP-UX) * removed a debug fprintf() 1.2.0: * fix a bug in the HMAC implementation (thanks to Cesar Tascon for help in tracking down this one) * module to check the file system for SUID/SGID files 1.1.16 (never released): * fix the recursion depth -1 option as described in the manual * optional database reload on SIGHUP * fix a race condition when checking that /dev/random is a charakter device * redirect stderr to /dev/null for c_random (AIX may segfault in netstat...) * check whether /dev/random is a charakter device in c_random.sh (we know at least one sysadmin who has set up a fake /dev/random ...) * don't give NULL as 2. and 3. arg to execve if not Linux - some Unices (notably Solaris) don't like it * init ptr = NULL in my_malloc (compiler warning) * make the bitmask for tests configureable (suggestion by A. Dunkel) * make the bitmask for tests a static variable * make (database/logfile/lockfile) path configurable (to run multiple instances of samhain from an NFS share - on the wishlist of J. Patton) 1.1.15 (never released): * fix minor error in testcompile.sh (rm test_log only at start) * return from subroutines on sig_terminate == 1 (faster exit on SIGTERM) * fix re-configuration of addresses * use sh_util_flagval() in sh_mail_setFlag and sh_kern_set_activate * SysV message queue as compile option * config file option to set console device * removed the pre 1.1.9 code bloat * don't print the LOGKEY to the console 1.1.14: * fix an error in the setup consistency check * make target to uninstall runtime files * trustfile.c: check return code of readlink(), fix off-by-one error * sh_files.c: fix placement of terminator after readlink() call * sh_files.c: fix a missing set_suid()/unset_suid() - suid should work, but is not recommended - * more debug statements in c/s code * avoid re-entry in sh_unix_sigexit * put a block around free() and malloc() in wrapper functions * ditto for glob()/globfree(), regcomp()/regfree(), fdopen()/fclose() - i.e. avoid corrupting the heap from a signal handler - 1.1.13: * optimized the size of the configure script somewhat * modify the compile and hash test scripts * read '\0's in sh_unix_getline * exponential schedule for connection attempts * make stealth working properly with signed files - config file should be signed now before embedding in picture - * fix a race in using signed files * updated err messages for PWNULL, GRNULL * add missing shell script for test 11 * add mandatory source file/line info with -p debug * add mandatory source line info with BADCONN * fix a latex error in the manual 1.1.12: * debug output to console if compiled with --enable-debug and running as daemon * make reportonlyonce=true the default * make sure state changes of a file are always reported, even with reportonlyonce=true * Linux kernel modules (samhain_hide, samhain_erase) * fixed incorrect return value of sh_util_flagval * fixed an error in sh_files.c: happens with -t init and first file that is checked does not exist * revised install/uninstall targets in the Makefile * module to check for clobbered kernel syscalls (tested on Linux 2.2) * more diagnostic error messages in sh_gpg.c * more diagnostic error messages in sh_mail.c * error in mail.c fixed (address -> address_list[i] for multiple recipients) * docs updated, better(?) explanation of signed files * skip over path in gpg checksum output * check client name against IP address and FQDN * fix for --disable-* in config file * fixed a server crash (MSG_TCP_OKMSG without arg) if the server is run with debug level output threshold * catch EAGAIN in sh_gpg.c pipe reader * fix the 'external logging' test to make it work on BSD * error message if no local path to init DB * check for i86/Solaris in configure (vsnprintf prototype) * make SRP the default 1.1.11: * make log file verification more convenient * fix problem with message classes in stealth mode * linux: do not try to read file attributes for devices * handle the root directory correctly (avoid "//" in listing) * fix problems with blockin on FIFOs/char dev pointed out by I. Rogalsky (rog@iis.fhg.de) - open in nonblocking mode for read, then set to blocking - open file only if regular * fix alignment in memory profiler 1.1.10: * minor code cleanup * fix an error in trustfile.c (handling of empty/incomplete group entries in /etc/group, bug report by A. Capriotti ) 1.1.9: * compatibility option for old behaviour (plain hash instead of HMAC, ECB instead of CBC mode) * use CBC rather than ECB mode for encryption * use HMAC-TIGER for message authentication codes * handle NULL data in sh_tiger_hash * option to set syslog facility (default is LOG_AUTHPRIV) * longer timeout (300 sec) on /dev/random if no /dev/urandom * fix minor output error with stealth option * option not to log names of config/database files on startup 1.1.8: * fix error in syslog routine * fix missing 'test' in configure.in * fix error in replace_tab() in sh_html.c * fix minor memory leak in sh_util_regcmp() 1.1.7: * timeout on read_mbytes (from /dev/random; fallback to /dev/urandom) * fix for FreeBSD: ut_user -> ut_name in sh_utmp.c * fix for Alpha: consider $ac_cv_sizeof_unsigned_int_ in configure.in * fix for Alpha: format string in sh_tiger0.sh * on Linux, now compiles cleanly with -Wall -W -Wstrict-prototypes -Wcast-align * fix problem with recursion depth (pointed out by Vic ) * #include "sh_tools.h" in sh_unix.c and fix the --with-timeserver option (reported by Vic ) * place read_port(), MSG_TCP_NETRP outside ifdefs * close fd/zero skey before execve * verify client name against socket peer * ... with configureable error priority * use strcmp() rather than strncmp() in search_register() * fix race between lstat() and open() for checksum (reported by dynamo , JJohnson ) * enable globbing for filenames * fix Solaris problem: siginfo_t may be NULL * fix missing SL_EBADGID in tf_trust_check * test case for external scripts, fix flushing pipe * fix a typo in sh_ext_type * do an fdexec w/checksum on Linux if calling external program * even safer tmp file creation * allow db update * fix compile options for --enable-debug * fixed a spelling error in the output * test program for full CS support (config/database download) * tell which file is searched for cs download 1.1.6: * fix bug in sh_readconf_line (segfault on erroneous config lines) 1.1.5: * sh_unix.c: sh_unix_getinfo_attr: f -> flags * use gettimeofday as last resort 1.1.4: * fix AIX compiler warning in sh_forward (cast arg1 of sh_tiger_hash to (char *) * configure: add static link flags for some more os (from tar) * don't strip twice (some stupid systems abort) * fix for reading from /dev/random on non-Linux systems (untested) * sh_mail.c: end all message lines with \r\n * stealth: ignore \r, \" * take out tracing from --enable-debug (presently useless anyway) * fix some remaining cleartext with debug && stealth combined * fixed a small memory leak in sh_err_log.c 1.1.3: * fixed circular logic in taus_seed() (fallback method only) * fix for missing _SC_OPEN_MAX (runaway close()) 1.1.2: * implement message classes * let server recognize client message severity and class * secondary log server * keep database in memory (allows to close file if retrieved from server) * encrypt client/server communication 1.1.1: * Compilation problems with native Solaris compiler fixed * fill in euid/ruid variable * manual.pdf --> MANUAL.pdf * debug sh_util_formatted() * http refresh 120sec for server stat page * trace/debug options * fixed problem with utmp.c options * fixed problem with sh_mail_setaddress * option for custom message header * fixed problem in compdata * fixed problem in mail verification * remove eventual trailing '/' in file names * fixed problem with report string for modified files * option to report in full detail 1.1.0: * Move error messages to catalog * Make error message format more uniform * Wrap sytem calls that could be interrupted by signals * Warn on append to database * Option for full details on mod. files * Option to report only once on mod. files * Generally speaking, major modifications with potential new bugs 0.9.5: * sh_hash.c: fixed erroneous checksum for config file * sh_html.c: fixed erroneous timestamp (last) * sh_tools.c: fixed connect_port (set port for cached address) * sh_srp.c: fix for '00' (='\0') in pw (last two fixes by Andreas Piesk) 0.9.4: * samhain.c: fcntl(1, ..) -> fcntl(2, ..) * sh_hash.c: copy 12 instead of 10 byte for c_attributes * 'empty directory' WARN -> INFO 0.9.3: * FreeBSD fixes: - c_random.sh: make sure /dev/random provides something rather than nothing - check for and include it - include early - sh_utmp.c: fixed an occurence of ut_user - sh_utmp.c: #ifdef HAVE_UTTYPE static char terminated_line #endif - sh_forward.c: EBADMSG -> ENOMSG * sh_unix.c: check return value of gethostbyname * sh_entropy.c: fallback on /dev/urandom if /dev/random blocks for more than 30 sec * ... and fix the timestamp format ... 0.9.2: * ISO 8601 timestamps * Bugfix in sh_utmp (timestring overwrite) * don't use siginfo_t on Linux (garbage as of 2.2.14) * check for Linux capabilities bug when dropping root * include README for gcc compiler bug (pointed out by A. Piesk) * explicitely set -fno-strength-reduce with gcc * fixed ignoring missing files with the IgnoreAll policy 0.9.1: * more ext2flags (breaks backward database compatibility on Linux) * IgnoreAll policy modified - missing/added files reported with SeverityIgnoreAll (to handle files that may or may not be present) * Check all files, not only regular ones (bug in sh_files, originally introduced because checksum of regular files only is computed) 0.9: * use O_NOATIME if supported * --with-nocl takes argument (PW to re-enable CL parsing) * no daemon mode if initializing database * fixed segfault in yule with 'unknown file type' request * enlarged MAX_GLOBS 24 -> 32 and made the array linear * server uses last registry entry for any given client now * deploy.sh script to deploy clients to remote hosts * enhanced signal handling: SIGUSR1/SIGUSR2/SIGABRT/SIGQUIT/SIGHUP * allow y/Y/n/N for login monitoring (in addition to 0/1) * external logging scripts/programs * trustfile.c: define STICKY on Linux * reset signal mask when initializing * EINTR_RETRY wrapper * slib: sl_read, sl_write EINTR update * use sstrip when installing * more compact database format (breaks backward database compatibility) * larger download packets * TcpFlags unsigned char * cast to (char *) head in write_port * m(un)lock cast to (char *) * (1 << 31) --> (1UL << 31) * support e2fs attributes on Linux * fixes for AIX and Solaris native compilers * fixed Makefile for non-GNU make (pattern rule --> suffix rule) 0.8.1: * fixed 'is_numeric()' return value 0.8: * added option for static compilation * added option for stealth with non-hidden config file * added option for disabling command line parsing * all options can be set in the configuration file now * stealth: xor strings in database file * fixed bug in mailer code ([] in HELO) * print timestamp when asking for key * 'micro' stealth mode (no hidden configuration file) * simplified slib * int->long for uids/gids in trustfile * moved mailkey from data to code * shell script for entropy (stronger default key) * general code cleanup * better error checking in client/server code * detect out-of-sync messages * check state across protocol passes in server * make sure authentication is mutual * file download to client * reserve six file descriptors in server * mlock queue buffer if LOG_KEY * improved robustness in bignum (don't fail on free()) * per-directory recursion depths * RFC821 compliance: empty line at end of header, To field, Date field * RFC821 compliance: make e-mail transfer relieable * fix detection of hardlink changes * checksum verification for calling gpg/pgp * CL option '-S' not required for server-only binary * eliminate CL options that may leak privileged information if the program is SUID * skip leading white space in configuration file * allow nested conditionals in configuration file * allow whitespace before and after '=' in configuration file * don't leak file descriptors to child processes * make message transfer relieable * always report error on abnormal termination of connection 0.7: * support for alpha machines * stop TCP logging after exit message * limit connections in server (DoS attacks) * move string handling to slib * move file handling to slib * timestring without space * changed report format * SUID bugfix - use euid when checking logfile ownership * SUID bugfix - get root for lstat() * SUID bugfix - get root for opendir() * store number of hardlinks * send no message if polling empty queue * include tiger 64-bit implementation (portability) * codes for error conditions * mail check: handle multiple, overlapping audit trails * security fix: no append to database if SUID * fix sh_entropy.c (BUFSIZ -> BUF_ENT) * read command line before config file * PGP signing of config/database files * checksum of config file reported * checking for attributes only 0.6: * more syslogish priority specification * fixed segfault in sh_mem_check, apparently this was also the reason for the segfault in atexit() * allow for compilation with SRP authentication * fixed tiger checksum computation * fixed broken logfile verification for second and further audit trails * test program added * documentation improved * sh_forward_make_client: bug fixed in[8]->in[i] * sh_error.h: fixed missing #include * configure.in: fixed missing strerror() test * sh_utmp.c: check logins/logouts * check for missing files * only reset access time if necessary * O_EXCL in open() * limit environment to TZ in execve (sh_entropy.c, not used on Linux) * use trustfile() to determine whether logfile dir is trustworthy * strip head instead of tail for numerical address * store messages in fifo during log server outage * re-init session key after server outage 0.5 (21-12-1999): * added option for mail relay server * own popen() implementation in sh_entropy() (portability) * fixed error in sh_util_basename() (returned NULL for base == "/") * fixed segfault in strlcpy/strlcat (check for src == NULL) * FILENAME_MAX -> PATH_MAX (HP-UX 10.20) * use TIGER for 32-byte compilers (portability) * fixed hash function (do not include stdlib.h) * flush buffer before write in mailer code (IBM AIX 4.1) * make mailer code non-forking * cast argument of is...() to int (portability) * return() after _exit() for braindead compilers (portability) * optionally use inet_addr (portability) * check for broken mlock() (HP-UX 10.20) * minor code cleanups * fixed incorrect size of munlock()'ed memory in sh_error_string() * fixed a buffer overflow in the error printing routine * fixed a buffer overflow in sh_util_safe_name () * implement SRP session key exchange * implement client/server facility * implement @host/@end construct in configuration file * preferably use uname(), and do gethostbyname() for FQDN * make vernam cipher base numeric * make OnlyStderr private in sh_error * test -e "/dev/random" --> test -r "/dev/random" (portability) * check for libsocket (portability) * add #defines for IPPORT_SMTP, IPPORT_TIMESERVER (portability) * eliminate superfluous /proc test * some unreachable code removed * cast to (byte*) replaced by cast to (word64*) in sh_tiger_hash() * check for setresuid() if no seteuid() (HP-UX 10.20) 0.4 (09-11-1999): * make sure output from /dev/random has no NULL's * one-time pad encryption for emailed keys (better than nothing ...) 0.3 (04-11-1999): * logfile readable for group * verify signatures for any file * signature block in tarball * use select() in time server routine * better protection for session keys (mlock) 0.2: * fixed incorrect man page * fixed incorrect example rc file * recursive error logging should work now 0.1: * initial release -- on Samhain 1999, of course development start: * probably 29-06-1999 samhain-4.1.4/docs/Changelog0000644000175000017500000032533112724017472012640 000000000000004.1.4: * fix problems with wildcard pattern re-evaluation (reported by A. Ansari): - not stored if no match at startup - only one (the first) stored if same pattern for file and dir * fix problems with directory creation in inotify watched tree (reported by A. Ansari): - recursive depth not decreased - watched as directory even when recursion depth should drop below zero 4.1.3 (19-04-2016): * on Cygwin, the AvoidBlock function is now off by default (problem reported by Fred C) * tighter sanity checks in sh_static.c * fix regression with '--enable-static' in sh_static.c (reported by amaiket). 4.1.2 (21-12-2015): * add options --enable-selinux and --enable-posix-acl for "hard fail" if libraries aren't found (requested feature) * fix wrong policy assignment when inotify is active and change occurs during a reload (reported by Bond) * fix failure to detect open UDP port for some daemons (reported by James) * fix broken 'rpm' and 'rpm-light' makefile targets (reported by Bond) * fix message for self-check 4.1.1 (01-11-2015): * fix problem with timezone calculation on month rollover for negative timezones (west of GMT; reported by Bond) * fix problem with rotated logfiles when content is always constant, i.e. checksum does not change (reported by Bond). * fix problem with baseline update on FreeBSD and probably other non-GNU/Linux systems (reported by L.Vasiliev) * fix bad check_libwrap() call in sh_xfer_server.c (reported by L.Vasiliev) 4.1.0 (24-09-2015): * fix quirks with Linux audit support * implement 'silent check' (requested feature) * fix call of self_check for exit on sigterm * fix safe_logger() - uses the logger utility with a non-posix option * fix missing reporting on shell expansion capability in --version * fix missing error message on invalid list for skipchecksum (reported by Bond) * fix missing definition for a sh_dummy_ var on BSD et al. (reported by Andrew) 4.0.0 (20-07-2015): * fix and document default settings for mounts check * new -w CL option to wait on scan completion * new option ReportCheckflags * enhance testsuite to cover new functionality * implement draft for change control integration: * new database format to store change flags * refactoring of db I/O and client/server code * option StartupLoadDelay * --create-database CL option * --outfile CL option * --binary, --list-filter CL options * --verify-database CL option * yulectl -c DELTA: command * option SetDeltaRetryCount * option SetDeltaRetryInterval * update documentation * remove old/unused code * fix compiler warnings with gcc 5.1.0 * update config.sub, config.guess 3.1.6 (08-06-2015): * Modify testcompile.sh to remove 'smatch' and use 'clang' instead. * Fix compile problems with clang. * Modify testcompile.sh to remove 'uno' and use 'cppcheck' for static checking * Move AC_CHECK_FUNCS( getnameinfo getaddrinfo ) behind the check for libsocket to have them found on Solaris * Fix IPv4-only bug in bind_addr use in retry_connect() * Add more debug code in connect_port() 3.1.5 (26-03-2015): * Fix IPv6 issue with portcheck (need to be able to specify IPv6 interfaces). * Fix minor issues with bugs in testing code * Add command line option '--server-host' to set the log server * In samhain.startLinux.in start script template, add code to read options from /etc/sysconfig/${NAME} for RedHat 3.1.4 (17-02-2015): * Add non-existent file to the regression test config * Fix erroneous call to sh_hash_init when a missing file is specified in the configuration * Fix buffer allocation for getgrnam_r for large groups (problem reported by Sergio B) * Search RPM in $HOME/rpmbuild if test -d _topdir fails (CentOS recommends '%(echo $HOME)/topdir', reported by E. Taft) 3.1.3 (01-11-2014): * Remove initgroups() from the popen call in unix entropy gatherer * Add error message for update mode if local baseline cannot be found 3.1.2 (07-08-2014): * Fixed incorrect memset in sh_checksum.c (sha256) * Circumvent a gcc compiler bug with inline asm (gcc 4.8) * Allow multiple exclusions for SUID check * Use calloc instead of malloc * Add overflow check in minilzo.c (but the potential integer overflow [CVE-2014-4607,LMS-2014-06-16-1] is irrelevant anyway because the function is never used on external data). * Fixed a minor bug in exepack_fill.c that was unearthed by the minilzo overflow check (the required buffer length information for the check wasn't provided) * Fixed incorrect logic in setting the ALLIGNORE flag (more specific directory / file directives were ignored) * Fix for tickets #358 (repetitive lstat warning about deleted directory) and #359 (reporting of deleted/added top level directory) * Fix a free() on NULL (harmless but avoids spurious warning) 3.1.1 (01-05-2014): * Disable inline asm on Cygwin (issue reported by Erik) * Fix sh_ipvx_is_ipv4 such that numeric hostnames are not incorrectly recognised as IP address (reported by A. Hofland) * Fix sh_ipvx_is_ipv6 3.1.0 (31-10-2013): * Add support for SHA2-256 checksum function * Drop support for --enable-khide on kernel version 3.x and above * Fix IgnoreAdded to anchor regex at beginning of path (reported by R.Lindner) * Add check to detect availability of pmap_getmaps() (missing in static library on recent Linux systems as reported by Ian Baldwin) * Fixes for Ubuntu 13.4: - no error msg for failing stat on /run/user/Username/gvfs in suidcheck - no error message for failing hardlink check on /run/user/Username - eliminate compiler warnings * Add option '--disable-asm' to work around a gcc issue in Debian unstable (reported by micah) * Remove option '-i' from mkitab in samhain-install.sh.in (reported by N. Kerski) 3.0.13 (11-06-2013): * Fix detection of nonfunctional /dev/kmem * Fix race condition in GrowingLogfiles policy that causes spurious reports (problem noticed by J. Daubert) 3.0.12 (16-05-2013): * Fix compiler warning in bignum.c (unused parameter) * Detect if /var/run is a symlink and /run exists * Fix for broken support for audit subsystem (reported by isquish) * Fix for incorrect use of sh_inotify_add_watch_later which causes a steady increase in memory usage (issue reported by Maxime V) * Fix for potential minor memory leak * Fix for bug in negated conditionals for config file (reported by M. Ward) 3.0.11 (08-04-2013): * Fix for compile error on HP-UX (reported by P. Alves) * Propagate ERANGE error from getgrxxx_r (issue raised by C. Feikes) * Fix reconnecting to database for Oracle * Add better logrotate handling for the GrowingLogs policy (search rotated log and verify it, don't report if this succeeds) * Add ability to create debian packages with preset password (use env var PASSWORD) * Add option KernelCheckProc (bool) to suppress kernel /proc test * Add option IgnoreModified to cover transient files that not only get added/deleted but also modified 3.0.10 (13-01-2013): * Revert to previous logic in samhain.c because it will block otherwise (reported by Alexandr Sabitov) 3.0.9 (21-12-2012): * Fixed a Cygwin compile warning * Change logic in samhain.c to make sure inotify doesn't cause excessive full scans * Add option IgnoreTimestampsOnly in Windows registry check (ignore changes if only timestamp has changed) * Fix the probe command (misses clients if their startup message has been missed) * Fix the RPM spec file for --enable-network=client and no password (reported by Mitch St Martin) * Fix build error with Linux audit (reported by Andy Jack) * Fix detection of utmpx.h (reported by D. Thiel) 3.0.8 (01-11-2012): * rename to 3.0.8 for release * useful exit status for samhainadmin.pl --examine 3.0.7a (25-12-2012): * add ability to create RPM with preset password (use env var PASSWORD) * fix the rpm-light makefile target * fix minor bug in samhain_setpwd.c (incorrect error message) 3.0.7 (25-10-2012): * update documentation for prelude * fix configure to properly search for Oracle Instantclient SDK * pass through TNS_ADMIN environment variable for Oracle * optimize audit rules automatically * zero out the html status file at server exit * don't check for assembly optimization unless linux or *BSD 3.0.6 (01-09-2012): * install logrotate script if /etc/logrotate.d is detected * new option --enable-suid for nagios * fix for --enable-ptrace: make the save_tv variable thread specific * fix bug in inotify code which made it follow symlinks (by [anonymous]) * fix two missing SH_MUTEX_LOCK(mutex_thread_nolog) (by [anonymous]) * fix for 'no such process' message from sh_fInotify_init_internal() (by [anonymous]) * fix for --enable-ptrace with threads (by [anonymous]) * option SetReportFile for writing out summary after file check 3.0.5 (11-07-2012): * fix xml format templates for registry check * fix database download on registry check init (reported by ldieu) 3.0.4 (01-05-2012): * fix verbosity of message for alerts on already deleted watches (set it to debug - suggested by xrx) * fix extraneous error messages about file not found from sh_fInotify_init_internal() (bug reports by xrx and aj) 3.0.3 (28-03-2012): * fix potential deadlock in sh_ext_popen() * make sure sh_processes_readps cannot hang forever * fix for deadlock if sh_processes_readps hangs * fix for deadlock if suid check and inotify are used together (reported by A. Jack) * fixed problem with samhain_stealth.c (handle input config files that don't end with a newline) * fixed compiler warnings for yulectl.c with stealth * fixed lacking support for O_NOATIME on 64bit linux 3.0.2a (23-02-2012): * Fix compile error on Solaris 10 3.0.2 (16-02-2012): * change sql init scripts to make bigint fields unsigned (problem reported by A. Sabitov) * patch by Andy Jack for issue with the --with-gpg option (hangs with high cpu load at startup) * call ./samhain-install.sh as /bin/sh ./samhain-install.sh in the RPM spec file, because /var might be mounted noexec (reported by GC) * fixed configure.ac for the case that --with-gpg and --enable-nocl are used (./samhain for gpg checksum; problem report by Andy Jack) * fixed a potential NULL pointer dereference in sh_inotify.c on systems where inotify is not available (reported by ) * fixed: the config file template mentions (in a comment) the non-existent directive SetLockPath instead of the correct SetLockfilePath (reported by Curtis). * fixed: the definition of O_NOATIME isn't seen in sh_files.c. 3.0.1 (07-12-2011): * fix a memory leak (reported by C. Westlake) * fix an uninitialized variable in the suidcheck code (problem reports by T- Luettgert and Kai) * fix a bug in the port check with --disable-ipv6 (reported by C. Westlake) * fix potential deadlock in sh_files.c (reported by S. Mirolo) * change Makefile.in to stop on compile error rather than at link stage (suggested by S. Mirolo) * fix compile errors caused by missing #define (pthread disabled) and wrong function call (OSX specific code), reported by S. Mirolo * fix warning by the llvm/clang static checker * fix compile issues on freebsd * handle (ignore) SIGPIPE more thoroughly * update config.guess, config.sub 3.0.0a (06-10-2011): * Fix compile-time issues on RHEL5 (reported by Thomas) 3.0.0 (01-11-2011): * Add support for the inotify API * If --disable-shellexpand is used, also disable setting the prelink/ps paths * Fix missing check_mask storage for glob pattern * Add support for integer keys in zAVL * Fix compiler warnings with gcc 4.6.1 (variables that get set but then remain unused) * Add more server-side debugging for IPv6 * Make kern_head compile with 3.x kernels 2.8.6 (20-09-2011): * Manual updated. * Added an option LogmonDeadtime to avoid repetitive reporting on correlated events. * Fix problems with timestamp handling in logfile correlation (problem reported by D. Dearmore) * List the policy under which a directory/file is checked * Option to use a textfile with a list of files for update * Fix --enable-db-reload option (reported by David L.) * Fix samhain_kmem compilation, need to compile under chosen name if --enable-install-name is used (reported by David L.) * Fix uninitialized string in error message (reported by mimox) 2.8.5a (16-06-2011): * Fix autolocal.m4 for new configure option 2.8.5 (15-06-2011): * Detect non-working /dev/kmem in configure script, and fix a bug in the samhain_kmem kernel module. * Fix wrong handler for LogmonMarkSeverity (reported by S. Chittenden) * Better protection against the 'intruder on server' scenario pointed out by xrx. Add option to disable shell expansion in configuration files, and check gpg signature earlier. * Support /opt/local/bin in the Unix entropy gatherer (suggestion by Sean Chittenden) * Cache timeserver response for one second (suggestion by Sean Chittenden) 2.8.4a (11-05-2011): * Fix for compile error with --with-prelude (reported by Sean Chittenden), missing regression test added * Fix for compile error with --enable-udp (reported by Sean Chittenden), missing regression test added 2.8.4 (30-04-2011): * Fix another reload bug in the log monitoring module * Add unit tests for IgnoreAdded/IgnoreDeleted configuration directives * Fix deadlock after reload when compiled with --enable-login-watch (reported by M. Teege and O. Cobanoglu) * Fix compile error for samhain_hide.ko with recent kernel * Include patch by J. Graumann to specify the location of the secret keyring with samhainadmin.pl * Fix potential timeout problem in sh_sub_stat_int() and propagate the error (issue reported by mtg) * Add support for X-Forwarded-For in apache logfile parser, add option 'RE{regex}' to insert arbitrary regex * New options PortcheckMinPort, PortcheckMaxPort for the open ports check 2.8.3a (23-03-2011): * Fix two 'label at end of compound statement' errors on FreeBSD (reported by David E. Thiel) 2.8.3 (22-03-2011): * init scripts: load samhain_kmem.ko before samhain starts * slib.c: eliminate mutex from sl_create_ticket() * sh_entropy.c: move pthread usage out of child * sh_hash.c, sh_pthread.c, sh_pthread.h: sh_hash_hashdelete() needs deadlock detection, may be called from within sh_hash_init() via atexit handler on error condition * sh_suidchk.c, sh_calls.c, sh_calls.h: need a nosub version of lstat() to use with relative path after chdir() * samhain.c, sh_calls.c, sh_calls.h: only run (l)stat() in subprocess after reading config file (to allow disabling) * sh_unix.c: run sh_sub_kill() in parent after forking the daemon * fix zeroing of result from getnameinfo() (problem reported by Richard) * fix spurious warnings about unsupported address family (reported by N Silverman) * option to run lstat/stat in subprocess to avoid hanging on NFS mounts (off by default) * fix Windows/Cygwin compile error (reported by A. Schmidt) 2.8.2 (16-02-2011): * add function to skip checksumming * Fix missing check for recursion depth >= 0 if not IgnoreAll * Fix hardcoded path for temp directory in deployment scripts * Fix bad compile on CentOS 4.8 with gcc 4.1.2 * Fix minor bug in check_samhain.pl (pointed out by J.-S. Eon long ago) 2.8.1 (17-11-2010): * Document handling of missing files with secondary schedule * Fix incorrect handling of missing files when secondary schedule is used (reported by Sergey) * Fix null pointer dereference in config parse handler for SetMailAlias (reported by Sergey) * Fix incorrect memset() in sh_kern.c (passed struct by value...), reported by Roman and Stefan * Fix 'make install' to create user-defined directory * fix minor issues noticed by T. Luettgert (test code assumes port 0/tcp is unused, wrong ifdef order (without impact on compilation)) * fix compile error on AIX 5.3 with --enable-login-watch, reported by M. El Nahass (time.h missing in src/sh_login_track.c) 2.8.0 (01-11-2010): * Support IPv6 * Add registry checking * Use auditd records to find out who did it 2.7.2c (23-09-2010): * Fix uppercase hostname problem in client/server communication 2.7.2b (05-09-2010): * Fix compile errors on Solaris 10 (reported by A. Saheba) 2.7.2a (23-08-2010): * rewrote rijndaelKeySched() in a more conservative way to fix compile problem on SLES 11. 2.7.2 (16-08-2010): * sh_utils.c: fixed an endianess issue that prevented cross-verification of email signatures (reported by A. Zangerl) * sh_login_track.c: fix compiler warning (ignored return value of fwrite) * sh_readconf.c: fix comparison of SeverityUserX string (reported by max__) * sh_processcheck.c: sh_prochk_set_maxpid: set retval on success (reported by max__) * fixed some compiler warnings on cygwin * sh_extern.c: As reported by T. Luettgert, gcc 4.4.4 on Fedora 13 will throw a warning if execve is called with a NULL argv pointer. Need to provide a dummy argp[]. 2.7.1 (07-06-2010): * samhain_kmem.c: fix compile problems * fix problems with config file parser: increase max. line length, support quoting/escaping of filenames (as in 'ls --quoting-style=c') * check for pcre_dfa_exec (not available in old versions of libpcre, reported by Shinoj) * patch to allow server to log client reports to prelude (by J. Ventura) 2.7.0a (09-05-2010): * fix /dev/kmem detection (reported by S. Clormann) 2.7.0 (01-05-2010): * sh_utmp.c, sh_login_track.c: additional login checks * sh_unix.c: use SIGTTIN as alternative for SIGABRT (SIGABRT seems not to work on AIX, reported by Peter) * sh_utmp.c: fix compile error without pthreads (inotify_watch used) * sh_kern.c, kern_head.c: fix some 64bit issues * dnmalloc.c: fix compiler warning (ignored ret value) * Fix LSB init script for kernel module * samhain_kmem kernel module for /proc/kmem added 2.6.4 (22-03-2010): * Don't read proc_root_iops in sh_kern.c (Problem report by H. R.) * Logfile check can check output of shell commands * Use data directory as default for logfile checkpoints * Fix broken checkpoint save/restore for logfiles 2.6.3 (10-03-2010): * Fix bug in mail module, recipients incorrectly flagged as aliases, which breaks immediate mail for 'alert' (reported by Jesse) 2.6.2 (28-01-2010): * Makefile.in: fix problem in deploy system caused by adding build number for debs in 2.5.9 (reported by roman) * add option for per-rule email alias in log monitoring module * sh_readconf.c: make keywords case-independent * sh_mail.c: on error, report full reply of mail server * sh_mail.c: report smtp transcript at debug level * make sure mail aliases are not emailed twice, and recipients cannot be defined after aliasing them * handle named pipes in log monitoring module (open in nonblocking mode, ignore read error if empty) * fix bug in the server function to probe for necessity of configuration reload for client 2.6.1b (23-12-2009): * fix missing include for sh_inotify.h in sh_inotify.c (reported by Ack) 2.6.1a (22-12-2009): * fix typo in code for older inotify versions without inotify_init1(), reported by Forll 2.6.1 (21-12-2009): * add a routine to log monitoring module to guess the proper year for timestamps without year (standard syslog) * add feature to automatically detect and report bursts of similar messages in log monitoring module * add feature to check for missing heartbeat messages in log monitoring module * cache UIDs/GIDs to reduce the number of lookups * use inotify to track login/logout (sh_inotify.c, sh_utmp.c) * support event correlation in log monitoring module * make sure host matching is done in a case insensitive way (reported by Tracy) * fix invalid use of mutex_mlock in src/sh_unix.c, function sh_unix_count_mlock() (reported by Remco Landegge). 2.6.0 (01-11-2009): * don't use statvfs() for process checking on FreeBSD * fix bug with parallel compilation of cutest in Makefile * sh_mem.c: fix deadlock in debug-only code * Evaluate glob patterns for each run of file check * Add compile option to disable compiling with SSP * Run SUID check in seperate thread * By default disable scanning ..namedfork/rsrc (deprecated by Apple) 2.5.10 (12-10-2009): * sh_suidchk.c: handle $HOME/.gvfs mount gracefully * slib.c: fix race condition caused by closing a stream and the fd 2.5.9c (01-10-2009): * move stale file record error message closer to problem zone * sh_port2proc.c: fix flawed logic for interpreting /proc/net/udp,tcp 2.5.9b (22-09-2009): * remove stale file record when creating handle, and raise diagnostic error to find origin of stale record * sh_port2proc.c: check /proc/net/upd6 for IPv6-only UDP sockets 2.5.9a (17-09-2009): * fixed a race condition in closing of file handles 2.5.9 (11-09-2009): * added code to generate directory for pid file, since it would get cleaned if /var/run is a tmpfs mount (problem reported by M. Athanasiou) * fixed a bug that prevented reporting of user/executable path for open UDP ports (issue reported by N. Rath) * added more debugging code 2.5.8a (18-08-2009): * fixed a bug in sh_files.c that would prevent samhain from running on MacOS X (reported by David) 2.5.8 (06-08-2009): * fixed a bug in the MX resolver routine which causes it to fail sometimes (issue reported by N. Rath). * fixed deadlock with mutex_listall in sh_nmail_test_recipients() if error occurs within sh_nmail_flush (problem reported by N. Rath) 2.5.7 (21-07-2009): * sh_userfiles.c: set userUids = NULL at reconfiguration (issue reported by U. Melzer) * if available, use %z to print timezone as hour offset from GMT in email date headers (problem reported by NP, solution suggested by TimB). * eliminate C99-style comments (problem reported by venkat) * fix bad variable name for AC_CACHE_CHECK * fix potential deadlock when external programm is called (problem reported by A. Dunkel) 2.5.6 (09-06-2009): * recognize fdesc filesystem on MacOS X for suid check (Problem reported by David) 2.5.5 (01-05-2009): * fix some warnings from gcc 4.4 (strict aliasing) * fix minor memory leak in process check * t-test1.c: change function names because of clashes with an AIX system header file * fix warnings with -fstack-check (too large stack frames) * fix for incorrect handling of hostnames in database insertion (reported by byron) 2.5.4 (04-03-2009): * fix for incorrect input check in SRP implementation (discovered by Thomas Ptacek) * option KernelCheckPCI to switch off check of PCI expansion ROMs 2.5.3 (25-02-2009): * disable dnmalloc on MacOS X, doesn't work properly * stat -> lstat in sh_unix_file_exists (OS X nameforks, report by David) * Fix problem in standalone trustfile, does not work correctly on group-writeable files (reported by David). * Option SetThrottle to throttle throughput for db download * Option SetConnectionTimeout to configure the client connection timeout configurable * Provide getrpcbynumber, getservbyname implementations to avoid dependencies with static linkage * Fix missing sh.host.(system|release|machine) on FreeBSD, reported by D.Lowry * New option SetMailPort to allow setting of SMTP port (patch by lucas sizzo org) * allow POSIX regexes for filters * consolidate filtering code from sh_extern.c, sh_(n)mail.c * rewrite mail subsystem to allow individual filtering for recipients * allow shell expansion for values of config file options * allow list as value for option PortCheckInterface * fix bug in trustfile.c (with slapping on "/../" for symlinks) * lock baseline database upon writing 2.5.2b (29-01-2009): * turn warnings into errors in the compile test suite * fix missing define in sh_portcheck.c to eliminate compiler warning (reported by joerg) 2.5.2a (26-01-2009): * fix problem building deb package (bit rot; reported by joerg) 2.5.2 (22-01-2009): * samhain.c: report module failure with positive offset * sh_database.c: parse numerical fields into ulong * fix regression test script for postgresql * fix regression test script for SELinux/ACL test * fix reporting of user for open ports to prelude * report process pid for open ports * replace _exit() by raise(SIGKILL) b/o pthread problem * new option LooseDirCheck ([false]/true), request by Alexander * improved help output of samhain_stealth (as suggested by Michael Athanasiou) * new option ProcessCheckIsOpenVZ ([false]/true) 2.5.1 (07-12-2008): * workaround for freebsd7 amd64 lossage (compiler toolchain, no mmap to 32bit address space) * samhain-install.sh: check for presence of stealth_template.ps before trying to create it * use -Wno-empty-body if supported to suppress warnings about glibc pthread_cleanup_pop implementation * fix text relocations for i386 in src/sh_tiger1.s * implement server->client SCAN command to initiate file check * implement @if / @else conditionals with more tests in config file * new option SetDropCache to drop checksummed files from cache * report process/user for open ports on FreeBSD (code lifted from FreeBSD sockstat.c) * fix for config reload issue with stealth mode (reported by siim) * add -fstack-protector flags to LDFLAGS * cygwin fix: don't use dnmalloc, doesn't work with pthreads * cygwin fix: make trust check in samhain-install.sh return zero * improved diagnostics for file read errors * fixed script permissions (754 -> 755), reported by Christoph * constness patch by Joe MacDonald * GnuPG key ID patch by Jim Dutton * sh_kern.c: more error checking for reads from kernel 2.5.0 (01-11-2008): * dnmalloc.c: fix inconsistent chunksize on 64bit systems * fix improved error reporting for failed fstat in checksumming * report process/user for open ports (Linux only currently) * fix deadlock on exit in sh_hash_init() * fix --enable-mounts-check for FreeBSD 7.0 (no MNT_NODEV anymore) * log monitoring support * fixed constness in trustfile interface * remove libprelude 0.8 support (obsolete) * sh_forward.c: increase TIME_OUT_DEF to 900 secs * dnmalloc.c: initialize rc in dnmalloc_fork_child(), reported by B. Podlipnik 2.4.6a (09-10-2008): * fix compile problem on Fedora 9 (reported by pierpaolo), 'struct ucred' in sh_socket.c requires _GNU_SOURCE 2.4.6 (27-08-2008): * fix compile failure on win2k/cygwin (sh_unix_mlock prototype), reported by jhamilton * fix potential deadlock with dnmalloc upon fork() * fix non-portable use of 'hostname -f' in regression test suite (reported by Borut Podlipnik) 2.4.5a (18-08-2008): * fix compile problem in dnmalloc.c (remove prototypes for memset/memcpy), problem reported by Juergen Daubert 2.4.5 (07-08-2008): * testscripts: 'chmod -R' -> 'chmod -f -R', since Solaris 10 bails out on a chmod on a dangling link * fix bug in check_samhain.pl nagios script (J.-S. Eon) * use the UNO static checker * compile as position independent executable (PIE) * handle EINPROGRESS error (Windows/cygwin issue) * make sure every function uses less than one page of stack (proactive security against gap jumping, Gael Delalleau) * use dnmalloc instead of system malloc (proactive security against heap buffer overflows) * fix dnmalloc bugs and portability problems * check for compressBound, since older zlibs don't have it 2.4.4 (30-04-2008): * sh_database.c: fix maximum size of sql query string, maximum size of strings in struct dbins_ * sh_hash.c: fix maximum size of message string * fix typo in the base64 decoder * fix 'make cutest' for parallel compiling * fix compile warnings with -Wstrict-prototypes * sh_static.c: override getgrgid, getpwuid for libacl * fix more warnings about variables clobbered by 'longjmp' or 'vfork' (due to library internal handling of mutexes) * fix configure warning about unused datarootdir * configure.ac: warn, but accept nonexistent tmp dir (Problem reported by Brian) * sh_unix.c: undef P_ALL, P_PID, P_PGID before including sys/wait.h (compile problem reported by Reputation) * syslog function tested ok with Syslog Fuzzer v0.1 by Jaime Blasco (c) 2008 * slib.c: call fflush when writing trace to file * sh_readconf.c: don't set OnlyStderr to false if gpg (problem reported by Irene Reed) * fix unconditional removal of pid file in atexit handler (bug reported by Brian) * fix invalid free() in sh_unix_checksum_size() * sh_processcheck.c: workaround for stupid OpenBSD bug (returns ENODEV instead of EAGAIN, because fgetc does fcntl(0,F_SETFL,O_NONBLOCK) [ENODEV] internally), problem reported by Roman R. * fix buf that cause incomplete reporting of modified symlink if symlink has changed and both old and new paths are >48 bytes * fix bug that prevented mount check from running in one-shot mode * enable mount check for openbsd * fix processcheck default options and test script for openbsd * option --list-file to list content of file (if saved) * sh_tools.c: use strcasecmp in reverse lookup since DNS is case insensitive (bug reported by Phil) * fill content if MODI_TXT, zlib compress, base64 encode and add as link_path in sh_unix.c; add to report in sh_hash.c * testsuite: add test for gpg fingerprint option * sh_extern.c: add 'CloseCommand' for syntactic sugar, add in testsuite 2.4.3a (12-02-2008): * fix compile error caused by open() with O_CREAT and no third argument (reported by J.-S. Eon) 2.4.3 (31-01-2008): * sh_kern.c: don't require asm/segment.h for kernel check module * use global var with pid of initial thread instead of getpid(), since LinuxThreads returns different value in each thread (problem reported by Steffen Mueller) * sh_kern.c: no inode check for pci rom (creates spurious messages) * slib.c: eliminate prototype for vsnprintf (compile problem reported by eddy_cs) * Makefile.in: fix missing dependency on 'encode' for $(OBJECTS) (reported by Matthias Ehrmann) 2.4.2 (17-01-2008): * fix broken option --with-checksum (reported by halosfan), regression test added * change HP-UX default optimization to +O2 since +O3 breaks cutest unit testing framework * put result vector of rng in skey struct * fix more compiler warnings, and a potential (compiler-dependent) NULL dereference in the unix entropy collector * fix some compiler warnings * use -D_FORTIFY_SOURCE=1 -fstack-protector-all instead of -fstack-protector * always add PTHREAD_CFLAGS to LDFLAGS * sh_tiger0.c: checksum functions return length of file hashed, needed to fix GrowingLogfile bug (researched by siim at p6drad dash teel dot net) * sh_static.c: fix more 'label at end of compound statement' (SH_MUTEX_UNLOCK closing brace; reported anonymously) * make sh_hash.c thread-safe * remove plenty of tiny allocations * improve sh_mem_dump * modify port check to run as thread * new option PortCheckSkip to skip ports * fix unsetting of sh_thread_pause_flag (was too early) 2.4.1a (28-11-2007): * fix overwrite of ErrFlags (functionality bug) 2.4.1 (26-11-2007): * security fix: regression in the seeding routine for the PRNG (detected by C. Mueller) * regression test added for PRNG seeding routine * fix problem with PCI ROM check (spurious messages about modified timestamps, reported by S. Clormann) 2.4.0a (08-11-2007): * fix compile failure with --enable-static (reported by S. Clormann) * fix potential deadlock if SIGHUP is received while suspended 2.4.0 (01-11-2007): * eliminate alarm() for I/O timeout (replaced by select) * use getgrgid_r, getpwnam_r, getpwuid_r, gmtime_r, localtime_r, rand_r, strtok_r if available * protect readdir(), getpwent(), gethostname() with mutexes (readdir_r considered harmful) * make checksum/hash, entropy, rng functions reentrant * use thread-specific conversion buffer for globber() * fixed compile problems and problems with test suite * modify login watch to run as thread * modify process check to run as thread 2.3.8 (03-10-2007): * new option PortCheckIgnore = interface:portlist 2.3.7 (13-09-2007): * Makefile.in: fix 'make deb' target, wrong name of config file written to debian/conffiles (reported by marc) * configure.ac: fix incorrect order of with-prelude, enable-static (libprelude test was always without -static) 2.3.6 (06-09-2007): * added yuleadmin.pl script contributed by Riccardo Murri * fix compile error with -f-stack-protector on some systems (reported by marc); we now check for libssp * fix local DoS attack on BSD systems lacking getpeereid() (reported by Rob Holland). * fix yulectl password reading from $HOME/.yulectl_cred, erroneously rejected passwords with exactly 14 chars (reported by Jerry Brown) * introduce 'fflags' flag for suid files to detect new files already found in regular file check (problem reported by J. Crutchfield); also add regression test to ascertain that files in baseline database are not quarantined erroneously * sh_hash.c: replace check for prefix 'K' with check for not prefix'/' to allow for arbitrary module-specific store/lookup in db * replace 'visited', 'reported', 'allignore' with generic 'fflags' field * sh_cat.c: reduce priority of MSG_TCP_RESET to avoid spamming if port checking is used on same host as server (reported by kadafax) * Install.sh: don't use --separate-output with non-checklist widgets (problem discovered by D. Denton) * sh_gpg.c, sh_userfiles.c: use sh_getpwnam et al. wrappers 2.3.5 (20-06-2007): * sh_portcheck.c: try to tear down connections more gracefully (request by S. Petersen) * fix incorrect handling of files with zero size in GrowingLogFiles (problem reported by S. Petersen) * fix incorrect encoding of null checksums in stealth mode * sh_hash.c: fix repeated printing of acl/attributes in database dump * sh_unix.c: fix option useaclcheck ignored if both useaclcheck and useselinuxcheck are supported 2.3.4 (01-05-2007): * sh_processcheck.c: fix missing init of sh_prochk_res array before check (leads to degrading functionality over time and 'fake pid' warnings; reported by D. Ossenbrueggen and soren dot petersen at musiker dot nu) * sh_processcheck.c: fix memory leak * sh_kern.c: for 2.6.21+ don't check proc_root_lookup (not possible anymore? proc_root_inode.lookup != proc_root_lookup) * sh_extern.c: flush streams before forking (problem if [Prelink] used together with prelude logging, reported by M. deJong) * fixed compilation of kern_head (regression cause by cross-compiling fix; problem reported by S. Clormann) * more typos fixed (reported by John Horne) 2.3.3 (27-03-2007): * fixed typos in configure.ac and manual (reported by John Horne) * don't use mysql_options on x86_64, since libmysql is broken * fixed cross-compiling (patch by Joe MacDonald) * refactor sh_kern.c, sh_suidchk.c * fix bug with leading slashes in linked path of symlinks within the root directory * sh_kern.c: check PCI ROM (Linux), refactor code * move file descriptor closing more towards program startup * kernel check: support OpenBSD 4.0 (wishlist) * fix samhain_hide module (in-)compatibility with recent kernels (reported by Jonny Halfmoon) 2.3.2 (29-01-2007): * fix regression in full stealth mode (incorrect comparison of bytes read vs. maximum capacity), reported by B. Fleming 2.3.1a (21-01-2007): * fix incorrect use of sh_gpg_fill_startup if option --with-fp is used (reported by zeroXten) 2.3.1 (21-01-2007): * fix bug that may cause accidental closure of yule TCP socket (problem reported by B. Masuda) * fix sh_kern.c for kernel 2.6.19 (reported by S. Clormann) * don't use sstrip in 'make deb', since dh_shlibdeps uses objdump (reported by B. Masuda) * rm report.pl from rules.deb.in (reported by B. Masuda) * samhainctl(): longer timeout (bad status reporting at startup, reported by Phil and by Dan Track) * sh_portcheck.c: make connect errors more descriptive * sh_portcheck.c: fix ignored setting of PortCheckActive * sh_processcheck.c: add statvfs, and wrap for EINTR * sh_portcheck.c: add wrappers for EINTR * report user and executable for hidden processes * fix update failure if reportonlyonce = false (reported by D. Strine) * fix compile error in sh_portcheck.c (problem on cygwin reported by J. D. Fiori) * check filenames ending in space (also for utf8 spaces) * check and escape csv formatted db listing * cache results of sl_trustfile_euid() * trustfile: use 4096 for MAXFILENAME, switch to strncpy * CL option -v|--version for info on version and compiled-in options 2.3.0a (01-11-2006): * fix compile failure with portcheck + stealth (reported by lucas) 2.3.0 (01-11-2006): * fix concurrency for inserts in oracle db * add acl_(new|old) to database schema * check for selix attributes and/or posix acl * new option UseSelinuxCheck (bool) * new option UseAclCheck (bool) * regression tests for above * add module to check for open ports * add module to check processes (hidden/fake/missing) * use const char* for argument of module configuration callbacks 2.2.6 (31-10-2006): * fix missing support for MacOX X init script (reported by Daniel Kowalewski) * fix error about non-readable file with no checksum required * fix server warning about 'no server name known' * fix 'make deb' makefile target * fix default export severity for server 2.2.5 (05-10-2006): * fix broken Install.sh, reported by Alexander Kraemer * workaround for glob(3) sillyness on MacOS X (reported by David) * fix for broken resorce fork check (reported by David) * fix for broken compilation on cygwin (reported by Elias) 2.2.4 (03-09-2006): * add regression test for the GrowingLogFiles issue to test suite * fixed sh_unix.c: bug in database init if GrowingLogFiles used with signed database (reported by Timothy Stotts) * bug in manual fixed (incorrect documentation of --enable-user, noticed by M. Brown) * rc.subr compatible init script for FreeBSD/NetBSD * improve routine to find rpm after build * add netbsd rc file from Brian Seklecki (taken from pkgsrc-wip) * fix error in manual (location of lock file) * fix bug with SuidExclude (files in directory were still checked) 2.2.3 (31-07-2006): * fix samhainadmin.pl: check for gpg-agent running if use-agent is set (ticket #28 by anonymous) * fix stealth mode (regression in parser), problem reported by Joschi Kuphal * fix minor typo in sh_database.c (compile problem reported by Joschi Kuphal) 2.2.2 (17-07-2006) * minor fixes for regression test scripts * minor updates to the manual (suggested by Brian A. Seklecki) * fix sh_kern.c, kern_head.c: kernel rootkit detection for 2.6.17+ (problem reported by Leonhard Maylein) * fix samhain_hide.c for 2.6.17+: use module_param() if MODULE_PARM is not defined 2.2.1c (11-07-2006) * fix sh_extern.c: sh_ext_add_default() cast to (void) was too early (Solaris 8 build failure reported by Jesse) * fix sh_unix.c: wrong prototype for sh_unix_mlock() if HAVE_BROKEN_MLOCK (AIX 5.2 build failure reported by Jonathan Kaufman) 2.2.1b (20-06-2006): * fix compile error on SuSE 10.1 (reported by Leonhard Maylein) 2.2.1a (15-06-2006): * fix compile error on i686/MacOS X (reported by Andreas Neth) 2.2.1 (13-06-2006): * fix gcc 4 warnings and build failure on x86_64 (debian bug #370808) * fix compiling with Oracle (noticed by Colapinto Giovanni) * fix configure.ac for most recent autoconf version (debian bug #369503) * fix a regression that would make impossible local updates w/clients * fix a few missing '\n' in sh_getopt.c * sh_kern.c: fall back on mmap() if read() fails on /dev/kmem * fix Solaris package creation * recognize Solaris doors and event ports * fix the idmef_inode_t patch: provide required info to avoid stat() * fix bug on database update: fill in dev and rdev fields * fix get_file_infos() in sh_prelude.c: avoid premature return * GCC_STACK_PROTECT_CC: AC_TRY_COMPILE -> AC_TRY_LINK * deploy.sh: allow to set a group for hosts upon installation * patch by Yoann: fix an issue when setting the idmef_inode_t object * fix memory leaks in error paths in sh_prelude.c * fix concurrent inserts with postgres in sh_database.c * code cleanup * fix manual version in spec file, first noticed by Imre Gergely 2.2.0 (01-05-2006): * patch by Jim Simmons for samhainadmin.pl.in * fix testsuite portability problems * fix md5 endianess problem detected on HP-UX 11i / PA-RISC 8700 * fix potential NULL dereference in sh_utmp_endutent() * patch by Neil Gorsuch for suidchk.c (do not scan lustre, afs, mmfs) * fix sh_ext_popen (OpenBSD needs non-null argv[0] in execve) * fix make_tests.sh portability (echo '"\n"' does not work on OpenBSD) * fix bug in sh_utils_obscurename (check isascii) * scan h_aliases for FQDN if h_name is not * add copyright/license info to test scripts * add copyright/license info to deployment system scripts * support server-to-server relay * new CL option --server-port * minor improvements in manual * patch by Yoann Vandoorselaere for sh_prelude.c * allow --longopt arg as well as --longopt=arg * verify checksum of growing log files (up to previous size) * rewrite of the test suite * added a bit of unit testing * minor optimizations in various places * optimized implementation of tiger checksum algorithm * read in 64k blocks (faster than 4k) * sh_unix.c, sh_hash.c: support file flags on *BSD, update Linux file attribute code * kern_head: fix compilation of kernel check module on OpenBSD * updated samhainrc.linux, samhainrc.freebsd * sh_unix.c: fix setrlimit (RLIMIT_NOFILE, ..) * sh_files.c: fix missing use of flag_err_info * sh_tiger0.c: remove repetitive use of mlock * slib.c: remove fcntl's from sl_read_timeout (caller sets O_NONBLOCK), add function sl_read_timeout_prep 2.1.3 (13-03-2006): * fix compile problem in slib.c (reported by Lawrence Bowie) * fix bug with combination of one-shot update mode and file check schedule (reportedby Dan Track) * improved the windows howto according to suggestions by Jorge Morgado * fix samhain_hide kernel module for new linux kernel versions * fix minor problem with dead client detection (problem reported by Michal Kustosik) 2.1.2 (10-01-2006): * fix startup error with combination of gpg+prelude 2.1.1a (22-12-2005): * fixed a stupid bug in sh_files.c (break if file = dir) 2.1.1 (21-12-2005): * sh_calls.c: protect sh_calls_set_bind_addr against overriding * comINSTALL, updateDB: use locking * samhainadmin.pl: use locking * fix typos in samhainrc.solaris (noticed by Robby Cauwerts) * improve zAVLSearch (remove redundant strcmp) * use AVL tree in sh_files.c instead of linked list (better scaling) * fix bug with suidcheck (no update/check in one-shot mode with schedule instead of check interval; noticed by R. Rati) * fix for problem with '-t update -i' if daemon mode (problem report by Peter van der Does) * fix for bug in sh_util_ask_update (two returns were required ...) 2.1.0 (31-10-2005): * minor fix for cross-compiling with --with-kcheck * sh_forward.c: handle bad fds in the select() fd sets (reported by hmy) * sh_extern.c: fix debugging code * slib.c, sh_calls.c, sh_calls.h: improve handling of O_NOATIME (reported by Gabor Kiss) * makefile.in: fix for solaris package creation * sh_mail.c, sh_readconf.c: mail filtering options * sh_database.c: Oracle reconnect on connection failure (bug report by Alexander A. Sobyanin) * sh_unix.c: don't purge MYSQL_UNIX_PORT environment variable (problem reported by Peter) * sh_calls.c: fix for a HP-UX accept() problem caused by the gcc4 fix * fixes for gcc 4.0.2 compiler warnings * ability to use daemon mode together with update (wishlist Yoan Vandoorselaere) * fixes for debugging 2.0.10a (22-08-2005): * fix for overlapping directory check specification (reported by Bub) 2.0.10 (21-08-2005): * fix for segfault (free() on a constant string) with libprelude (problem reported by Grae Noble) * upgrade FreeBSD kernel check to 5.4, minor fixes * useful script for users of Linux kernel check (contributed by marc heisterkamp) * documentation improvements (suggested by Brian Seklecki and Robby) 2.0.9 (25-08-2005): * samhain_erase.c: add #define for NULL * sh_suidchk.c: fix incorrect use of escaped filename * sh_prelude.[ch], sh_readconf.c: configurable mapping from samhain severity to prelude severity * sh_unix.h: second arg of gettimeofday should be NULL * sh_files.c: fix checking of directory special file (use specified policy, not that of parent dir, problem found by Brian A. Seklecki) * sh_entropy.c: longer timeout for entropy collector * sh_socket.c, sh_forward.c: allow probing of clients for necessity of configuration reload * yulectl: minor fixes, option -v (verbose), new command PROBE * fix 'File not found' messages for files flagged with IgnoreMissing * sh_database.c: strip newline from oracle error messages * sh_files.c: fix rsrc fork issue with MacOS X Tiger (reported by A. Koren) * never compute checksum if not checked (problem report by D.Hughes) * sh_prelude.c: cleanup and bugfix by Yoann * sh_hash.c: for prelude, make sure mode is supplied with user/group and vice versa * sh_prelude.c: provide proper FileAccess objects (bug report by Mihai Ilinca) 2.0.8 (03-07-2005): * configure.ac: use $LIBPRELUDE_PTHREAD_CFLAGS rather than $LIBPRELUDE_CFLAGS (bugfix by Yoann) * samhain.spec.in: remove support for chkconfig (it's too buggy). Strangely, if invoked as install_initd it behaves sanely ... * src/sh_err_log.c: fix key input (this time for real) * fix --with-altlogserver (bug from 2.0.7b) * remove server socket in start/stop script 2.0.7e (not released): * Makefile.in: introduce a total of 6 sec delay for 'make' utilities that use 1 sec resolution, and consider target out-of-date if timestamp(target) = timestamp(dependency) ... * src/sh_err_log.c: fix key input * another fix for yulectl (use pwent->pw_dir) * dsys/comINSTALL, dsys/comUNINSTALL, dsys/comBUILD: fix PATH 2.0.7d (not released): * one more fix for the spec file (stupid rpm finds tags in comments!!!) 2.0.7c (not released): * test/testrun_1b.sh, test/testrun_2b.sh: use $GPG_PATH * dsys/comINSTALL, dsys/funcDB, dsys/funcINSTALL: some bugfixes * samhain-install.sh.in: fix test -z $verbose * sh_hash.c: speedup database reading * Makefile.in: fix the problem that BSD make would make too much * deploy: yulerc.clients -> yulerc.install.db, provide $defdatabase for backward compatibility * deploy: allow for comma in client_install_date 2.0.7b (not released): * hp_ux.psf.in: fix psf file * dsys/comINSTALL: fix $yule_date -> $yule_data * Makefile.in: fix 'make depot' * sh_tools.c, sh_unix.c: fix detection of open file limit * sh_readconf.c: reset read_mode after reading conf file * yulectl.c: better error messages, use homedir from getpwuid(geteuid) * init/samhain.startLSB.in: fix misleading message in lsb init script * sh_forward.c: better display for nonce u in debug mode * sh_tiger*.c: fix checksum for HP-UX 64bit * samhain.c: don't fetch database twice * configure.ac: accept nodename for --with-logserver=... * samhain_setpwd.c: return proper exit status for samhain_setpwd * respond to SIGTERM on initializing * fix problems with samhainadmin.pl * sh_utils.c: fix bug with AddOKChars (found by Karol) 2.0.7a (not released): * remove 'df' from entropy gatherer (NFS may hang) * modify va_copy check (doesn't work with HP-UX PA64 compiler) * fix compile warnings in sh_database.c * samhain-install.sh.in: check for /usr/bin/false in /etc/shells * fix install-boot on HP-UX * aclocal.m4: fix configure CL parsing to recognize VAR=VALUE 2.0.7 (11-06-2005): * yet another fix for the spec file (use internal dependency generator) * sh_error.c, sh_prelude.c: init libprelude after open fds are closed * error message if queue is full * fix two compiler warnings on HP-UX * fix sh_mail.c for Interix (no resolver routines) * fix sh_unix_initgroups2() if no initgroups() function (bug reported by Geries Handal) * remove references to 'struct timezone' (Interix; problem reported by Geries Handal) * init/stop for prelude on SIGHUP * sh_cat.h: fix a stupid bug with messages classes * manual: new section on nagios (with help from kiarna), more on prelude * sh_prelude.c: cleanup and improvements (Yoann Vandorselaere) * default prelude profile name now is 'samhain' (lowercase) * sh_readconf.c: new option PreludeProfile (by Yoann Vandorselaere) * remove obsolete check for linux/module.h, linux/unistd.h * remove dependency on virtual/glibc in gentoo ebuild (problem reported by Willis Sarka) 2.0.6 (01-03-2005): * sh_prelude.c, configure.ac, aclocal.m4: support for libprelude 0.9 (Yoann Vandoorselaere) * sh_html.c: fix bug with entry.html template (reported by Stephane Sanchez) * Install.sh: fix mandir option (reported by Rodney Smith) * Fixed Linux/64bit bug in definition of EUIDSLOT * New targets 'make depot', 'make depot-light' (HP-UX, untested) * Use sstrip for RPMs and DEBs (automatic stripping disabled) * Fix aclocal.m4 for autoconf 2.59 (missing $ac_cr_alnum et al., problem noticed by Yoann Vandoorselaere) * Modify samhain.spec.in to disable automatic stripping upon install * Fix deploy.sh + '--enable-gpg', and fix 'make rpm' and 'make deb' for '--with-khide' (problems reported by Mark) * Fix compile error in sh_tools.c on HP-UX 10.20 (problem reported by Dennis Boylan) * Runtime configuration of server listening port (wishlist) * Runtime configuration of server listening interface (wishlist) * Ignore SIGTTIN (consistency) * Use SIGTTOU to force file check (wishlist) 2.0.5b (01-04-2005): * Fix build problem b/o timestamp on stamp file 2.0.5a (16-03-2005): * Fix problem with 'make rpm' (reported by Dirk Brmmer) 2.0.5 (02-03-2005): * Fix bug with partial reads from clients in server (bug report by Brian) * Support gpg checksum bootstrap with yule * Support mount option check on HP-UX * For MAIL FROM, use 'example.com' as domain part if hostname is numeric (problem reported by Eric Raymond) * The HOWTO-write-modules has been updated. * Convenience functions to insert data in database have been added. * Use int0x03 only on i386 in sh_derr() (portability problem reported by John Mandeville) 2.0.4 (09-02-2005): * Fixed broken 'make deb' (problem report by olfi) * Fixed minor bug in test scripts (detection of gmake vs. make) * Fixed Tru64/OSF compile warnings (reported by B. Terp) * Normalize list parsing to allow comma, space, and tab as separators * Some more descriptive error messages in kern_head.c * Absolute path to utilities in init/samhain.startLinux.in * Fixed is_root variable in deploy.sh * Fixed 'deploy.sh info' * Fixed 'deploy.sh install' client startup * Fixed 'make tbz': don't remove ebuild scripts in 'make dist' (issue reported by W. Sarky) 2.0.3 (14-12-2004): * Fix CPPFLAGS with mysql/postgresql (repoted by P. Smith) * Fix missing sys/time.h include in slib.c (reported by Jonas) * Workaround for file closing problem with Prelude+GPG * Fixed memory leak with Prelude. * Fixed bug in samhain_stealth (PGP signature not correctly retrieved from hidden configuration; report and patch by V. Tuska) * Added Perl script to concatenate file signature database files * Fix compile error with combination of --enable-nocl and --enable-stealth (reported by Zdenek Polach) * Fix bug in dsys/initscript with --enable-nocl * Fix declaration of sh_kern_timer() * Fix missing Mounts+Userfiles options in appendix of manual * Updated the README (bug report by H. Franzke) * Fix some compiler warnings 2.0.2a (09-11-2004): * Fixed OoM condition when client rc file not found (reported by Eilko) 2.0.2 (08-11-2004): * Fixed buffer overflow in sh_hash_compdata() (only in 'update' code) * Fixed uninitialized variable in sh_mail_msg() (problem reported by Michael Milvich) * Fixed potential NULL pointer dereference in sh_hash_compdata() 2.0.1 (01-11-2004): * Fixed compilation bug reported by jue (--with-kcheck broken). * Fixed start option (bug reported by sanek). Behaviour wrt. environment variables depended on the way the daemon was started. 2.0.0 (31-10-2004): * The deployment system has been rewritten from scratch in a cleaner and more modular and extensible way. Deployment of native packages is supported now. * The build system has been revised. Building outside the source directory is supported now. * Support for checksumming of prelinked executables / libraries has been added. * The configure script now checks for the SSP/ProPolice patch in GCC, and enables it if present. * The install-boot option in samhain-install.sh has been fixed (use absolute paths for sbin utilities). * A nagios plugin (scripts/check_samhain.pl) has been added. * The LSB (Linux Standard Base) init script has been fixed (the output was incorrect). * Fetching of built binary packages has been fixed ($(PACKAGE)->@install_name@). * For files in proc, the timeout has been reduced, and no error messages are issued upon timeout. * A function has been added to print out full details for missing files if encountered while in sh_files(). * The reporting for SuidCheck has been fixed (incorrect policy noticed by JiM). * On Linux, SuidCheck does not report on files marked as candidates for mandatory locking (group-id bit set, group-execute bit cleared). * Fix for oracle init script (by Matt Warner) 1.8.12b (11-10-2004): * fix bug in MSG_MSTAMP (%ld -> %lu) * fix bugs in sh_suidchk.c (%ld -> %lu), check fopen for NULL, mkdir mode for quarantine directory * fix the fix for modlist_lock search in System.map 1.8.12a (01-10-2004): * fix bug in samhain-install.sh.in (only occurs on Solaris), reported by J. Roland 1.8.12 (27-09-2004): * fix compile bug with --enable-static + --with-database=postgresql * fix search for modlist_lock in System.map * password auth for yule command socket (request by D. Kocic) * more info about pending/sent commands to clients 1.8.11 (30-08-2004): * fix static linking on Linux by use of replacement routines from uClib - however, this means, there is no NIS support anymore * new option AddOKChars=... to modify the set of characters for filenames considered 'obscure' * new option HardlinkOffset=... to specify an offset from the canonical hardlink count for a directory * fix some warning with HP 11.23 native compiler * fix minor OpenBSD portability problems (EIDRM, compiler warning) * samhainrc.5, samhain.8: updated the man pages * sh_unix.c, sh_files.c: ignore 'no user/group' and 'obscure name' for AllIgnore * sh_kern.c: fix 'update' to display modifications * sh_kern.c: fix bug with IDT check (spurious alerts b/o uninitialized fields) * stealth kernel modules: fix for linux 2.6, fix redefine of KERNEL_VERSION * warn about stealth kernel module problem with 2.6 in manual * sh_unix.c: remove some cruft * fix a typo in the manual (noticed by J. Rubin) * configure.ac: re-order output from libprelude-config (required for static linking - problem reported by E. Neber) * kern_head.h, kern_head.c: fixes for Linux 2.6 kernel 1.8.10b (13-07-2004): * fix incorrect usage of 'retry_msleep()' in sh_kern.c (reported by Pat Smith) 1.8.10a (13-07-2004): * depend-gen.c: fix for FreeBSD 'make' which does not understand the dependencies ... (problem reported by David Thiel) 1.8.10 (13-07-2004): * sh_unix.c/sh_unix.h: fix defaults for 'GrowingLogFiles' policy (bug report by VZoubkov) * fix some warnings (unreachable statement) with HP-UX native compiler * kern_check.c: silence warning about 'sendfile' for 4.10 (noticed by Ryan Beasley) * modify depend-gen.c to ignore sh_gpg_chksum.h * add a non-plaintext version of GPG_HASH (sh_gpg_chksum.h) * .. and for fingerprint * sh_suidchk.c: fix some compiler warnings on solaris * allow commas to separate multiple entries in a RedefXXX= directive * replace sleep/usleep with nanosleep wrapper function * replace alarm() for read timeout with select() in sl_read_timeout (should fix bug reported by Scott Kelley) * increase lstat/open timeout to 6 sec 1.8.9 (16-06-2004): * made 'no action specified' error message more informative (suggested by Stephen Gill) * fix memory leak in mysql sh_database_query() (bug report by Dejan) * remove some cruft from the code * sh_files.c: check MacOS X resource forks (idea from Osiris) * sh_files.c: no hardlink check for MacOS X * sh_util_ask_update: fix bug with no terminal in non-interactive mode (report and debug data by Kris Dom) * manual refactored * fix redundant messages when updating with suidcheck * allow interactive update for suid files * don't remove the TZ environment variable to guard against misconfigured hosts * also use gethostname if uname returns possibly truncated name * fix improper file descriptor handling in sh_mail.c (bug report by Alex Weiss) * cleanup MBLK cruft * use SH_ALLOC/SH_FREE in sh_prelude.c * update sstrip to Version 2.0 1.8.8 (25-05-2004): * fix compilation problem on AIX 5.2 (nameser_compat.h; report by Tim Evans and Ian McCulloch) * don't check for trusted paths on Cygwin * add Windows HOWTO written by Kris Dom * kern_check.h: extend FreeBSD syscall table for 5.x 1.8.7a (03-05-2004): * sh_mail.c: fix subject length * sh_mail.c: fix the sh.mailNum.alarm_last fix (report by Kris Dom) * sh_utils.c: sh_util_ask_update(): fix ISO C conformance bug (compile problem reported by Kris Dom) 1.8.7 (01-05-2004): * sh_mail.c: fix incorrect count of sh.mailNum.alarm_last, causing empty mails (introduced with segfault fix in 1.8.6, report by Kris Dom) * sh_utils.c: sh_util_ask_update(): check whether stdin is a terminal, try to reopen on controlling terminal if not * sh_utmp.c: fix order of options (problem report by Uri) * sh_files.c: sh_files_chk(): set tmp = NULL at end of loop (may cause segfault on null dereference for missing files) * sh_unix.c: patch by Marc Schtz (order of sh_unix_getinfo_type, sh_unix_getinfo_attr) * don't use dh_installmanpages in 'make deb' (samhain/yule conflict reported by xavier) * on HP-UX, define _XOPEN_SOURCE_EXTENDED in sh_mail.c and sh_tools.c (suggested by Kris) * include nameser_compat.h in sh_mail.c (for MacOS X, suggestion by jna) * sh_utmp.c: fix time for logout events (reported by Erich van der Velde) 1.8.6 (15-04-2004): * add CL option to set threshold for prelude and RDBMS * sh_mail.c: fix bug with MailSubject option (segfault on NULL pointer dereference; reported by Micha Silver) * fix compiling with --disable-encrypt (reported by Pat Smith) * fix minor problem in scheduler (don't return before all schedules are tested, to set last_exec correctly) 1.8.5 (05-04-2004): * fix bugs in sh_utmp.c (unlinking of list head); may fix an OpenBSD problem (endless loop; report and debugging aid by Joe MacDonald) * fix hardlink check (null dereference in error message, segfaults on solaris - noticed by Bob Bloom) * sh_suidcheck: don't truncate quarantined file if nlink > 1 * fix Install.sh (no --seperate-output with --radiolist); patch by Greg Kimberly 1.8.4 (17-03-2004): * add Prelude patch by Patrice Bourgin * add license statement to sh_mounts.c, sh_userfiles.c after receiving a clarifying e-mail from Cian Synnott * support UsePersistent = no for Oracle (problem spotted and fix tested by Michael Somers) * fix bug in samhainadmin.pl * sh_gpg.c: describe type of gpg error (if any) * fix persistent connections with postgresql (reported by Erwin Van de Velde) * prelude: local 'meaning' shadows global in sh_prelude_alert (spotted by David Maciejak) * uname: workaround for cases where nodename would be a possibly truncated FQDN (problem reported by Cian Synnott) * re-write parts of sh_kern.c, store kernel info in baseline database -> no need to recompile after kernel upgrade * modify timeouts in sh_unix_getinfo, add timeout warning * change handling of dangling symlinks (store in db) * fix typo with MSG_FI_OBSC2 (double slash) * remove redundant operation in sh_utils_safe_name * fix occasional random start bytes of long messages in sh_error_string (sl_strlcat -> sl_strlcpy) * provide details for missing files (as for added files) * remove duplicate message for no such group/user * add fixes for samhain.oracle.init (supplied by Michael Somers) * fix date insertion for Oracle (fix by Michael Somers) * manual: fix incorrect statement about RPM (noticed by Lars Kellogg-Stedman) 1.8.3 (02-02-2004): * add a HOWTO-client+server-troubleshooting document * fix another bug with SIGUSR2 (suspend mode) * new option SetBindAddress (--bind-address=...) to force interface for outgoing connections on multi-interface box * don't link against libgmp if not required (i.e. standalone) * test for ext2fs/ext2_fs.h or linux/ext2_fs.h * new make targets 'emerge' and 'tbz2' for gentoo * update rules.deb.in based on the Debian package by Javier Fernandez-Sanguino * updated config.guess, config.sub to version 2002-09-05 * external command: report failure only once * console: reset failure status after success * README.UPGRADE: explain 1.7.x <-> 1.8.x client/server compatibility * use persistent connection to database by default * option UsePersistent=no to switch off persistent connection 1.8.2 (19-01-2004): * sh_userfiles.c: new option UserfilesCheckUids (requested) * sh_error.c: server: don't log to logfile before dropping root * new script scripts/samhainadmin.pl (administrative tasks for signed config/database files) * add changes code to log_msg for reports on modified files * change default log threshold to 'mark', as 'none' tends to confuse new users * faster response time for SIGUSR2 * revised (mostly backward-compatible) message classes * fix missing check of mailTime in server select loop * add support for libprelude (version 0.8.10) * fix format for MSG_E_GRNULL (reported by Stefan Hudson) * fix Bourne shell incompatibility (export) in samhain-install.sh (first reported by David Thiel) * fix typo in spec file (first reported by Christian Vanguers) * remove some cruft (signal handler, memory handling) * return from sigterm handler, rather than exit directly (re-entrancy problem causes more problems than it's worth) 1.8.1 (03-12-2003): * fix gmp detection (problem pointed out by Nix) * fix/improve the error message if test compiling with mysql fails * new CL option --interactive for interactive db update * fix some compiler warnings from IRIX MIPS compiler * kern_head.h, kern_head.c: option to disable IDT check * kern_head.h, kern_head.c: update kernel syscall table (2.4.20,2.6) * sh_utmp.c: count number of logins (request by Erwin Van De Velde) * change username -> userid, remove (long) userid (bug noticed by Erwin Van De Velde) * emit ADDED message for new SUID/SGID files * add trailing slash to excluded directory if there is none 1.8.0a (04-11-2003): * sh_error.c: remove two debug printf's 1.8.0 (31-10-2003): * manual: make ps file fit on both a4 and letter paper * sh_socket.c, sh_socket.h, sh_forward.c: socket interface to send (quit/reload) commands to clients * sh_forward.c, configure.ac: enable build with libwrap (Wietse Venema's TCP Wrappers library) * sh_ignore.c, sh_ignore.h, sh_files.c, sh_hash.c, sh_readconf.c: new option to suppress messages for new and/or deleted files * samhainrc.aix5.2.0: contributed by Christoph Kiefer * samhain.c: fix compile warning on solaris (noticed by Ian Hunt) * sh_database.c: undef debug code for oracle * samhain.oracle.init: contributed by Joern Michael Krueger * configure.ac, sh_utils.ac, Makefile.in, sh_modules.c, sh_cat.c, sh_cat.h, sh_mounts.c/h, sh_userfiles.c/h: check-mounts and userfiles modules contributed by eircom.net * sh_utils.c: fix off-by-one bug in sh_util_compress() * sh_forward.c, sh_tools.c, configure.ac: version 2 client/server protocol * sh_mail.c: add %S to include severity in subject (user request) * sh_suidchk.c, 1093: fix warning about unused var 'flags' on FreeBSD * samhain.h, sh_unix.h, sh_unix.c: extern inline -> static inline for --enable-ptrace * samhain.c: lower priority for 'uninitialized module' message * sh_entropy.c: lower priority for message if /dev/random blocks and /dev/urandom is available * improved error messages in sh_readconf.c * print system error message for getpwuid, getgrgid * fix missing module init after SIGHUP (noticed by Cian Synnott) 1.7.12 (13-10-2003): * sh_mail.c: fix buffer overflow in mail handler (introduced in 1.7.10) thanks to bug reports by Jason Martin and Matthew P. Cox 1.7.11 (01-09-2003): * samhain.c, samhain.h, sh_unix.c, sh_forward.c, sh_html.h: - change SIG_USR1 to switch between dbg on/off - change SIG_USR2 to switch between suspend on/off - fix CLT_ILLEGAL to actually work - introduce new state CLT_SUSPEND - force reauthentication after suspend * slib.c: change MAXFD from FOPEN_MAX (16) -> 1024 * sh_suidchk.c: better AIX fs detection (Christoph) * sh_entropy.c: increase buffer size for unix entropy gatherer (problem reported by D. Danielson) * default config files: add lots of comments, list more options * sh_error.c: set default severities to 'crit' * sh_readconf.c, sh_cat.c, sh_cat.h: stricter check on config file syntax, issue warnings (triggered by C. Kiefer) * Makefile.in: handle depend-gen errors more gracefully * sh_err_console.c: fix bug in enable_msgq (reported by F. Behrens) * configure.ac: workaround for mysql_config weird output (reported by G. Faron) * sh_unix.c, sh_tiger0.c: check IO limit during read of large files * depend-gen.c: close streams before attempting to rename (Cygwin) * Makefile.in: fail gracefully if depend-gen fails * sh_database.c: sh_database_query(postgresql): fixed missing SL_ENTER 1.7.10 (27-07-2003): * FreeBSD init script: define $pidfile (reported by D. Thiel) * sh_unix.c, sh_unix.h: fix compile error on AIX 4.2 * sh_schedule.c: fix bad array size * samhain.c: fix pid_t <> int casts * sh_kern.c: fix repetitive messages * configure.ac: try to bootstrap if TIGER192 not supported by gpg, provide a detailed error message * configure.ac: try harder to locate mysql * docs/Changelog: retroactively add release dates, if known * sh_mail.c: fix potential message truncation in mailer * sh_unix.c, samhain.c, samhain.h: make --enable-ptrace more portable * sh_readconf.c: fix segfault (dereference of uninitialized pointer) if --with-gpg and --enable-stealth are used together (reported by Anthony Caetano) * sh_unix.c, samhain.c, sh_calls.c: fix problems with descriptive error messages (larger GLOB_LEN, stat fills aud_err_message) 1.7.9 (30-06-2003): * sh_err_log.c: fix segfault on SIGABRT (dereference of freed memory), problems with SIGABRT noticed by Brian and Alf B Lervg * deploy.sh.in: fix some bugs (found by Alf B Lervg) * scripts/chroot.sh: fix typo (found by Alf B Lervg) * configure.ac (khide): search also for 'd sys_call_table' (noted by cuek_saja) * strip whitespace before checking gpg checksum (noted by D. Thiel) * manual (faq section): explain how to stop console output * Makefile.in: fix re-naming of yule with --enable-install-name * HOWTO-client+server.html: fix typo (noted by xavier renaut) * configure.ac: escape '-' in awk regex (required by GNU awk 3.1.1) 1.7.8 (28-05-2003): * sh_unix.c: new mlock implementation with reference count and page alignment (fix for solaris problem) * kern_head.c: search also for 'xxxxxxxx d sys_call_table' * sh_html.c: write status comment (for Beltane 2) * add CL option --delimited for comma-delimited signature database dump * sh_mail.c: check exit status of push_list to fix counting bug (bug reported by Alan Moore) * configure.ac: add error message to --with-libs * fix spelling of $DAEMON in init script (noted by C. Grigoriu) * fix missing initgroups() 1.7.7 (06-05-2003): * sh_forward.c: fix bug if compiled with --enable-udp, but disabled in config file (found by Andy OBrien) * sh_database.c: sh_database_entry(): size -> c_size (two places) to fix writing of '\0' to arbitrary places :( (problem pointed out by Stefan Giesen) * profiles/*/configopts: fix --with-base -> --enable-base 1.7.6 (24-04-2003): * sh_forward.c, entry.html, head.html: fix/additions by Stefan Giesen * fix samhain_hide for the O(1) scheduler used by RedHat: configure.ac, acconfig.h: check for next_task in struct task_struct samhain_hide.c: use find_task_by_pid if no next_task in task_struct * samhain_erase.c: add MODULE_LICENSE("GPL") to fix warning 1.7.5 (15-04-2003): * sh_cat.c, sh_forward.c, sh_hash.c: fix double 'msg' tag * manual: point out the bmaxdata problem on AIX in faq section * trustfile.c: don't check symlinks (permissions of directory count) * sh_schedule.c: fix problem with daylight saving switchover * sh_samhain.c: close all open fd's >2 before reading the conf file * sh_unix.c: fix dereferenced NULL pointer when exiting on non-existing user * sh_forward.c: fix dereferenced NULL pointer when exiting on udp error * sh_forward.c: place timestamp code before select() timeout handler * fix incorrect class of timestamp messages (conflict with manual) * sh_readconf.c, sh_forward.c: new config option SetStripDomain * configure.ac: add warning if /lib/modules/`uname -r`/build/include not found * samhain_hide.c: adapt for RedHat 2.4 kernel (fetch sys_call_table address from System.map) * sh_err_syslog.c: fix for Solaris * samhain.spec.in: strip REQ_FROM_SERVER from config file install path 1.7.4 (21-03-2003): * configure.ac: fix bug in defargs (--with-base > --enable-base) * aclocal.ac: detect unsupported options * kern_check: add syscalls, skip unused syscalls * fix Manual (--enable.../--with... inconsistency) * add two HOWTOs (signed files, server/client) * moved manual into new subdirectory docs/ * add admin scripts by S.Bailey/M.Redinger * option to have a version string in db file 1.7.3 (23-02-2003): * samhain-install.sh: use yule user key for signing on install * fix a bug in sh_err_console.c (attempted write to const char) * sh_gpg.c: if server, always use ~unprivileged_user/.gnupg * Makefile.in: make target 'trustfile' depend on config.h * configure.ac: don't use install_name before it is defined ... * sh_tiger0.c: fix bug in checksum computation introduced in 1.7.2 * samhain.c: make sure daemon cannot be forced into 'update' mode * sh_hash.c: remove AIX workaround (AIX has been fixed meanwhile) 1.7.2 (04-02-2003): * sh_kern.c: use sys_call_table address from System.map * fix for reserved SQL keyword 'group' * add AC_SYS_LARGEFILE to configure.ac * allow separate client-specific log files for server * sstrip.c: compile sstrip code only for i386 * sh_unix.c: closeall: don't close trace file * slib.c: don't trace sl_is_suid (leads to recursion in trace handler) * samhain-install.sh.in: fix detection of LSB compliant systems * sh_tools.c: get_client_*_file: lstat -> stat to allow symlinks * sh_forward.c: sh_forward_do_write: set O_NONBLOCK for fd (may block otherwise, for no good reason apparently ...) * samhain.spec.in: replace %configure with ./configure * sh_unix.c: re-write signal handling (use __malloc_hook et al. to check whether we are in the middle of a free/malloc/realloc/memalign) * sh_unix.c: use new safe_logger() function to log from signal handler * sh_err_log.c: fix xml * * fix Makefile.in to exit non-zero on compile failure * database init: create index on log_host, entry_status * sh_suidchk.c: fix path building * sh_tiger0.c: read larger blocks * sh_hash.c: cast inode to UINT32 * sh_tools.c: check that config/database files size fits in uint * sh_error.c: export flag_err_debug to avoid unnecessary calls * sh_unix.c: save the open() call in sh_unix_getinfo_attr() * profiles/redhat_i386/bootscript: add # description field * deploy.sh.in: set owner + permissions for files in yule_filedir * profiles/debianlinux_i386: fix bootscript * Makefile.in: fix deploy file lists and targets (include init+scripts) * MLOCK GOOD/BAD -> SL_FALSE/SL_TRUE * sh_mail.c: GOOD/BAD -> SL_FALSE/SL_TRUE (AIX sys/param.h) * sh_err_syslog.c: split long messages rather than truncating * sh_error.c: allocate msg to fix truncation limit * sh_unix.c: closeall fd's >= 3 in non-daemon mode (inherited filedescriptors may exceed FOPEN_MAX, causing problems in sl_open_file) * sh_err_console.c: avoid stdio * trustfile: dirz: make swp[] static * slib.c: speed up sl_strlcat * clean up some bad heap allocation (PATH_MAX+(1|2) -> PATH_MAX) * remove some unused code * slib.c: support long long int in the snprintf replacement * configure.ac: new configure macro to check whether sa_sigaction works * Makefile.in: make sstrip, encode dependent on config.h 1.7.1a (08-01-2003): * fix a syntax error in samhain-install.sh.in 1.7.1 (07-01-2003): * search runlevel scripts in ./init or ./ * handle all distro-specific Linux runlevel script issues within a single script * support install-boot on Yellow Dog Linux and Slackware * samhain-install.sh: fix a bug for unknown Linux ('"' not closed, DVER not set) * samhain-install.sh: check for /etc/yellowdog-release * sh_database.c: fix missing entry for 'userid' in attr_tab[] * fix debian.rules.in (disable sstrip) * update make targets: 'srpm', 'srpm-dist', 'rpm' * check for zlib if mysql is used * workaround for NetBSD bug with libresolve * fixed problems with spec files 1.7.0 (22-12-2002): * improved spec files (Andre Oliveira da Costa ) * sh_unix.c: fix a dereferenced static pointer in tf_trust_check * runlevel scripts: remove pid file after stop * make the data directory read-only for the daemon * treat 'localhost' specially in MX resolver * sh_err_log.c: set sh.flag.log_start == TRUE after writing * deploy.sh.in: fix quoting (fix by Simon Bailey) * slib.c: make sl_get_euid et al. behave well if uids not stored * trustfile.c: use euid = uid(SH_IDENT) if server * sh_mail.c: include an MX resolver * Makefile.in: install-user routine for user installation * have yule drop root * sh_tools.c: open_temp use logdir if server * unified options for runlevel script * HP-UX, IRIX runlevel scripts * AIX inittab entry 1.6.6 (13-12-2002): * configure.ac: solaris cc -O2 -> -xO2 * sstrip.c: avoid alpha architecture * profiles/solaris/configopts: no --enable-static * sh_forward.c: sh_forward_req_file: copy argument to local array 1.6.5 (04-12-2002): * sh_utmp.c: set userlist = NULL in sh_utmp_end () * sh_unix.c: do not assume that environ is sane * exit handler: write * sh_log_file(NULL): test sh.flag.log_start != S_TRUE * FreeBSD rc script does not blindly accept content of pid file * configure.ac: allow 'localhost' for log server * sh_calls.c: retry_connect: ntohs (port) * testrun_2[abc].sh: --with-logserver=localhost for client 1.6.4 (12-11-2002): * sh_tools.c: fix error when escaping '=<' * fix the 'make srpm' target * deploy.sh.in: avoid that client is named 'yule' * define memset to sl_memset * fix type cast of uid_t, gid_t 1.6.3 (31-10-2002): * fix options for Sun/Solaris native compiler * sh_unix.c: MSG_FI_LIST (line 2333): cast theFile->size to fix error * test sstrip on freebsd * default config file for freebsd * make target to build .deb packages * sh_readconf.c: fix bug in error message * samhain.c, sh_suidchk.c: fix initialization of suidchk * samhain-install.sh.in: don't remove config file by default * samhain-install.sh.in: support complete de-installation * samhain-install.sh.in: add support for Gentoo, FreeBSD, and Solaris * samhain-install.sh.in: check more paths * sh_unix.c: fix sys_siglist declaration [NetBSD portability issue] * sh_calls.c: save error message in retry_lstat() 1.6.2 (04-10-2002): * make target to build rpms * update samhain.spec.in, samhain.startRedHat * support DESTDIR, as in 'make DESTDIR=/what/ever install' * explicitely set -fno-omit-frame-pointer b/o gcc bug * mv configure.in to configure.ac to benefit from autoconf wrapper * sh_modules.c, sh_modules.h: add mod_reconf() to run at SIGHUP * slib.c: fix debug messages (no msgs for dlogActive <= 1) * sh_schedule.c, samhain.c, sh_suidchk.c: scheduler may accept multiple schedules 1.6.1 (04-09-2002): * sh_schedule.c: bugfix (executes only after first day) * rm obsolete WITH_TRACE stuff * new dlog() function for debug logging * some more descriptive error messages 1.6.0 (27-08-2002): * omit the -fomit-frame-pointer option (bugs in some gcc versions ?) * sh_error.c: fix escape mode when logging to database * sh_forward.c: fix error (twice escape) in recv_syslog_socket * sh_tools.c: change escape mode for server-received data * sh_mem.c: change ulong -> size_t in sh_mem_malloc() * configure.in: fix localstatedir if --prefix=USR * sh_hash.c: snprintf() -> sl_snprintf() 1.5.5 (07-08-2002): * sh_err_log.c: fix incorrect xml syntax for client messages logged by server * sh_err_log.c: fix incorrect '' entries on client EXIT * sh_files.c: introduce file_class_next this fixes the problem that a policy for the directory inode erroneously becomes a policy for the directory itself. 1.5.4 (17-07-2002): * sh_hash.c: fix buffer overflow with (micro-)stealth * sh_database.c: set path[] 1024 -> 12288 * sh_database.c: set query[] 2048 -> 16383 * sh_database.c: set values[] 1024 -> 16383 * sh_forward.c: larger limit for message size (16 kB) * trustfile.c: set MAXFILENAME 2048 -> 4096 * fixed a bug in the handling of filenames with embedded newlines * sh_files.c: fix missing sh_util_safe_name() in debug output * --with-sender can specify a full address * fix xml log in a backwards compatible way 1.5.3 (03-07-2002): * fix combination of stealth and sql logging * fix some more places where invalid UIDs/GIDs trigger errors 1.5.2 (01-07-2002): * include solaris config file from (sean [at] boran d.o.t com) * test for files/dirz defined twice in the configuration file * option to disable reverse lookup on outbound connections * option to use socket peer as client name (with name resolving) * sh_html.c: fix an HTML bug (twice ) * sh_suidchk.c: fix warning on AIX b/o dirname() * allow logging server -> syslog if yule is NOT configured to receive syslog messages * define PRIi64 to "lld" if undefined * invalid UIDs: use gid/uid as name, error level SeverityNames * minor fixes for connect_port * sh_hash.c: flush output of db listing before _exit() * configure.in: fix incorrect default ${install_name} for server * configure.in: try harder to find mysql.h / libpq-fe.h * sh_files.c: sh_files_checkdir: closedir() early to not exhaust OPEN_MAX 1.5.1a (30-05-2002): * fix missing LSB init script 1.5.1 (27-05-2002): * fix '-t update' option 1.5.0a (23-05-2002): * fix configure.in 1.5.0 (22-05-2002): * include solaris nosuid patch from (nathoo [at] co d.o.t ru) * similar fix for bsd nosuid * speed up -t update * convert manual to DocBook, distribute html and ps * fix some more problems with configure.in, Makefile.in * fix testsuite, add tests for udp, mysql * MSG_TCP_MSG: host -> remote_host * convert to autoconf 2.53 * make c_bits.sh exit with status 0 * sh_database.c #include "mysql.h" --> , ditto libpq-fe.h to avoid dependency tracking problems * samhain.c remove *YULE* #ifdefs * acconfig.h remove *YULE* #undefs * samhain.c: procdirSamhain: lstat --> stat (allow symlink) * configure.in: add checks for correct user input * Makefile.in: add automatic dependency tracking * depend-gen: tool to figure out dependencies * chkconfig comments in redhat start scripts 1.4.8: * sh_database.c: fix missing attr_old, attr_new, (from)host columns * configure.in, Makefile.in: fix an error in the configfile definition with REQ_FROM_SERVER * sh_err_console, sh_err_log: avoid recurrent failure messages * timeout on read from files (/proc) * fix errrors with setjmp/longjmp/alarm * fix memory leak in server (~20 byte/file download in sh_tools, 930) * check gpg signature for files downloaded from server, add a regression test * fix chown in solaris bootscript * provide second scheduler for file check * provide scheduler for file check * provide scheduler for SUID check 1.4.7 (08-04-2002): * make daemon control LSB-compliant (arguments, exit status) * set log_ref = 0 for server messages * boolean option SetDBServerTstamp to disable entering server timestamps for received client messages into database * sh_suidcheck: check for "nosuid" mount option if getmntent is used * fix logrotate script in manual (reported by Scott Worthington) * don't strip numerical IP addresses * check item->status_now != CLT_TOOLONG in client_time_check() * set log_host to client in db client message 1.4.6a (20-03-2002): * define prefix in deploy.sh 1.4.6 (19-03-2002): * modify samhain_hide.c to hide processes on new Linux kernels * better error diagnostics in kern_head.c * fix compile error in all_items () * check length of install-name in enable-khide (max is 15) * define exec_prefix in deploy.sh.in * make configure a bit more cross-compiler friendly 1.4.5 (07-03-2002): * Make sure missing file is reported even if ptr->reported == S_TRUE because the file has been added. * propagate 'reported' flag from sh_files_checkdir() into file list * close checkfd in sh_gpg_check_file_sign() * sh_derr(): kill(parent, SIGCONT) after ptrace(PT_DETACH,...) * use sh.srvcons.name in dbg() to get debugging info from daemon * option to log file timestamps with localtime instead of GMT * comment out MSG_FI_ADD in sh_dirs_chk () - obsoleted by mandatory sh_files_filecheck(directory) that triggers MSG_FI_ADD in sh_hash.c * set ptr->reported = S_FALSE; for reappeared files in sh_files_chk() to make sure re-disappearing will get reported * new function sh_hash_set_missing() to remove file record without (duplicate) 'missing' message * make sure all items are reported for added files * fix stealth mode with sh_kern (encode sh_ks.h -> sh_ks_xor.h) * clarify in the documentation which gpg options to use for signing 1.4.4 (11-02-2002): * check that parent process has exited before writing PID file * promote MGG_W_CHDIR to SH_ERR_ERR * add error message to sh_unix_testlock * fix missing _() macro in sh_aud_set_functions 1.4.3 (05-02-2002): * don't check attributes for symlinks (may cause device access) * add USE mysql; USE samhain; to samhain.mysql.init * point out the MessageHeader/mysql problem in manual * add -lz to LIBS for mysql * strip after install, avoid double strip 1.4.2 (27-01-2002): * support for EGD * fix some more problems with install-deploy / deploy.sh * fix a bug in profiles/suselinux_i386/bootscript (INSTALL_NAME_) * fixed the 'external logging' test (init rather than none in rc file) 1.4.1: * SuSE: include run level 4+5 * install location of hiding kernel modules changed - some insmod variants do not test for /lib/modules/$(uname -r)/module_name.o * new make targets 'install-deploy', 'uninstall-deploy' * fixed make targets 'deploydir', 'deploydirfast' * bail on unsupported CL option in deploy.sh * fix various bugs in deploy.sh 1.4.0 (16-01-2002): * fixed missing 'dirname' on Mac OS X * fixed && tested for/with postgres * 'user=' -> 'userid=' (reserved word in sql) * fix the endianess + size of file database; this changes db format for any non-Linux OS * --enable-old-format for old (V1.3) database format * getopt, samhain.c, samhain.h: option -f to loop if not daemon * sh_hash: list numeric + char data to allow file db update on server side * sh_database: modify handling of integer (long) data * sh_database: datetime in database * sh_database: hash field in database * sh_database: rewrite database insert string construction [use INSERT INTO log (fields) VALUES (values);] * makefile suse 7.x runlevel entries 1.3.7 (06-01-2002): * fix incorrect escape in sh_tools_safe_name * fix sh_error_handle (4. argument) in sh_extern.c 1.3.6c: * fix segfault in sh_database (mysql logging) on solaris 1.3.6b (03-01-2002): * fix syntax error ('==') in Makefile.in * fix configure.in (path for /lib/modules/$(uname -r)/build/include) * fix sh_kern.c (redeclaration of 'j') 1.3.6 (03-01-2002): * sh_kern.c: check integrity of int 80h vector (SucKIT rootkit - Phrack 58) * make sure childs in sh_kern are wait()'ed for * provide start/stop/restart/reload/status interface * fix a potential segfault (dereferenced NULL pointer) in the server * use sh_util_flagval for sh_unix_setdaemon * documentation for logging to SQL database * configure.in: check for -I/lib/modules/$(uname -r)/build/include * fix trustfile.c to ignore invalid users * separate 'make install-samhain' and 'make install-yule' * separate default log/pid/config files for server/client - less problems running server and client on same host * rewrite deploy.sh(.in): - don't use (make|install) if deploying - use command line options - better integrate into server environment - write install db * always write a pidfile if daemon * don't use server's config file as fallback for downloading client * don't overwrite config file when doing 'make install' 1.3.5 (28-12-2001): * fix --enable-message-queue for newer glibc versions * log to SQL database: implemented, but undocumented yet, needs to be tested further * xml: escape received syslog messages * xml: rename 'time' to 'tstamp' * make targets: make [un]install-[boot-]yule (for server-only installation) * fix samhain_hide.c for 2.4 kernel * fix sh_kern for updated samhain_hide.c * new option -j to just list the logfile * sh_getopt.c: recognize -Dt check for -D -t check * sh_tiger0.c: fix compiler warning (memmove) on Solaris 1.3.4 (12-12-2001): * sh_suidchk.c: option to limit files per second * sh_unix.c: option to limit (kilo)bytes per second * sh_hash.c: fix potential problem with '\n' in filename (not backward compatible if there are filenames with '=') 1.3.3 (03-12-2001): * sh_readconf.c, samhain.h, samhain.c, sh_suidchk.c: option SetNiceLevel to set scheduling priority * sh_hash.c: bugfix for database listing on Solaris * taus_seed: bugfix for emergency backup rng seed * sh_util_safe_name: fix for XML * sh_utmp_set_login_activate: use sh_util_flagval * sh_utils.c: sh_util_obscurename: rm 'space' from list * more backtrace macros * sh_util_flagval: fix bug to recognize 1/0 * fix test scripts testtimesrv.sh, testext.sh (test.sh 6/5) * rm stray debug fprintf in sh_srp.c 1.3.2 (27-11-2001): * sh_hash.c: fix an error introduced in 1.3.1 * set RLIMIT_CORE to RLIM_INFINITY if --enable-debug 1.3.1 (25-11-2001): * slib.c: get backtrace with --enable-debug * sh_unix.c: allow core dumps when --enable-debug * configure.in: fix default message queue permissions * sh_suidchk.c: automatically include suid/sgid files in database * sh_suidchk.c: check all suid/sgid files * sh_hash.c: don't insert duplicates when reading the database * sh_utmp, sh_kern, samhain: fix 1sec offset in timer * sh_unix.c: don't require /dev/random to be non-world-writeable * server: fix segfault in zAVLTree.c if avltree == NULL (no clients) * client: fix segfault on Solaris if path_conf == NULL * testrun_1b.sh: \(^/.*\) -> \(/.*\) for Solaris sed 1.3.0 (31-10-2001): * support compiling with GNU gmp library * set 3 sec timer on client_time_check to avoid excessive (and unnecessary) calls under heavy load * replace sl_strlen with a macro * store client_t structure in AVL tree * database format incompatible with previous format, up the magic# * sh_html.c: cache entry template for speedup * slib.c: reset islong(double) in sl_printf_count * sh_hash.c: report on rdev change * sh_hash.c: print size in 64 bit * sh_hash.c: save in absolute size types * sh_unix.c: get values as appropriate type (time_t, dev_t, ...) 1.2.10: * update MANUAL * sh_unix.c: tiger_hash -> tiger_generic_hash * sh_readcon.c: DigestAlgo option * sh_tiger0.c: add MD5 and SHA1 * sh_unix.c: fix minor problem with win2k/cygwin 1.2.9 (17-10-2001): * fix problem with entry template/empty hostname * fix MASK_USER_ (MTM -> ATM) * typo fixed in configure.in (${install_name} -> {install_name}) * bugfix group_old -> size_old in XML code * skip armor header in signed files 1.2.8 (29-09-2001): * Mac OS X: in sh_getopt.c, rename table[] to op_table[] to avoid obscure compiler warning * Mac OS X: fix test scripts * Mac OS X: import newest config.guess, config.sub from ftp.gnu.org * implement deadtime in syslog recv code to protect against flooding * sh_err_log: sl_close(fd) if lock|forward fails * compliance with Filesystem Hierarchy Standard -- Version 2.2 final * add policies User0, User1 * fix compile problem (FreeBSD) in sh_suidchk.c * macro to check for debugger breakpoints (linux/i386) * check for solaris (does not work) in sh_derr (--enable-ptrace) * option to listen on 514/udp for syslog, drop root irrevocably if compiled thus * use (check_mask & MODI_ATM) to decide whether to reset utime * reset the policy masks on sighup * option to write XML log messages * cleanup of message catalog * modified error messages for BADCONN * error messages for Rijndael * block recursive error messages within sh_error_handler() - would hang the machine ... - 1.2.7: * sh_files, sh_utils: check top level directory * sh_kern, sh_cat, kern_head: check syscall code, fork subprocess for reading from /dev/kmem * include /boot in default samhainrc * change source distribution signing/packaging system * Makefile, README, MANUAL: adhere to file system standard, document new locations * fix a bug in samhain_hide.c 1.2.6: * reset list of trusted users before config file re-read * TrustedUser=... can be a list * fix severity for files missing from IgnoreAll 1.2.5: * include example_pager.pl, example_sms.pl scripts * explain paging/sms setup in docs * allow manual exclusion of a directory in suidcheck * automatically track all file changes * remove missing files from in-memory database * add $(KERN) to DEPLOYFILES 1.2.4: * log IP address for login/logout events, if supported by the OS * release block in globerr (callback) ------------- 1.2.3: * fix problem with reading stealth configuration * fix a few formats in sh_cat.c * always use strncmp for file system type check in sh_suidchk.c (trailing 'fs' may be system specific for some types) * no bare LF in messages (RFC 2822) * no lines longer than 998 chars (RFC 2822) * fix error in testrc_1 1.2.2: * make tmp file directory a compile time option * fix minor bugs in tmp file allocator (potential memory leak, double slash if root directory) * obsolete testpipe script removed 1.2.1: * fix memory alignment in rijndael-api-fst.c: blockEncrypt() * fix byte order in HMAC code (compatibility fix for Linux/HP-UX) * removed a debug fprintf() 1.2.0: * fix a bug in the HMAC implementation (thanks to Cesar Tascon for help in tracking down this one) * module to check the file system for SUID/SGID files 1.1.16 (never released): * fix the recursion depth -1 option as described in the manual * optional database reload on SIGHUP * fix a race condition when checking that /dev/random is a charakter device * redirect stderr to /dev/null for c_random (AIX may segfault in netstat...) * check whether /dev/random is a charakter device in c_random.sh (we know at least one sysadmin who has set up a fake /dev/random ...) * don't give NULL as 2. and 3. arg to execve if not Linux - some Unices (notably Solaris) don't like it * init ptr = NULL in my_malloc (compiler warning) * make the bitmask for tests configureable (suggestion by A. Dunkel) * make the bitmask for tests a static variable * make (database/logfile/lockfile) path configurable (to run multiple instances of samhain from an NFS share - on the wishlist of J. Patton) 1.1.15 (never released): * fix minor error in testcompile.sh (rm test_log only at start) * return from subroutines on sig_terminate == 1 (faster exit on SIGTERM) * fix re-configuration of addresses * use sh_util_flagval() in sh_mail_setFlag and sh_kern_set_activate * SysV message queue as compile option * config file option to set console device * removed the pre 1.1.9 code bloat * don't print the LOGKEY to the console 1.1.14: * fix an error in the setup consistency check * make target to uninstall runtime files * trustfile.c: check return code of readlink(), fix off-by-one error * sh_files.c: fix placement of terminator after readlink() call * sh_files.c: fix a missing set_suid()/unset_suid() - suid should work, but is not recommended - * more debug statements in c/s code * avoid re-entry in sh_unix_sigexit * put a block around free() and malloc() in wrapper functions * ditto for glob()/globfree(), regcomp()/regfree(), fdopen()/fclose() - i.e. avoid corrupting the heap from a signal handler - 1.1.13: * optimized the size of the configure script somewhat * modify the compile and hash test scripts * read '\0's in sh_unix_getline * exponential schedule for connection attempts * make stealth working properly with signed files - config file should be signed now before embedding in picture - * fix a race in using signed files * updated err messages for PWNULL, GRNULL * add missing shell script for test 11 * add mandatory source file/line info with -p debug * add mandatory source line info with BADCONN * fix a latex error in the manual 1.1.12: * debug output to console if compiled with --enable-debug and running as daemon * make reportonlyonce=true the default * make sure state changes of a file are always reported, even with reportonlyonce=true * Linux kernel modules (samhain_hide, samhain_erase) * fixed incorrect return value of sh_util_flagval * fixed an error in sh_files.c: happens with -t init and first file that is checked does not exist * revised install/uninstall targets in the Makefile * module to check for clobbered kernel syscalls (tested on Linux 2.2) * more diagnostic error messages in sh_gpg.c * more diagnostic error messages in sh_mail.c * error in mail.c fixed (address -> address_list[i] for multiple recipients) * docs updated, better(?) explanation of signed files * skip over path in gpg checksum output * check client name against IP address and FQDN * fix for --disable-* in config file * fixed a server crash (MSG_TCP_OKMSG without arg) if the server is run with debug level output threshold * catch EAGAIN in sh_gpg.c pipe reader * fix the 'external logging' test to make it work on BSD * error message if no local path to init DB * check for i86/Solaris in configure (vsnprintf prototype) * make SRP the default 1.1.11: * make log file verification more convenient * fix problem with message classes in stealth mode * linux: do not try to read file attributes for devices * handle the root directory correctly (avoid "//" in listing) * fix problems with blockin on FIFOs/char dev pointed out by I. Rogalsky (rog@iis.fhg.de) - open in nonblocking mode for read, then set to blocking - open file only if regular * fix alignment in memory profiler 1.1.10: * minor code cleanup * fix an error in trustfile.c (handling of empty/incomplete group entries in /etc/group, bug report by A. Capriotti ) 1.1.9: * compatibility option for old behaviour (plain hash instead of HMAC, ECB instead of CBC mode) * use CBC rather than ECB mode for encryption * use HMAC-TIGER for message authentication codes * handle NULL data in sh_tiger_hash * option to set syslog facility (default is LOG_AUTHPRIV) * longer timeout (300 sec) on /dev/random if no /dev/urandom * fix minor output error with stealth option * option not to log names of config/database files on startup 1.1.8: * fix error in syslog routine * fix missing 'test' in configure.in * fix error in replace_tab() in sh_html.c * fix minor memory leak in sh_util_regcmp() 1.1.7: * timeout on read_mbytes (from /dev/random; fallback to /dev/urandom) * fix for FreeBSD: ut_user -> ut_name in sh_utmp.c * fix for Alpha: consider $ac_cv_sizeof_unsigned_int_ in configure.in * fix for Alpha: format string in sh_tiger0.sh * on Linux, now compiles cleanly with -Wall -W -Wstrict-prototypes -Wcast-align * fix problem with recursion depth (pointed out by Vic ) * #include "sh_tools.h" in sh_unix.c and fix the --with-timeserver option (reported by Vic ) * place read_port(), MSG_TCP_NETRP outside ifdefs * close fd/zero skey before execve * verify client name against socket peer * ... with configureable error priority * use strcmp() rather than strncmp() in search_register() * fix race between lstat() and open() for checksum (reported by dynamo , JJohnson ) * enable globbing for filenames * fix Solaris problem: siginfo_t may be NULL * fix missing SL_EBADGID in tf_trust_check * test case for external scripts, fix flushing pipe * fix a typo in sh_ext_type * do an fdexec w/checksum on Linux if calling external program * even safer tmp file creation * allow db update * fix compile options for --enable-debug * fixed a spelling error in the output * test program for full CS support (config/database download) * tell which file is searched for cs download 1.1.6: * fix bug in sh_readconf_line (segfault on erroneous config lines) 1.1.5: * sh_unix.c: sh_unix_getinfo_attr: f -> flags * use gettimeofday as last resort 1.1.4: * fix AIX compiler warning in sh_forward (cast arg1 of sh_tiger_hash to (char *) * configure: add static link flags for some more os (from tar) * don't strip twice (some stupid systems abort) * fix for reading from /dev/random on non-Linux systems (untested) * sh_mail.c: end all message lines with \r\n * stealth: ignore \r, \" * take out tracing from --enable-debug (presently useless anyway) * fix some remaining cleartext with debug && stealth combined * fixed a small memory leak in sh_err_log.c 1.1.3: * fixed circular logic in taus_seed() (fallback method only) * fix for missing _SC_OPEN_MAX (runaway close()) 1.1.2: * implement message classes * let server recognize client message severity and class * secondary log server * keep database in memory (allows to close file if retrieved from server) * encrypt client/server communication 1.1.1: * Compilation problems with native Solaris compiler fixed * fill in euid/ruid variable * manual.pdf --> MANUAL.pdf * debug sh_util_formatted() * http refresh 120sec for server stat page * trace/debug options * fixed problem with utmp.c options * fixed problem with sh_mail_setaddress * option for custom message header * fixed problem in compdata * fixed problem in mail verification * remove eventual trailing '/' in file names * fixed problem with report string for modified files * option to report in full detail 1.1.0: * Move error messages to catalog * Make error message format more uniform * Wrap sytem calls that could be interrupted by signals * Warn on append to database * Option for full details on mod. files * Option to report only once on mod. files * Generally speaking, major modifications with potential new bugs 0.9.5: * sh_hash.c: fixed erroneous checksum for config file * sh_html.c: fixed erroneous timestamp (last) * sh_tools.c: fixed connect_port (set port for cached address) * sh_srp.c: fix for '00' (='\0') in pw (last two fixes by Andreas Piesk) 0.9.4: * samhain.c: fcntl(1, ..) -> fcntl(2, ..) * sh_hash.c: copy 12 instead of 10 byte for c_attributes * 'empty directory' WARN -> INFO 0.9.3: * FreeBSD fixes: - c_random.sh: make sure /dev/random provides something rather than nothing - check for and include it - include early - sh_utmp.c: fixed an occurence of ut_user - sh_utmp.c: #ifdef HAVE_UTTYPE static char terminated_line #endif - sh_forward.c: EBADMSG -> ENOMSG * sh_unix.c: check return value of gethostbyname * sh_entropy.c: fallback on /dev/urandom if /dev/random blocks for more than 30 sec * ... and fix the timestamp format ... 0.9.2: * ISO 8601 timestamps * Bugfix in sh_utmp (timestring overwrite) * don't use siginfo_t on Linux (garbage as of 2.2.14) * check for Linux capabilities bug when dropping root * include README for gcc compiler bug (pointed out by A. Piesk) * explicitely set -fno-strength-reduce with gcc * fixed ignoring missing files with the IgnoreAll policy 0.9.1: * more ext2flags (breaks backward database compatibility on Linux) * IgnoreAll policy modified - missing/added files reported with SeverityIgnoreAll (to handle files that may or may not be present) * Check all files, not only regular ones (bug in sh_files, originally introduced because checksum of regular files only is computed) 0.9: * use O_NOATIME if supported * --with-nocl takes argument (PW to re-enable CL parsing) * no daemon mode if initializing database * fixed segfault in yule with 'unknown file type' request * enlarged MAX_GLOBS 24 -> 32 and made the array linear * server uses last registry entry for any given client now * deploy.sh script to deploy clients to remote hosts * enhanced signal handling: SIGUSR1/SIGUSR2/SIGABRT/SIGQUIT/SIGHUP * allow y/Y/n/N for login monitoring (in addition to 0/1) * external logging scripts/programs * trustfile.c: define STICKY on Linux * reset signal mask when initializing * EINTR_RETRY wrapper * slib: sl_read, sl_write EINTR update * use sstrip when installing * more compact database format (breaks backward database compatibility) * larger download packets * TcpFlags unsigned char * cast to (char *) head in write_port * m(un)lock cast to (char *) * (1 << 31) --> (1UL << 31) * support e2fs attributes on Linux * fixes for AIX and Solaris native compilers * fixed Makefile for non-GNU make (pattern rule --> suffix rule) 0.8.1: * fixed 'is_numeric()' return value 0.8: * added option for static compilation * added option for stealth with non-hidden config file * added option for disabling command line parsing * all options can be set in the configuration file now * stealth: xor strings in database file * fixed bug in mailer code ([] in HELO) * print timestamp when asking for key * 'micro' stealth mode (no hidden configuration file) * simplified slib * int->long for uids/gids in trustfile * moved mailkey from data to code * shell script for entropy (stronger default key) * general code cleanup * better error checking in client/server code * detect out-of-sync messages * check state across protocol passes in server * make sure authentication is mutual * file download to client * reserve six file descriptors in server * mlock queue buffer if LOG_KEY * improved robustness in bignum (don't fail on free()) * per-directory recursion depths * RFC821 compliance: empty line at end of header, To field, Date field * RFC821 compliance: make e-mail transfer relieable * fix detection of hardlink changes * checksum verification for calling gpg/pgp * CL option '-S' not required for server-only binary * eliminate CL options that may leak privileged information if the program is SUID * skip leading white space in configuration file * allow nested conditionals in configuration file * allow whitespace before and after '=' in configuration file * don't leak file descriptors to child processes * make message transfer relieable * always report error on abnormal termination of connection 0.7: * support for alpha machines * stop TCP logging after exit message * limit connections in server (DoS attacks) * move string handling to slib * move file handling to slib * timestring without space * changed report format * SUID bugfix - use euid when checking logfile ownership * SUID bugfix - get root for lstat() * SUID bugfix - get root for opendir() * store number of hardlinks * send no message if polling empty queue * include tiger 64-bit implementation (portability) * codes for error conditions * mail check: handle multiple, overlapping audit trails * security fix: no append to database if SUID * fix sh_entropy.c (BUFSIZ -> BUF_ENT) * read command line before config file * PGP signing of config/database files * checksum of config file reported * checking for attributes only 0.6: * more syslogish priority specification * fixed segfault in sh_mem_check, apparently this was also the reason for the segfault in atexit() * allow for compilation with SRP authentication * fixed tiger checksum computation * fixed broken logfile verification for second and further audit trails * test program added * documentation improved * sh_forward_make_client: bug fixed in[8]->in[i] * sh_error.h: fixed missing #include * configure.in: fixed missing strerror() test * sh_utmp.c: check logins/logouts * check for missing files * only reset access time if necessary * O_EXCL in open() * limit environment to TZ in execve (sh_entropy.c, not used on Linux) * use trustfile() to determine whether logfile dir is trustworthy * strip head instead of tail for numerical address * store messages in fifo during log server outage * re-init session key after server outage 0.5 (21-12-1999): * added option for mail relay server * own popen() implementation in sh_entropy() (portability) * fixed error in sh_util_basename() (returned NULL for base == "/") * fixed segfault in strlcpy/strlcat (check for src == NULL) * FILENAME_MAX -> PATH_MAX (HP-UX 10.20) * use TIGER for 32-byte compilers (portability) * fixed hash function (do not include stdlib.h) * flush buffer before write in mailer code (IBM AIX 4.1) * make mailer code non-forking * cast argument of is...() to int (portability) * return() after _exit() for braindead compilers (portability) * optionally use inet_addr (portability) * check for broken mlock() (HP-UX 10.20) * minor code cleanups * fixed incorrect size of munlock()'ed memory in sh_error_string() * fixed a buffer overflow in the error printing routine * fixed a buffer overflow in sh_util_safe_name () * implement SRP session key exchange * implement client/server facility * implement @host/@end construct in configuration file * preferably use uname(), and do gethostbyname() for FQDN * make vernam cipher base numeric * make OnlyStderr private in sh_error * test -e "/dev/random" --> test -r "/dev/random" (portability) * check for libsocket (portability) * add #defines for IPPORT_SMTP, IPPORT_TIMESERVER (portability) * eliminate superfluous /proc test * some unreachable code removed * cast to (byte*) replaced by cast to (word64*) in sh_tiger_hash() * check for setresuid() if no seteuid() (HP-UX 10.20) 0.4 (09-11-1999): * make sure output from /dev/random has no NULL's * one-time pad encryption for emailed keys (better than nothing ...) 0.3 (04-11-1999): * logfile readable for group * verify signatures for any file * signature block in tarball * use select() in time server routine * better protection for session keys (mlock) 0.2: * fixed incorrect man page * fixed incorrect example rc file * recursive error logging should work now 0.1: * initial release -- on Samhain 1999, of course development start: * probably 29-06-1999 samhain-4.1.4/docs/FAQ.html0000644000175000017500000011631712615253277012331 00000000000000 Frequently Asked Questions for Samhain

samhain file integrity scanner | online documentation


Frequently Asked Questions for Samhain


Rainer Wichmann


  • If you encounter problems after installing samhain, disable daemon mode and run it in the foreground with samhain --foreground [more options] for debugging.
  • If you have problems getting client/server mode to work, please check the HOWTO client+server troubleshooting document.

FAQ Revised: Wednesday 14 January 2015 20:41:15


Table of Contents

1. Most frequently
2. Build and install
3. File checking
4. Client/Server
5. Email
6. Misc
7. Database

1. Most frequently

1.1. Owner not trustworthy / Group writeable and member not trustworthy
An untrusted user (might be an untrusted group member for group writeable files/directories) owns or can write to an element in the path listed in the error message. This concerns the configuration file, the log file, and the database file. The offending element in the path is identified as obj=/xxx in the error message. To fix the problem, see next entry.

1.2. samhain exits with the message "Untrusted path" for config/log/pid/database files
Paths to critical files (e.g. the configuration file) must be writeable by trusted users only. If a path element is group writeable, all group members must be trusted. By default, only root and the (effective) user of the program are trusted. To add trusted users, use the compile time option
$ ./configure --with-trusted=0,...
or the configure file option:
[Misc]
TrustedUser=username
If the path to the configuration file itself is writeable by other users than root and the effective user these must be defined as trusted already at compile time.

1.3. It does not log anything / Can't stop logging to console
(1) There is a section in the manual dealing with logging and filtering.
(2) To log to the console:
$ samhain -p info ...
or in the configuration file:
[Log]
PrintSeverity=info
To stop logging to the console:
$ samhain -p none ...
or in the configuration file:
[Log]
PrintSeverity=none
Defining /dev/null as console device works as well, but is a bad idea, because samhain will open the device and write (i.e. it is a very inefficient method).

1.4. Client cannot self-resolve, but nslookup works fine
  • Nslookup is a program to query Internet domain name servers.
  • Applications (like samhain) are not supposed to query DNS servers directly. Rather, they are supposed to query the resolver library that:
    • is provided by the operating system,
    • configured by the system administrator,
    • may use several different method to determine host names, as configured in /etc/nsswitch.conf, and
    • usually is configured to give precedence to the /etc/hosts file.
  • Therefore, whether nslookup gives correct answers may be completely irrelevant. For self-resolving the own hostname, the resolver library probably will use /etc/hosts, rather than querying a DNS server.

Below you can find some examples of good and bad /etc/hosts files:

        # CORRECT
	#
        127.0.0.1  localhost
        xxx.xxx.xxx.xxx myhost.mydomain.tld  myhost
        # CORRECT
	#
        127.0.0.1  localhost.localdomain localhost
        xxx.xxx.xxx.xxx myhost.mydomain.tld  myhost
        # BAD
	#
        127.0.0.1  myhost.mydomain.tld  localhost
        xxx.xxx.xxx.xxx myhost.mydomain.tld  myhost
        # BAD
	#
        127.0.0.1  localhost myhost
        xxx.xxx.xxx.xxx myhost.mydomain.tld  myhost


1.5. Server logs hostname instead of FQDN (or vice versa)
The default is to log the hostname only, if you want the FQDN then there is an option for the server configuration:
        [Misc]
	SetStripDomain = true / false



2. Build and install

2.1. [Fedora Core] Cannot compile with --enable-khide
The Fedora Core kernel is patched to unconditionally deny reading from /dev/kmem. Compiling the stealth kernel modules is not possible under these circumstances.

2.2. [Fedora Core] Cannot compile with --with-kcheck
The Fedora Core kernel is patched to unconditionally deny reading from /dev/kmem. Checking the kernel for the presence of rootkits is not possible under these circumstances.

2.3. "make" loops infinitely !
This may happen (e.g. when building via NFS for multiple architectures) if the relative timestamps in the source directory are wrong (time not in sync on different machines) or some intermediate target is unusable (up-to-date, but built for a different OS). Use "touch * && make distclean" in the source directory to recover.

2.4. Why does static compiling (--enable-static) on Solaris fail ?
Ingo Rogalsky has provided the following information: It isn't possible to link Samhain statically with Solaris. This is a Solaris issue (see Sun Infodoc ID12624) and not a samhain problem.

2.5. Compilation fails with '/usr/bin/ld: cannot find -lnss_files'
For Linux, this is a known problem with --enable-static if you compile in MySQL support. The problem is that the mysql_config that comes as part of the MySQL distribution script incorrectly lists dependencies on the libnss_files and libnss_dns libraries which are only available as shared libraries, so the linker cannot find the static libraries. You can check this by inspecting the output of mysql_config --libs. The version of mysql_config that comes with the RedHat mysql RPM (RedHat 9) does not have this bug; the one distributed by the MySQL people has. You can fix the problem by editing mysql_config: search for the client_libs variable, and remove all instances of -lnss_files and -lnss_dns.

2.6. The executable is corrupted after installation
The executable will get stripped during the installation. On suitable systems (i386 Linux/FreeBSD currently), additionally the "sstrip" utility (copyright 1999 by Brian Raiter, under the GNU GPL) will be used to strip the executable even more, to prevent debugging with the GNU "gdb" debugger. The "strip" utility cannot handle the resulting executable, therefore trying to strip manually after installation will corrupt the executable.

2.7. --enable-xml-log has no effect
If you have compiled for stealth, you won't see much, because if obfuscated, then both a 'normal' and an XML logfile look, well ... obfuscated. Use samhain -jL /path/to/logfile to view the logfile.

2.8. ./install-sh: strip: not found (Solaris)
Install the SUNWbtool package.

2.9. What is sh_tiger1.s?
This is a precompiled assembly file for the i386 architecture generated from sh_tiger1.c using gcc 3.4.0 with the following options, that were found to generate the fastest code:
 -O1 -fno-delayed-branch -fexpensive-optimizations -fstrength-reduce 
     -fpeephole2 -fschedule-insns2 -fregmove -frename-registers -fweb 
     -momit-leaf-frame-pointer -funroll-loops
These options were determined using acovea 5.1.1 by Scott Robert Ladd. The file is provided as precompiled assembly because different versions of gcc can have very different performance, require different options to compile optimal code, and it would be impossible to maintain a library of optimal compile options for every version of gcc.

2.10. Why does static compiling (--enable-static) on MaxOS X fail ?
Static linking is not supported on MacOS X, see Technical Q&A QA1118. This is a MacOS X issue and not a bug in samhain.

2.11. Why does compiling with MySQL fail on Solaris ?
The reason is often the shell script 'mysql_config' that comes as part of MySQL. This script is intended to print appropriate compiler flags for compiling applications that use MySQL. Unfortunately, since Sun compiles MySQL with the Solaris compiler, this script outputs options for the Solaris compiler (i.e. unsuitable for gcc). To solve this problem, you need to move this script (i.e. 'mysql_config') out of your PATH before running ./configure (unless of course you are using the Solaris compiler rather than gcc).


3. File checking

3.1. How can I exclude a (sub-)directory ?
[IgnoreAll]
dir=-1/ignore/this/subdirectory


3.2. In messages about policy violations, what does the code after POLICY [XYZ] mean ?
This code indicates which items are modified (e.g. C = checksum). You can find a description in section 5.4.9 in the user manual. It is there because then you can see in the message list of the Beltane web console what has been modified, without the need to look at the message in detail.

3.3. Does samhain support prelink ?
Yes. There is a special checking policy [Prelink]. Directories with prelinked executables / shared libraries (see /etc/prelink.conf) should be placed under this policy, rather than under the [ReadOnly] policy.

3.4. I get error messages about 'subdirectory count != hardlinks'
Some filesystems do not always follow the rule that the number of directory hardlinks equals the number of subdirectories. E.g. the root directory of reiserfs partitions generally seems to have two additional hardlinks. To account for such exceptions, you can either switch off the hardlink check globally, or specify exceptions:
[Misc]
# Switch off hardlink check
#
UseHardlinkCheck=no
[Misc]
# Specify exceptions for the hardlink check
#
HardlinkOffset=N:/path
Here, N is the numerical offset (actual - expected hardlinks) for '/path'. For multiple exceptions, use this options multiple times (note that '/path N:/path2' would itself be a valid path, so using the option only once with multiple exceptions on the same line would be ambiguous).


4. Client/Server

4.1. I don't want to poke a hole into my firewall to let the client connect to the server !
Pat Smith has posted the following solution. On the client, create an iptable rule as follows (note: you probably don't need this if you configure / compile in 127.0.0.1 as the server address):
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 49777 -d server-ip -j REDIRECT
On the server, create an ssh tunnel for each client outside the firewall:
ssh -f -C -R 49777:localhost:49777 -N client-ip
It is necessary that each client has a distinct name, and that the server knows the name of the client. With the setup above, each client will appear as "localhost" to the server, thus the server needs to trust the client name as reported by the client itself, and suppress all errors on resolving this name to the apparent address. In the server configuration:
[Misc]
SetClientFromAccept = false
SeverityLookup = debug
Obviously, self-resolving must work on the client machine, otherwise you are in trouble (see next issue).

4.2. The client sends 127.0.0.1 (or some other numerical address) as its name to the log server
See 'Client cannot self-resolve' in the 'Most frequently' section

4.3. The server wants to send rc.ip-adress rather than rc.fqdn to the client
The client self-resolves to its ip address. See 'Client cannot self-resolve' in the 'Most frequently' section

4.4. Cannot resolve client name host=XXX
The server must be able to determine the client name.
This is because only authenticated connections from registered 
clients are allowed, and
the server must be able to check the client hostname against the list of
allowed hosts, and look up the password verifier for that
host.
There are two different ways to accomplish this. Unfortunately, judging from customer feedback as well from common sense, both do not work very well with a messed up local DNS (including /etc/hosts files) and/or überparanoid or misconfigured firewalls (in case of connections across one).
  • First method: Determine client name on client, and try to cross-check on server

    This does not work for a number of people because (1) the /etc/hosts file on the client machine has errors (yes, there are plenty machines with a completely messed up /etc/hosts file), (2) the server cannot resolve the client address because the local DNS is f***ed up, or (3) the client machine has multiple network interfaces, and the interface used is not the one the client name resolves to.

    If the client uses the wrong interface on a multi-interface machine, there is a config file option SetBindAddress=IP address that allows to choose the interface the client will use for outgoing connections.

    If you want to download the config file from the server, you should instead use the corresponding command line --bind-address=IP address to select the interface.

    If you encounter problems, you may (1) fix your /etc/hosts file(s), (2) fix your local DNS, or (3) switch to the second method.

    Errors in name resolving/cross-checking can be avoided by setting a very low severity (lower than the logging threshold), e.g.

    SeverityLookup=debug

    in the Misc section of the server configuration, if you prefer running unsafe at any speed instead of fixing the problem (you have been warned). Doing so will allow an attacker to pose as the client.

  • Second method: Use address of connecting entity as known to the communication layer

    This has been dropped as default long ago because it may not always be the address of the client machine. To enable this method, use

    SetClientFromAccept=true

    in the Misc section of the server configuration file. If the address cannot be resolved, or reverse lookup of the resolved name fails, no error message will be issued, but the numerical address will be used.



4.5. Cannot resolve socket peer IP for client host=XXX peer=YYY
See above

4.6. Reverse lookup of socket peer failed host=XXX peer=YYY obj=ZZZ
See above

4.7. No socket peer alias matches client name host=XXX peer=YYY
See above

4.8. Session key negotiation failed
See the document HOWTO client+server troubleshooting

4.9. Invalid connection attempt: Not in client list
See the document HOWTO client+server troubleshooting

4.10. Invalid connection attempt: Session key mismatch
See the document HOWTO client+server troubleshooting

4.11. How do I update the file signature database ?
If you keep the file signature database on the server, the database is supposed to be updated on the server, using the beltane web-based console (currently in beta) and the log messages from the client.

Alternatively, you can scp the database to the client, run samhain -t update -l none --foreground (you need to avoid logging because otherwise you will get in conflict with the running samhain daemon), and then scp the database back to the server. Actually, with a properly set up "ssh", using RSA/DSA authentication and ssh-agent you could write a script to automate this.

4.12. Time limit exceeded
The respective client for that this message is generated has not sent anything for some interval of time (default 84600 sec = 1 day). The interval can be set as follows:
        [Misc]
	# unit is seconds
        SetClientTimeLimit=NNN
This feature has the purpose to detect if a client is dead. You might want to ensure that timestamps are sent to the server:
        [Log]
	ExportSeverity=mark
If you don't want to use this feature, set the time limit to some very large value.

4.13. Invalid connection attempt: Signature mismatch
Clients sign their messages using a session key negotiated with the server. The message indicates that the server could not verify the signature. This may be caused by a running two instances of samhain on the same client machine, both of them accessing the server (and negotiating different session keys ...). The system will recover automatically from the problem by forcing the failed client to negotiate a fresh session key.

4.14. [Server] PANIC .. Address already in use   subroutine=bind
The server cannot bind to its port because the port is already used. Maybe you have accidentially already an instance of the server running.


5. Email

5.1. Reverse lookup failed
Fix your DNS (reverse lookup: numerical IP address to FQDN, to verify FQDN to numerical IP address).
Whether "nslookup" works is not very informative, because 
"nslookup" does not use the resolver library of the operating
system. Therefore,
it is not exactly the
best tool for debugging name resolving problems (see the book
"DNS and bind").


5.2. From daemon@example.com
samhain fails to resolve the self-address of the host. See 'Client cannot self-resolve' in the 'Most frequently' section.

5.3. How do I define more than one email addresses ?
Use SetMailAddress=... multiple times (upt to eight addresses are possible, with at most 63 characters per address):
[Misc]
SetMailAddress=aaa@foo.com
SetMailAddress=bbb@foo.com



6. Misc

6.1. Error message: "Invalid line XYZ in configuration file"
This message indicates that line XYZ in the configuration file contains an unrecognized directive. The primary reasons are:
(a) The directive should be placed into a particular section of the configuration file, but the section header is not present (or you forgot to uncomment it).
(b) Samhain is compiled without support for this directive.
(c) You have a typo in the directive.


6.2. Why do I get a local logfile if I log to the server ?
Because you can use all log facilities in parallel. You should switch off in the config file what you don't want/need:
        [Log]
        # local log file
        LogSeverity=none


6.3. Why is there no NIS support with a static samhain executable on Linux ?
Some functions (including NIS) require libraries that are only available as shared libraries with modern GLIBC versions. While you can always compile a static executable, normally it would still open the shared library at runtime. As of version 1.8.11, samhain avoids this by providing replacement functions from uClibc. However, these do not include NIS support.

6.4. Why do I get hundreds of messages about modified CTIME ?
This happens because some backup applications reset the atime/mtime timestamps, which causes the ctime timestamp to be modified (rootkits avoid this by temporarily resetting the system clock to the original ctime ...).

To fix this problem, read the manual of your backup application, or redefine the ReadOnly policy to not check the ctime timestamp:

        [Misc]
        RedefReadOnly=-CTM
        Order matters - you must first redefine 
        ReadOnly before you use it


6.5. PANIC — File not accessible
Most likely permission denied because of unsufficient privileges.

6.6. How can I avoid error messages for invalid UIDs (no such user) ?
Set SeverityNames to a low value
[EventSeverity]
SeverityNames=debug


6.7. [Redhat] The /etc/init.d/(samhain|yule) init script hangs
Redhat uses "initlog" (see man initlog) in initscripts. If it hangs, most probably samhain/yule runs in the foreground rather than as daemon. Set daemon mode in the configuration file:
[Misc]
Daemon=yes


6.8. The /etc/init.d/(samhain|yule) init script exits with: execvp: No such file or directory
Either the program is not installed, or it is not in the PATH (the one used by the init script, which may be different from your PATH).

6.9. Why am I not receiving the "BEGIN LOGKEY" message by email ?
This message (which contains the key to verify the log file) is generated when logging to the log file starts. It has the severity "ALRT", thus you should make sure that you have set the logging threshold for email correctly to receive it.

6.10. Why does console logging fail if I compile with --enable-(micro-)stealth ?
The default logging options are more "stealthy". Set the threshold explicitely rather than relying on the default.

6.11. I need a list for my schedule !
You can have the same effect with a list of schedules. See the section "Timing file checks" in the manual.

6.12. The hiding kernel module has no effect !
Most probably you compiled using the wrong "System.map" file.

6.13. What does the message "Large lstat/open overhead" mean ?
Your system needs several seconds to proceed from an lstat() system call to an open() system call. This is a tremenduous overhead, and indicates that either your system has a really severe performance problem, or someone tries to slow down samhain.

6.14. What does the message "Device not available path=/dev/random" mean ? I have /dev/random !
/dev/random blocks unless there is some entropy it can deliver. Samhain will time out and fall back on /dev/urandom after some seconds to avoid hanging for a potentially long time. It will try /dev/random again next time it needs entropy.

6.15. Logging to an external program fails; the program receives no data on stdin !
Probably your program is not designed to wait for input, but exits if reading fails (because there is no data yet). You may want to let your program wait for the terminating "[EOF]" line.

6.16. SIGILL on AIX
For each scanned file, samhain needs to store some information in memory (e.g. to recognize changes that have already been reported, and avoid duplicate reports). On AIX, if you are checking a really huge number of files, memory usage may exceed the default limit of 256 MB, and the process may terminate with SIGILL.

The problem can be solved by linking with the flag -bmaxdata:0x80000000. This allows the application to access up to 8 segments (where each segment is 256MB).

If you are using gcc, you need to use instead the flag -Wl,bmaxdata:0x80000000, which tells gcc to pass on the bmaxdata flag to the AIX linker. You can use the LDFLAGS environment variable to pass linker flags to the configure script:

     export LDFLAGS="-Wl,bmaxdata:0x80000000"



7. Database

7.1. Why are client messages corrupted / incompletely stored in the DB ?
Because the messages are not in XML format, and therefore incorrectly parsed. The most frequent reasons are:
        1.) Your server is compiled with --enable-xml-log, but your client(s)
        is/are not.

        2.) In your client or server configuration file, you are using
        the option for a custom message header, but without paying attention
        to preserving the XML format.


7.2. I want / don't want the server timestamps (for client messages) in the SQL database
[Database]
SetDBServerTstamp = true/false
This will enable/disable logging of the server timestamp for client messages. The server timestamp will be written to a seperate record, with log_ref set to the value of log_index of the corresponding client message.

7.3. I don't want the client TIMESTAMP messages in the SQL database
     Sending timestamps from the client allows the server to detect if
     a client is not running anymore (use SetClientTimeLimit=NNN in the
     [Misc] section of the server config file to set the number of seconds
     after which the server will issue an error message if no timestamp has
     been received).
However, you might not want to log these timestamps to the database (or other log facilities). To filter them, you can use two methods (examples are for the SQL database). The first one has the disadvantage that only messages of severity err or higher will be logged:
     [Misc]
     UseClientSeverity=yes

     [Log]
     DatabaseSeverity=err
The second method is more specific — log everything not belonging to the STAMP class of messages:
     [Misc]
     UseClientClass=yes

     [Log]
     DatabaseClass=PANIC RUN FIL TCP ERR ENET EINPUT


7.4. What does the log_ref field mean ?
NULL are client messages. Nonzero integer is a server timestamp for a client message (where log_ref indicates the log_index entry number of the corresponding client message). Zero indicates a message by the server itself (e.g. the server's start message).

7.5. How can I check what is in the database ?
Use a command line client to login to the database and query it:
     sh$ mysql -u <user_name> -p <database_name>
     Enter password: ****
     mysql> SELECT log_index,log_ref,log_host,log_sev,log_msg,path FROM <table_name> WHERE entry_status = 'NEW' ORDER BY log_index;
     ....
     mysql> \q 



Copyright (c) 2004 Rainer Wichmann

This list of questions and answers was generated by makefaq.

samhain-4.1.4/samhainrc.linux0000644000175000017500000003642312615253270013122 00000000000000##################################################################### # # Configuration file template for samhain. # ##################################################################### # # -- empty lines and lines starting with '#', ';' or '//' are ignored # -- boolean options can be Yes/No or True/False or 1/0 # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # # SETUP for file system checking: # # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) Section [EventSeverity]: # To each policy, you can assign a severity (further below). # (iii) Section [Log]: # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### ##################################################################### # # Files are defined with: file = /absolute/path # # Directories are defined with: dir = /absolute/path # or with an optional recursion depth (N <= 99): dir = N/absolute/path # # Directory inodes are checked. If you only want to check files # in a directory, but not the directory inode itself, use (e.g.): # # [ReadOnly] # dir = /some/directory # [IgnoreAll] # file = /some/directory # # You can use shell-style globbing patterns, like: file = /path/foo* # ###################################################################### [Misc] ## ## Add or subtract tests from the policies ## - if you want to change their definitions, ## you need to do that before using the policies ## # RedefReadOnly = (no default) # RedefAttributes=(no default) # RedefLogFiles=(no default) # RedefGrowingLogFiles=(no default) # RedefIgnoreAll=(no default) # RedefIgnoreNone=(no default) # RedefUser0=(no default) # RedefUser1=(no default) # # --------- / -------------- # [ReadOnly] dir = 0/ [Attributes] file = /tmp file = /dev file = /media file = /proc file = /sys # # --------- /etc ----------- # [ReadOnly] ## ## for these files, only access time is ignored ## dir = 99/etc [Attributes] ## ## check permission and ownership ## file = /etc/mtab file = /etc/adjtime file = /etc/motd file = /etc/lvm/.cache # On Ubuntu, these are in /var/lib rather than /etc file = /etc/cups/certs file = /etc/cups/certs/0 # managed by fstab-sync on Fedora Core file = /etc/fstab # modified when booting file = /etc/sysconfig/hwconf # There are files in /etc that might change, thus changing the directory # timestamps. Put it here as 'file', and in the ReadOnly section as 'dir'. file = /etc # # --------- /boot ----------- # [ReadOnly] dir = 99/boot # # --------- /bin, /sbin ----------- # [ReadOnly] dir = 99/bin dir = 99/sbin # # --------- /lib ----------- # [ReadOnly] dir = 99/lib # # --------- /dev ----------- # [Attributes] dir = 99/dev [IgnoreAll] ## ## pseudo terminals are created/removed as needed ## dir = -1/dev/pts # dir = -1/dev/.udevdb file = /dev/ppp # # --------- /usr ----------- # [ReadOnly] dir = 99/usr # # --------- /var ----------- # [ReadOnly] dir = 99/var [IgnoreAll] dir = -1/var/cache dir = -1/var/backups dir = -1/var/games dir = -1/var/gdm dir = -1/var/lock dir = -1/var/mail dir = -1/var/run dir = -1/var/spool dir = -1/var/tmp dir = -1/var/lib/texmf dir = -1/var/lib/scrollkeeper [Attributes] dir = /var/lib/nfs dir = /var/lib/pcmcia # /var/lib/rpm changes if packets are installed; # /var/lib/rpm/__db.00[123] even more frequently file = /var/lib/rpm/__db.00? file = /var/lib/acpi-support/vbestate file = /var/lib/alsa/asound.state file = /var/lib/apt/lists/lock file = /var/lib/apt/lists/partial file = /var/lib/cups/certs file = /var/lib/cups/certs/0 file = /var/lib/dpkg/lock file = /var/lib/gdm file = /var/lib/gdm/.cookie file = /var/lib/gdm/.gdmfifo file = /var/lib/gdm/:0.Xauth file = /var/lib/gdm/:0.Xservers file = /var/lib/logrotate/status file = /var/lib/mysql file = /var/lib/mysql/ib_logfile0 file = /var/lib/mysql/ibdata1 file = /var/lib/slocate file = /var/lib/slocate/slocate.db file = /var/lib/slocate/slocate.db.tmp file = /var/lib/urandom file = /var/lib/urandom/random-seed file = /var/lib/random-seed file = /var/lib/xkb [GrowingLogFiles] ## ## For these files, changes in signature, timestamps, and increase in size ## are ignored. Logfile rotation will cause a report because of shrinking ## size and different inode. ## dir = 99/var/log [Attributes] # # rotated logs will change inode # file = /var/log/*.[0-9].gz file = /var/log/*.[0-9].log file = /var/log/*.[0-9] file = /var/log/*.old file = /var/log/*/*.[0-9].gz file = /var/log/*/*.[0-9][0-9].gz file = /var/log/*/*.log.[0-9] [Misc] # # Various naming schemes for rotated logs # IgnoreAdded = /var/log/.*\.[0-9]+$ IgnoreAdded = /var/log/.*\.[0-9]+\.gz$ IgnoreAdded = /var/log/.*\.[0-9]+\.log$ # # Subdirectories # IgnoreAdded = /var/log/[[:alnum:]]+/.*\.[0-9]+$ IgnoreAdded = /var/log/[[:alnum:]]+/.*\.[0-9]+\.gz$ IgnoreAdded = /var/log/[[:alnum:]]+/.*\.[0-9]+\.log$ # IgnoreAdded = /var/lib/slocate/slocate.db.tmp IgnoreMissing = /var/lib/slocate/slocate.db.tmp # # --------- other policies ----------- # [IgnoreNone] ## ## for these files, all modifications (even access time) are reported ## - you may create some interesting-looking file (like /etc/safe_passwd), ## just to watch whether someone will access it ... ## [Prelink] ## ## Use for prelinked files or directories holding them ## [User0] [User1] ## User0 and User1 are sections for files/dirs with user-definable checking ## (see the manual) [EventSeverity] ## ## Here you can assign severities to policy violations. ## If this severity exceeds the treshold of a log facility (see below), ## a policy violation will be logged to that facility. ## ## Severity for verification failures. ## # SeverityReadOnly=crit # SeverityLogFiles=crit # SeverityGrowingLogs=crit # SeverityIgnoreNone=crit # SeverityAttributes=crit # SeverityUser0=crit # SeverityUser1=crit # SeverityIgnoreAll=crit ## Files : file access problems # SeverityFiles=crit ## Dirs : directory access problems # SeverityDirs=crit ## Names : suspect (non-printable) characters in a pathname # SeverityNames=crit [Log] ## ## Switch on/OFF log facilities and set their threshold severity ## ## Values: debug, info, notice, warn, mark, err, crit, alert, none. ## 'mark' is used for timestamps. ## ## ## Use 'none' to SWITCH OFF a log facility ## ## By default, everything equal to and above the threshold is logged. ## The specifiers '*', '!', and '=' are interpreted as ## 'all', 'all but', and 'only', respectively (like syslogd(8) does, ## at least on Linux). Examples: ## MailSeverity=* ## MailSeverity=!warn ## MailSeverity==crit ## E-mail ## # MailSeverity=none ## Console ## # PrintSeverity=info ## Logfile ## # LogSeverity=mark ## Syslog ## # SyslogSeverity=none ## Remote server (yule) ## # ExportSeverity=none ## External script or program ## # ExternalSeverity = none ## Logging to a database ## # DatabaseSeverity = none ## Logging to a Prelude-IDS ## # PreludeSeverity = crit ##################################################### # # Optional modules # ##################################################### # [SuidCheck] ## ## --- Check the filesystem for SUID/SGID binaries ## ## Switch on # # SuidCheckActive = yes ## Interval for check (seconds) # # SuidCheckInterval = 7200 ## Alternative: crontab-like schedule # # SuidCheckSchedule = NULL ## Directory to exclude # # SuidCheckExclude = NULL ## Limit on files per second (0 == no limit) # # SuidCheckFps = 0 ## Alternative: yield after every file # # SuidCheckYield = no ## Severity of a detection # # SeveritySuidCheck = crit ## Quarantine SUID/SGID files if found # # SuidCheckQuarantineFiles = yes ## Method for Quarantining files: # 0 - Delete or truncate the file. # 1 - Remove SUID/SGID permissions from file. # 2 - Move SUID/SGID file to quarantine dir. # # SuidCheckQuarantineMethod = 0 ## For method 1 and 3, really delete instead of truncating # # SuidCheckQuarantineDelete = yes # [Utmp] ## ## --- Logging of login/logout events ## ## Switch on/off # # LoginCheckActive = True ## Severity for logins, multiple logins, logouts # # SeverityLogin=info # SeverityLoginMulti=warn # SeverityLogout=info ## Interval for login/logout checks # # LoginCheckInterval = 300 # [Database] ## ## --- Logging to a relational database ## ## Database name # # SetDBName = samhain ## Database table # # SetDBTable = log ## Database user # # SetDBUser = samhain ## Database password # # SetDBPassword = (default: none) ## Database host # # SetDBHost = localhost ## Log the server timestamp for received messages # # SetDBServerTstamp = True ## Use a persistent connection # # UsePersistent = True # [External] ## ## Interface to call external scripts/programs for logging ## ## The absolute path to the command ## - Each invocation of this directive will end the definition of the ## preceding command, and start the definition of ## an additional, new command # # OpenCommand = (no default) ## Type (log or rv) ## - log for log messages, srv for messages received by the server # # SetType = log ## The command (full command line) to execute # # SetCommandLine = (no default) ## The environment (KEY=value; repeat for more) # # SetEnviron = TZ=(your timezone) ## The TIGER192 checksum (optional) # # SetChecksum = (no default) ## User who runs the command # # SetCredentials = (default: samhain process uid) ## Words not allowed in message # # SetFilterNot = (none) ## Words required (ALL of them) # # SetFilterAnd = (none) ## Words required (at least one) # # SetFilterOr = (none) ## Deadtime between consecutive calls # # SetDeadtime = 0 ## Add default environment (HOME, PATH, SHELL) # # SetDefault = no ##################################################### # # Miscellaneous configuration options # ##################################################### [Misc] ## whether to become a daemon process ## (this is not honoured on database initialisation) # # Daemon = no Daemon = yes ## whether to test signature of files (init/check/none) ## - if 'none', then we have to decide this on the command line - # # ChecksumTest = none ChecksumTest=check ## Set nice level (-19 to 19, see 'man nice'), ## and I/O limit (kilobytes per second; 0 == off) ## to reduce load on host. # # SetNiceLevel = 0 # SetIOLimit = 0 ## The version string to embed in file signature databases # # VersionString = NULL ## Interval between time stamp messages # # SetLoopTime = 60 SetLoopTime = 600 ## Interval between file checks # # SetFileCheckTime = 600 SetFileCheckTime = 7200 ## Alternative: crontab-like schedule # # FileCheckScheduleOne = NULL ## Alternative: crontab-like schedule(2) # # FileCheckScheduleTwo = NULL ## Report only once on modified files ## Setting this to 'FALSE' will generate a report for any policy ## violation (old and new ones) each time the daemon checks the file system. # # ReportOnlyOnce = True ## Report in full detail # # ReportFullDetail = False ## Report file timestamps in local time rather than GMT # # UseLocalTime = No ## The console device (can also be a file or named pipe) ## - There are two console devices. Accordingly, you can use ## this directive a second time to set the second console device. ## If you have not defined the second device at compile time, ## and you don't want to use it, then: ## setting it to /dev/null is less effective than just leaving ## it alone (setting to /dev/null will waste time by opening ## /dev/null and writing to it) # # SetConsole = /dev/console ## Activate the SysV IPC message queue # # MessageQueueActive = False ## If false, skip reverse lookup when connecting to a host known ## by name rather than IP address (i.e. trust the DNS) # # SetReverseLookup = True ## --- E-Mail --- # Only highest-level (alert) reports will be mailed immediately, # others will be queued. Here you can define, when the queue will # be flushed (Note: the queue is automatically flushed after # completing a file check). # # SetMailTime = 86400 ## Maximum number of mails to queue # # SetMailNum = 10 ## Recipient (max. 8) # # SetMailAddress=root@localhost ## Mail relay (IP address) # # SetMailRelay = NULL ## Custom subject format # # MailSubject = NULL ## --- end E-Mail --- ## Path to the prelink executable # # SetPrelinkPath = /usr/sbin/prelink ## TIGER192 checksum of the prelink executable # # SetPrelinkChecksum = (no default) ## Path to the executable. If set, will be checksummed after startup ## and before exit. # # SamhainPath = (no default) ## The IP address of the log server # # SetLogServer = (default: compiled-in) ## The IP address of the time server # # SetTimeServer = (default: compiled-in) ## Trusted Users (comma delimited list of user names) # # TrustedUser = (no default; this adds to the compiled-in list) ## Path to the file signature database # # SetDatabasePath = (default: compiled-in) ## Path to the log file # # SetLogfilePath = (default: compiled-in) ## Path to the PID file # # SetLockfilePath = (default: compiled-in) ## The digest/checksum/hash algorithm # # DigestAlgo = TIGER192 ## Custom format for message header. ## CAREFUL if you use XML logfile format. ## ## %S severity ## %T timestamp ## %C class ## ## %F source file ## %L source line # # MessageHeader="%S %T " ## Don't log path to config/database file on startup # # HideSetup = False ## The syslog facility, if you log to syslog # # SyslogFacility = LOG_AUTHPRIV SyslogFacility=LOG_LOCAL2 ## The message authentication method ## - If you change this, you *must* change it ## on client *and* server # # MACType = HMAC-TIGER ## The Prelude-IDS profile to use for reporting ## default value is "samhain" # # PreludeProfile = samhain ## Map these samhain severities to impact severity 'info' severity # # PreludeMapToInfo = ## Map these samhain severities to impact severity 'low' severity # # PreludeMapToLow = debug info ## Map these samhain severities to impact severity 'medium' severity # # PreludeMapToMedium = notice warn err ## Map these samhain severities to impact severity 'high' severity # # PreludeMapToHigh = crit alert ## everything below is ignored [EOF] ##################################################################### # This would be the proper syntax for parts that should only be # included for certain hosts. # You may enclose anything in a @HOSTNAME/@end bracket, as long as the # result still has the proper syntax for the config file. # You may have any number of @HOSTNAME/@end brackets. # HOSTNAME should be the fully qualified 'official' name # (e.g. 'nixon.watergate.com', not 'nixon'), no aliases. # No IP number - except if samhain cannot determine the # fully qualified hostname. # # @HOSTNAME # file=/foo/bar # @end # # These are two examples for conditional inclusion/exclusion # of a machine based on the output from 'uname -srm' # $Linux:2.*.7:i666 # file=/foo/bar3 # $end # # !$Linux:2.*.7:i686 # file=/foo/bar2 # $end # ##################################################################### samhain-4.1.4/depend.sum0000644000175000017500000000001312615253270012043 000000000000002959213307 samhain-4.1.4/sql_init/0000755000175000017500000000000012615253270011766 500000000000000samhain-4.1.4/sql_init/samhain.postgres.init0000644000175000017500000000545612615253277016101 00000000000000CREATE SEQUENCE log_log_index_seq START 1; CREATE TABLE log ( log_index INTEGER NOT NULL, log_ref BIGINT NULL, log_host VARCHAR(64) NOT NULL DEFAULT 'localhost', log_time TIMESTAMP NOT NULL, log_sev VARCHAR(4) NOT NULL, log_msg TEXT, log_hash VARCHAR(32), entry_status VARCHAR(16) NOT NULL DEFAULT 'NEW', path TEXT, userid VARCHAR(8), grp VARCHAR(8), program VARCHAR(8), subroutine VARCHAR(16), status VARCHAR(12), hash VARCHAR(50), path_data TEXT, hash_data VARCHAR(50), key_uid VARCHAR(64), key_uid_data VARCHAR(64), key_id VARCHAR(16), module VARCHAR(8), return_code INTEGER, syscall VARCHAR(16), ip VARCHAR(46), tty VARCHAR(16), peer VARCHAR(64), fromhost VARCHAR(64), obj TEXT, interface VARCHAR(64), time VARCHAR(64), dir TEXT, linked_path TEXT, port INTEGER, service VARCHAR(64), facility VARCHAR(32), priority VARCHAR(32), syslog_msg TEXT, mode_old VARCHAR(16), mode_new VARCHAR(16), attr_old VARCHAR(16), attr_new VARCHAR(16), device_old VARCHAR(16), device_new VARCHAR(16), owner_old VARCHAR(9), owner_new VARCHAR(9), group_old VARCHAR(9), group_new VARCHAR(9), ctime_old TIMESTAMP, ctime_new TIMESTAMP, atime_old TIMESTAMP, atime_new TIMESTAMP, mtime_old TIMESTAMP, mtime_new TIMESTAMP, chksum_old VARCHAR(50), chksum_new VARCHAR(50), link_old TEXT, link_new TEXT, size_old NUMERIC(20), size_new NUMERIC(20), hardlinks_old NUMERIC(20), hardlinks_new NUMERIC(20), inode_old NUMERIC(20), inode_new NUMERIC(20), imode_old NUMERIC(20), imode_new NUMERIC(20), iattr_old NUMERIC(20), iattr_new NUMERIC(20), idevice_old NUMERIC(20), idevice_new NUMERIC(20), iowner_old NUMERIC(20), iowner_new NUMERIC(20), igroup_old NUMERIC(20), igroup_new NUMERIC(20), checkflags_old NUMERIC(20), checkflags_new NUMERIC(20), acl_old TEXT, acl_new TEXT ); CREATE UNIQUE INDEX log_log_index_key on log (log_index); CREATE INDEX ix_hash ON log (log_hash); CREATE INDEX ix_log_host ON log (log_host); CREATE INDEX ix_entry_status ON log (entry_status); GRANT INSERT ON log TO samhain; GRANT UPDATE ON log_log_index_seq TO samhain; GRANT SELECT ON log_log_index_seq TO samhain; samhain-4.1.4/sql_init/samhain.oracle.init0000644000175000017500000000620712615253277015473 00000000000000CREATE SEQUENCE log_log_index_seq START WITH 1; CREATE TABLE log ( log_index INTEGER NOT NULL, log_ref NUMBER(20) NULL, log_host VARCHAR2(64) DEFAULT 'localhost' NOT NULL, log_time DATE NOT NULL, log_sev VARCHAR2(4) NOT NULL, log_msg VARCHAR2(4000), log_hash VARCHAR2(32), entry_status VARCHAR2(16) DEFAULT 'NEW' NOT NULL, path CLOB, userid VARCHAR2(8), grp VARCHAR2(8), program VARCHAR2(8), subroutine VARCHAR2(16), status VARCHAR2(12), hash VARCHAR2(50), path_data VARCHAR2(4000), hash_data VARCHAR2(50), key_uid VARCHAR2(64), key_uid_data VARCHAR2(64), key_id VARCHAR2(16), module VARCHAR2(8), return_code INTEGER, syscall VARCHAR2(16), ip VARCHAR2(46), tty VARCHAR2(16), peer VARCHAR2(64), fromhost VARCHAR2(64), obj VARCHAR2(4000), interface VARCHAR2(64), time VARCHAR2(64), dir CLOB, linked_path CLOB, port INTEGER, service VARCHAR2(64), facility VARCHAR2(32), priority VARCHAR2(32), syslog_msg VARCHAR2(4000), mode_old VARCHAR2(16), mode_new VARCHAR2(16), attr_old VARCHAR2(16), attr_new VARCHAR2(16), device_old VARCHAR2(16), device_new VARCHAR2(16), owner_old VARCHAR2(9), owner_new VARCHAR2(9), group_old VARCHAR2(9), group_new VARCHAR2(9), ctime_old VARCHAR2(25), ctime_new VARCHAR2(25), atime_old VARCHAR2(25), atime_new VARCHAR2(25), mtime_old VARCHAR2(25), mtime_new VARCHAR2(25), chksum_old VARCHAR2(50), chksum_new VARCHAR2(50), link_old CLOB, link_new CLOB, size_old NUMBER(20), size_new NUMBER(20), hardlinks_old NUMBER(20), hardlinks_new NUMBER(20), inode_old NUMBER(20), inode_new NUMBER(20), imode_old NUMBER(20), imode_new NUMBER(20), iattr_old NUMBER(20), iattr_new NUMBER(20), idevice_old NUMBER(20), idevice_new NUMBER(20), iowner_old NUMBER(20), iowner_new NUMBER(20), igroup_old NUMBER(20), igroup_new NUMBER(20), checkflags_old NUMBER(20), checkflags_new NUMBER(20), acl_old VARCHAR2(4000), acl_new VARCHAR2(4000) ); CREATE UNIQUE INDEX log_log_index_key on log (log_index); CREATE INDEX ix_hash ON log (log_hash); CREATE INDEX ix_log_host ON log (log_host); CREATE INDEX ix_log_ref ON log (log_ref); CREATE INDEX ix_entry_status ON log (entry_status); GRANT INSERT ON log TO samhain; GRANT ALTER ON log_log_index_seq TO samhain; GRANT SELECT ON log_log_index_seq TO samhain; samhain-4.1.4/sql_init/samhain.mysql.init0000644000175000017500000000562112615253277015372 00000000000000CREATE DATABASE samhain; USE mysql; INSERT INTO db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv) VALUES ('localhost','samhain','','N','Y','N','N','N','N'); USE samhain; CREATE TABLE samhain.log ( log_index BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, log_ref BIGINT UNSIGNED NULL, log_host VARCHAR(64) NOT NULL DEFAULT "localhost", INDEX ix_log_host (log_host), log_time DATETIME NOT NULL, log_sev ENUM("DEBG","INFO","NOTE","WARN","MARK","ERRO","CRIT","ALRT","RCVT") NOT NULL, log_msg BLOB, log_hash VARCHAR(32) NOT NULL, KEY ix_hash (log_hash), entry_status VARCHAR(16) NOT NULL DEFAULT "NEW", INDEX ix_entry_status (entry_status), path BLOB, userid VARCHAR(8), grp VARCHAR(8), program VARCHAR(8), subroutine VARCHAR(16), status VARCHAR(12), hash VARCHAR(50), path_data BLOB, hash_data VARCHAR(50), key_uid VARCHAR(64), key_uid_data VARCHAR(64), key_id VARCHAR(16), module VARCHAR(8), return_code INTEGER, syscall VARCHAR(16), ip VARCHAR(46), tty VARCHAR(16), peer VARCHAR(64), fromhost VARCHAR(64), obj BLOB, interface VARCHAR(64), time VARCHAR(64), dir BLOB, linked_path BLOB, port INTEGER, service VARCHAR(64), facility VARCHAR(32), priority VARCHAR(32), syslog_msg BLOB, mode_old VARCHAR(16), mode_new VARCHAR(16), attr_old VARCHAR(16), attr_new VARCHAR(16), device_old VARCHAR(16), device_new VARCHAR(16), owner_old VARCHAR(9), owner_new VARCHAR(9), group_old VARCHAR(9), group_new VARCHAR(9), ctime_old DATETIME, ctime_new DATETIME, atime_old DATETIME, atime_new DATETIME, mtime_old DATETIME, mtime_new DATETIME, chksum_old VARCHAR(50), chksum_new VARCHAR(50), link_old BLOB, link_new BLOB, size_old BIGINT UNSIGNED, size_new BIGINT UNSIGNED, hardlinks_old BIGINT UNSIGNED, hardlinks_new BIGINT UNSIGNED, inode_old BIGINT UNSIGNED, inode_new BIGINT UNSIGNED, imode_old BIGINT UNSIGNED, imode_new BIGINT UNSIGNED, iattr_old BIGINT UNSIGNED, iattr_new BIGINT UNSIGNED, idevice_old BIGINT UNSIGNED, idevice_new BIGINT UNSIGNED, iowner_old BIGINT UNSIGNED, iowner_new BIGINT UNSIGNED, igroup_old BIGINT UNSIGNED, igroup_new BIGINT UNSIGNED, checkflags_old BIGINT UNSIGNED, checkflags_new BIGINT UNSIGNED, acl_old BLOB, acl_new BLOB ); samhain-4.1.4/config.h.in0000664000175000017500000007402612724114667012131 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ #ifndef CONFIG_H #define CONFIG_H /* ---- compile options ------------ */ /* Define if you want database support */ #undef WITH_DATABASE /* Define if the database is unixODBC */ #undef WITH_ODBC /* Define if the database is oracle */ #undef WITH_ORACLE /* Define if the database is mysql */ #undef WITH_MYSQL /* Define if the database is postgresql */ #undef WITH_POSTGRES /* Define if the server may listen on 514/udp */ #undef INET_SYSLOG /* Define if you want logfile in XML format */ #undef SH_USE_XML /* Define if you want external programs. */ #undef WITH_EXTERNAL /* Define if you want to reload the database */ /* on SIGHUP. */ #undef RELOAD_DATABASE /* Define if you want SysV message queue. */ #undef WITH_MESSAGE_QUEUE /* Define the mode of the message queue. */ #undef MESSAGE_QUEUE_MODE /* Define which users are always trusted. */ /* default = 0 ( = root) */ #undef SL_ALWAYS_TRUSTED /* Define if you want network time. */ /* default = no */ #undef HAVE_NTIME /* The time server host address. */ /* default = "NULL" */ #undef DEFAULT_TIMESERVER #undef ALT_TIMESERVER /* Define if you want to use the mail code. */ /* default = yes */ #undef SH_WITH_MAIL /* Define if you want client/server encryption*/ #undef SH_ENCRYPT /* Define if you want version 2 encryption */ #undef SH_ENCRYPT_2 /* Define if you want to watch for login/-out.*/ /* default = no */ #undef SH_USE_UTMP /* Define if you want to check mount options on filesystems */ /* default = no */ #undef SH_USE_MOUNTS /* Define if you want to keep an eye on */ /* sensitive files that your users own */ #undef SH_USE_USERFILES /* Define if you want to watch for suid/sgid */ /* files */ #undef SH_USE_SUIDCHK /* Define if you want to check kernel syscall */ /* table to detect LKM rootkits. */ /* default = no */ #undef SH_USE_KERN /* Define if you want to use the Kernel */ /* module to hide samhain. */ #undef SH_USE_LKM /* Define if you have a vanilla Kernel */ /* (2.4 or 2.2) */ #undef SH_VANILLA_KERNEL /* Define to the name of the MAGIC_HIDE */ /* string if you use the Kernel module to */ /* hide samhain. */ #undef SH_MAGIC_HIDE /* Define if you want 'micro' stealth mode. */ /* default = no */ #undef SH_STEALTH_MICRO /* Define if you want to use stealth mode. */ /* default = no */ #undef SH_STEALTH /* Define if you want stealth w/o CL parsing. */ /* default = no */ #undef SH_STEALTH_NOCL /* The magic argv[1] to re-enable CL parsing. */ /* default = "yes" */ #undef NOCL_CODE /* XOR value to hide literal strings. */ /* default = 0 */ #undef XOR_CODE /* The port number for TCP/IP connection. */ /* default = 49777 */ #undef SH_DEFAULT_PORT /* The identity to assume when dropping root */ /* default = "nobody" */ #undef DEFAULT_IDENT /* Directory for tmp files */ #undef SH_TMPDIR /* The data root directory. */ /* default="/var/lib/samhain" */ #undef DEFAULT_DATAROOT /* The quarantine directory. */ /* default="/var/lib/samhain/.quarantine */ #undef DEFAULT_QDIR /* The location of the log file. */ /* default="/var/log/samhain_log" */ #undef DEFAULT_ERRFILE /* The directory of the log file. */ /* default="/var/log" */ #undef DEFAULT_LOGDIR /* The location of the pid file. */ /* default="/var/run/samhain.pid" */ #undef DEFAULT_ERRLOCK /* The location of the pid file directory. */ /* default="/var/run " */ #undef DEFAULT_PIDDIR /* The location of the configuration file. */ /* default="/etc/samhainrc" */ #undef DEFAULT_CONFIGFILE /* The location of the checksum data. */ /* default="/var/lib/samhain/samhain_file" */ #undef DEFAULT_DATA_FILE /* The location of the html report. */ /* default="/var/log/.samhain.html" */ #undef DEFAULT_HTML_FILE /* The install directory. */ /* default="/usr/local/sbin" */ #undef SH_INSTALL_DIR /* The install path. */ /* default="/usr/local/sbin/samhain" */ #undef SH_INSTALL_PATH #undef SH_INSTALL_YULE_PATH /* The install name. */ /* default="samhain" */ #undef SH_INSTALL_NAME /* The sender name to use. */ /* default = "daemon" */ #undef DEFAULT_SENDER /* The address to send mail to. */ /* default = "NULL" */ #undef DEFAULT_MAILADDRESS #undef ALT_MAILADDRESS /* The log server. */ /* default = "NULL" */ #undef DEFAULT_LOGSERVER #undef ALT_LOGSERVER /* The console. */ /* default = "NULL" */ #undef DEFAULT_CONSOLE #undef ALT_CONSOLE /* The default base for one-time pads. */ /* default = compile_time,compile_time */ #undef DEFKEY /* Define if you want more debug options. */ /* default = no */ #undef MEM_DEBUG /* Define if you want more debug output. */ /* default = no */ #undef WITH_TPT /* Define if you want tracing. */ /* default = no */ #undef WITH_TRACE /* Define if you want slib debug. */ /* default = no */ #undef SL_DEBUG /* Define if you want slib to abort on errors.*/ /* default = no */ #undef SL_FAIL_ON_ERROR /* Define if you want to use SRP authenticaton*/ #undef USE_SRP_PROTOCOL /* Define if you want to use GnuPG to */ /* verify database and configuation file. */ #undef WITH_GPG /* The full path to GnuPG */ #undef DEFAULT_GPG_PATH /* Define if using the gpg/pgp checksum. */ #undef HAVE_GPG_CHECKSUM /* The tiger checksum of the gpg/pgp binary. */ #undef GPG_HASH /* Define if you want to compile in the */ /* public key fingerprint. */ #undef USE_FINGERPRINT /* The public key fingerprint. */ #undef SH_GPG_FP /* Use ptrace - screw up signal handling. */ #undef SCREW_IT_UP /* ---- misc ------------ */ /* Define the package name. */ #undef PACKAGE /* Define the package version. */ #undef VERSION /* Define to the position of the key (1...8). */ #undef POS_TF /* Init key for exepack. */ #undef EXEPACK_STATE_0 #undef EXEPACK_STATE_1 #undef EXEPACK_STATE_2 /* ---- system-specific options ------------ */ /* Define to the address of sys_call_table */ #undef SH_SYSCALLTABLE /* Define to use SVR4 statvfs to get filesystem type. */ #undef FSTYPE_STATVFS /* Define to use SVR3.2 statfs to get filesystem type. */ #undef FSTYPE_USG_STATFS /* Define to use AIX3 statfs to get filesystem type. */ #undef FSTYPE_AIX_STATFS /* Define to use 4.3BSD getmntent to get filesystem type. */ #undef FSTYPE_MNTENT /* Define to use 4.4BSD and OSF1 statfs to get filesystem type. */ #undef FSTYPE_STATFS /* Define to use Ultrix getmnt to get filesystem type. */ #undef FSTYPE_GETMNT /* the basic type to which we can cast a uid */ #undef UID_CAST /* for ext2fs flags */ #undef HAVE_EXT2_IOCTLS #undef HAVE_STAT_FLAGS /* obvious */ #undef HOST_IS_LINUX #undef HOST_IS_I86LINUX /* obvious */ #undef HOST_IS_CYGWIN /* obvious */ #undef HOST_IS_DARWIN /* obvious */ #undef HOST_IS_FREEBSD /* obvious */ #undef HOST_IS_AIX /* obvious */ #undef HOST_IS_SOLARIS /* obvious */ #undef HOST_IS_I86SOLARIS /* obvious */ #undef HOST_IS_HPUX /* Define to the name of the random devices. */ #undef NAME_OF_DEV_RANDOM #undef NAME_OF_DEV_URANDOM /* Define if you have long long. */ #undef HAVE_LONG_LONG /* Define if short is 32 bits. */ #undef HAVE_SHORT_32 /* Define if int is 32 bits. */ #undef HAVE_INT_32 /* Define if long is 32 bits. */ #undef HAVE_LONG_32 /* Define if long is 64 bits. */ #undef HAVE_LONG_64 /* Define if UINT64 is 32 bits. */ #undef UINT64_IS_32 /* Define if you have uint64_t. */ #undef HAVE_UINT16_T /* Define if you have uint64_t. */ #undef HAVE_UINT64_T /* Define if you have utmpx.h. */ #undef HAVE_UTMPX_H /* Define if your struct utmpx has ut_xtime. */ #undef HAVE_UTXTIME /* Define if your struct utmp has ut_type. */ #undef HAVE_UTTYPE /* Define if your struct utmp has ut_host. */ #undef HAVE_UTHOST /* Define if your struct utmp has ut_addr. */ #undef HAVE_UTADDR /* Define if your struct utmp has ut_addr_v6 */ #undef HAVE_UTADDR_V6 /* Define if your includes are broken. */ #undef HAVE_BROKEN_INCLUDES /* Define if your getcwd uses 'popen'. */ #undef HAVE_BROKEN_GETCWD /* Define if your vsnprintf is broken. */ #undef HAVE_BROKEN_VSNPRINTF /* Define if you have va_copy. */ #undef VA_COPY /* Define if va_list may be copied as array. */ #undef VA_COPY_AS_ARRAY /* Define if you need unix entropy gatherer. */ #undef HAVE_UNIX_RANDOM /* Define if you have EGD. */ #undef HAVE_EGD_RANDOM /* Define if you have /dev/random. */ #undef HAVE_URANDOM /* Soket name for EGD. */ #undef EGD_SOCKET_NAME /* Define if your mlock() is broken. */ #undef HAVE_BROKEN_MLOCK /* Define the proc f_type. */ #undef SH_PROC_MAGIC /* Define if you have statfs. */ #undef HAVE_STATFS /* Define if statfs works. */ #undef STATFS_WORKS /* Define to long if not defined. */ #undef ptrdiff_t /* type of arg3 of accept */ #undef ACCEPT_TYPE_ARG3 /* Define if 's AC_ETIME field is a COMP_T. */ #undef ACETIME_COMPT /* Define if 's AC_IO field is a COMP_T. */ #undef ACIO_COMPT /* Define if 's AC_MAJFLT field is a COMP_T. */ #undef ACMAJFLT_COMPT /* Define if 's AC_MEM field is a COMP_T. */ #undef ACMEM_COMPT /* Define if 's AC_MINFLT field is a COMP_T. */ #undef ACMINFLT_COMPT /* Define if 's AC_STIME field is a COMP_T. */ #undef ACSTIME_COMPT /* Define if 's AC_SWAPS field is a COMP_T. */ #undef ACSWAPS_COMPT /* Define if 's AC_UTIME field is a COMP_T. */ #undef ACUTIME_COMPT /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Debug dnmalloc */ #undef DNMALLOC_CHECKS /* Define if SSP C support is enabled. */ #undef ENABLE_SSP_CC /* gcc version major */ #undef GCC_VERSION_MAJOR /* gcc version minor */ #undef GCC_VERSION_MINOR /* Define if has struct acctv2. */ #undef HAVE_ACCTV2 /* Define if has struct acct_v3. */ #undef HAVE_ACCT_V3 /* Define if has the AC_ETIME field. */ #undef HAVE_ACETIME /* Define if has the AC_IO field. */ #undef HAVE_ACIO /* Define to 1 if you have the `acl_free' function. */ #undef HAVE_ACL_FREE /* Define to 1 if you have the `acl_get_fd' function. */ #undef HAVE_ACL_GET_FD /* Define to 1 if you have the `acl_get_file' function. */ #undef HAVE_ACL_GET_FILE /* Define if has the AC_MEM field. */ #undef HAVE_ACMEM /* Define if has the AC_STIME field. */ #undef HAVE_ACSTIME /* Define if has the AC_UTIME field. */ #undef HAVE_ACUTIME /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_COMPAT_H /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_H /* Define to 1 if you have the header file. */ #undef HAVE_ASM_SEGMENT_H /* Define to 1 if you have the header file. */ #undef HAVE_ATTR_XATTR_H /* Define to 1 if you have the header file. */ #undef HAVE_AUPARSE_H /* Define if you have the auparse lib */ #undef HAVE_AUPARSE_LIB /* Define to 1 if you have the `basename' function. */ #undef HAVE_BASENAME /* Define if you have a broken version of the `vsnprintf' function. */ #undef HAVE_BROKEN_VSNPRINTF /* Define to 1 if you have the `compressBound' function. */ #undef HAVE_COMPRESSBOUND /* Define if uses the COMP_T type. */ #undef HAVE_COMP_T /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #undef HAVE_DECL_SYS_SIGLIST /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_ELF_H /* Define to 1 if you have the `endpwent' function. */ #undef HAVE_ENDPWENT /* Define to 1 if you have the header file. */ #undef HAVE_EXT2FS_EXT2_FS_H /* Define to 1 if you have the `fchmod' function. */ #undef HAVE_FCHMOD /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fgetxattr' function. */ #undef HAVE_FGETXATTR /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H /* Define to 1 if you have the `fpurge' function. */ #undef HAVE_FPURGE /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `getgrgid_r' function. */ #undef HAVE_GETGRGID_R /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `getnameinfo' function. */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getpeereid' function. */ #undef HAVE_GETPEEREID /* Define to 1 if you have the `getpgid' function. */ #undef HAVE_GETPGID /* Define to 1 if you have the `getpriority' function. */ #undef HAVE_GETPRIORITY /* Define to 1 if you have the `getpwent' function. */ #undef HAVE_GETPWENT /* Define to 1 if you have the `getpwnam_r' function. */ #undef HAVE_GETPWNAM_R /* Define to 1 if you have the `getpwuid_r' function. */ #undef HAVE_GETPWUID_R /* Define to 1 if you have the `getsid' function. */ #undef HAVE_GETSID /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the `getwd' function. */ #undef HAVE_GETWD /* Define to 1 if you have the `getxattr' function. */ #undef HAVE_GETXATTR /* Define to 1 if you have the header file. */ #undef HAVE_GLOB_H /* Define to 1 if you have the header file. */ #undef HAVE_GMP_H /* Define to 1 if you have the `gmtime_r' function. */ #undef HAVE_GMTIME_R /* Define to 1 if you have the `hasmntopt' function. */ #undef HAVE_HASMNTOPT /* Define to 1 if you have the `inet_aton' function. */ #undef HAVE_INET_ATON /* Define to 1 if you have the `initgroups' function. */ #undef HAVE_INITGROUPS /* Define to 1 if you have the `inotify_init1' function. */ #undef HAVE_INOTIFY_INIT1 /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `lgetxattr' function. */ #undef HAVE_LGETXATTR /* Define to 1 if you have the header file. */ #undef HAVE_LIBGEN_H /* Have GNU gmp library */ #undef HAVE_LIBGMP /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL /* Have libprelude */ #undef HAVE_LIBPRELUDE /* Define to 1 if you have the `resolv' library (-lresolv). */ #undef HAVE_LIBRESOLV /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_ELF_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_EXT2_FS_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_FS_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define to 1 if the type `long double' works and has more range or precision than `double'. */ #undef HAVE_LONG_DOUBLE /* Define to 1 if the type `long double' works and has more range or precision than `double'. */ #undef HAVE_LONG_DOUBLE_WIDER /* Define if type is defined in stdint.h or inttypes.h */ #undef HAVE_LONG_LONG /* Define if you have 64bit long long */ #undef HAVE_LONG_LONG_64 /* Define to 1 if you have the `lstat' function. */ #undef HAVE_LSTAT /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memcmp' function. */ #undef HAVE_MEMCMP /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mincore' function. */ #undef HAVE_MINCORE /* Define to 1 if you have the `mlock' function. */ #undef HAVE_MLOCK /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP /* Define to 1 if you have the header file. */ #undef HAVE_MNTENT_H /* Define to 1 if you have the header file. */ #undef HAVE_MYSQL_MYSQL_H /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define if has the AC_MINFLT, AC_MAJFLT and AC_SWAPS fields. */ #undef HAVE_PAGING /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H /* Define if you have pcre_dfa_exec */ #undef HAVE_PCRE_DFA_EXEC /* Define if you have pcre/pcre.h. */ #undef HAVE_PCRE_PCRE_H /* Define to 1 if you have the header file. */ #undef HAVE_PGSQL_LIBPQ_FE_H /* Define if pmap_getmaps available */ #undef HAVE_PMAP_GETMAPS /* Define to 1 if you have the `posix_fadvise' function. */ #undef HAVE_POSIX_FADVISE /* Define to 1 if you have the header file. */ #undef HAVE_POSTGRESQL_LIBPQ_FE_H /* Define if you have a proc fs */ #undef HAVE_PROCFS /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Define if you have recursive mutexes. */ #undef HAVE_PTHREAD_MUTEX_RECURSIVE /* Define to 1 if you have the `ptrace' function. */ #undef HAVE_PTRACE /* Define to 1 if you have the `rand_r' function. */ #undef HAVE_RAND_R /* Define to 1 if you have the `readdir_r' function. */ #undef HAVE_READDIR_R /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the header file. */ #undef HAVE_RPC_RPCENT_H /* Define to 1 if you have the header file. */ #undef HAVE_RPC_RPC_H /* Define if you have SA_SIGINFO */ #undef HAVE_SA_SIGINFO /* Define to 1 if you have the header file. */ #undef HAVE_SCHED_H /* Define to 1 if you have the `sched_yield' function. */ #undef HAVE_SCHED_YIELD /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID /* Define to 1 if you have the `setpriority' function. */ #undef HAVE_SETPRIORITY /* Define to 1 if you have the `setresuid' function. */ #undef HAVE_SETRESUID /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID /* Define to 1 if you have the `setrlimit' function. */ #undef HAVE_SETRLIMIT /* Define to 1 if you have the `setutent' function. */ #undef HAVE_SETUTENT /* Define if you have SI_USER */ #undef HAVE_SI_USER /* Define if you have socklen_t */ #undef HAVE_SOCKLEN_T /* Have SO_PEERCRED define */ #undef HAVE_SO_PEERCRED /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_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 `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* strftime supports %z */ #undef HAVE_STRFTIME_Z /* 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 `strlcat' function. */ #undef HAVE_STRLCAT /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if you have the `strptime' function. */ #undef HAVE_STRPTIME /* Define to 1 if you have the `strsignal' function. */ #undef HAVE_STRSIGNAL /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtok_r' function. */ #undef HAVE_STRTOK_R /* Have cmsgcred structure */ #undef HAVE_STRUCT_CMSGCRED /* Have fcred structure */ #undef HAVE_STRUCT_FCRED /* Have sockcred structure */ #undef HAVE_STRUCT_SOCKCRED /* Define to 1 if `f_flags' is a member of `struct statfs'. */ #undef HAVE_STRUCT_STATFS_F_FLAGS /* Define if you have the header file. */ #undef HAVE_SYS_ACCT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ACL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_INOTIFY_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IPC_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MSG_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_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_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SEM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_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_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_H /* Define to 1 if you have the `ttyname' function. */ #undef HAVE_TTYNAME /* Define to 1 if you have the `tzset' function. */ #undef HAVE_TZSET /* Define if type is defined in stdint.h or inttypes.h */ #undef HAVE_UINT16_T /* Define if type is defined in stdint.h or inttypes.h */ #undef HAVE_UINT32_T /* Define if type is defined in stdint.h or inttypes.h */ #undef HAVE_UINT64_T /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* Define to 1 if you have the `writev' function. */ #undef HAVE_WRITEV /* Define if host OS is 64bit Linux */ #undef HOST_IS_64LINUX /* Define if host OS is OPENBSD */ #undef HOST_IS_OPENBSD /* Define if host OS is OSF */ #undef HOST_IS_OSF /* Define to 1 if `major', `minor', and `makedev' are declared in . */ #undef MAJOR_IN_MKDEV /* Define to 1 if `major', `minor', and `makedev' are declared in . */ #undef MAJOR_IN_SYSMACROS /* 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 home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Paranoia level for dnmalloc */ #undef PARANOIA /* Argument for ps */ #undef PSARG /* Path to ps */ #undef PSPATH /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Application is samhain */ #undef SAMHAIN /* Define if sa_sigaction works */ #undef SA_SIGACTION_WORKS /* Use abort */ #undef SH_ABORT_ON_ERROR /* Define if you want to allow suid execution for samhain */ #undef SH_ALLOW_SUID /* Define if compiling static */ #undef SH_COMPILE_STATIC /* Define if you want shell expansion in configuration file */ #undef SH_EVAL_SHELL /* Build with tcp wrapper support */ #undef SH_USE_LIBWRAP /* Define if you want to check ports */ #undef SH_USE_PORTCHECK /* Define if you want to check processes */ #undef SH_USE_PROCESSCHECK /* The size of `char *', as computed by sizeof. */ #undef SIZEOF_CHAR_P /* The size of `size_t', as computed by sizeof. */ #undef SIZEOF_SIZE_T /* The size of `unsigned int', as computed by sizeof. */ #undef SIZEOF_UNSIGNED_INT /* The size of `unsigned long', as computed by sizeof. */ #undef SIZEOF_UNSIGNED_LONG /* The size of `unsigned long long', as computed by sizeof. */ #undef SIZEOF_UNSIGNED_LONG_LONG /* The size of `unsigned short', as computed by sizeof. */ #undef SIZEOF_UNSIGNED_SHORT /* Define to 1 if the `S_IS*' macros in do not work properly. */ #undef STAT_MACROS_BROKEN /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to use tiger 32 bit i386 assembler */ #undef TIGER_32_BIT_S /* Define to use tiger 64 bit implementation */ #undef TIGER_64_BIT /* Define to use tiger x86_64 optimized assembly */ #undef TIGER_OPT_ASM /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Define if you want ACL support. */ #undef USE_ACL /* Define if you do not want IPv6 */ #undef USE_IPV4 /* Define if you want the logfile monitor module. */ #undef USE_LOGFILE_MONITOR /* Define for registry check */ #undef USE_REGISTRY_CHECK /* Define if you want to use the system malloc */ #undef USE_SYSTEM_MALLOC /* Define if you want extended attributes support. */ #undef USE_XATTR /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define if POSIX functions are required */ #undef _POSIX_SOURCE /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to `long' if does not define. */ #undef ptrdiff_t /* Define to the equivalent of the C99 'restrict' keyword, or to nothing if this is not supported. Do not define if restrict is supported directly. */ #undef restrict /* Work around a bug in Sun C++: it does not support _Restrict or __restrict__, even though the corresponding Sun C compiler ends up with "#define restrict _Restrict" or "#define restrict __restrict__" in the previous line. Perhaps some future version of Sun C++ will work with restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ #if defined __SUNPRO_CC && !defined __RESTRICT # define _Restrict # define __restrict__ #endif /* Define to `unsigned int' if does not define. */ #undef size_t /* dont modify this, unless you know what you do */ #define SRP_GENERATOR_1024 "2" #define SRP_MODULUS_1024_1 \ _("f488fd584e49dbcd20b49de49107366b336c380d451d0f7c88b31c7c5b2d8ef6") #define SRP_MODULUS_1024_2 \ _("f3c923c043f0a55b188d8ebb558cb85d38d334fd7c175743a31d186cde33212c") #define SRP_MODULUS_1024_3 \ _("b52aff3ce1b1294018118d7c84a70a72d686c40319c807297aca950cd9969fab") #define SRP_MODULUS_1024_4 \ _("d00a509b0246d3083d66a45d419f9c7cbd894b221926baaba25ec355e92f78c7") #define SDG_0RETU _("return.\n") #define SDG_TERRO _("ERROR: file=<%s>, line=<%d>, reason=<%s>\n") #define SDG_AERRO _("ERROR: file=<%s>, line=<%d>, failed_assertion=<%s>\n") #define SDG_AFAIL _("FAILED: file=<%s>, line=<%d>, assertion=<%s>\n") #define SDG_ENTER _("enter=<%s>\n") #define SDG_RETUR _("return=<%s>.\n") #define SDG_ERROR _("error=<%ld>.\n") #ifdef SH_STEALTH char * globber(const char * string); #define _(string) globber(string) #define N_(string) string #else #define _(string) string #define N_(string) string #endif #endif samhain-4.1.4/man/0000755000175000017500000000000012620160603010710 500000000000000samhain-4.1.4/man/samhain.80000644000175000017500000005326112615253277012366 00000000000000.TH SAMHAIN 8 "26 June 2015" "" "Samhain manual" .SH NAME samhain \- check file integrity .SH SYNOPSIS .SS "INITIALIZING, UPDATING, AND CHECKING" .PP .B samhain { .I \-t init|\-\-set\-checksum\-test=init } [\-\-init2stdout] [\-r DEPTH|\-\-recursion=DEPTH] [log-options] .B samhain { .I \-t update|\-\-set\-checksum\-test=update } [\-D | \-\-daemon | \-\-foreground] [\-\-forever] [\-r DEPTH|\-\-recursion=DEPTH] [log-options] .B samhain { .I \-t check|\-\-set\-checksum\-test=check } [\-D | \-\-daemon | \-\-foreground] [\-\-forever] [\-r DEPTH,\-\-recursion=DEPTH] [log-options] .B samhain [ \-p threshold ] { .I \-\-verify\-database=database } .B samhain [ \-p threshold ] { .I \-\-create\-database=file\-list } .SS "LISTING THE DATABASE" .PP .B samhain [\-a | \-\-full\-detail] [\-\-delimited] [\-\-binary] [\-\-list\-filter=file] \-d .IR file | .RI \-\-list\-database= file .SS "VERIFYING AN AUDIT TRAIL" .PP .B samhain [\-j | \-\-just\-list] \-L .IR logfile | .RI \-\-verify\-log= logfile .B samhain \-M .IR mailbox | .RI \-\-verify\-mail= mailbox .SS "MISCELLANEOUS" .PP .B samhain .RI \-\-server\-port= portnumber .B samhain \-H .I string | .RI \-\-hash\-string= string .B samhain \-c | \-\-copyright .B samhain \-v | \-\-version .B samhain \-h | \-\-help .B samhain \-V key@/path/to/executable | \-\-add\-key=key@/path/to/executable .SS "SERVER STARTUP" .PP .B yule [\-q | \-\-qualified] [ .RI \-\-chroot= chrootdir ] [\-D | \-\-daemon | \-\-foreground] [log-options] .SS "SERVER MISCELLANEOUS" .PP .B yule [\-P .I password | .RI \-\-password= password ] .B yule [\-G | \-\-gen-password] .SS "LOG OPTIONS" .PP [\-s .I threshold | .RI \-\-set\-syslog\-severity= threshold ] [\-l .I threshold | .RI \-\-set\-log\-severity= threshold ] [\-m .I threshold | .RI \-\-set\-mail\-severity= threshold ] [\-e .I threshold | .RI \-\-set\-export\-severity= threshold ] [\-p .I threshold | .RI \-\-set\-print\-severity= threshold ] [\-x .I threshold | .RI \-\-set\-external\-severity= threshold ] [ .RI \-\-set\-prelude\-severity= threshold ] [ .RI \-\-set\-database\-severity= threshold ] [ .RI \-\-enable\-trace ] [ .RI \-\-trace\-logfile= tracefile ] .SH WARNING .PP The information in this man page is not always up to date. The authoritative documentation is the user manual. .SH DESCRIPTION .PP .B samhain is a file integrity / intrusion detection system both for single hosts and networks. It consists of a monitoring application .RB ( samhain ) running on individual hosts, and (optionally) a central log server .RB ( yule ). Currently, samhain can monitor the integrity of files/directories, and (optionally) also check for kernel rootkits (Linux and FreeBSD only), search the disk for SUID/SGID, and watch for login/logout events. .PP .B samhain/yule can log by email, to a tamper-resistant, signed log file, to syslog, to the Prelude IDS, to a MySQL/PostgreSQL/Oracle database, and/or to stdout .RI ( /dev/console if run as daemon). .B samhain/yule can run as a daemon, and can use a time server instead of the host's system clock. Most of the functionality is defined by a configuration file that is read at startup. .PP Most options of these usually would be set in the configuration file. Options given on the command line will override those in the configuration file. .SS "OPTIONS FOR INITIALIZING, UPDATING, AND CHECKING" .PP .B samhain .I "\-t init, \-\-set\-checksum-test=init" .RI [ options ] Initialize the database of file signatures. The path to the database is compiled in, and initializing will .B append to the respective file (or create it, if it does not exist). .B "It is ok to append to e.g. a JPEG image, but it is an error" .B "to append to an already existing file signature database." .PP .TP [\-\-init2stdout] Write the database to stdout. .TP [\-r DEPTH|\-\-recursion=DEPTH] Set the (global) recursion depth. .PP .B samhain .I "\-t update, \-\-set\-checksum-test=update" .RI [ options ] Update the database of file signatures. The path to the database is compiled in, and updating will .B overwrite the database, starting from the start of the database (which may not be identical to the start of the file \- see above). .PP .TP [\-r DEPTH|\-\-recursion=DEPTH] Set the (global) recursion depth. .TP [\-D|\-\-daemon] Run as daemon. File checks are performed as specified by the timing options in the configuration file. Updates are saved after each file check. .TP [\-\-foreground] Run in the foreground. This will cause samhain to exit after the update, unless the option .I "\-\-forever" is used. .TP [\-\-forever] If not running as daemon, do not exit after finishing the update, but loop forever, and perform checks with corresponding database updates according to the timing options in the configuration file. .TP [\-i|\-\-interactive] Run update in interactive mode. .TP [\-\-listfile=PATH] Run the update with a list of 'good' filepaths given in file (one path per line). .PP .B samhain .I "\-t check, \-\-set\-checksum-test=check" .RI [ options ] Check the filesystem against the database of file signatures. The path to the database is compiled in. .PP .TP [\-r DEPTH|\-\-recursion=DEPTH] Set the (global) recursion depth. .TP [\-D|\-\-daemon] Run as daemon. File checks are performed as specified by the timing options in the configuration file. .TP [\-\-foreground] Run in the foreground. This will cause samhain to exit after the file check, unless the option .I "\-\-forever" is used. .TP [\-\-forever] If not running as daemon, do not exit after finishing the check, but loop forever, and perform checks according to the timing options in the configuration file. .PP .B samhain [ \-p\ threshold ] .I "\-\-verify\-database=database" Check the filesystem against the database given as argument, and exit with an appropriate exit status. The configuration file will .B not be read. .PP .B samhain [ \-p\ threshold ] .I "\-\-create\-database=file\-list" Initialize a database from the given file list. The configuration file will .B not be read. The policy used will be .I ReadOnly. File content will be stored for a file if its path in the list is preceded with a .B + sign. .SS "OPTIONS FOR LISTING THE DATABASE" .PP .B samhain [\-a | \-\-full\-detail] [\-\-delimited] \-d .IR file | .RI \-\-list\-database= file List the entries in the file signature database in a .B ls \-l like format. .PP .TP [\-a | \-\-full\-detail] List all informations for each file, not only those you would get with ls \-l. Must precede the \-d option. .TP [\-\-delimited] List all informations for each file, in a comma-separated format. Must precede the \-d option. .TP [\-\-binary] List data in the binary format of the database, thus writing another database. Must precede the \-d option. .TP .RI [\-\-list\-filter= file ] Filter the output of the database listing by a list of files given in a text file. Together with \-\-binary this allows to write a partial database. Must precede the \-d option. .TP .RI [\-\-list\-file= file ] List the literal content of the given file as stored in the database. Content is not stored by default, must be enabled in the runtime configuration file. Must precede the \-d option. .SS "OPTIONS TO VERIFY AN AUDIT TRAIL" .PP These options will only work, if the executable used for verifying the audit trail is compiled with the same \-\-enable\-base=... option as the executable of the reporting process. .B samhain [\-j | \-\-just\-list] \-L .IR logfile | .RI \-\-verify\-log= logfile Verify the integrity of a signed logfile. The signing key is auto\-generated on startup, and sent by email. .B samhain will ask for the key. Instead of entering the key, you can also enter the path to the mailbox holding the respective email message. .PP .TP [\-j | \-\-just\-list] Just list the logfile, do not verify it. This option must come .BR first . It is mainly intended for listing the content of an obfuscated logfile, if .B samhain is compiled with the .B stealth option. .B samhain \-M .IR mailbox | .RI \-\-verify\-mail= mailbox Verify the integrity of the email reports from samhain. All reports must be in the same file. .SS "MISCELLANEOUS OPTIONS" .PP .B samhain .RI \-\-server\-port= portnumber Choose the port on the server host to which the client will connect. .B samhain \-H .I string | .RI \-\-hash\-string= string Compute the TIGER192 checksum of a string. If the string starts with a '/', it is considered as a pathname, and the checksum of the corresponding file will be computed. .B samhain \-c | \-\-copyright Print the copyright statement. .B samhain \-v | \-\-version Show version and compiled-in options. .B samhain \-h | \-\-help Print supported command line options (depending on compilation options). .B samhain \-V key@/path/to/executable | \-\-add\-key=key@/path/to/executable See the section "SECURITY" below. .SS "SERVER STARTUP OPTIONS" .PP .B yule [\-q | \-\-qualified] [ .RI \-\-chroot= chrootdir ] [\-D | \-\-daemon | \-\-foreground] [log-options] Start the server, which is named .B yule by default. If the server is started with superuser privileges, it will drop them after startup. .PP .TP [\-q | \-\-qualified] Log client hostnames with fully qualified path. The default is to log only the leftmost domain label (i.e. the hostname). .TP [ .RI \-\-chroot= chrootdir ] Chroot to the listed directory after startup. .TP [\-D | \-\-daemon] Run as daemon. .TP [\-\-foreground] Run in the foreground. .SS "MISCELLANEOUS SERVER OPTIONS" .PP .B yule [\-G | \-\-gen-password] Generate a random 8\-byte password and print it out in hexadecimal notation. .B yule [\-P .I password | .RI \-\-password= password ] Use the given .I password and generate an entry suitable for the [Clients] section of the configuration file. .SS "LOGGING OPTIONS" .PP Depending on the compilation options, some logging facilities may not be available in your executable. .PP .TP .I "\-s threshold, \-\-set\-syslog\-severity=threshold" Set the threshold for logging events via syslogd(8). Possible values are .IR debug , .IR info , .IR notice , .IR warn , .IR mark , .IR err , .IR crit , .IR alert , and .IR none . By default, everything equal to and above the threshold will be logged. Time stamps have the priority .IR warn , system\-level errors have the priority .IR err , and important start\-up messages the priority .IR alert . The signature key for the log file will never be logged to syslog or the log file itself. .TP .I "\-l threshold, \-\-set\-log\-severity=threshold" Set the threshold for logging events to the log file. .TP .I "\-m threshold, \-\-set\-mail\-severity=threshold" Set the threshold for logging events via e\-mail. .TP .I "\-e threshold, \-\-set\-export\-severity=threshold" Set the threshold for forwarding events via TCP to a log server. .TP .I "\-x threshold, \-\-set\-extern\-severity=threshold" Set the threshold for calling external logging programs/scripts (if any are defined in the configuration file). .TP .I "\-p threshold, \-\-set\-print\-severity=threshold" Set the threshold for logging events to stdout. If .B samhain runs as a daemon, this is redirected to /dev/console. .TP .I "\-\-set\-prelude\-severity=threshold" Set the threshold for logging events to the Prelude IDS. .TP .I "\-\-set\-database\-severity=threshold" Set the threshold for logging events to the MySQL/PostgreSQL/Oracle database. .SH SIGNALS .TP .I SIGUSR1 Switch on/off maximum verbosity for console output. .TP .I SIGUSR2 Suspend/continue the process, and (on suspend) send a message to the server. This message has the same priority as timestamps. This signal allows to run .I samhain -t init -e none on the client to regenerate the database, with download of the configuration file from the server, while the daemon is suspended (normally you would get errors because of concurrent access to the server by two processes from the .IR "same host" ")." .TP .I SIGHUP Reread the configuration file. .TP .I SIGTERM Terminate. .TP .I SIGQUIT Terminate after processing all pending requests from clients. .TP .I SIGABRT Unlock the log file, pause for three seconds, then proceed, eventually re-locking the log file and starting a fresh audit trail on next access. .TP .I SIGTTOU Force a file check (only client/standalone, and only in daemon mode). .SH DATABASE The database (default name .IR samhain_file ) is a binary file, which can be created or updated using the .B \-t .I init or the .B \-t .I update option. If you use .B \-t .IR init , you need to .I remove the old database first, otherwise the new version will be .I appended to the old one. The file may be (clear text) signed by PGP/GnuPG. .br It is recommended to use GnuPG with the options .B gpg .I -a --clearsign --not-dash-escaped .br .B samhain will check the signature, if compiled with support for that. .PP At startup .B samhain will compute the checksum of the database, and verify it for each further access. This checksum is not stored on disk (i.e. is lost after program termination), as there is no secure way to store it. .SH LOG FILE .PP Each entry in the log file has the format .BR "Severity : [Timestamp] Message" , where the timestamp may be obtained from a time server rather than from the system clock, if .B samhain has been compiled with support for this. Each entry is followed by a .IR signature , which is computed as .BR "Hash(Entry Key_N)" , and .B Key_N is computed as .BR "Hash(Key_N\-1)" , i.e. only knowledge of the first signature key in this chain allows to verify the integrity of the log file. This first key is autogenerated and e\-mailed to the designated recipient. .PP The default name of the log file is .IR samhain_log . To prevent multiple instances of .B samhain from writing to the same log file, the log file is locked by creating a .IR "lock file" , which is normally deleted at program termination. The default name of the .I "lock file" is .IR samhain.lock . If .B samhain is terminated abnormally, i.e. with kill \-9, a stale lock file might remain, but usually .B samhain will be able to recognize that and remove the stale lock file on the next startup. .PP .SH EMAIL .PP E\-mails are sent (using built-in SMTP code) to one recipient only. The subject line contains timestamp and hostname, which are repeated in the message body. The body of the mail contains a line with a .I signature similar to that in the log file, computed from the message and a key. The key is iterated by a hash chain, and the initial key is revealed in the first email sent. Obviously, you have to believe that this first e\-mail is authentical ... .PP .SH CLIENT/SERVER USAGE .PP To monitor several machines, and collecting data by a central log server, .B samhain may be compiled as a client/server application. The log server .RB ( yule ) will accept connection requests from registered clients only. With each client, the server will first engage in a challenge/response protocol for .I authentication of the client and .I establishing a .IR "session key" . .PP This protocol requires on the client side a .IR "password" , and on the server side a .IR "verifier" that is computed from the .IR "password" . .PP To .I register a client, simply do the following: .br First, with the included utility program .B samhain_setpwd re\-set the compiled\-in default password of the client executable to your preferred value (with no option, a short usage help is printed). To allow for non-printable chars, the new value must be given as a 16\-digit hexadecimal string (only 0123456789ABCDEF in string), corresponding to an 8-byte password. .br Second, after re\-setting the password in the client executable, you can use the server's convenience function .B yule .B \-P .I password that will take as input the (16\-digit hex) password, compute the corresponding verifier, and outputs a default configuration file entry to register the client. .br Third, in the configuration file for the server, under the [Clients] section, enter the suggested registration entry of the form .IR "Client=hostname@salt@verifier" , where .I hostname must be the (fully qualified) hostname of the machine on which the client will run. .B "Don't forget to reload the server configuration thereafter." .PP If a connection attempt is made, the server will lookup the entry for the connecting host, and use the corresponding value for the .I verifier to engage in the session key exchange. Failure to verify the client's response(s) will result in aborting the connection. .PP .SH STEALTH .PP .B samhain may be compiled with support for a .I stealth mode of operation, meaning that the program can be run without any obvious trace of its presence on disk. The supplied facilities are simple - they are more sophisticated than just running the program under a different name, and might thwart efforts using 'standard' Unix commands, but they will not resist a search using dedicated utilities. .PP In this mode, the runtime executable will hold no printable strings, and the configuration file is expected to be a postscript file with .I uncompressed image data, wherein the configuration data are hidden by steganography. To create such a file from an existing image, you may use e.g. the program .BR convert (1), which is part of the .BR ImageMagick (1) package, such as: .B "convert +compress" .IR "ima.jpg ima.ps" . .PP To hide/extract the configuration data within/from the postscript file, a utility program .B samhain_stealth is provided. Use it without options to get help. .PP Database and log file may be e.g. existing image files, to which data are appended, xor'ed with some constant to mask them as binary data. .PP The user is responsible by herself for re-naming the compiled executable(s) to unsuspicious names, and choosing (at compile time) likewise unsuspicious names for config file, database, and log (+lock) file. .PP .SH SECURITY .PP For security reasons, .B samhain will not write log or data files in a directory, remove the lock file, or read the configuration file, if any element in the path is owned or writeable by an untrusted user (including group-writeable files with untrusted users in the group, and world-writeable files). .br .I root and the .I effective user are always trusted. You can add more users in the configuration file. .PP Using a .I "numerical host address" in the e\-mail address is more secure than using the hostname (does not require DNS lookup). .PP If you use a .I precompiled .B samhain executable (e.g. from a binary distribution), in principle a prospective intruder could easily obtain a copy of the executable and analyze it in advance. This will enable her/him to generate fake audit trails and/or generate a trojan for this particular binary distribution. .br For this reason, it is possible for the user to add more key material into the binary executable. This is done with the command: .PP .BI "samhain " \-\-add\-key=key@/path/to/executable .PP This will read the file .I /path/to/executable, add the key .I key, which should not contain a '@' (because it has a special meaning, separating key from path), overwrite any key previously set by this command, and write the new binary to the location .I /path/to/executable.out (i.e. with .out appended). You should then copy the new binary to the location of the old one (i.e. overwrite the old one). .PP .B Note that using a precompiled samhain executable from a binary .B package distribution is not recommended unless you add in key material as .B described here. .PP .SH NOTES .PP For initializing the key(s), .I "/dev/random" is used, if available. This is a device supplying cryptographically strong (non-deterministic) random noise. Because it is slow, .B samhain might appear to hang at startup. Doing some random things (performing rain dances, spilling coffee, hunting the mouse) might speed up things. If you do not have .IR "/dev/random" , lots of statistics from .BR vmstat (8) and the like will be pooled and mixed by a hash function. .PP Some hosts might check whether the sender of the mail is valid. Use only .I "login names" for the sender. .br For sending mails, you may need to set a relay host for the sender domain in the configuration file. .PP .SH BUGS .PP Whoever has the original signature key may change the log file and send fake e\-mails. The signature keys are e\-mailed at program startup with a one\-time pad encryption. This should be safe against an eavesdropper on the network, but not against someone with read access to the binary, .I if she has caught the e\-mail. .PP .SH FILES .PP .I /etc/samhainrc .br .I /usr/local/man/man8/samhain.8 .br .I /usr/local/man/man5/samhainrc.5 .br .I /var/log/samhain_log .br .I /var/lib/samhain/samhain_file .br .I /var/lib/samhain/samhain.html .br .I /var/run/samhain.pid .SH SEE ALSO .PP .BR samhainrc (5) .SH AUTHOR .PP Rainer Wichmann (http://la\-samhna.de) .SH BUG REPORTS .PP If you find a bug in .BR samhain , please send electronic mail to .IR support@la\-samhna.de . Please include your operating system and its revision, the version of .BR samhain , what C compiler you used to compile it, your 'configure' options, and any information that you deem helpful. .PP .SH COPYING PERMISSIONS .PP Copyright (\(co) 1999, 2004 Rainer Wichmann .PP Permission is granted to make and distribute verbatim copies of this manual page provided the copyright notice and this permission notice are preserved on all copies. .ig Permission is granted to process this file through troff and print the results, provided the printed document carries copying permission notice identical to this one except for the removal of this paragraph (this paragraph not being relevant to the printed manual page). .. .PP Permission is granted to copy and distribute modified versions of this manual 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. samhain-4.1.4/man/samhainrc.50000644000175000017500000005130312615253277012703 00000000000000.TH SAMHAINRC 5 "Jul 29, 2004" "" "samhainrc manual" .SH NAME samhainrc \- samhain(8) configuration file .SH WARNING .PP The information in this man page is not always up to date. The authoritative documentation is the user manual. .SH DESCRIPTION .PP The configuration file for .BR samhain (8) is named .I samhainrc and located in .I /etc by default. .PP It contains several sections, indicated by headings in square brackets. Each section may hold zero or more .BI key= value pairs. Blank lines and lines starting with '#' are comments. Everything before the first section and after an .I "[EOF]" is ignored. The file may be (clear text) signed by PGP/GnuPG, and .B samhain may invoke GnuPG to check the signature if compiled with support for it. .PP Conditional inclusion of entries for some host(s) is supported via any number of .BI @ hostname /@ end directives. .BI @ hostname and .BI @ end must each be on separate lines. Lines in between will only be read if .I "hostname" (which may be a regular expression) matches the local host. .PP Likewise, conditional inclusion of entries based on system type is supported via any number of .BI $ sysname:release:machine /$ end directives. .br .I "sysname:release:machine" can be inferred from .I "uname -srm" and may be a regular expression. .PP Filenames/directories to check may be wildcard patterns. .PP Options given on the command line will override those in the configuration file. The recognized sections in the configuration file are as follows: .PP Boolean options can be set with any of 1|true|yes or 0|false|no. .TP .I "[ReadOnly]" This section may contain .br .BI file= PATH and .br .BI dir= [depth]PATH entries for files and directories to check. All modifications except access times will be reported for these files. .I [depth] (use without brackets) is an optional parameter to define a per\-directory recursion depth. .TP .I "[LogFiles]" As above, but modifications of timestamps, file size, and signature will be ignored. .TP .I "[GrowingLogFiles]" As above, but modifications of file size will only be ignored if the size has .IR increased . .TP .I "[Attributes]" As above, but only modifications of ownership and access permissions will be checked. .TP .I "[IgnoreAll]" As above, but report no modifications for these files/directories. Access failures will still be reported. .TP .I "[IgnoreNone]" As above, but report all modifications for these files/directories, including access time. .TP .I "[User0]" .TP .I "[User1]" .TP .I "[User2]" .TP .I "[User3]" .TP .I "[User4]" These are reserved for user-defined policies. .TP .I "[Prelink]" For prelinked executables / libraries or directories holding them. .TP .I "[Log]" This section defines the filtering rules for logging. It may contain the following entries: .br .BI MailSeverity= val where the threshold value .I val may be one of .IR debug , .IR info , .IR notice , .IR warn , .IR mark , .IR err , .IR crit , .IR alert , or .IR none . By default, everything equal to and above the threshold will be logged. The specifiers .IR * , .IR ! , and .I = are interpreted as 'all', 'all but', and 'only', respectively (like in the Linux version of syslogd(8)). Time stamps have the priority .IR warn , system\-level errors have the priority .IR err , and important start\-up messages the priority .IR alert . The signature key for the log file will never be logged to syslog or the log file itself. For failures to verify file integrity, error levels are defined in the next section. .br .BI PrintSeverity= val, .br .BI LogSeverity= val, .br .BI ExportSeverity= val, .br .BI ExternalSeverity= val, .br .BI PreludeSeverity= val, .br .BI DatabaseSeverity= val, and .br .BI SyslogSeverity= val set the thresholds for logging via stdout (or .IR /dev/console ), log file, TCP forwarding, calling external programs, and .BR syslog (3). .TP .I "[EventSeverity]" .BI SeverityReadOnly= val, .br .BI SeverityLogFiles= val, .br .BI SeverityGrowingLogs= val, .br .BI SeverityIgnoreNone= val, .br .BI SeverityIgnoreAll= val, .br .BI SeverityPrelink= val, .br .BI SeverityUser0= val, .br .BI SeverityUser1= val, .br .BI SeverityUser2= val, .br .BI SeverityUser3= val, and .br .BI SeverityUser4= val define the error levels for failures to verify the integrity of files/directories of the respective types. I.e. if such a file shows unexpected modifications, an error of level .I val will be generated, and logged to all facilities with a threshold of at least .IR val . .br .BI SeverityFiles= val sets the error level for file access problems, and .br .BI SeverityDirs= val for directory access problems. .br .BI SeverityNames= val sets the error level for obscure file names (e.g. non\-printable characters), and for files with invalid UIDs/GIDs. .TP .I "[External]" .BI OpenCommand= path Start the definition of an external logging program|script. .br .BI SetType= log|srv Type/purpose of program (log for logging). .br .BI SetCommandline= list Command line options. .br .BI SetEnviron= KEY=val Environment for external program. .br .BI SetChecksum= val Checksum of the external program (checked before invoking). .br .BI SetCredentials= username User as who the program will run. .br .BI SetFilterNot= list Words not allowed in message. .br .BI SetFilterAnd= list Words required (ALL) in message. .br .BI SetFilterOr= list Words required (at least one) in message. .br .BI SetDeadtime= seconds Time between consecutive calls. .TP .I "[Utmp]" Configuration for watching login/logout events. .br .BI LoginCheckActive= 0|1 Switch off/on login/logout reporting. .br .BI LoginCheckInterval= val Interval (seconds) between checks for login/logout events. .br .BI SeverityLogin= val .br .BI SeverityLoginMulti= val .br .BI SeverityLogout= val Severity levels for logins, multiple logins by same user, and logouts. .TP .I "[SuidCheck]" Settings for finding SUID/SGID files on disk. .br .BI SuidCheckActive= 0|1 Switch off/on the check. .br .BI SuidCheckExclude= path A directory (and its subdirectories) to exclude from the check. Only one directory can be specified this way. .br .BI SuidCheckSchedule= schedule Crontab-like schedule for checks. .br .BI SeveritySuidCheck= severity Severity for events. .br .BI SuidCheckFps= fps Limit files per seconds for SUID check. .br .BI SuidCheckNosuid= 0|1 Check filesystems mounted as nosuid. Defaults to not. .br .BI SuidCheckQuarantineFiles= 0|1 Whether to quarantine files. Defaults to not. .br .BI SuidCheckQuarantineMethod= 0|1|2 Quarantine method. Delete = 1, remove suid/sgid flags = 1, move to quarantine directory = 2. Defaults to 1 (remove suid/sgid flags). .br .BI .TP .I "[Mounts]" Configuration for checking mounts. .br .BI MountCheckActive= 0|1 Switch off/on this module. .br .BI MountCheckInterval= seconds The interval between checks (default 300). .br .BI SeverityMountMissing= severity Severity for reports on missing mounts. .br .BI SeverityOptionMissing= severity Severity for reports on missing mount options. .br .BI CheckMount= path [mount_options] .br Mount point to check. Mount options must be given as comma-separated list, separated by a blank from the preceding mount point. .TP .I "[UserFiles]" Configuration for checking paths relative to user home directories. .br .BI UserFilesActive= 0|1 Switch off/on this module. .br .BI UserFilesName= filename policy .br Files to check for under each $HOME. Allowed values for 'policy' are: allignore, attributes, logfiles, loggrow, noignore (default), readonly, user0, user1, user2, user3, and user4. .br .BI UserFilesCheckUids= uid_list A list of UIDs where we want to check. The default is all. Ranges (e.g. 100-500) are allowed. If there is an open range (e.g. 1000-), it must be last in the list. .TP .I "[ProcessCheck]" Settings for finding hidden/fake,required processes on the local host. .br .BI ProcessCheckActive= 0|1 Switch off/on the check. .br .BI ProcessCheckInterval= seconds The interval between checks (default 300). .br .BI SeverityProcessCheck= severity Severity for events (default crit). .br .BI ProcessCheckMinPID= pid The minimum PID to check (default 0). .br .BI ProcessCheckMaxPID= pid The maximum PID to check (default 32767). .br .BI ProcessCheckPSPath= path The path to ps (autodetected at compile time). .br .BI ProcessCheckPSArg= argument The argument to ps (autodetected at compile time). Must yield PID in first column. .br .BI ProcessCheckExists= regular_expression Check for existence of a process matching the given regular expression. .TP .I "[PortCheck]" Settings for checking open ports on the local host. .br .BI PortCheckActive= 0|1 Switch off/on the check. .br .BI PortCheckInterval= seconds The interval between checks (default 300). .br .BI PortCheckUDP= yes|no Whether to check UPD ports as well (default yes). .br .BI SeverityPortCheck= severity Severity for events (default crit). .br .BI PortCheckInterface= ip_address Additional interface to check. .br .BI PortCheckOptional= ip_address:list Ports that may, but need not be open. The ip_address is the one of the interface, the list must be comma or whitespace separated, each item must be (port|service)/protocol, e.g. 22/tcp,nfs/tcp/nfs/udp. .br .BI PortCheckRequired= ip_address:list Ports that are required to be open. The ip_address is the one of the interface, the list must be comma or whitespace separated, each item must be (port|service)/protocol, e.g. 22/tcp,nfs/tcp/nfs/udp. .TP .I "[Database]" Settings for .I logging to a database. .br .BI SetDBHost= db_host Host where the DB server runs (default: localhost). Should be a numeric IP address for PostgreSQL. .br .BI SetDBName= db_name Name of the database (default: samhain). .br .BI SetDBTable= db_table Name of the database table (default: log). .br .BI SetDBUser= db_user Connect as this user (default: samhain). .br .BI SetDBPassword= db_password Use this password (default: none). .br .BI SetDBServerTstamp= true|false Log server timestamp for client messages (default: true). .br .BI UsePersistent= true|false Use a persistent connection (default: true). .TP .I "[Misc]" .BI Daemon= no|yes Detach from controlling terminal to become a daemon. .br .BI MessageHeader= format Costom format for message header. Replacements: .I %F source file name, .I %L source file line, .I %S severity, .I %T timestamp, .I %C message class. .br .BI VersionString= string Set version string to include in file signature database (along with hostname and date). .br .BI SetReverseLookup= true|false If false, skip reverse lookups when connecting to a host known by name rather than IP address. .br .BI HideSetup= yes|no Don't log name of config/database files on startup. .br .BI SyslogFacility= facility Set the syslog facility to use. Default is LOG_AUTHPRIV. .br .BI MACType= HASH-TIGER|HMAC-TIGER Set type of message authentication code (HMAC). Must be identical on client and server. .br .BI StartupLoadDelay= val Defines the interval (in seconds) to wait after startup before loading the databse from the server. Default is no wait. .br .BI SetLoopTime= val Defines the interval (in seconds) for timestamps. .br .BI SetConsole= device Set the console device (default /dev/console). .br .BI MessageQueueActive= 1|0 Whether to use a SysV IPC message queue. .br .BI PreludeMapToInfo= list of severities The severities (see section .IR [Log] ) that should be mapped to impact severity .I info in prelude. .br .BI PreludeMapToLow= list of severities The severities (see section .IR [Log] ) that should be mapped to impact severity .I low in prelude. .br .BI PreludeMapToMedium= list of severities The severities (see section .IR [Log] ) that should be mapped to impact severity .I medium in prelude. .br .BI PreludeMapToHigh= list of severities The severities (see section .IR [Log] ) that should be mapped to impact severity .I high in prelude. .br .BI SetMailTime= val defines the maximum interval (in seconds) between succesive e\-mail reports. Mail might be empty if there are no events to report. .br .BI SetMailNum= val defines the maximum number of messages that are stored before e\-mailing them. Messages of highest priority are always sent immediately. .br .BI SetMailAddress= username @ host sets the recipient address for mailing. .I "No aliases should be used." For security, you should prefer a numerical host address. .br .BI SetMailRelay= server sets the hostname for the mail relay server (if you need one). If no relay server is given, mail is sent directly to the host given in the mail address, otherwise it is sent to the relay server, who should forward it to the given address. .br .BI SetMailSubject= val defines a custom format for the subject of an email message. .br .BI SetMailSender= val defines the sender for the 'From:' field of a message. .br .BI SetMailFilterAnd= list defines a list of strings all of which must match a message, otherwise it will not be mailed. .br .BI SetMailFilterOr= list defines a list of strings at least one of which must match a message, otherwise it will not be mailed. .br .BI SetMailFilterNot= list defines a list of strings none of which should match a message, otherwise it will not be mailed. .br .BI SamhainPath= /path/to/binary sets the path to the samhain binary. If set, samhain will checksum its own binary both on startup and termination, and compare both. .br .BI SetBindAddress= IP_address The IP address (i.e. interface on multi-interface box) to use for outgoing connections. .br .BI SetTimeServer= server sets the hostname for the time server. .br .BI TrustedUser= name|uid Add a user to the set of trusted users (root and the effective user are always trusted. You can add up to 7 more users). .br .BI SetLogfilePath= AUTO|/path Path to logfile (AUTO to tack hostname on compiled-in path). .br .BI SetLockfilePath= AUTO|/path Path to lockfile (AUTO to tack hostname on compiled-in path). .TP .B Standalone or client only .br .BI SetNiceLevel= -19..19 Set scheduling priority during file check. .br .BI SetIOLimit= bps Set IO limits (kilobytes per second) for file check. .br .BI SetFilecheckTime= val Defines the interval (in seconds) between succesive file checks. .br .BI FileCheckScheduleOne= schedule Crontab-like schedule for file checks. If used, .I SetFilecheckTime is ignored. .br .BI UseHardlinkCheck= yes|no Compare number of hardlinks to number of subdirectories for directories. .br .BI HardlinkOffset= N:/path Exception (use multiple times for multiple exceptions). N is offset (actual - expected hardlinks) for /path. .br .BI AddOKChars= N1,N2,.. List of additional acceptable characters (byte value(s)) for the check for weird filenames. Nn may be hex (leading '0x': 0xNN), octal (leading zero: 0NNN), or decimal. Use .I all for all. .br .BI FilenamesAreUTF8= yes|no Whether filenames are UTF-8 encoded (defaults to no). If yes, filenames are checked for invalid UTF-8 encoding and for ending in invisible characters. .br .BI IgnoreAdded= path_regex Ignore if this file/directory is added/created. .br .BI IgnoreMissing= path_regex Ignore if this file/directory is missing/deleted. .br .BI ReportOnlyOnce= yes|no Report only once on a modified file (default yes). .br .BI ReportFullDetail= yes|no Report in full detail on modified files (not only modified items). .br .BI UseLocalTime= yes|no Report file timestamps in local time rather than GMT (default no). Do not use this with Beltane. .br .BI ChecksumTest= {init|update|check|none} defines whether to initialize/update the database or verify files against it. If 'none', you should supply the required option on the command line. .br .BI SetPrelinkPath= path Path of the prelink executable (default /usr/sbin/prelink). .br .BI SetPrelinkChecksum= checksum TIGER192 checksum of the prelink executable (no default). .br .BI SetLogServer= server sets the hostname for the log server. .br .BI SetServerPort= portnumber sets the port on the server to connect to. .br .BI SetDatabasePath= AUTO|/path Path to database (AUTO to tack hostname on compiled-in path). .br .BI DigestAlgo= SHA1|MD5 Use SHA1 or MD5 instead of the TIGER checksum (default: TIGER192). .br .BI RedefReadOnly= +/-XXX,+/-YYY,... Add or subtract tests XXX from the ReadOnly policy. Tests are: CHK (checksum), TXT (store literal content), LNK (link), HLN (hardlink), INO (inode), USR (user), GRP (group), MTM (mtime), ATM (atime), CTM (ctime), SIZ (size), RDEV (device numbers) and/or MOD (file mode). .br .BI RedefAttributes= +/-XXX,+/-YYY,... Add or subtract tests XXX from the Attributes policy. .br .BI RedefLogFiles= +/-XXX,+/-YYY,... Add or subtract tests XXX from the LogFiles policy. .br .BI RedefGrowingLogFiles= +/-XXX,+/-YYY,... Add or subtract tests XXX from the GrowingLogFiles policy. .br .BI RedefIgnoreAll= +/-XXX,+/-YYY,... Add or subtract tests XXX from the IgnoreAll policy. .br .BI RedefIgnoreNone= +/-XXX,+/-YYY,... Add or subtract tests XXX from the IgnoreNone policy. .br .BI RedefUser0= +/-XXX,+/-YYY,... Add or subtract tests XXX from the User0 policy. .br .BI RedefUser1= +/-XXX,+/-YYY,... Add or subtract tests XXX from the User1 policy. .br .BI RedefUser2= +/-XXX,+/-YYY,... Add or subtract tests XXX from the User2 policy. .br .BI RedefUser3= +/-XXX,+/-YYY,... Add or subtract tests XXX from the User3 policy. .br .BI RedefUser4= +/-XXX,+/-YYY,... Add or subtract tests XXX from the User4 policy. .TP .B Server Only .br .BI SetUseSocket= yes|no If unset, do not open the command socket. The default is no. .br .BI SetSocketAllowUid= UID Which user can connect to the command socket. The default is 0 (root). .br .BI SetSocketPassword= password Password (max. 14 chars, no '@') for password-based authentication on the command socket (only if the OS does not support passing credentials via sockets). .br .BI SetChrootDir= path If set, chroot to this directory after startup. .br .BI SetStripDomain= yes|no Whether to strip the domain from the client hostname when logging client messages (default: yes). .br .BI SetClientFromAccept= true|false If true, use client address as known to the communication layer. Else (default) use client name as claimed by the client, try to verify against the address known to the communication layer, and accept (with a warning message) even if this fails. .br .BI UseClientSeverity= yes|no Use the severity of client messages. .br .BI UseClientClass= yes|no Use the class of client messages. .br .BI SetServerPort= number The port that the server should use for listening (default is 49777). .br .BI SetServerInterface= IPaddress The IP address (i.e. interface on multi-interface box) that the server should use for listening (default is all). Use INADDR_ANY to reset to all. .br .BI SeverityLookup= severity Severity of the message on client address != socket peer. .br .BI UseSeparateLogs= true|false If true, messages from different clients will be logged to separate log files (the name of the client will be appended to the name of the main log file to construct the logfile name). .br .BI SetClientTimeLimit= seconds The maximum time between client messages. If exceeded, a warning will be issued (the default is 86400 sec = 1 day). .br .BI SetUDPActive= yes|no yule 1.2.8+: Also listen on 514/udp (syslog). .TP .I "[Clients]" This section is only relevant if .B samhain is run as a log server for clients running on another (or the same) machine. .br .BI Client= hostname @ salt @ verifier registers a client at host .I hostname (fully qualified hostname required) for access to the log server. Log entries from unregistered clients will not be accepted. To generate a salt and a valid verifier, use the command .B "samhain -P" .IR "password" , where .I password is the password of the client. A simple utility program .B samhain_setpwd is provided to re\-set the compiled\-in default password of the client executable to a user\-defined value. .TP .I "[EOF]" An optional end marker. Everything below is ignored. .SH SEE ALSO .PP .BR samhain (8) .SH AUTHOR .PP Rainer Wichmann (http://la\-samhna.de) .SH BUG REPORTS .PP If you find a bug in .BR samhain , please send electronic mail to .IR support@la\-samhna.de . Please include your operating system and its revision, the version of .BR samhain , what C compiler you used to compile it, your 'configure' options, and anything else you deem helpful. .SH COPYING PERMISSIONS .PP Copyright (\(co) 2000, 2004, 2005 Rainer Wichmann .PP Permission is granted to make and distribute verbatim copies of this manual page provided the copyright notice and this permission notice are preserved on all copies. .ig Permission is granted to process this file through troff and print the results, provided the printed document carries copying permission notice identical to this one except for the removal of this paragraph (this paragraph not being relevant to the printed manual page). .. .PP Permission is granted to copy and distribute modified versions of this manual 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. samhain-4.1.4/Install.sh0000755000175000017500000004123412615253270012035 00000000000000#! /bin/sh # Please have a TMP or TMPDIR environment variable if you don't trust /tmp, # or don't run this as root. # # -- partly taken from PureFTPd # VERSION=1.6.4 # exits with a custom error message bail_error () { echo echo $1 echo exit 1 } get_config() { mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --$z" done } get_error() { ge_rval=0 if cat $tmp 2>&1 | grep Error > /dev/null ; then ge_rval=1 fi return ${ge_rval} } #------------------------------------------------------------ # # Find a 'dialog' program # #------------------------------------------------------------ PATH=/usr/local/bin:/usr/local/sbin:$PATH; export PATH WELCOME=`cat < /dev/null && dialog='Xdialog' gauge='--gauge' fi fi if [ -z "$dialog" ] ; then dialog --msgbox "$WELCOME" 20 75 2> /dev/null && dialog='dialog' # Workaround for old versions of 'dialog' (Slackware) if "$dialog" 2>&1 | grep gauge > /dev/null ; then gauge='--gauge' elif "$dialog" 2>&1 | grep guage > /dev/null ; then gauge='--guage' else gauge='' fi fi if [ -z "$dialog" ] ; then lxdialog --msgbox "$WELCOME" 20 75 2> /dev/null && dialog='lxdialog' fi if [ -z "$dialog" ] ; then /usr/src/linux/scripts/lxdialog/lxdialog --msgbox "$WELCOME" 20 75 2> /dev/null && dialog='/usr/src/linux/scripts/lxdialog/lxdialog' fi if [ -z "$dialog" ] ; then bail_error "No \"dialog\" found, GUI installation impossible" fi #------------------------------------------------------------ # # Find a writable temporary directory # #------------------------------------------------------------ tempdir='' for tmpdir in "$TMP" "$TMPDIR" /tmp /var/tmp; do if [ -z "$tempdir" ] && [ -d "$tmpdir" ] && [ -w "$tmpdir" ]; then tempdir="$tmpdir" fi done if [ -z "$tempdir" ]; then bail_error "Unable to find a suitable temporary directory" fi # Create a temporary file tmp=`mktemp $tempdir/build.gui.XXXXXX` if [ $? -ne 0 ]; then bail_error "Cannot create temp file, exiting..." fi trap "rm -f $tmp; exit 1" EXIT SIGHUP SIGINT SIGQUIT SIGSEGV SIGTERM #------------------------------------------------------------ # # Build config line # #------------------------------------------------------------ cfgline=''; $dialog \ --title "Compile-time options" \ --backtitle "Samhain $VERSION" \ --radiolist "Samhain can run as standalone application on a single dektop machine, or as a client/server application for centralized monitoring of many hosts" \ 10 75 3 \ "disable-network" "Single desktop machine" on \ "enable-network=client" "Network (client)" off \ "enable-network=server" "Network (server)" off \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then get_config else get_error || bail_error "Your \"dialog\" does not support --radiolist, GUI installation impossible" cfgline="--disable-network" fi cfgtest=`echo $cfgline | grep disable` #------------------------------------------------------------ # # Server options # #------------------------------------------------------------ if [ -z $cfgtest ]; then INET=yes HTML="\n /usr/local/var/samhain/samhain.html" $dialog \ --backtitle "Samhain $VERSION" \ --msgbox "You have chosen to build SAMHAIN as a client/server application.\n\nThis requires some additional configuration.\nPlease read the manual if you are not sure\nwhich options are useful or neccessary for you." 10 75 if [ $? = -1 ]; then exit 1 fi $dialog \ --title 'Network options' \ --separate-output \ --backtitle "Samhain $VERSION" \ --checklist 'Use SPACE to set/unset. If in doubt, read the manual.' \ 20 75 10 \ 'enable-udp' "Server listens also on 514/udp" off \ 'disable-encrypt' "Disable client/server encryption" off \ 'disable-srp' "Disable SRP client/server authentication" off \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then get_config fi $dialog \ --title 'Network options' \ --backtitle "Samhain $VERSION" \ --inputbox "Server port" 10 75 "49777" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-port=$z" done fi $dialog \ --title 'Network options' \ --backtitle "Samhain $VERSION" \ --inputbox "Server address" 10 75 "127.0.0.1" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-logserver=$z" done fi $dialog \ --title "Network options" \ --backtitle 'Samhain $VERSION' \ --inputbox "Backup server address" 10 75 "none" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do if [ "x$z" != "xnone" ]; then cfgline="$cfgline --with-altlogserver=$z" fi done fi # if [ -z $cfgtest ]; then fi os=`uname -s` if [ x"$os" = xLinux ] then PROC=`uname -m` if [ x"$PROC" = xi686 ] ; then I386_LINUX=yes fi if [ x"$PROC" = xi586 ] ; then I386_LINUX=yes fi if [ x"$PROC" = xi486 ] ; then I386_LINUX=yes fi if [ x"$PROC" = xi386 ] ; then I386_LINUX=yes fi fi $dialog \ --title 'General options' \ --separate-output \ --backtitle "Samhain $VERSION" \ --checklist 'Use SPACE to set/unset. If in doubt, read the MANUAL.' \ 20 75 10 \ 'enable-static' "Don't link with shared libraries" on \ 'enable-suidcheck' "Check for suid/sgid files" on \ 'enable-login-watch' "Watch for login/logout events" off \ 'enable-ptrace' "Enable anti-debugger code" off \ 'enable-db-reload' "Reload database on SIGHUP" off \ 'enable-xml-log' "Write log in XML format" off \ 'disable-mail' "Compile without built-in mailer" off \ 'disable-external-scripts' "Disable use of external scripts" off \ 'enable-debug' "Compile in debugging code" off \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then get_config fi #------------------------------------------------------------ # # Signature options # #------------------------------------------------------------ $dialog \ --title "Signed database and configuration" \ --backtitle "Samhain $VERSION" \ --yesno "Samhain can be configured to support PGP signed database\nand configuration files. This requires a working installation\nof GnuPG.\n\nDo you want to use this option ?" \ 10 75 \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then $dialog \ --title "Signed database and configuration" \ --backtitle "Samhain $VERSION" \ --inputbox "Please enter the full path to gpg (i.e. the GnuPG binary)" \ 10 75 "/usr/bin/gpg" \ 2> $tmp mtest=$? if [ $mtest = -1 ] then exit 1 fi if [ $mtest = 0 ] then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-gpg=$z" done $dialog \ --title "Signed database and configuration" \ --backtitle "Samhain $VERSION" \ --inputbox "Please enter the fingerprint of the key to use (one string, no spaces)" \ 10 75 "6BD9050FD8FC941B43412DCC68B7AB8957548DCD" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then z=`cat $tmp` cfgline="$cfgline --with-fp=$z" fi fi # want signed fi #------------------------------------------------------------ # # Stealth options # #------------------------------------------------------------ $dialog \ --title "Stealth options" \ --backtitle "Samhain $VERSION" \ --yesno "Samhain has some stealth options to hide its presence.\nDo you want to take advantage of these ?" \ 10 75 \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then $dialog \ --title "Stealth options" \ --backtitle "Samhain $VERSION" \ --radiolist "Full stealth mode will hide ascii strings within the binary, and use a config file that is hidden by steganography within an image file. Micro stealth is just strings hiding, without the stego config file." \ 20 75 4 \ 'full' "Enable full stealth mode" off \ 'micro' "Enable micro stealth mode" on \ 'none' "None of both" off \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do mtest=$z done else mtest="none" fi if [ "x$mtest" != "xnone" ]; then if [ "x$mtest" = "xfull" ]; then FULL_STEALTH="yes" fi $dialog \ --title 'Stealth options' \ --backtitle "Samhain $VERSION" \ --inputbox "Please select a number between 128 and 255. This number will be used to obfuscate strings within the binary by xoring them." 10 75 "137" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do mnum=$z done else mnum="137" fi if [ "x$FULL_STEALTH" = "xyes" ]; then cfgline="$cfgline --enable-stealth=$mnum" else cfgline="$cfgline --enable-micro-stealth=$mnum" fi # if [ "x$mtest" != "xnone" ]; then fi $dialog \ --title 'Stealth options' \ --backtitle "Samhain $VERSION" \ --inputbox "Please choose a new name to replace \"samhain\" upon installation" \ 10 75 "samhain" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --enable-install-name=$z" done fi $dialog \ --title "Stealth options" \ --backtitle "Samhain $VERSION" \ --inputbox "You can set a magic string such that command line arguments will be ignored unless the first argument is this magic string, and read from stdin otherwise. If you do not want this, select CANCEL, otherwise choose a string and select OK." \ 10 75 "foo" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --enable-nocl=$z" done fi if [ "x$I386_LINUX" = "xyes" ]; then $dialog \ --title "Stealth options" \ --backtitle "Samhain $VERSION" \ --yesno "SAMHAIN can compile and install a kernel module to hide the SAMHAIN daemon process. Do you want that ?"\ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then cfgline="$cfgline --enable-khide" fi # f [ "x$I386_LINUX" = "xyes" ]; then fi # want stealth fi #------------------------------------------------------------ # # Paths to configure # #------------------------------------------------------------ $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --radiolist "Do you wish to change the default paths ?\n\nThe default paths are:\n\n /usr/local/sbin all binaries\n /etc/samhainrc configuration file\n /var/lib/samhain/samhain_file data file\n /var/log/samhain_log log file\n /var/run/samhain.pid pid file $HTML" 20 76 5 \ 'usr' "Install binaries in /usr/sbin" off \ 'opt' "Use /opt/samhain, /etc/opt, /var/opt" off \ 'all' "Set paths individually" off \ 'cancel' "Don't change the paths" on \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then # # edit paths # mfile=`cat $tmp` for z in $mfile ; do if [ "x$z" = "xopt" ]; then cfgline="$cfgline --prefix=OPT" fi if [ "x$z" = "xusr" ]; then cfgline="$cfgline --prefix=USR" fi if [ "x$z" = "xall" ]; then $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Exec prefix" 10 75 "/usr/local" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --exec-prefix=$z" done fi $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Configuration" 10 75 "/etc/samhainrc" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-config-file=$z" done fi $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Man pages" 10 75 "/usr/local/share/man" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-mandir=$z" done fi $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Database" 10 75 "/var/lib/samhain/samhain_data" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-data-file=$z" done fi $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Log file" 10 75 "/var/log/samhain_log" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-log-file=$z" done fi $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Lock file" 10 75 "/var/run/samhain.pid" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-pid-file=$z" done fi if [ "x$INET" = "xyes" ]; then $dialog \ --title 'Paths' \ --backtitle "Samhain $VERSION" \ --inputbox "Server status" 10 75 "/var/lib/samhain/samhain.html" \ 2> $tmp mtest=$? if [ $mtest = -1 ]; then exit 1 fi if [ $mtest = 0 ]; then mfile=`cat $tmp` for z in $mfile ; do cfgline="$cfgline --with-html-file=$z" done fi # if [ "x$INET" = "xyes" ]; then fi fi done # edit paths fi if [ ! -f "configure" ] ; then bail_error "Setup problem... try to install manually" fi echo "./configure $cfgline" > Install.log 2>/dev/null if [ $? != 0 ]; then $dialog --infobox "ERROR writing to \"Install.log\".\n\nAborting." 10 55 exit 1 fi if [ "x$KCHECK" = "xyes" ]; then if [ `id -u` != 0 ]; then $dialog --msgbox "Compiling with --with-kcheck option (kernel rootkit detection). This\nrequires root privileges for at least one command during compilation,\nbut you are not running this as root. Please expect compilation to fail.\n\nYou need to follow the instructions shown in the \nerror message after failure." 20 75 fi fi if [ -n "$gauge" ] ; then ( sfail=0 echo 20 rm -f config.cache 2> /dev/null echo 30 if [ -z "$cfgline2" ]; then ./configure $cfgline >> Install.log 2>&1 else ./configure $cfgline --with-checksum="$cfgline2" >> Install.log 2>&1 fi cfail=$? echo 50 if [ $cfail = 0 ]; then make clean >> Install.log 2>&1 cfail=$? else sfail=1 fi echo 60 if [ $cfail = 0 ]; then make >> Install.log 2>&1 cfail=$? else sfail=1 fi echo 80 if [ $cfail = 0 ]; then make install >> Install.log 2>&1 cfail=$? else sfail=1 fi echo 100 echo cfail=$cfail > $tmp echo sfail=$sfail >> $tmp ) | $dialog \ --title 'Compilation and installation' \ --backtitle "Samhain $VERSION" \ "$gauge" 'Please wait...' 10 75 10 else sfail=0 rm -f config.cache 2> /dev/null $dialog --infobox "Running configure ..." 4 44 if [ -z "$cfgline2" ]; then ./configure $cfgline >> Install.log 2>&1 else ./configure $cfgline --with-checksum="$cfgline2" >> Install.log 2>&1 fi cfail=$? if [ $cfail = 0 ]; then $dialog --infobox "Running make clean ..." 4 44 make clean >> Install.log 2>&1 cfail=$? else sfail=1 fi if [ $cfail = 0 ]; then $dialog --infobox "Running make ..." 4 44 make >> Install.log 2>&1 cfail=$? else sfail=1 fi if [ $cfail = 0 ]; then $dialog --infobox "Running make install ..." 4 44 make install >> Install.log 2>&1 cfail=$? else sfail=1 fi echo cfail=$cfail > $tmp echo sfail=$sfail >> $tmp fi . $tmp echo "SAMHAIN is now installed on your system." > $tmp echo "Please read the documentation to know how to run it." >> $tmp if [ "x$sfail" = "x0" ] ; then if [ "x$cfail" = "x0" ] ; then if [ "x${FULL_STEALTH}" = "xyes" ]; then tail -21 Install.log >> $tmp else tail -11 Install.log >> $tmp fi $dialog --title "Build report (use arrow keys to scroll the text box)" \ --backtitle "Samhain $VERSION installed. PLEASE READ THE MANUAL." \ --textbox \ $tmp \ 20 75 else $dialog --title "Problem report" \ --backtitle "Samhain $VERSION: Build failed (see Install.log):" \ --msgbox \ "Compilation was successful, but you need to be root in\norder to install the files to the selected prefix.\nPlease run 'make install' as root." \ 10 75 fi else MSG=`tail -10 Install.log` $dialog --title "Problem report" \ --backtitle "Samhain $VERSION: Build failed (see Install.log):" \ --msgbox "$MSG" 20 75 fi rm -f $tmp exit 0 samhain-4.1.4/samhain.spec0000664000175000017500000002124712724114713012367 00000000000000# # Accepted parameters for 'rpmbuild': # # --with tests - make tests before building Summary: File integrity and host-based IDS Name: samhain Version: 4.1.4 Release: 1 License: GPL Group: System Environment/Base Source: samhain-%{version}.tar.gz BuildRoot: %{_tmppath}/samhain-%{version}-root Packager: Andre Oliveira da Costa Provides: %{name} Requires(pre): shadow-utils # dummy (fix configure warning) # datarootdir = @datarootdir@ # no quotes here - aparently will be expanded literally %define password %(echo $PASSWORD) %define withpwd_prg xDSH_STANDALONE %define withstg_prg x # disable automatic stripping of binaries upon installation %define __spec_install_post %{nil} # required because DeadRat wants to package some debug info otherwise # (this debug info would be created by debug_install_post called # from spec_install_post) %define debug_package %{nil} # Use internal dependency generator rather than external helpers? %define _use_internal_dependency_generator 0 %description samhain is an open source file integrity and host-based intrusion detection system for Linux and Unix. It can run as a daemon process, and and thus can remember file changes -- contrary to a tool that runs from cron, if a file is modified you will get only one report, while subsequent checks of that file will ignore the modification as it is already reported (unless the file is modified again). samhain can optionally be used as client/server system to provide centralized monitoring for multiple host. Logging to a (MySQL or PostgreSQL) database is supported. NOTE: for security reasons, if you distribute binary executables to third parties you should point out the use of the --add-key option to modify the key material within the executable. This spec file is intended to facilitate installation on YOUR system. If you use this spec file to build a SRPM for distribution to third parties, make sure to remove the --enable-base configure option below. %prep %setup -q -n samhain-%{version} %build %if %{?_with_tests:1}%{!?_with_tests:0} # test installation (test #7 is only included if --with gpg has been # specified) for i in `seq 6` %{?_with_gpg:7}; do ./test/test.sh $i; done %endif # # configure with the user-supplied arguments to './configure' # ./configure --enable-base=6365215,1343398076 make %if "%{withpwd_prg}" == "xDSH_WITH_CLIENT" %if 0%{?password} ./samhain_setpwd samhain new %{password} mv samhain samhain.old mv samhain.new samhain %endif %endif %install rm -rf ${RPM_BUILD_ROOT} # sstrip shouldn't be used since binaries will be stripped later ## cat << EOF > sstrip ## #!/bin/sh ## echo "*** SSTRIP DISABLED ***" ## EOF make DESTDIR=${RPM_BUILD_ROOT} install # copy script files to /var/lib/samhain so that we can use them right # after the package is installed # install -m 700 samhain-install.sh init/samhain.startLinux init/samhain.startLSB ${RPM_BUILD_ROOT}/var/lib/samhain # # file list (helpful advice from Lars Kellogg-Stedman) # echo "/usr/local/sbin/samhain" > sh_file_list find %{buildroot}/lib/modules \! -type d -print | \ sed 's,%{buildroot},,' >> sh_file_list %clean rm -rf ${RPM_BUILD_ROOT} %pre if test "xsamhain" = "xyule" then getent group samhain >/dev/null || groupadd -r samhain getent passwd yule >/dev/null || \ useradd -r -g samhain -d /var/lib/samhain -s /sbin/nologin \ -c "samhain server daemon" yule fi exit 0 %post if test "x@sh_lkm@" = x; then : else if test -f /sbin/depmod; then /sbin/depmod -a fi fi if [ "$1" -ge 1 ]; then # Activate boot-time start up cd /var/lib/samhain /bin/sh ./samhain-install.sh --verbose install-boot rm -f ./samhain.startLSB rm -f ./samhain.startLinux if [ -f /usr/local/sbin/samhain_stealth ]; then rm -f samhain-install.sh fi shkeep=yes if test x"$shkeep" = xno; then rm -f ./samhain-install.sh rm -f /usr/local/sbin/samhain_stealth fi fi if [ "$1" = 1 ]; then if test -f /usr/lib/lsb/install_initd; then /usr/lib/lsb/install_initd /etc/init.d/samhain fi fi %if "%{name}" != "yule" cat << EOF Samhain is installed but is NOT running yet, and the database of file signatures is NOT initialized yet. Read the documentation, review configuration files, and then (i) initialize it (/usr/local/sbin/samhain -t init) and (ii) start it manually (/usr/local/sbin/samhain start). It is configured to start automatically on the next boot for runlevels [2-5]. EOF %endif %if "%{name}" == "yule" cat << EOF Yule is installed but is NOT running yet, read the documentation, review configuration files, and then start it (/usr/local/sbin/yule) It is configured to start automatically on the next boot for runlevels [2-5]. EOF %endif %preun # stop running instance of samhain, if any if [ -f /run/%{name}.pid ]; then /usr/local/sbin/samhain stop fi if [ "$1" = 0 ]; then # remove boot-time scripts and links cd /var/lib/samhain if [ -f ./samhain-install.sh ]; then /bin/sh ./samhain-install.sh --verbose uninstall-boot else if test -f /usr/lib/lsb/remove_initd; then /usr/lib/lsb/remove_initd /etc/init.d/samhain fi rm -f /etc/init.d/samhain fi fi %files -f sh_file_list %defattr(-,root,root) %dir /run %dir /var/log %doc docs/BUGS COPYING docs/Changelog %doc LICENSE docs/FAQ.html docs/HOWTO* docs/MANUAL-2_4.* docs/README* /var/lib/samhain %if "%{withstg_prg}" == "xsamhain_stealth" /usr/local/sbin/samhain_stealth %endif %if "%{withpwd_prg}" == "xDSH_WITH_CLIENT" /usr/local/sbin/samhain_setpwd %endif %if "%{withpwd_prg}" == "xDSH_WITH_SERVER" /usr/local/sbin/samhainctl %exclude /usr/local/sbin/samhain_setpwd %endif %attr(644,root,root) /usr/local/man/man5/samhain* %attr(644,root,root) /usr/local/man/man8/samhain* %attr(644,root,root) /etc/logrotate.d/samhain %if "%{name}" == "yule" %attr(750,root,samhain) /var/lib/samhain %attr(750,yule,samhain) /var/log %endif %config(noreplace) /etc/samhainrc %changelog * Tue Oct 23 2012 Rainer Wichmann - fixes for yule installation * Tue May 16 2006 Rainer Wichmann - fix manual version, noticed by Imre Gergely * Tue Apr 05 2005 Rainer Wichmann - disable automatic stripping, use sstrip * Thu Mar 17 2005 Rainer Wichmann - fixes for enable-khide * Wed Oct 20 2004 Rainer Wichmann - more fixes for client/server detection - fix for samhain_stealth * Sun Aug 15 2004 Rainer Wichmann - fix detection of client/server * Sat Jun 19 2004 Rainer Wichmann - replace ./test.sh $i with make test$i - add logic for rpm-light (remove some more files after install) - make postun posix compliant (avoid empty argument list for rm -f) * Wed Dec 31 2003 Stijn Jonker - Fixed correctly build of yule-*-rpm - Fixed excluding of yule_setpwd, and including of yulectl on yule build - Fixed including of samhain_setpwd in samhain client build - Above changes required for correct build in newer rpms, with defaults for abort on unpacked files due to %_unpackaged_files_terminate_build 1 setting - Fixed installation text for yule, not to display samhain text - Added /sbin/chkconfig install_name on to enable the rc scripts * Thu Dec 11 2003 Christian Vanguers - Fixed typo in samhain.spec - Compiled on RedHat Enterprise Linux ES 3 * Thu Mar 26 2003 Rainer Wichmann - strip REQ_FROM_SERVER in config file path (%config(noreplace) ...) * Sun Jan 12 2003 Rainer Wichmann - replace %configure with ./configure * Tue Dec 24 2002 Rainer Wichmann - backported applicable changes to samhain.spec.in - warn user that database must be initialized - fix version of MANUAL in '%files' - test for chkconfig, use only if found * Sun Dec 22 2002 Andre Oliveira da Costa 1.7.0 - fixed typo with _usr macro on ./configure - stops running samhain before uninstall - implemented conditionals to allow proper uninstalls/upgrades - 'BuildPreReq: gpg' is considered only if '--with gpg' is provided - run 'chkconfig' to activate samhain after installation - warn user that samhain must be manually started after install/upgrade * Fri Dec 20 2002 Rainer Wichmann - backported to samhain.spec.in (take over user's choices from configure) - also save samhain.startLSB and samhain.startSuSE for install-boot * Thu Dec 19 2002 Andre Oliveira da Costa 1.6.6 - optional parameters '--with gpg' and '--with tests' - use of pre-defined macros whenever possible * Wed Dec 18 2002 Andre Oliveira da Costa 1.6.6 - Fixed installation process, avoiding hardcoded paths on the binaries (thks to samhain's author Rainer Wichmann) * Mon Dec 16 2002 Andre Oliveira da Costa 1.6.6 - First attempt to build from sources samhain-4.1.4/configure0000775000175000017500000131545512724114661012014 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 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 more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } 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.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= 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 $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_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 || $as_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" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error 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 if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # 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 as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # 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" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # 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 } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac 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 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' 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='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # 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'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/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= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="src/samhain.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS mydefargs myhtmlfile myqdir mydataroot myrpmdatafile mydatafile mylockdir mylockfile mylogdir mylogfile myrpmconffile myconffile mytmpdir mytrust mykeytag mykeyid mygpg mykeybase my_key_4 my_key_3 my_key_2 my_key_1 my_key_B my_key_A xor_code stegin_prg INSTALL_NAME install_name need_user_install myident nocl_code mylogsrv myport mydebugdef HAVE_MYSQL_CONFIG LIBPRELUDE_CONFIG_PREFIX LIBPRELUDE_PREFIX LIBPRELUDE_LIBS LIBPRELUDE_LDFLAGS LIBPRELUDE_PTHREAD_CFLAGS LIBPRELUDE_CFLAGS LIBPRELUDE_CONFIG PTHREAD_LDFLAGS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC acx_pthread_config clmytclient mytclient sh_main_prg samhainadmin_prg yulectl_prg setpwd_prg tiger_src sh_libsocket selectconfig EGREP GREP cmd_hostname AWK LN_S CPP BUILD_CC OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build SET_MAKE VERSION PACKAGE INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localstatedir sysconfdir sbindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_largefile enable_selinux enable_posix_acl enable_ssp enable_db_reload enable_xml_log enable_mail enable_suid enable_shellexpand enable_external_scripts enable_message_queue with_cflags with_libs with_libwrap enable_network enable_static with_libprelude_prefix with_prelude with_database with_console with_altconsole with_timeserver with_alttimeserver enable_login_watch enable_mounts_check enable_logfile_monitor enable_process_check enable_port_check enable_userfiles enable_debug enable_asm enable_ipv6 enable_dnmalloc enable_ptrace with_rnd with_egd_socket enable_udp enable_encrypt enable_srp with_port with_logserver with_altlogserver enable_nocl enable_stealth enable_micro_stealth enable_install_name enable_identity enable_suidcheck enable_base with_gpg with_keyid with_checksum with_fp with_recipient with_sender with_trusted with_tmp_dir with_config_file with_log_file with_pid_file with_state_dir with_data_file with_html_file ' ac_precious_vars='build_alias host_alias target_alias LIBS CC CFLAGS LDFLAGS CPPFLAGS CPP' 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 # Sed expression to map a string onto a valid CPP name. as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } # 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 DESTDIR= SH_ENABLE_OPTS="selinux posix-acl asm ssp db-reload xml-log message-queue login-watch process-check port-check mounts-check logfile-monitor userfiles debug ptrace static network udp nocl stealth micro-stealth install-name identity khide suidcheck base largefile mail external-scripts encrypt srp dnmalloc ipv6 shellexpand suid" SH_WITH_OPTS="prelude libprelude-prefix database libwrap cflags libs console altconsole timeserver alttimeserver rnd egd-socket port logserver altlogserver kcheck gpg keyid checksum fp recipient sender trusted tmp-dir config-file log-file pid-file state-dir data-file html-file" # 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. sbindir='${exec_prefix}/sbin' sysconfdir='${prefix}/etc' localstatedir='${prefix}/var' mandir='${prefix}/share/man' sbindir='${exec_prefix}/sbin' sysconfdir='${prefix}/etc' localstatedir='${prefix}/var' mandir='${prefix}/share/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= 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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -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 ;; -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 && as_fn_error $? "invalid feature name: $ac_feature" ac_feature=`echo $ac_feature | sed 's/-/_/g'` ac_enable_check_opt=no for f in ${SH_ENABLE_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_feature}" then ac_enable_check_opt=yes fi done if test x${ac_enable_check_opt} = xno then as_fn_error $? "unrecognized option: $ac_option Try \`$0 --help' for more information." fi eval "enable_$ac_feature=no" ;; -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 && as_fn_error $? "invalid feature name: $ac_feature" ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac ac_enable_check_opt=no for f in ${SH_ENABLE_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_feature}" then ac_enable_check_opt=yes fi done if test x${ac_enable_check_opt} = xno then as_fn_error $? "unrecognized option: $ac_option Try \`$0 --help' for more information." fi 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 ac_exec_prefix_set="yes" ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ac_exec_prefix_set="yes" ;; -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" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ac_localstatedir_set="yes" ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ac_localstatedir_set="yes" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ac_mandir_set="yes" ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ac_mandir_set="yes" ;; -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 ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ac_prefix_set="yes" ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ac_prefix_set="yes" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ac_sbindir_set="yes" ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ac_sbindir_set="yes" ;; -bindir | --bindir | --bindi | --bind | --bin | --bi | --b) echo "WARNING: bindir will be ignored, use sbindir" ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* \ | --bi=* | --b=*) echo "WARNING: bindir will be ignored, use sbindir" ;; -datadir | --datadir) echo "WARNING: datadir will be ignored" ;; -datadir=* | --datadir=*) echo "WARNING: datadir will be ignored" ;; -includedir | --includedir) echo "WARNING: includedir will be ignored" ;; -includedir=* | --includedir=*) echo "WARNING: includedir will be ignored" ;; -infodir | --infodir) echo "WARNING: infodir will be ignored" ;; -infodir=* | --infodir=*) echo "WARNING: infodir will be ignored" ;; -libdir | --libdir) echo "WARNING: libdir will be ignored" ;; -libdir=* | --libdir=*) echo "WARNING: libdir will be ignored" ;; -libexecdir | --libexecdir) echo "WARNING: libexecdir will be ignored" ;; -libexecdir=* | --libexecdir=*) echo "WARNING: libexecdir will be ignored" ;; -sharedstatedir | --sharedstatedir) echo "WARNING: sharedstatedir will be ignored" ;; -sharedstatedir=* | --sharedstatedir=*) echo "WARNING: sharedstatedir will be ignored" ;; -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 ac_sysconfdir_set="yes" ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ac_sysconfdir_set="yes" ;; -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) 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 && as_fn_error $? "invalid package name: $ac_package" ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac ac_with_check_opt=no for f in ${SH_WITH_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_package}" then ac_with_check_opt=yes fi done if test x${ac_with_check_opt} = xno then as_fn_error $? "unrecognized option: $ac_option Try \`$0 --help' for more information." fi 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 && as_fn_error $? "invalid package name: $ac_package" ac_package=`echo $ac_package | sed 's/-/_/g'` ac_with_check_opt=no for f in ${SH_WITH_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_package}" then ac_with_check_opt=yes fi done if test x${ac_with_check_opt} = xno then as_fn_error $? "unrecognized option: $ac_option Try \`$0 --help' for more information." fi eval "with_$ac_package=no" ;; -*) as_fn_error $? "unrecognized option: $ac_option Try \`$0 --help' for more information." ;; *=*) 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 && as_fn_error $? "invalid variable name: $ac_envvar" ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_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 as_fn_error $? "missing argument to --\`echo $ac_prev | sed 's/_/-/g'\`" fi # Be sure to have absolute paths. for ac_var in prefix exec_prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' | OPT | USR ) ;; *) as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val";; esac done # Be sure to have absolute paths. for ac_var in sbindir sysconfdir localstatedir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val";; esac 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 $as_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 .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # 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 -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | 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 .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" 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 System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-largefile omit support for large files --enable-selinux support checking selinux attributes --enable-posix-acl support checking posix acls --disable-ssp disable the GCC stack protector --enable-db-reload enable database reload on SIGHUP [no] --enable-xml-log enable XML logfile format [no] --disable-mail disable the internal SMTP mailer --enable-suid allow suid --disable-shellexpand disable shell expansion in config file --disable-external-scripts disable interface to external scripts --enable-message-queue[=MODE] enable SysV message queue [MODE=0700] --enable-network=[client|server] compile client or server [no] --enable-static enable static linking [no] --enable-login-watch watch for login/logout [no] --enable-mounts-check check mount options on filesystems [no] --enable-logfile-monitor monitor logfiles [no] --enable-process-check check processes [no] --enable-port-check check ports [no] --enable-userfiles check for users' config files [no] --enable-debug enable debug options [no] --disable-asm disable asm inline code --disable-ipv6 disable ipv6 support --disable-dnmalloc disable dnmalloc --enable-ptrace use anti-debugger options [no] --enable-udp server can listen on port 514/udp [no] --disable-encrypt disable client/server encryption --disable-srp disable SRP for authentication --enable-nocl=PW no CL parsing unless first CL argument is PW --enable-stealth=XOR_VAL enable stealth mode [no] --enable-micro-stealth=XOR_VAL enable micro stealth mode [no] --enable-install-name=NAME name under which to install [samhain|yule] --enable-identity=USER user if dropping root [daemon] --enable-suidcheck check for suid/sgid files [no] --enable-base=B1,B2 base key (0...2147483647) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-cflags additional flags to pass to compiler --with-libs additional libraries to link with --with-libwrap=PATH Compile in libwrap (TCP Wrappers) support --with-libprelude-prefix=PFX Prefix where libprelude is installed (optional) --with-prelude Prelude IDS support [no] --with-database=[mysql|postgresql|oracle|odbc] database support [no] --with-console=PATH set path to console device [/dev/console] --with-altconsole=PATH set path to second console device [none] --with-timeserver=HOST set host address for time server [none] --with-alttimeserver=HOST set address for backup time server [none] --with-rnd=[egd|unix|dev|default] random number generator [default] --with-egd-socket=NAME EGD socket name --with-port=PORT set port to use for TCP/IP connection [49777] --with-logserver=HOST set host address for log server [none] --with-altlogserver=HOST set address for backup log server [none] --with-gpg=PATH use GnuPG to verify database/config [no] --with-keyid=KEYID specify KeyID (0x...) for GPG/PGP functions [none] --with-checksum=CHKSUM compile in gpg/pgp checksum [yes] --with-fp=FINGERPRINT compile in public key fingerprint [no] --with-recipient=ADDR set recipient(s) for e-mail [none] --with-sender=SENDER set sender for e-mail [daemon] --with-trusted=UID Set uid(s) of trusted users [0] --with-tmp-dir=PFX set directory for temporary files [HOME] --with-config-file=FILE configuration file [/etc/{install_name}rc] --with-log-file=FILE path of log file [/var/log/{install_name}_log] --with-pid-file=FILE set path of pid file [/var/run/{install_name}.pid] --with-state-dir=PFX set state data directory [/var/lib/{install_name}] --with-data-file=FILE set path of data file --with-html-file=FILE set path of html file, Some influential environment variables: LIBS libraries to link against, e.g. -lintl CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP 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. Report bugs to the package provider. _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" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && 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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_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 $as_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.69 Copyright (C) 2012 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 ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 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 ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 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 ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" 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 eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* 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 $2 (); /* 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_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else 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 as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 &5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" 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 eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type 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.69. 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=. $as_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=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append 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 as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset 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 $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" 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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; 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 $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_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'; as_fn_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 $as_echo "/* confdefs.h */" > 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 cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } 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. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_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,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_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 # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_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. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## 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 as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 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. # 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. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&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 as_fn_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 rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$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' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi PACKAGE=samhain VERSION=4.1.4 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF $as_echo "#define SAMHAIN 1" >>confdefs.h # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&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 && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&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` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; 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 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&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 as_fn_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" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.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 ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; 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 | *.dSYM | *.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 ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; 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 | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; 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 | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* 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" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg 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) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : 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 "$host" != "$build"; then for ac_prog in gcc cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$BUILD_CC"; then ac_cv_prog_BUILD_CC="$BUILD_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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_BUILD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi BUILD_CC=$ac_cv_prog_BUILD_CC if test -n "$BUILD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 $as_echo "$BUILD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$BUILD_CC" && break done else BUILD_CC=$CC 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld" >&5 $as_echo_n "checking for ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Extract the first word of "hostname", so it can be a program name with args. set dummy hostname; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_cmd_hostname+:} false; then : $as_echo_n "(cached) " >&6 else case $cmd_hostname in [\\/]* | ?:[\\/]*) ac_cv_path_cmd_hostname="$cmd_hostname" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_cmd_hostname="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi cmd_hostname=$ac_cv_path_cmd_hostname if test -n "$cmd_hostname"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cmd_hostname" >&5 $as_echo "$cmd_hostname" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$GCC" = "xyes"; then GCC_VERSION="" gcc_VERSION_MAJOR=0 gcc_VERSION_MINOR=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc version" >&5 $as_echo_n "checking for gcc version... " >&6; } if test "x$GCC" = "xyes" then $CC -dumpversion >/dev/null 2>&1 if test $? -eq 0 then GCC_VERSION=`$CC -dumpversion` gcc_VERSION_MAJOR=`echo $GCC_VERSION | cut -d'.' -f1` gcc_VERSION_MINOR=`echo $GCC_VERSION | cut -d'.' -f2` cat >>confdefs.h <<_ACEOF #define GCC_VERSION_MAJOR ${gcc_VERSION_MAJOR} _ACEOF cat >>confdefs.h <<_ACEOF #define GCC_VERSION_MINOR ${gcc_VERSION_MINOR} _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCC_VERSION" >&5 $as_echo "$GCC_VERSION" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC -dumpversion working" >&5 $as_echo "$CC -dumpversion working" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: compiler is not gcc" >&5 $as_echo "compiler is not gcc" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then 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" as_fn_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 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_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 as_fn_arith $ac_count + 1 && ac_count=$as_val 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 if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then 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" as_fn_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 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_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 as_fn_arith $ac_count + 1 && ac_count=$as_val 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 if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h 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=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/ipc.h sys/sem.h sys/msg.h sys/uio.h fcntl.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OS specific issues" >&5 $as_echo_n "checking for OS specific issues... " >&6; } mydebugflag=no myneedg3=no uid_cast="signed long" selectconfig=linux mynetbsd=no sh_use_lcaps="undef" dnmalloc_ok=yes sh_use_pie=yes enable_asm_ok=yes case "$host_os" in *linux*) sh_use_lcaps="yes" $as_echo "#define HOST_IS_LINUX 1" >>confdefs.h $as_echo "#define HAVE_EXT2_IOCTLS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: use ioctl to get e2fs flags" >&5 $as_echo "use ioctl to get e2fs flags" >&6; } case "$host_cpu" in i*86*) $as_echo "#define HOST_IS_I86LINUX 1" >>confdefs.h ;; x86_64) $as_echo "#define HOST_IS_64LINUX 1" >>confdefs.h ;; *) ;; esac ;; *osf*) $as_echo "#define HOST_IS_OSF 1" >>confdefs.h if test "x$GCC" != "xyes"; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` CFLAGS="$CFLAGS -O2 -assume noaligned_objects" myneedg3=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: compiler needs assume noaligned_objects" >&5 $as_echo "compiler needs assume noaligned_objects" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi ;; *cygwin*) $as_echo "#define HOST_IS_CYGWIN 1" >>confdefs.h $as_echo "#define USE_REGISTRY_CHECK 1" >>confdefs.h dnmalloc_ok=no enable_asm_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no trusted paths, no dnmalloc. no asm optimize" >&5 $as_echo "no trusted paths, no dnmalloc. no asm optimize" >&6; } ;; *darwin*|*apple*) $as_echo "#define HOST_IS_DARWIN 1" >>confdefs.h dnmalloc_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: check resource forks, no dnmalloc" >&5 $as_echo "check resource forks, no dnmalloc" >&6; } ;; *freebsd8*|*freebsd9*) $as_echo "#define HOST_IS_FREEBSD 1" >>confdefs.h selectconfig=freebsd case "$host_cpu" in amd64|x86_64) dnmalloc_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no dnmalloc" >&5 $as_echo "no dnmalloc" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } ;; esac ;; *freebsd7*) $as_echo "#define HOST_IS_FREEBSD 1" >>confdefs.h selectconfig=freebsd case "$host_cpu" in amd64|x86_64) sh_use_pie=no dnmalloc_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no dnmalloc and broken compiler toolchain" >&5 $as_echo "no dnmalloc and broken compiler toolchain" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } ;; esac ;; *freebsd*) $as_echo "#define HOST_IS_FREEBSD 1" >>confdefs.h selectconfig=freebsd { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } ;; *openbsd*) $as_echo "#define HOST_IS_OPENBSD 1" >>confdefs.h selectconfig=freebsd dnmalloc_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: dnmalloc does not work with pthreads" >&5 $as_echo "dnmalloc does not work with pthreads" >&6; } ;; *netbsd*) mynetbsd=yes selectconfig=netbsd { $as_echo "$as_me:${as_lineno-$LINENO}: result: bug with libresolve" >&5 $as_echo "bug with libresolve" >&6; } ;; *solaris*) selectconfig=solaris $as_echo "#define HOST_IS_SOLARIS 1" >>confdefs.h case "$host_cpu" in i*86) $as_echo "#define HOST_IS_I86SOLARIS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: vsnprintf prototype" >&5 $as_echo "vsnprintf prototype" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } ;; esac if test "x$GCC" != "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g" 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\-xO2" 2> /dev/null`"; then CFLAGS="$CFLAGS -xO2" fi if test -z "`echo "$CFLAGS" | grep "\-Xa" 2> /dev/null`"; then CFLAGS="$CFLAGS -Xa" fi LIBS="-lc $LIBS" fi ;; *sun*) selectconfig=solaris $as_echo "#define HOST_IS_SOLARIS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } ;; *aix*) $as_echo "#define HOST_IS_AIX 1" >>confdefs.h selectconfig=aix5.2.0 uid_cast="unsigned long" if test "x$GCC" != "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g" 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\-O3" 2> /dev/null`"; then CFLAGS="$CFLAGS -O3" fi if test -z "`echo "$CFLAGS" | grep "\-qstrict" 2> /dev/null`"; then CFLAGS="$CFLAGS -qstrict" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: AIX size_t in the accept call and optimize O3 qstrict" >&5 $as_echo "AIX size_t in the accept call and optimize O3 qstrict" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: AIX size_t in the accept call" >&5 $as_echo "AIX size_t in the accept call" >&6; } fi ;; *hpux*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: HPUX need _XOPEN_SOURCE_EXTENDED for h_errno" >&5 $as_echo "HPUX need _XOPEN_SOURCE_EXTENDED for h_errno" >&6; } $as_echo "#define HOST_IS_HPUX 1" >>confdefs.h if test "x$GCC" != "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g" 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\+O2" 2> /dev/null`"; then CFLAGS="$CFLAGS +O2" fi fi ;; *ultrix*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ULTRIX getcwd uses popen" >&5 $as_echo "ULTRIX getcwd uses popen" >&6; } $as_echo "#define HAVE_BROKEN_GETCWD 1" >>confdefs.h ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } ;; esac cat >>confdefs.h <<_ACEOF #define UID_CAST ${uid_cast} _ACEOF ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/types.h defines makedev" >&5 $as_echo_n "checking whether sys/types.h defines makedev... " >&6; } if ${ac_cv_header_sys_types_h_makedev+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return makedev(0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_header_sys_types_h_makedev=yes else ac_cv_header_sys_types_h_makedev=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_types_h_makedev" >&5 $as_echo "$ac_cv_header_sys_types_h_makedev" >&6; } if test $ac_cv_header_sys_types_h_makedev = no; then ac_fn_c_check_header_mongrel "$LINENO" "sys/mkdev.h" "ac_cv_header_sys_mkdev_h" "$ac_includes_default" if test "x$ac_cv_header_sys_mkdev_h" = xyes; then : $as_echo "#define MAJOR_IN_MKDEV 1" >>confdefs.h fi if test $ac_cv_header_sys_mkdev_h = no; then ac_fn_c_check_header_mongrel "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default" if test "x$ac_cv_header_sys_sysmacros_h" = xyes; then : $as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat file-mode macros are broken" >&5 $as_echo_n "checking whether stat file-mode macros are broken... " >&6; } if ${ac_cv_header_stat_broken+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if defined S_ISBLK && defined S_IFDIR extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1]; #endif #if defined S_ISBLK && defined S_IFCHR extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1]; #endif #if defined S_ISLNK && defined S_IFREG extern char c3[S_ISLNK (S_IFREG) ? -1 : 1]; #endif #if defined S_ISSOCK && defined S_IFREG extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1]; #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stat_broken=no else ac_cv_header_stat_broken=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stat_broken" >&5 $as_echo "$ac_cv_header_stat_broken" >&6; } if test $ac_cv_header_stat_broken = yes; then $as_echo "#define STAT_MACROS_BROKEN 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "sys_siglist" "ac_cv_have_decl_sys_siglist" "#include /* NetBSD declares sys_siglist in unistd.h. */ #ifdef HAVE_UNISTD_H # include #endif " if test "x$ac_cv_have_decl_sys_siglist" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SYS_SIGLIST $ac_have_decl _ACEOF for ac_header in stddef.h libgen.h sched.h malloc.h sys/uio.h \ sys/mman.h sys/param.h sys/inotify.h \ sys/vfs.h mntent.h \ sys/select.h sys/socket.h netinet/in.h \ regex.h glob.h fnmatch.h \ linux/ext2_fs.h linux/fs.h ext2fs/ext2_fs.h asm/segment.h \ elf.h linux/elf.h auparse.h \ paths.h arpa/nameser.h arpa/nameser_compat.h \ rpc/rpcent.h rpc/rpc.h sys/statvfs.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "utmpx.h" "ac_cv_header_utmpx_h" "$ac_includes_default" if test "x$ac_cv_header_utmpx_h" = xyes; then : sh_utmpx="yes" else sh_utmpx="no" fi if test "x$sh_utmpx" = "xyes"; then $as_echo "#define HAVE_UTMPX_H 1" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_host" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTHOST 1" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTADDR 1" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr_v6" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTADDR_V6 1" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_xtime" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTXTIME 1" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_type" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTTYPE 1" >>confdefs.h fi rm -f conftest* else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTADDR 1" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_host" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTHOST 1" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_type" >/dev/null 2>&1; then : $as_echo "#define HAVE_UTTYPE 1" >>confdefs.h fi rm -f conftest* fi ac_fn_c_check_header_mongrel "$LINENO" "sys/acct.h" "ac_cv_header_sys_acct_h" "$ac_includes_default" if test "x$ac_cv_header_sys_acct_h" = xyes; then : $as_echo "#define HAVE_SYS_ACCT_H /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_utime" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACUTIME /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_utime" >/dev/null 2>&1; then : $as_echo "#define ACUTIME_COMPT /**/" >>confdefs.h fi rm -f conftest* fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_stime" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACSTIME /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_stime" >/dev/null 2>&1; then : $as_echo "#define ACSTIME_COMPT /**/" >>confdefs.h fi rm -f conftest* fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_etime" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACETIME /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_etime" >/dev/null 2>&1; then : $as_echo "#define ACETIME_COMPT /**/" >>confdefs.h fi rm -f conftest* fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_io" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACIO /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_io" >/dev/null 2>&1; then : $as_echo "#define ACIO_COMPT /**/" >>confdefs.h fi rm -f conftest* fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_mem" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACMEM /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_mem" >/dev/null 2>&1; then : $as_echo "#define ACMEM_COMPT /**/" >>confdefs.h fi rm -f conftest* fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_minflt" >/dev/null 2>&1; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_majflt" >/dev/null 2>&1; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ac_swaps" >/dev/null 2>&1; then : $as_echo "#define HAVE_PAGING /**/" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_minflt" >/dev/null 2>&1; then : $as_echo "#define ACMINFLT_COMPT /**/" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_mayflt" >/dev/null 2>&1; then : $as_echo "#define ACMAJFLT_COMPT /**/" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t.*ac_swaps" >/dev/null 2>&1; then : $as_echo "#define ACSWAPS_COMPT /**/" >>confdefs.h fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "comp_t" >/dev/null 2>&1; then : $as_echo "#define HAVE_COMP_T /**/" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct acct_v3" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACCT_V3 /**/" >>confdefs.h fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct acctv2" >/dev/null 2>&1; then : $as_echo "#define HAVE_ACCTV2 /**/" >>confdefs.h fi rm -f conftest* fi ac_fn_c_check_member "$LINENO" "struct statfs" "f_flags" "ac_cv_member_struct_statfs_f_flags" " #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif " if test "x$ac_cv_member_struct_statfs_f_flags" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STATFS_F_FLAGS 1 _ACEOF fi # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether _POSIX_SOURCE is necessary" >&5 $as_echo_n "checking whether _POSIX_SOURCE is necessary... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include void fileno(int);int fdopen(int, char *); int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRFTIME 1 _ACEOF else # strftime is in -lintl on SCO UNIX. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 $as_echo_n "checking for strftime in -lintl... " >&6; } if ${ac_cv_lib_intl_strftime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 strftime (); int main () { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_strftime=yes else ac_cv_lib_intl_strftime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 $as_echo "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes; then : $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done for ac_func in memcmp memcpy memmove memset getpwent endpwent fpurge \ gettimeofday strlcat strlcpy strstr strchr strerror strsignal \ seteuid setreuid setresuid lstat getwd getcwd ptrace \ usleep setpriority getpeereid nanosleep \ strptime basename sched_yield hasmntopt \ inet_aton gethostbyname setutent setrlimit gethostname uname \ initgroups getpagesize \ ttyname fchmod writev mmap tzset \ getsid getpriority getpgid statvfs \ strerror_r getgrgid_r getpwnam_r getpwuid_r \ gmtime_r localtime_r rand_r readdir_r strtok_r \ mincore posix_fadvise inotify_init1 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs" if test "x$ac_cv_func_statfs" = xyes; then : $as_echo "#define HAVE_STATFS 1" >>confdefs.h statfs="yes" else statfs="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy()" >&5 $as_echo_n "checking for va_copy()... " >&6; } if ${sh_cv_va_copy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : sh_cv_va_copy=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include void f (int i, ...) { va_list args1, args2; va_start (args1, i); va_copy (args2, args1); if (va_arg (args2, int) != 42) exit (1); if (va_arg (args1, int) != 42) exit (1); va_end (args1); va_end (args2); } int main() { f (0, 42); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : sh_cv_va_copy=yes else sh_cv_va_copy=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv_va_copy" >&5 $as_echo "$sh_cv_va_copy" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __va_copy()" >&5 $as_echo_n "checking for __va_copy()... " >&6; } if ${sh_cv___va_copy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : sh_cv___va_copy=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include void f (int i, ...) { va_list args1, args2; va_start (args1, i); __va_copy (args2, args1); if (va_arg (args2, int) != 42) exit (1); if (va_arg (args1, int) != 42) exit (1); va_end (args1); va_end (args2); } int main() { f (0, 42); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : sh_cv___va_copy=yes else sh_cv___va_copy=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv___va_copy" >&5 $as_echo "$sh_cv___va_copy" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether va_lists can be copied by value" >&5 $as_echo_n "checking whether va_lists can be copied by value... " >&6; } if ${sh_cv_va_val_copy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : sh_cv_va_val_copy=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include void f (int i, ...) { va_list args1, args2; va_start (args1, i); args2 = args1; if (va_arg (args2, int) != 42) exit (1); if (va_arg (args1, int) != 42) exit (1); va_end (args1); va_end (args2); } int main() { f (0, 42); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : sh_cv_va_val_copy=yes else sh_cv_va_val_copy=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test "x$sh_cv_va_copy" = "xyes"; then $as_echo "#define VA_COPY va_copy" >>confdefs.h else if test "x$sh_cv___va_copy" = "xyes"; then $as_echo "#define VA_COPY __va_copy" >>confdefs.h fi fi if test "x$sh_cv_va_val_copy" = "xno"; then $as_echo "#define VA_COPY_AS_ARRAY 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv_va_val_copy" >&5 $as_echo "$sh_cv_va_val_copy" >&6; } for ac_func in vsnprintf do : ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" if test "x$ac_cv_func_vsnprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VSNPRINTF 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vsnprintf" >&5 $as_echo_n "checking for working vsnprintf... " >&6; } if ${ac_cv_func_vsnprintf+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vsnprintf=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int doit(char * s, ...) { char buffer[32]; va_list args; int r; buffer[5] = 'X'; va_start(args, s); r = vsnprintf(buffer, 5, s, args); va_end(args); /* -1 is pre-C99, 7 is C99. R.W. 17.01.2003 disallow -1 */ if (r != 7) exit(1); /* We deliberately do not care if the result is NUL-terminated or not, since this is easy to work around like this. */ buffer[4] = 0; /* Simple sanity check. */ if (strcmp(buffer, "1234")) exit(1); if (buffer[5] != 'X') exit(1); exit(0); } int main(void) { doit("1234567"); exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vsnprintf=yes else ac_cv_func_vsnprintf=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vsnprintf" >&5 $as_echo "$ac_cv_func_vsnprintf" >&6; } if test $ac_cv_func_vsnprintf = yes; then : else $as_echo "#define HAVE_BROKEN_VSNPRINTF 1" >>confdefs.h fi fi done for ac_func in mlock do : ac_fn_c_check_func "$LINENO" "mlock" "ac_cv_func_mlock" if test "x$ac_cv_func_mlock" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MLOCK 1 _ACEOF fi done if test "$ac_cv_func_mlock" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mlock is broken" >&5 $as_echo_n "checking whether mlock is broken... " >&6; } if ${ac_cv_have_broken_mlock+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_have_broken_mlock="assume-no" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include int main() { char *pool; int err; long int pgsize = getpagesize(); pool = malloc( 4096 + pgsize ); if( !pool ) return 2; pool += (pgsize - ((long int)pool % pgsize)); err = mlock( pool, 4096 ); if( !err || errno == EPERM ) return 0; /* okay */ return 1; /* hmmm */ } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_have_broken_mlock="no" else ac_cv_have_broken_mlock="yes" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test "$ac_cv_have_broken_mlock" = "yes"; then $as_echo "#define HAVE_BROKEN_MLOCK 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else if test "$ac_cv_have_broken_mlock" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming no" >&5 $as_echo "assuming no" >&6; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strftime supports %z" >&5 $as_echo_n "checking whether strftime supports %z... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { struct tm tm; char tt[64]; memset(&tm, 0, sizeof(tm)); strftime(tt, sizeof(tt), "%z", &tm); if (strlen(tt) != 5) return 1; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_STRFTIME_Z 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to get filesystem type" >&5 $as_echo_n "checking how to get filesystem type... " >&6; } fstype=no # The order of these tests is important. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : $as_echo "#define FSTYPE_STATVFS 1" >>confdefs.h fstype=SVR4 fi rm -f conftest.err conftest.i conftest.$ac_ext if test $fstype = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : $as_echo "#define FSTYPE_USG_STATFS 1" >>confdefs.h fstype=SVR3 fi rm -f conftest.err conftest.i conftest.$ac_ext fi if test $fstype = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : $as_echo "#define FSTYPE_AIX_STATFS 1" >>confdefs.h fstype=AIX fi rm -f conftest.err conftest.i conftest.$ac_ext fi if test $fstype = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : $as_echo "#define FSTYPE_MNTENT 1" >>confdefs.h fstype=4.3BSD fi rm -f conftest.err conftest.i conftest.$ac_ext fi if test $fstype = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "f_type;" >/dev/null 2>&1; then : $as_echo "#define FSTYPE_STATFS 1" >>confdefs.h fstype=4.4BSD/OSF fi rm -f conftest* fi if test $fstype = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : $as_echo "#define FSTYPE_GETMNT 1" >>confdefs.h fstype=Ultrix fi rm -f conftest.err conftest.i conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fstype" >&5 $as_echo "$fstype" >&6; } sh_libsocket= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyname=yes else 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSL 1 _ACEOF LIBS="-lnsl $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : ac_need_libsocket=1 else ac_try_nsl=1 fi if test x$ac_need_libsocket = x1; then LIBS="$LIBS -lsocket" sh_libsocket="-lsocket" fi if test x$ac_try_nsl = x1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyname=yes else 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : ac_need_libnsl=1 fi if test x$ac_need_libnsl = x1 then LIBS="$LIBS -lnsl" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_search in -lsocket" >&5 $as_echo_n "checking for res_search in -lsocket... " >&6; } if ${ac_cv_lib_socket_res_search+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 res_search (); int main () { return res_search (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_res_search=yes else ac_cv_lib_socket_res_search=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_res_search" >&5 $as_echo "$ac_cv_lib_socket_res_search" >&6; } if test "x$ac_cv_lib_socket_res_search" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dn_skipname in -lresolv" >&5 $as_echo_n "checking for dn_skipname in -lresolv... " >&6; } if ${ac_cv_lib_resolv_dn_skipname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 dn_skipname (); int main () { return dn_skipname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_dn_skipname=yes else ac_cv_lib_resolv_dn_skipname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_dn_skipname" >&5 $as_echo "$ac_cv_lib_resolv_dn_skipname" >&6; } if test "x$ac_cv_lib_resolv_dn_skipname" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRESOLV 1 _ACEOF LIBS="-lresolv $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __dn_skipname in -lresolv" >&5 $as_echo_n "checking for __dn_skipname in -lresolv... " >&6; } if ${ac_cv_lib_resolv___dn_skipname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 __dn_skipname (); int main () { return __dn_skipname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv___dn_skipname=yes else ac_cv_lib_resolv___dn_skipname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv___dn_skipname" >&5 $as_echo "$ac_cv_lib_resolv___dn_skipname" >&6; } if test "x$ac_cv_lib_resolv___dn_skipname" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRESOLV 1 _ACEOF LIBS="-lresolv $LIBS" fi if test x$ac_need_libsocket = x1; then : else LIBS="$LIBS -lsocket" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_search in -lresolv" >&5 $as_echo_n "checking for res_search in -lresolv... " >&6; } if ${ac_cv_lib_resolv_res_search+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 res_search (); int main () { return res_search (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_res_search=yes else ac_cv_lib_resolv_res_search=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_search" >&5 $as_echo "$ac_cv_lib_resolv_res_search" >&6; } if test "x$ac_cv_lib_resolv_res_search" = xyes; then : LIBS="$LIBS -lresolv" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dn_skipname in -lresolv" >&5 $as_echo_n "checking for dn_skipname in -lresolv... " >&6; } if ${ac_cv_lib_resolv_dn_skipname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 dn_skipname (); int main () { return dn_skipname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_dn_skipname=yes else ac_cv_lib_resolv_dn_skipname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_dn_skipname" >&5 $as_echo "$ac_cv_lib_resolv_dn_skipname" >&6; } if test "x$ac_cv_lib_resolv_dn_skipname" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRESOLV 1 _ACEOF LIBS="-lresolv $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __dn_skipname in -lresolv" >&5 $as_echo_n "checking for __dn_skipname in -lresolv... " >&6; } if ${ac_cv_lib_resolv___dn_skipname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 __dn_skipname (); int main () { return __dn_skipname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv___dn_skipname=yes else ac_cv_lib_resolv___dn_skipname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv___dn_skipname" >&5 $as_echo "$ac_cv_lib_resolv___dn_skipname" >&6; } if test "x$ac_cv_lib_resolv___dn_skipname" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRESOLV 1 _ACEOF LIBS="-lresolv $LIBS" fi fi fi for ac_func in getnameinfo getaddrinfo do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done sh_auparse=no if test "x$ac_cv_header_auparse_h" = "xyes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for auparse_find_field in -lauparse" >&5 $as_echo_n "checking for auparse_find_field in -lauparse... " >&6; } if ${ac_cv_lib_auparse_auparse_find_field+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lauparse $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 auparse_find_field (); int main () { return auparse_find_field (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_auparse_auparse_find_field=yes else ac_cv_lib_auparse_auparse_find_field=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_auparse_auparse_find_field" >&5 $as_echo "$ac_cv_lib_auparse_auparse_find_field" >&6; } if test "x$ac_cv_lib_auparse_auparse_find_field" = xyes; then : LIBS="$LIBS -lauparse" sh_auparse=yes $as_echo "#define HAVE_AUPARSE_LIB 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5 $as_echo_n "checking for socklen_t... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif socklen_t x; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >>confdefs.h <<_ACEOF #define ACCEPT_TYPE_ARG3 socklen_t _ACEOF $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif int accept (int, struct sockaddr *, size_t *); int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: size_t" >&5 $as_echo "size_t" >&6; } cat >>confdefs.h <<_ACEOF #define ACCEPT_TYPE_ARG3 size_t _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: int" >&5 $as_echo "int" >&6; } cat >>confdefs.h <<_ACEOF #define ACCEPT_TYPE_ARG3 int _ACEOF fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check whether --enable-selinux was given. if test "${enable_selinux+set}" = set; then : enableval=$enable_selinux; else enable_selinux=check fi if test "x$enable_selinux" != xno; then for ac_header in attr/xattr.h do : ac_fn_c_check_header_mongrel "$LINENO" "attr/xattr.h" "ac_cv_header_attr_xattr_h" "$ac_includes_default" if test "x$ac_cv_header_attr_xattr_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ATTR_XATTR_H 1 _ACEOF fi done if test $ac_cv_header_attr_xattr_h = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getxattr in -lattr" >&5 $as_echo_n "checking for getxattr in -lattr... " >&6; } if ${ac_cv_lib_attr_getxattr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lattr $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 getxattr (); int main () { return getxattr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_attr_getxattr=yes else ac_cv_lib_attr_getxattr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_attr_getxattr" >&5 $as_echo "$ac_cv_lib_attr_getxattr" >&6; } if test "x$ac_cv_lib_attr_getxattr" = xyes; then : sh_lattr=yes else sh_lattr=no fi if test x"$sh_lattr" = xyes; then LIBATTR=-lattr else LIBATTR= fi OLDLIBS="$LIBS" LIBS="$LIBS $LIBATTR" for ac_func in getxattr lgetxattr fgetxattr do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF sh_fattr=yes else sh_fattr=no fi done LIBS="$OLDLIBS" fi if test x"$sh_fattr" = xyes; then $as_echo "#define USE_XATTR 1" >>confdefs.h LIBS="$LIBS $LIBATTR" else if test "x$enable_selinux" != xcheck; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "--enable-selinux was given, but test for selinux support failed See \`config.log' for more details" "$LINENO" 5; } fi fi fi # Check whether --enable-posix-acl was given. if test "${enable_posix_acl+set}" = set; then : enableval=$enable_posix_acl; else enable_posix_acl=check fi if test "x$enable_posix_acl" != xno; then for ac_header in sys/acl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/acl.h" "ac_cv_header_sys_acl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_acl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_ACL_H 1 _ACEOF fi done if test $ac_cv_header_sys_acl_h = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get_file in -lacl" >&5 $as_echo_n "checking for acl_get_file in -lacl... " >&6; } if ${ac_cv_lib_acl_acl_get_file+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lacl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 acl_get_file (); int main () { return acl_get_file (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_acl_acl_get_file=yes else ac_cv_lib_acl_acl_get_file=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_get_file" >&5 $as_echo "$ac_cv_lib_acl_acl_get_file" >&6; } if test "x$ac_cv_lib_acl_acl_get_file" = xyes; then : sh_lacl=yes else sh_lacl=no fi if test x"$sh_lacl" = xyes; then LIBACL=-lacl else LIBACL= fi OLDLIBS="$LIBS" LIBS="$LIBS $LIBACL" for ac_func in acl_free acl_get_file acl_get_fd do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF sh_facl=yes else sh_facl=no fi done LIBS="$OLDLIBS" fi if test x"$sh_facl" = xyes; then $as_echo "#define USE_ACL 1" >>confdefs.h LIBS="$LIBS $LIBACL" else if test "x$enable_posix_acl" != xcheck; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "--enable-posix-acl was given, but test for acl support failed See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long double with more range or precision than double" >&5 $as_echo_n "checking for long double with more range or precision than double... " >&6; } if ${ac_cv_type_long_double_wider+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include long double const a[] = { 0.0L, DBL_MIN, DBL_MAX, DBL_EPSILON, LDBL_MIN, LDBL_MAX, LDBL_EPSILON }; long double f (long double x) { return ((x + (unsigned long int) 10) * (-1 / x) + a[0] + (x ? f (x) : 'c')); } int main () { static int test_array [1 - 2 * !((0 < ((DBL_MAX_EXP < LDBL_MAX_EXP) + (DBL_MANT_DIG < LDBL_MANT_DIG) - (LDBL_MAX_EXP < DBL_MAX_EXP) - (LDBL_MANT_DIG < DBL_MANT_DIG))) && (int) LDBL_EPSILON == 0 )]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_long_double_wider=yes else ac_cv_type_long_double_wider=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_double_wider" >&5 $as_echo "$ac_cv_type_long_double_wider" >&6; } if test $ac_cv_type_long_double_wider = yes; then $as_echo "#define HAVE_LONG_DOUBLE_WIDER 1" >>confdefs.h fi ac_cv_c_long_double=$ac_cv_type_long_double_wider if test $ac_cv_c_long_double = yes; then $as_echo "#define HAVE_LONG_DOUBLE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long typedef" >&5 $as_echo_n "checking for long long typedef... " >&6; } sh_cv_typedef_foo=`echo sh_cv_typedef_long long | sed -e 's% %_%g'` if eval \${$sh_cv_typedef_foo+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif int main () { #undef long long int a = sizeof(long long); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_cv_typedef=yes else sh_cv_typedef=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv_typedef" >&5 $as_echo "$sh_cv_typedef" >&6; } if test "$sh_cv_typedef" = yes; then $as_echo "#define HAVE_LONG_LONG 1" >>confdefs.h sh_HAVE_LONG_LONG=yes else sh_HAVE_LONG_LONG=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint16_t typedef" >&5 $as_echo_n "checking for uint16_t typedef... " >&6; } sh_cv_typedef_foo=`echo sh_cv_typedef_uint16_t | sed -e 's% %_%g'` if eval \${$sh_cv_typedef_foo+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif int main () { #undef uint16_t int a = sizeof(uint16_t); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_cv_typedef=yes else sh_cv_typedef=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv_typedef" >&5 $as_echo "$sh_cv_typedef" >&6; } if test "$sh_cv_typedef" = yes; then $as_echo "#define HAVE_UINT16_T 1" >>confdefs.h sh_HAVE_UINT16_T=yes else sh_HAVE_UINT16_T=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint32_t typedef" >&5 $as_echo_n "checking for uint32_t typedef... " >&6; } sh_cv_typedef_foo=`echo sh_cv_typedef_uint32_t | sed -e 's% %_%g'` if eval \${$sh_cv_typedef_foo+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif int main () { #undef uint32_t int a = sizeof(uint32_t); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_cv_typedef=yes else sh_cv_typedef=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv_typedef" >&5 $as_echo "$sh_cv_typedef" >&6; } if test "$sh_cv_typedef" = yes; then $as_echo "#define HAVE_UINT32_T 1" >>confdefs.h sh_HAVE_UINT32_T=yes else sh_HAVE_UINT32_T=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint64_t typedef" >&5 $as_echo_n "checking for uint64_t typedef... " >&6; } sh_cv_typedef_foo=`echo sh_cv_typedef_uint64_t | sed -e 's% %_%g'` if eval \${$sh_cv_typedef_foo+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif int main () { #undef uint64_t int a = sizeof(uint64_t); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_cv_typedef=yes else sh_cv_typedef=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_cv_typedef" >&5 $as_echo "$sh_cv_typedef" >&6; } if test "$sh_cv_typedef" = yes; then $as_echo "#define HAVE_UINT64_T 1" >>confdefs.h sh_HAVE_UINT64_T=yes else sh_HAVE_UINT64_T=no fi if test "$sh_HAVE_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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5 $as_echo_n "checking size of unsigned long long... " >&6; } if ${ac_cv_sizeof_unsigned_long_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_long_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned long long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_long_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5 $as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long _ACEOF sh_sizeof_unsigned_long_long=`echo "$ac_cv_sizeof_unsigned_long_long" | sed 's%^0-9%%g'` if test "$sh_sizeof_unsigned_long_long" = "8"; then $as_echo "#define HAVE_LONG_LONG_64 1" >>confdefs.h fi fi ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" if test "x$ac_cv_type_ptrdiff_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define ptrdiff_t long _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi # 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char *" >&5 $as_echo_n "checking size of char *... " >&6; } if ${ac_cv_sizeof_char_p+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char *))" "ac_cv_sizeof_char_p" "$ac_includes_default"; then : else if test "$ac_cv_type_char_p" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (char *) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_char_p=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char_p" >&5 $as_echo "$ac_cv_sizeof_char_p" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_CHAR_P $ac_cv_sizeof_char_p _ACEOF # 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 $as_echo_n "checking size of size_t... " >&6; } if ${ac_cv_sizeof_size_t+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then : else if test "$ac_cv_type_size_t" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (size_t) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_size_t=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 $as_echo "$ac_cv_sizeof_size_t" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SIZE_T $ac_cv_sizeof_size_t _ACEOF # 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5 $as_echo_n "checking size of unsigned long... " >&6; } if ${ac_cv_sizeof_unsigned_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5 $as_echo "$ac_cv_sizeof_unsigned_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long _ACEOF # 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5 $as_echo_n "checking size of unsigned int... " >&6; } if ${ac_cv_sizeof_unsigned_int+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_int" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_int=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5 $as_echo "$ac_cv_sizeof_unsigned_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int _ACEOF # 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5 $as_echo_n "checking size of unsigned short... " >&6; } if ${ac_cv_sizeof_unsigned_short+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short))" "ac_cv_sizeof_unsigned_short" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_short" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned short) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_short=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short" >&5 $as_echo "$ac_cv_sizeof_unsigned_short" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short _ACEOF sh_sizeof_unsigned_long=`echo "$ac_cv_sizeof_unsigned_long" | sed 's%^0-9%%g'` if test "$sh_sizeof_unsigned_long" = "4"; then $as_echo "#define HAVE_LONG_32 1" >>confdefs.h fi if test "$sh_sizeof_unsigned_long" = "8"; then $as_echo "#define HAVE_LONG_64 1" >>confdefs.h fi sh_sizeof_unsigned_int=`echo "$ac_cv_sizeof_unsigned_int" | sed 's%^0-9%%g'` if test "$sh_sizeof_unsigned_int" = "4"; then $as_echo "#define HAVE_INT_32 1" >>confdefs.h fi sh_sizeof_unsigned_short=`echo "$ac_cv_sizeof_unsigned_short" | sed 's%^0-9%%g'` if test "$sh_sizeof_unsigned_short" = "4"; then $as_echo "#define HAVE_SHORT_32 1" >>confdefs.h fi samhain_64=no tiger_src=sh_tiger1.c samhain_64_asm=no # # if sizeof(unsigned long) = 4, try compiler macros for 64bit # if test "x$ac_cv_sizeof_unsigned_long" = x4; then if test "x$ac_cv_sizeof_unsigned_long_long" = x8; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a known 64 bit programming environment" >&5 $as_echo_n "checking for a known 64 bit programming environment... " >&6; } # Compile and run a program that determines the programming environment if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int argc,char **argv) { if (argc > 1) { #if defined(__arch64__) printf("__arch64__\n"); #elif defined(__ia64__) printf("__ia64__\n"); #elif defined(__x86_64__) printf("__x86_64__\n"); #elif defined(__LP64__) printf("__LP64__\n"); #elif defined(__64BIT__) printf("__64BIT__\n"); #elif defined(_LP64) printf("_LP64\n"); #elif defined(_M_IA64) printf("_M_IA64\n"); #elif defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64) printf("_MIPS_64\n"); #else choke me #endif } return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : # Program compiled and ran, so get version by adding argument. samhain_prg_ENV=`./conftest$ac_exeext x` samhain_64=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $samhain_prg_ENV" >&5 $as_echo "$samhain_prg_ENV" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "x$samhain_64" = xyes; then tiger_src=sh_tiger1_64.c fi # # if GCC and __i386__, use precompiled assembler # if test "x$GCC" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-apple non-cygwin i386" >&5 $as_echo_n "checking for non-apple non-cygwin i386... " >&6; } samhain_i386=no $CC -E -dM - < /dev/null | egrep '__i386__' >/dev/null 2>&1 if test $? = 0; then case "$host_os" in *linux*) # apples gcc does not understand the assembly we provide $CC -E -dM - < /dev/null | egrep '(__sun__|__APPLE__|__CYGWIN__)' >/dev/null 2>&1 || samhain_i386=yes ;; *) ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $samhain_i386" >&5 $as_echo "$samhain_i386" >&6; } if test "x$samhain_i386" = xyes; then if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -pie -fPIE" >&5 $as_echo_n "checking whether ${CC} accepts -pie -fPIE... " >&6; } if ${pie_cv_cc+:} false; then : $as_echo_n "(cached) " >&6 else pie_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -pie -fPIE" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : pie_cv_cc=yes else pie_cv_cc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$pie_old_cflags" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pie_cv_cc" >&5 $as_echo "$pie_cv_cc" >&6; } if test $pie_cv_cc = yes; then case "$host_os" in *cygwin*) ;; *) PIE_CFLAGS="-fPIE" PIE_LDFLAGS="-pie" ;; esac fi fi if test $pie_cv_cc = yes; then tiger_src=sh_tiger1.s $as_echo "#define TIGER_32_BIT_S 1" >>confdefs.h fi fi fi # # # else samhain_64=no tiger_src=sh_tiger1.c fi else # # sizeof(unsigned long) = 8 # tiger_src=sh_tiger1_64.c samhain_64=yes # # check for x86_64 (enables assembly optimizations) # if test "x$GCC" = xyes; then $CC -E -dM - < /dev/null | egrep '__clang__' >/dev/null 2>&1 if ! test $? = 0; then case "$host_os" in *linux*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86_64" >&5 $as_echo_n "checking for x86_64... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { __asm__ volatile ( "movq %rax, %rax" ); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } samhain_64=yes tiger_src=sh_tiger1_64.c samhain_64_asm=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi ;; *bsd*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86_64" >&5 $as_echo_n "checking for x86_64... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { __asm__ volatile ( "movq %rax, %rax" ); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } samhain_64=yes tiger_src=sh_tiger1_64.c samhain_64_asm=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86_64" >&5 $as_echo_n "checking for x86_64... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { __asm__ volatile ( "movq %rax, %rax" ); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } samhain_64=yes tiger_src=sh_tiger1_64.c samhain_64_asm=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi ;; esac fi fi fi if test "x$samhain_64" = xyes; then $as_echo "#define TIGER_64_BIT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64 bit environment" >&5 $as_echo_n "checking for 64 bit environment... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $samhain_64" >&5 $as_echo "$samhain_64" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tiger source to use" >&5 $as_echo_n "checking for tiger source to use... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tiger_src" >&5 $as_echo "$tiger_src" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct stat has a st_flags field" >&5 $as_echo_n "checking whether struct stat has a st_flags field... " >&6; } if ${e2fsprogs_cv_struct_st_flags+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct stat stat; stat.st_flags = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : e2fsprogs_cv_struct_st_flags=yes else e2fsprogs_cv_struct_st_flags=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $e2fsprogs_cv_struct_st_flags" >&5 $as_echo "$e2fsprogs_cv_struct_st_flags" >&6; } if test "$e2fsprogs_cv_struct_st_flags" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether st_flags field is useful" >&5 $as_echo_n "checking whether st_flags field is useful... " >&6; } if ${e2fsprogs_cv_struct_st_flags_immut+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct stat stat; stat.st_flags |= UF_IMMUTABLE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : e2fsprogs_cv_struct_st_flags_immut=yes else e2fsprogs_cv_struct_st_flags_immut=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $e2fsprogs_cv_struct_st_flags_immut" >&5 $as_echo "$e2fsprogs_cv_struct_st_flags_immut" >&6; } if test "$e2fsprogs_cv_struct_st_flags_immut" = yes; then $as_echo "#define HAVE_STAT_FLAGS 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct cmsgcred" >&5 $as_echo_n "checking for struct cmsgcred... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct cmsgcred cred; cred.cmcred_pid = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_have_struct_cmsgcred=yes else sh_have_struct_cmsgcred=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_have_struct_cmsgcred" >&5 $as_echo "$sh_have_struct_cmsgcred" >&6; } if test x$sh_have_struct_cmsgcred = xyes; then $as_echo "#define HAVE_STRUCT_CMSGCRED 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct fcred" >&5 $as_echo_n "checking for struct fcred... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { struct fcred sockcred; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_have_struct_fcred=yes else sh_have_struct_fcred=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_have_struct_fcred" >&5 $as_echo "$sh_have_struct_fcred" >&6; } if test x$sh_have_struct_fcred = xyes; then $as_echo "#define HAVE_STRUCT_FCRED 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockcred" >&5 $as_echo_n "checking for struct sockcred... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { struct sockcred sockcred; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_have_struct_sockcred=yes else sh_have_struct_sockcred=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_have_struct_sockcred" >&5 $as_echo "$sh_have_struct_sockcred" >&6; } if test x$sh_have_struct_sockcred = xyes; then $as_echo "#define HAVE_STRUCT_SOCKCRED 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SO_PEERCRED" >&5 $as_echo_n "checking for SO_PEERCRED... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { int test = SO_PEERCRED; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sh_have_SO_PEERCRED=yes else sh_have_SO_PEERCRED=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sh_have_SO_PEERCRED" >&5 $as_echo "$sh_have_SO_PEERCRED" >&6; } if test x$sh_have_SO_PEERCRED = xyes; then $as_echo "#define HAVE_SO_PEERCRED 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* 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"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; 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 sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no 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 if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no 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 if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; 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 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 $as_echo_n "checking for C/C++ restrict keyword... " >&6; } if ${ac_cv_c_restrict+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_restrict=no # The order here caters to the fact that C++ does not require restrict. for ac_kw in __restrict __restrict__ _Restrict restrict; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ typedef int * int_ptr; int foo (int_ptr $ac_kw ip) { return ip[0]; } int main () { int s[1]; int * $ac_kw t = s; t[0] = 0; return foo(t) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_restrict=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_restrict" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5 $as_echo "$ac_cv_c_restrict" >&6; } case $ac_cv_c_restrict in restrict) ;; no) $as_echo "#define restrict /**/" >>confdefs.h ;; *) cat >>confdefs.h <<_ACEOF #define restrict $ac_cv_c_restrict _ACEOF ;; esac am_cv_val_SA_SIGACTION=no ac_fn_c_check_header_mongrel "$LINENO" "signal.h" "ac_cv_header_signal_h" "$ac_includes_default" if test "x$ac_cv_header_signal_h" = xyes; then : if test $ac_cv_header_signal_h = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SI_USER in signal.h" >&5 $as_echo_n "checking for SI_USER in signal.h... " >&6; } if ${am_cv_val_SI_USER+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return SI_USER ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_val_SI_USER=yes else am_cv_val_SI_USER=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_SI_USER" >&5 $as_echo "$am_cv_val_SI_USER" >&6; } if test $am_cv_val_SI_USER = yes; then $as_echo "#define HAVE_SI_USER 1" >>confdefs.h fi fi if test $ac_cv_header_signal_h = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SA_SIGINFO in signal.h" >&5 $as_echo_n "checking for SA_SIGINFO in signal.h... " >&6; } if ${am_cv_val_SA_SIGINFO+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return SA_SIGINFO ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_val_SA_SIGINFO=yes else am_cv_val_SA_SIGINFO=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_SA_SIGINFO" >&5 $as_echo "$am_cv_val_SA_SIGINFO" >&6; } if test $am_cv_val_SA_SIGINFO = yes; then $as_echo "#define HAVE_SA_SIGINFO 1" >>confdefs.h fi fi if test $am_cv_val_SI_USER = yes && test $am_cv_val_SA_SIGINFO = yes then if test "$cross_compiling" = yes; then : am_cv_val_SA_SIGACTION=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include volatile int xnum = 0; volatile int xcode = 0; jmp_buf Buf; int xsig = SIGSEGV; void sighandler (int xsignam, siginfo_t * xsiginfo, void * xsigadd) { static sigset_t x; if (xsiginfo == NULL) exit(__LINE__); if (xsiginfo->si_signo != xsignam) exit(__LINE__); ++xnum; xcode = xsiginfo->si_code; sigemptyset (&x); sigprocmask(SIG_SETMASK, &x, NULL); longjmp ( Buf, 1); } int main () { struct sigaction newact; newact.sa_sigaction = sighandler; sigemptyset (&newact.sa_mask); newact.sa_flags = SA_SIGINFO; if (0 != sigaction (xsig, &newact, NULL)) exit (__LINE__); if(setjmp ( Buf)) { if (xnum > 1) goto Third; goto Second; } memcpy((void *) 0x0, "test", 5); Second: if (xcode == SI_USER) exit (__LINE__); raise(xsig); Third: if (xcode != SI_USER) exit (__LINE__); if (xnum != 2) exit (__LINE__); return (0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : am_cv_val_SA_SIGACTION=yes else am_cv_val_SA_SIGACTION=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sa_sigaction is supported" >&5 $as_echo_n "checking whether sa_sigaction is supported... " >&6; } if test $am_cv_val_SA_SIGACTION = yes then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define SA_SIGACTION_WORKS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --enable-ssp was given. if test "${enable_ssp+set}" = set; then : enableval=$enable_ssp; else enable_ssp=yes; fi if test "x$GCC" = "xyes"; then if test x"${enable_ssp}" = xno; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libssp exists" >&5 $as_echo_n "checking whether libssp exists... " >&6; } if ${ssp_cv_lib+:} false; then : $as_echo_n "(cached) " >&6 else ssp_old_libs="$LIBS" LIBS="$LIBS -lssp" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ssp_cv_lib=yes else ssp_cv_lib=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ssp_old_libs" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssp_cv_lib" >&5 $as_echo "$ssp_cv_lib" >&6; } if test $ssp_cv_lib = yes; then LIBS="$LIBS -lssp" fi if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -fstack-protector-all" >&5 $as_echo_n "checking whether ${CC} accepts -fstack-protector-all... " >&6; } if ${ssp_cv_cc+:} false; then : $as_echo_n "(cached) " >&6 else ssp_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -fstack-protector-all" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ssp_cv_cc=yes else ssp_cv_cc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$ssp_old_cflags" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssp_cv_cc" >&5 $as_echo "$ssp_cv_cc" >&6; } if test $ssp_cv_cc = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -fstack-protector" >&5 $as_echo_n "checking whether ${CC} accepts -fstack-protector... " >&6; } if ${ssp_cv_cc+:} false; then : $as_echo_n "(cached) " >&6 else ssp_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -fstack-protector" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ssp_cv_cc=yes else ssp_cv_cc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$ssp_old_cflags" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssp_cv_cc" >&5 $as_echo "$ssp_cv_cc" >&6; } if test $ssp_cv_cc = yes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector" LDFLAGS="$LDFLAGS -fstack-protector" $as_echo "#define ENABLE_SSP_CC 1" >>confdefs.h fi else if test $ssp_cv_cc = yes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector-all" LDFLAGS="$LDFLAGS -fstack-protector-all" $as_echo "#define ENABLE_SSP_CC 1" >>confdefs.h fi fi fi if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -pie -fPIE" >&5 $as_echo_n "checking whether ${CC} accepts -pie -fPIE... " >&6; } if ${pie_cv_cc+:} false; then : $as_echo_n "(cached) " >&6 else pie_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -pie -fPIE" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : pie_cv_cc=yes else pie_cv_cc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$pie_old_cflags" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pie_cv_cc" >&5 $as_echo "$pie_cv_cc" >&6; } if test $pie_cv_cc = yes; then case "$host_os" in *cygwin*) ;; *) PIE_CFLAGS="-fPIE" PIE_LDFLAGS="-pie" ;; esac fi fi fi fi if test -d "/proc/$$" then $as_echo "#define HAVE_PROCFS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_init in -lgmp" >&5 $as_echo_n "checking for __gmpz_init in -lgmp... " >&6; } if ${ac_cv_lib_gmp___gmpz_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgmp $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 __gmpz_init (); int main () { return __gmpz_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gmp___gmpz_init=yes else ac_cv_lib_gmp___gmpz_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_init" >&5 $as_echo "$ac_cv_lib_gmp___gmpz_init" >&6; } if test "x$ac_cv_lib_gmp___gmpz_init" = xyes; then : sh_have_gmp=yes else sh_have_gmp=no fi if test "x${sh_have_gmp}" = xno then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mpz_init in -lgmp" >&5 $as_echo_n "checking for mpz_init in -lgmp... " >&6; } if ${ac_cv_lib_gmp_mpz_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgmp $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 mpz_init (); int main () { return mpz_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gmp_mpz_init=yes else ac_cv_lib_gmp_mpz_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp_mpz_init" >&5 $as_echo "$ac_cv_lib_gmp_mpz_init" >&6; } if test "x$ac_cv_lib_gmp_mpz_init" = xyes; then : sh_have_gmp=yes else sh_have_gmp=no fi fi if test "x${sh_have_gmp}" = xyes then # LIBS="-lgmp $LIBS" $as_echo "#define HAVE_LIBGMP 1" >>confdefs.h fi for ac_header in gmp.h do : ac_fn_c_check_header_mongrel "$LINENO" "gmp.h" "ac_cv_header_gmp_h" "$ac_includes_default" if test "x$ac_cv_header_gmp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GMP_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ps" >&5 $as_echo_n "checking for ps... " >&6; } PS= for ff in /usr/ucb /bin /usr/bin; do if test -x "$ff/ps"; then PS="$ff/ps" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PS" >&5 $as_echo "$PS" >&6; } break fi done if test x$PS = x then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Cannot find ps in any of /usr/ucb /bin /usr/bin" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define PSPATH _("$PS") _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use ps" >&5 $as_echo_n "checking how to use ps... " >&6; } $PS ax >/dev/null 2>&1 if test $? -eq 0; then case "$host_os" in *openbsd*) one=`$PS akx | wc -l` ;; *) one=`$PS ax | wc -l` ;; esac else one=0 fi $PS -e >/dev/null 2>&1 if test $? -eq 0; then two=`$PS -e | wc -l` else two=0 fi if test $one -ge $two then case "$host_os" in *openbsd*) PSARG="akx" ;; *) PSARG="ax" ;; esac else PSARG="-e" fi cat >>confdefs.h <<_ACEOF #define PSARG _("$PSARG") _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PS $PSARG" >&5 $as_echo "$PS $PSARG" >&6; } # Check whether --enable-db-reload was given. if test "${enable_db_reload+set}" = set; then : enableval=$enable_db_reload; if test "x${enable_db_reload}" = xyes; then $as_echo "#define RELOAD_DATABASE 1" >>confdefs.h fi fi # Check whether --enable-xml-log was given. if test "${enable_xml_log+set}" = set; then : enableval=$enable_xml_log; if test "x${enable_xml_log}" = xyes; then $as_echo "#define SH_USE_XML 1" >>confdefs.h fi fi # Check whether --enable-mail was given. if test "${enable_mail+set}" = set; then : enableval=$enable_mail; if test "x${enable_mail}" = xno; then : else $as_echo "#define SH_WITH_MAIL 1" >>confdefs.h fi else $as_echo "#define SH_WITH_MAIL 1" >>confdefs.h fi # Check whether --enable-suid was given. if test "${enable_suid+set}" = set; then : enableval=$enable_suid; if test "x${enable_suid}" = xyes; then $as_echo "#define SH_ALLOW_SUID 1" >>confdefs.h fi fi # Check whether --enable-shellexpand was given. if test "${enable_shellexpand+set}" = set; then : enableval=$enable_shellexpand; if test "x${enable_shellexpand}" = xno; then : else $as_echo "#define SH_EVAL_SHELL 1" >>confdefs.h fi else $as_echo "#define SH_EVAL_SHELL 1" >>confdefs.h fi # Check whether --enable-external-scripts was given. if test "${enable_external_scripts+set}" = set; then : enableval=$enable_external_scripts; if test "x${enableval}" = xno; then : else $as_echo "#define WITH_EXTERNAL 1" >>confdefs.h fi else $as_echo "#define WITH_EXTERNAL 1" >>confdefs.h fi # Check whether --enable-message-queue was given. if test "${enable_message_queue+set}" = set; then : enableval=$enable_message_queue; if test "x${ac_cv_header_sys_msg_h}" = "xyes"; then if test "x${enable_message_queue}" = xyes; then $as_echo "#define WITH_MESSAGE_QUEUE 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define MESSAGE_QUEUE_MODE 0700 _ACEOF elif test "x${enable_message_queue}" != xno; then echo "${enableval}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "With --enable-message-queue=MODE, MODE must be numeric" "$LINENO" 5 echo "${enableval}" | \ grep '0[0123456789][0123456789][0123456789]' >/dev/null 2>&1 || as_fn_error $? "With --enable-message-queue=MODE, MODE must be an octal (0nnn) number" "$LINENO" 5 $as_echo "#define WITH_MESSAGE_QUEUE 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define MESSAGE_QUEUE_MODE ${enable_message_queue} _ACEOF fi else echo echo "**********************************************" echo { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: sys/msg.h missing, --enable-message-queue disabled" >&5 $as_echo "$as_me: WARNING: sys/msg.h missing, --enable-message-queue disabled" >&2;} echo echo "**********************************************" echo fi fi # Check whether --with-cflags was given. if test "${with_cflags+set}" = set; then : withval=$with_cflags; if test "x$withval" != "xno" ; then CFLAGS="$CFLAGS $withval" fi fi # Check whether --with-libs was given. if test "${with_libs+set}" = set; then : withval=$with_libs; if test "x$withval" != "xno" ; then LIBS="$LIBS $withval" fi fi # # this is from ssh # { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libwrap" >&5 $as_echo_n "checking whether to use libwrap... " >&6; } LIBWRAP_LIB="" LIBWRAP_INC="" # Check whether --with-libwrap was given. if test "${with_libwrap+set}" = set; then : withval=$with_libwrap; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 $as_echo "$withval" >&6; } case "$withval" in no) ;; ""|yes) LIBWRAP_LIB="-lwrap" ;; *) if test -d "$withval"; then LIBWRAP_LIB="-L$withval -lwrap" sh_libwrap_inc=`echo ${withval} | sed 's%/[^/][^/]*$%%'` LIBWRAP_INC="-I${sh_libwrap_inc}/include" else LIBWRAP_LIB="-lwrap" sh_libwrap_inc=`echo ${withval} | sed 's%/[^/][^/]*$%%'` LIBWRAP_INC="-I${sh_libwrap_inc}" fi ;; esac if test -n "$LIBWRAP_LIB"; then # OLDLIBS="$LIBS" LIBS="$LIBWRAP_LIB $LIBS" # OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS $LIBWRAP_INC" ac_fn_c_check_header_mongrel "$LINENO" "tcpd.h" "ac_cv_header_tcpd_h" "$ac_includes_default" if test "x$ac_cv_header_tcpd_h" = xyes; then : else as_fn_error $? "Could not find tcpd.h for libwrap. You need to install tcp_wrappers." "$LINENO" 5 fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int allow_severity; int deny_severity; int main () { hosts_access((struct request_info *) 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define SH_USE_LIBWRAP 1" >>confdefs.h else as_fn_error $? "Could not find the libwrap library." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --enable-network was given. if test "${enable_network+set}" = set; then : enableval=$enable_network; if test "x$enable_network" = xclient; then mytclient="-DSH_WITH_CLIENT" yulectl_prg= samhainadmin_prg= setpwd_prg="samhain_setpwd" sh_main_prg="samhain" if test "x${sh_have_gmp}" = xyes then LIBS="-lgmp $LIBS" fi elif test "x$enable_network" = xserver; then mytclient="-DSH_WITH_SERVER" yulectl_prg="yulectl" samhainadmin_prg="scripts/samhainadmin.pl" setpwd_prg="samhain_setpwd" sh_main_prg="yule" if test "x${sh_have_gmp}" = xyes then LIBS="-lgmp $LIBS" fi sh_use_lcaps="undef" elif test "x$enable_network" = xno; then mytclient="-DSH_STANDALONE" yulectl_prg= samhainadmin_prg= setpwd_prg= sh_main_prg="samhain" else as_fn_error $? "With --enable-network=WHAT, WHAT must be client, server, or no" "$LINENO" 5 fi else mytclient="-DSH_STANDALONE" setpwd_prg= yulectl_prg= samhainadmin_prg= sh_main_prg="samhain" fi # needed for the rpm spec clmytclient=`echo ${mytclient} | sed s%\-%%` sh_no_gcc_static=no # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; if test x$enable_static = xyes; then if test x"$mynetbsd" = xyes then tmp_LIBS=`echo $LIBS | sed 's%\-lresolv%%' ` LIBS="${tmp_LIBS}" fi if test x"${sh_auparse}" = xyes then tmp_LIBS=`echo $LIBS | sed 's%\-lauparse%%' ` LIBS="${tmp_LIBS}" fi if test "x$GCC" = "xyes"; then case "$host_os" in *solaris*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: option --enable-static ignored on Solaris" >&5 $as_echo "$as_me: WARNING: option --enable-static ignored on Solaris" >&2;} ;; *) $as_echo "#define SH_COMPILE_STATIC 1" >>confdefs.h sh_no_gcc_static=no LDFLAGS="$LDFLAGS -static" ;; esac else $as_echo "#define SH_COMPILE_STATIC 1" >>confdefs.h sh_no_gcc_static=yes case "$host_os" in *aix*) LDFLAGS="$LDFLAGS -bnso -bI:/lib/syscalls.exp" ;; *hpux*) LDFLAGS="$LDFLAGS -Wl,-a,archive" ;; *osf*) LDFLAGS="$LDFLAGS -non_shared" ;; *irix*) LDFLAGS="$LDFLAGS -non_shared" ;; *sco*) LDFLAGS="$LDFLAGS -dn" ;; *sun*) LDFLAGS="$LDFLAGS -Bstatic" ;; *solaris*) LDFLAGS="$LDFLAGS -Bstatic" ;; *) echo "***********************************************" echo "*" echo "* Don't know how to enable static linking" echo "* with your compiler. Please set the environment" echo "* variable LDFLAGS to:" echo "* ${LDFLAGS} + the static linking flag" echo "* and run configure again" echo "*" echo "***********************************************" ;; esac fi fi fi if test x"${mytclient}" = x-DSH_STANDALONE -o x"${mytclient}" = x-DSH_WITH_CLIENT; then 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 acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -pthread) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_acx_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$acx_pthread_config"; then ac_cv_prog_acx_pthread_config="$acx_pthread_config" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_acx_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" fi fi acx_pthread_config=$ac_cv_prog_acx_pthread_config if test -n "$acx_pthread_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 $as_echo "$acx_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=$attr; return attr; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : attr_name=$attr; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 $as_echo "$attr_name" >&6; } if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then cat >>confdefs.h <<_ACEOF #define PTHREAD_CREATE_JOINABLE $attr_name _ACEOF fi # Solaris lossage: default is obsolete semantics for getpwnam_r, # getpwuid_r, getgrgid_r, unless _POSIX_PTHREAD_SEMANTICS is defined { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *-osf* | *-hpux*) flag="-D_REENTRANT";; *solaris*) flag="-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT";; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi # Detect PTHREAD_MUTEX_RECURSIVE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for recursive mutexes" >&5 $as_echo_n "checking for recursive mutexes... " >&6; } mutex_recursive=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE 500 #include int main () { pthread_mutexattr_t mta; pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : mutex_recursive=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "x$mutex_recursive" = "xyes" then $as_echo "#define HAVE_PTHREAD_MUTEX_RECURSIVE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mutex_recursive" >&5 $as_echo "$mutex_recursive" >&6; } LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then for ac_prog in xlc_r cc_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi if test x"$acx_pthread_ok" = xyes; then PTHREAD_CFLAGS="${PTHREAD_CFLAGS} -DUSE_MALLOC_LOCK=1" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h : else acx_pthread_ok=no 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 CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" LDFLAGS="$PTHREAD_CFLAGS $LDFLAGS" CC="$PTHREAD_CC" if test "x${ZLIB_HOME}" = "x"; then ZLIB_HOME=/usr/local if test ! -f "${ZLIB_HOME}/include/zlib.h" then ZLIB_HOME=/usr fi fi zlib_found=no ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$LDFLAGS if test "x${ZLIB_HOME}" = "x/usr"; then : else LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 inflateEnd (); int main () { return inflateEnd (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_inflateEnd=yes else ac_cv_lib_z_inflateEnd=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : zlib_cv_libz=yes else zlib_cv_libz=no fi ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : zlib_cv_zlib_h=yes else zlib_cv_zlib_h=no 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 "$zlib_cv_libz" = "yes" -a "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, use them # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 inflateEnd (); int main () { return inflateEnd (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_inflateEnd=yes else ac_cv_lib_z_inflateEnd=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking zlib in ${ZLIB_HOME}" >&5 $as_echo_n "checking zlib in ${ZLIB_HOME}... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } for ac_func in compressBound do : ac_fn_c_check_func "$LINENO" "compressBound" "ac_cv_func_compressBound" if test "x$ac_cv_func_compressBound" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_COMPRESSBOUND 1 _ACEOF fi done zlib_found=yes else # # If either header or library was not found, revert and bomb # { $as_echo "$as_me:${as_lineno-$LINENO}: checking zlib in ${ZLIB_HOME}" >&5 $as_echo_n "checking zlib in ${ZLIB_HOME}... " >&6; } LDFLAGS="$ZLIB_OLD_LDFLAGS" CPPFLAGS="$ZLIB_OLD_CPPFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib not found in ZLIB_HOME, /usr/local, or /usr" >&5 $as_echo "$as_me: WARNING: zlib not found in ZLIB_HOME, /usr/local, or /usr" >&2;} fi fi if test x$enable_static = xyes; then : else if test x$sh_use_pie = xyes; then LDFLAGS="$LDFLAGS $PIE_LDFLAGS" CFLAGS="$CFLAGS $PIE_CFLAGS" fi fi ac_fn_c_check_func "$LINENO" "pmap_getmaps" "ac_cv_func_pmap_getmaps" if test "x$ac_cv_func_pmap_getmaps" = xyes; then : $as_echo "#define HAVE_PMAP_GETMAPS /**/" >>confdefs.h fi # # this is from the snort configure.in # # Check whether --with-libprelude-prefix was given. if test "${with_libprelude_prefix+set}" = set; then : withval=$with_libprelude_prefix; libprelude_config_prefix="$withval" else libprelude_config_prefix="" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use prelude" >&5 $as_echo_n "checking whether to use prelude... " >&6; } # Check whether --with-prelude was given. if test "${with_prelude+set}" = set; then : withval=$with_prelude; if test "x${withval}" = "xno"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test x$libprelude_config_prefix != x ; then if test x${LIBPRELUDE_CONFIG+set} != xset ; then LIBPRELUDE_CONFIG=$libprelude_config_prefix/bin/libprelude-config fi fi # Extract the first word of "libprelude-config", so it can be a program name with args. set dummy libprelude-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LIBPRELUDE_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $LIBPRELUDE_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_LIBPRELUDE_CONFIG="$LIBPRELUDE_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LIBPRELUDE_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_LIBPRELUDE_CONFIG" && ac_cv_path_LIBPRELUDE_CONFIG="no" ;; esac fi LIBPRELUDE_CONFIG=$ac_cv_path_LIBPRELUDE_CONFIG if test -n "$LIBPRELUDE_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBPRELUDE_CONFIG" >&5 $as_echo "$LIBPRELUDE_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$LIBPRELUDE_CONFIG" = "xno" ; then HAVE_PRELUDE_CONFIG=no else HAVE_PRELUDE_CONFIG=yes fi if test "$HAVE_PRELUDE_CONFIG" = "yes"; then sh_libprelude_version=`$LIBPRELUDE_CONFIG --version` case "$sh_libprelude_version" in 0.8*) as_fn_error $? "You have Libprelude 0.8, which is too old. Version 0.9.6 or higher is required." "$LINENO" 5 ;; *) min_libprelude_version=0.9.6 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libprelude - version >= $min_libprelude_version" >&5 $as_echo_n "checking for libprelude - version >= $min_libprelude_version... " >&6; } no_libprelude="" if test "$LIBPRELUDE_CONFIG" = "no" ; then no_libprelude=yes else LIBPRELUDE_CFLAGS=`$LIBPRELUDE_CONFIG $libprelude_config_args --cflags` LIBPRELUDE_PTHREAD_CFLAGS=`$LIBPRELUDE_CONFIG $libprelude_config_args --pthread-cflags` LIBPRELUDE_LDFLAGS=`$LIBPRELUDE_CONFIG $libprelude_config_args --ldflags` LIBPRELUDE_LIBS=`$LIBPRELUDE_CONFIG $libprelude_config_args --libs` LIBPRELUDE_PREFIX=`$LIBPRELUDE_CONFIG $libprelude_config_args --prefix` LIBPRELUDE_CONFIG_PREFIX=`$LIBPRELUDE_CONFIG $libprelude_config_args --config-prefix` libprelude_config_version=`$LIBPRELUDE_CONFIG $libprelude_config_args --version` ac_save_CFLAGS="$CFLAGS" ac_save_LDFLAGS="$LDFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $LIBPRELUDE_CFLAGS" LDFLAGS="$LDFLAGS $LIBPRELUDE_LDFLAGS" LIBS="$LIBS $LIBPRELUDE_LIBS" rm -f conf.libpreludetest if test "$cross_compiling" = yes; then : echo $ac_n "cross compiling; assumed OK... $ac_c" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { system ("touch conf.libpreludetest"); if( strcmp( prelude_check_version(NULL), "$libprelude_config_version" ) ) { printf("\n*** 'libprelude-config --version' returned %s, but LIBPRELUDE (%s)\n", "$libprelude_config_version", prelude_check_version(NULL) ); printf("*** was found! If libprelude-config was correct, then it is best\n"); printf("*** to remove the old version of LIBPRELUDE. You may also be able to fix the error\n"); printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); printf("*** required on your system.\n"); printf("*** If libprelude-config was wrong, set the environment variable LIBPRELUDE_CONFIG\n"); printf("*** to point to the correct copy of libprelude-config, and remove the file config.cache\n"); printf("*** before re-running configure\n"); } else if ( strcmp(prelude_check_version(NULL), LIBPRELUDE_VERSION ) ) { printf("\n*** LIBPRELUDE header file (version %s) does not match\n", LIBPRELUDE_VERSION); printf("*** library (version %s)\n", prelude_check_version(NULL) ); } else { if ( prelude_check_version( "$min_libprelude_version" ) ) { return 0; } else { printf("no\n*** An old version of LIBPRELUDE (%s) was found.\n", prelude_check_version(NULL) ); printf("*** You need a version of LIBPRELUDE newer than %s. The latest version of\n", "$min_libprelude_version" ); printf("*** LIBPRELUDE is always available from http://www.prelude-ids.org/download/releases.\n"); printf("*** \n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the libprelude-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of LIBPRELUDE, but you can also set the LIBPRELUDE_CONFIG environment to point to the\n"); printf("*** correct copy of libprelude-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time))\n"); } } return 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else no_libprelude=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" LDFLAGS="$ac_save_LDFLAGS" fi if test "x$no_libprelude" = x ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBPRELUDE 1" >>confdefs.h CFLAGS="$CFLAGS $LIBPRELUDE_PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $LIBPRELUDE_LDFLAGS" LIBS="$LIBS $LIBPRELUDE_LIBS" else if test -f conf.libpreludetest ; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$LIBPRELUDE_CONFIG" = "no" ; then echo "*** The libprelude-config script installed by LIBPRELUDE could not be found" echo "*** If LIBPRELUDE was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the LIBPRELUDE_CONFIG environment variable to the" echo "*** full path to libprelude-config." else if test -f conf.libpreludetest ; then : else echo "*** Could not run libprelude test program, checking why..." CFLAGS="$CFLAGS $LIBPRELUDE_CFLAGS" LDFLAGS="$LDFLAGS $LIBPRELUDE_LDFLAGS" LIBS="$LIBS $LIBPRELUDE_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { return !!prelude_check_version(NULL); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding LIBPRELUDE or finding the wrong" echo "*** version of LIBPRELUDE. If it is not finding LIBPRELUDE, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" echo "***" else echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means LIBPRELUDE was incorrectly installed" echo "*** or that you have moved LIBPRELUDE since it was installed. In the latter case, you" echo "*** may want to edit the libprelude-config script: $LIBPRELUDE_CONFIG" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS="$ac_save_CFLAGS" LDFLAGS="$ac_save_LDFLAGS" LIBS="$ac_save_LIBS" fi fi LIBPRELUDE_CFLAGS="" LIBPRELUDE_LDFLAGS="" LIBPRELUDE_LIBS="" as_fn_error $? "Could not find libprelude (if you are using --enable-static, the static library libprelude.a might be missing)." "$LINENO" 5 fi rm -f conf.libpreludetest ;; esac else as_fn_error $? "Could not find libprelude-config." "$LINENO" 5 fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # # partly based on the snort configure.in # # Check whether --with-database was given. if test "${with_database+set}" = set; then : withval=$with_database; if test x"$enable_xml_log" != xyes; then as_fn_error $? "With --with-database, --enable-xml-log is required as well." "$LINENO" 5 fi if test "x${withval}" = "xmysql"; then if test "x$zlib_found" = "x" then if test "x${ZLIB_HOME}" = "x"; then ZLIB_HOME=/usr/local if test ! -f "${ZLIB_HOME}/include/zlib.h" then ZLIB_HOME=/usr fi fi zlib_found=no ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$LDFLAGS if test "x${ZLIB_HOME}" = "x/usr"; then : else LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 inflateEnd (); int main () { return inflateEnd (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_inflateEnd=yes else ac_cv_lib_z_inflateEnd=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : zlib_cv_libz=yes else zlib_cv_libz=no fi ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : zlib_cv_zlib_h=yes else zlib_cv_zlib_h=no 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 "$zlib_cv_libz" = "yes" -a "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, use them # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 inflateEnd (); int main () { return inflateEnd (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_inflateEnd=yes else ac_cv_lib_z_inflateEnd=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking zlib in ${ZLIB_HOME}" >&5 $as_echo_n "checking zlib in ${ZLIB_HOME}... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } for ac_func in compressBound do : ac_fn_c_check_func "$LINENO" "compressBound" "ac_cv_func_compressBound" if test "x$ac_cv_func_compressBound" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_COMPRESSBOUND 1 _ACEOF fi done zlib_found=yes else # # If either header or library was not found, revert and bomb # { $as_echo "$as_me:${as_lineno-$LINENO}: checking zlib in ${ZLIB_HOME}" >&5 $as_echo_n "checking zlib in ${ZLIB_HOME}... " >&6; } LDFLAGS="$ZLIB_OLD_LDFLAGS" CPPFLAGS="$ZLIB_OLD_CPPFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib not found in ZLIB_HOME, /usr/local, or /usr" >&5 $as_echo "$as_me: WARNING: zlib not found in ZLIB_HOME, /usr/local, or /usr" >&2;} fi fi # Extract the first word of "mysql_config", so it can be a program name with args. set dummy mysql_config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_HAVE_MYSQL_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$HAVE_MYSQL_CONFIG"; then ac_cv_prog_HAVE_MYSQL_CONFIG="$HAVE_MYSQL_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_HAVE_MYSQL_CONFIG="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_HAVE_MYSQL_CONFIG" && ac_cv_prog_HAVE_MYSQL_CONFIG="no" fi fi HAVE_MYSQL_CONFIG=$ac_cv_prog_HAVE_MYSQL_CONFIG if test -n "$HAVE_MYSQL_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_MYSQL_CONFIG" >&5 $as_echo "$HAVE_MYSQL_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$HAVE_MYSQL_CONFIG" = "yes"; then sh_mysql_libs="`mysql_config --libs`" sh_mysql_libs="`eval echo ${sh_mysql_libs}`" LIBS="$LIBS ${sh_mysql_libs}" sh_mysql_cflags="`mysql_config --cflags`" sh_mysql_cflags="`eval echo ${sh_mysql_cflags}`" CPPFLAGS="$CPPFLAGS ${sh_mysql_cflags}" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MySQL in /usr /usr/local /usr/local/mysql MYSQL_HOME" >&5 $as_echo_n "checking for MySQL in /usr /usr/local /usr/local/mysql MYSQL_HOME... " >&6; } mysql_directory="/usr /usr/local /usr/local/mysql ${MYSQL_HOME}" for i in $mysql_directory; do if test -r $i/include/mysql/mysql.h; then MYSQL_DIR=$i MYSQL_INC_DIR=$i/include # we use AC_CHECK_HEADERS to check for mysql/mysql.h fi done if test -z "$MYSQL_DIR"; then for i in $mysql_directory; do if test -r $i/include/mysql.h; then MYSQL_DIR=$i MYSQL_INC_DIR=$i/include fi done fi if test -z "$MYSQL_DIR"; then tmp="" for i in $mysql_directory; do tmp="$tmp $i/include $i/include/mysql" done echo echo echo "**********************************************" echo " ERROR: unable to find" "mysql headers (mysql.h)" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit fi for i in lib lib/mysql; do str="$MYSQL_DIR/$i/libmysqlclient.*" for j in `echo $str`; do if test -r $j; then MYSQL_LIB_DIR="$MYSQL_DIR/$i" break 2 fi done done if test -z "$MYSQL_LIB_DIR"; then for ff in $mysql_directory; do for i in lib lib/mysql; do str="$ff/$i/libmysqlclient.*" for j in `echo $str`; do if test -r $j; then MYSQL_LIB_DIR="$ff/$i" break 3 fi done done done fi if test -z "$MYSQL_LIB_DIR"; then tmp="" for i in $mysql_directory; do tmp="$i/lib $i/lib/mysql" done echo echo echo "**********************************************" echo " ERROR: unable to find" "mysql library libmysqlclient" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } LIBS="$LIBS -L${MYSQL_LIB_DIR} -lmysqlclient" # CFLAGS="$CFLAGS -I${MYSQL_INC_DIR}" CPPFLAGS="$CPPFLAGS -I${MYSQL_INC_DIR}" fi $as_echo "#define WITH_MYSQL 1" >>confdefs.h $as_echo "#define WITH_DATABASE 1" >>confdefs.h if test "x$zlib_found" = "xyes" then LIBS="$LIBS -lz -lm" else echo echo " Mysql library was not found or not useable." echo " Possible reasons include:" echo " - an old, incompatible version compiled from source" echo " - on Solaris, libmysql is compiled with the Solaris" echo " compiler, thus the mysql_config script provides" echo " compiler options unsuitable for gcc (move" echo " mysql_config out of your PATH)" echo " For other problems, check config.log for the error" echo " message from the compiler." echo echo " If your mysql libraries are installed in an" echo " unusual place, use --with-libs=-L/path/to/libdirectory" echo " where libdirectory is the directory holding libmysql." if test x"$enable_static" = xyes; then echo " Note that for compiling a static binary, you need" echo " the static libraries, rather than the shared ones." fi echo as_fn_error $? "Could not find libmysql, or it is not useable." "$LINENO" 5 fi for ac_header in mysql/mysql.h do : ac_fn_c_check_header_mongrel "$LINENO" "mysql/mysql.h" "ac_cv_header_mysql_mysql_h" "$ac_includes_default" if test "x$ac_cv_header_mysql_mysql_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MYSQL_MYSQL_H 1 _ACEOF fi done elif test "x${withval}" = "xpostgresql"; then $as_echo "#define WITH_POSTGRES 1" >>confdefs.h $as_echo "#define WITH_DATABASE 1" >>confdefs.h # PGCONF="no" MY_PATH="${PATH}:/usr/local/bin:/usr/local/pgsql/bin" OLD_IFS="$IFS" IFS=":" for ff in ${MY_PATH} do if test -f "$ff/pg_config" then PGCONF="$ff/pg_config" fi done IFS="${OLD_IFS}" # # if test "x${PGCONF}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PostgreSQL in /usr/local/pgsql /usr/pgsql /usr/local /usr PGSQL_HOME" >&5 $as_echo_n "checking for PostgreSQL in /usr/local/pgsql /usr/pgsql /usr/local /usr PGSQL_HOME... " >&6; } pgsql_directory="/usr/local/pgsql /usr/pgsql /usr/local /usr ${PGSQL_HOME}" for i in $pgsql_directory; do if test -r $i/include/pgsql/libpq-fe.h; then PGSQL_INC_DIR=$i/include PGSQL_DIR=$i # use AC_CHECK_HEADERS to check for pgsql/libpq-fe.h fi done if test -z "$PGSQL_DIR"; then for i in $pgsql_directory; do if test -r $i/include/postgresql/libpq-fe.h; then PGSQL_INC_DIR=$i/include PGSQL_DIR=$i fi done fi if test -z "$PGSQL_DIR"; then for i in $pgsql_directory; do if test -r $i/include/libpq-fe.h; then PGSQL_INC_DIR=$i/include PGSQL_DIR=$i fi done fi if test -z "$PGSQL_DIR"; then tmp="" for i in $pgsql_directory; do tmp="$tmp $i/include $i/include/pgsql $i/include/postgresql" done echo echo echo "**********************************************" echo " ERROR: unable to find" "PostgreSQL header file (libpq-fe.h)" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit fi for i in lib lib/pgsql lib/postgresql; do str="$PGSQL_DIR/$i/libpq.*" for j in `echo $str`; do if test -r $j; then PGSQL_LIB_DIR="$PGSQL_DIR/$i" break 2 fi done done if test -z "$PGSQL_LIB_DIR"; then for ff in $pgsql_directory; do for i in lib lib/pgsql lib/postgresql; do str="$ff/$i/libpq.*" for j in `echo $str`; do if test -r $j; then PGSQL_LIB_DIR="$ff/$i" break 3 fi done done done fi if test -z "$PGSQL_LIB_DIR"; then tmp="" for i in $pgsql_directory; do tmp="$i/lib $i/lib/pgsql $i/lib/postgresql" done echo echo echo "**********************************************" echo " ERROR: unable to find" "postgresql library libpq" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lm" if test x"$enable_static" = xyes; then LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lcrypt -lm" else LIBS="$LIBS -L${PGSQL_LIB_DIR} -lpq -lm" fi # CFLAGS="$CFLAGS -I${PGSQL_INC_DIR}" CPPFLAGS="$CPPFLAGS -I${PGSQL_INC_DIR}" for ac_header in pgsql/libpq-fe.h do : ac_fn_c_check_header_mongrel "$LINENO" "pgsql/libpq-fe.h" "ac_cv_header_pgsql_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_pgsql_libpq_fe_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PGSQL_LIBPQ_FE_H 1 _ACEOF fi done for ac_header in postgresql/libpq-fe.h do : ac_fn_c_check_header_mongrel "$LINENO" "postgresql/libpq-fe.h" "ac_cv_header_postgresql_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_postgresql_libpq_fe_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSTGRESQL_LIBPQ_FE_H 1 _ACEOF fi done else pg_lib_dir=`${PGCONF} --libdir` if test x"$enable_static" = xyes; then LIBS="$LIBS -L${pg_lib_dir} -lpq -lcrypt -lm" else LIBS="$LIBS -L${pg_lib_dir} -lpq -lm" fi pg_inc_dir=`${PGCONF} --includedir` # CFLAGS="$CFLAGS -I${pg_inc_dir}" CPPFLAGS="$CPPFLAGS -I${pg_inc_dir}" fi elif test "x${withval}" = "xodbc"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for odbc in /usr /usr/local ODBC_HOME" >&5 $as_echo_n "checking for odbc in /usr /usr/local ODBC_HOME... " >&6; } odbc_directory="/usr /usr/local" for i in $odbc_directory; do if test -r $i/include/sql.h; then if test -r $i/include/sqlext.h; then if test -r $i/include/sqltypes.h; then ODBC_DIR=$i ODBC_INC_DIR=$i/include fi fi fi done if test -z "$ODBC_DIR"; then tmp="" for i in $odbc_directory; do tmp="$tmp $i/include" done echo echo echo "**********************************************" echo " ERROR: unable to find" "odbc headers (sql.h sqlext.h sqltypes.h)" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit fi str="$ODBC_DIR/lib/libodbc.*" for j in `echo $str`; do if test -r $j; then ODBC_LIB_DIR="$ODBC_DIR/lib" ODBC_LIB="odbc" fi done if test -z "$ODBC_LIB_DIR"; then echo echo echo "**********************************************" echo " ERROR: unable to find" "odbc library (libodbc)" echo " checked in the following places" for i in `echo "$ODBC_DIR/lib"`; do echo " $i" done echo "**********************************************" echo exit fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CPPFLAGS="${CPPFLAGS} -I${ODBC_INC_DIR}" LIBS="${LIBS} -L${ODBC_LIB_DIR} -l$ODBC_LIB" $as_echo "#define WITH_ODBC 1" >>confdefs.h $as_echo "#define WITH_DATABASE 1" >>confdefs.h elif test "x${withval}" = "xoracle"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for oracle in ORACLE_HOME /usr/local /usr" >&5 $as_echo_n "checking for oracle in ORACLE_HOME /usr/local /usr... " >&6; } oracle_directory="/usr /usr/local ${ORACLE_HOME}" for i in $oracle_directory; do ff=`find $i -name oci.h 2>/dev/null | tail -1` if test "x$ff" = "x"; then : else ORACLE_INC=`dirname $ff` fi fg=`find $i -name libclntsh.so 2>/dev/null | tail -1` if test "x$fg" = "x"; then : else ORACLE_LIB=`dirname $fg` fi done if test -z "$ORACLE_INC"; then tmp="" for i in $oracle_directory; do tmp="$tmp $i" done echo echo echo "**********************************************" echo " ERROR: unable to find" "OCI header file (oci.h) please define ORACLE_INC directory where oci.h resides" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit elif test -z "$ORACLE_LIB"; then tmp="" for i in $oracle_directory; do tmp="$tmp $i" done echo echo echo "**********************************************" echo " ERROR: unable to find" "OCI library file (libclntsh.so) please define ORACLE_LIB directory where libclntsh.so resides" echo " checked in the following places" for i in `echo $tmp`; do echo " $i" done echo "**********************************************" echo exit else ORACLE_CPP_FLAGS="-I$ORACLE_INC" ORACLE_LIB_DIR="$ORACLE_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ORACLE_INC $ORACLE_LIB" >&5 $as_echo "$ORACLE_INC $ORACLE_LIB" >&6; } CPPFLAGS="${CPPFLAGS} ${ORACLE_CPP_FLAGS}" ORACLE_LIBS="-lclntsh" if test -r $ORACLE_LIB_DIR/libnnz11.so; then ORACLE_LIBS="${ORACLE_LIBS} -lnnz11" fi if test -r $ORACLE_LIB_DIR/libwtc9.so; then ORACLE_LIBS="${ORACLE_LIBS} -lwtc9" elif test -r $ORACLE_LIB_DIR/libwtc8.so; then ORACLE_LIBS="${ORACLE_LIBS} -lwtc8" fi LIBS="${LIBS} -L${ORACLE_LIB_DIR} ${ORACLE_LIBS}" if test "x$GCC" != "xyes"; then CFLAGS="${CFLAGS} -fno-strict-aliasing" fi fi $as_echo "#define WITH_ORACLE 1" >>confdefs.h $as_echo "#define WITH_DATABASE 1" >>confdefs.h else as_fn_error $? "Option --with-database=database used with unsupported database ${withval}" "$LINENO" 5 fi fi # Check whether --with-console was given. if test "${with_console+set}" = set; then : withval=$with_console; if test "x${withval}" != xno; then mycons="$withval" cat >>confdefs.h <<_ACEOF #define DEFAULT_CONSOLE _("${mycons}") _ACEOF fi fi # Check whether --with-altconsole was given. if test "${with_altconsole+set}" = set; then : withval=$with_altconsole; if test "x${withval}" != xno; then myaltcons="$withval" else myaltcons="NULL" fi else myaltcons="NULL" fi cat >>confdefs.h <<_ACEOF #define ALT_CONSOLE _("${myaltcons}") _ACEOF # Check whether --with-timeserver was given. if test "${with_timeserver+set}" = set; then : withval=$with_timeserver; if test "x${withval}" != xno; then mytimeserv="$withval" $as_echo "#define HAVE_NTIME 1" >>confdefs.h else mytimeserv="NULL" fi else mytimeserv="NULL" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_TIMESERVER _("${mytimeserv}") _ACEOF # Check whether --with-alttimeserver was given. if test "${with_alttimeserver+set}" = set; then : withval=$with_alttimeserver; if test "x${withval}" != xno; then myalttimeserv="$withval" $as_echo "#define HAVE_NTIME 1" >>confdefs.h else myalttimeserv="NULL" fi else myalttimeserv="NULL" fi cat >>confdefs.h <<_ACEOF #define ALT_TIMESERVER _("${myalttimeserv}") _ACEOF # Check whether --enable-login-watch was given. if test "${enable_login_watch+set}" = set; then : enableval=$enable_login_watch; if test "x${enable_login_watch}" = xyes; then $as_echo "#define SH_USE_UTMP 1" >>confdefs.h fi fi # Check whether --enable-mounts-check was given. if test "${enable_mounts_check+set}" = set; then : enableval=$enable_mounts_check; if test "x${enable_mounts_check}" = xyes; then $as_echo "#define SH_USE_MOUNTS 1" >>confdefs.h fi fi # Check whether --enable-logfile-monitor was given. if test "${enable_logfile_monitor+set}" = set; then : enableval=$enable_logfile_monitor; if test "x${enable_logfile_monitor}" = xyes; then ac_fn_c_check_header_mongrel "$LINENO" "pcre.h" "ac_cv_header_pcre_h" "$ac_includes_default" if test "x$ac_cv_header_pcre_h" = xyes; then : $as_echo "#define USE_LOGFILE_MONITOR 1" >>confdefs.h LIBS="-lpcre $LIBS" else ac_fn_c_check_header_mongrel "$LINENO" "pcre/pcre.h" "ac_cv_header_pcre_pcre_h" "$ac_includes_default" if test "x$ac_cv_header_pcre_pcre_h" = xyes; then : $as_echo "#define USE_LOGFILE_MONITOR 1" >>confdefs.h $as_echo "#define HAVE_PCRE_PCRE_H 1" >>confdefs.h LIBS="-lpcre $LIBS" else as_fn_error $? "The --enable-logfile-monitor option requires libpcre. For compiling the pcre development package is needed." "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_dfa_exec in -lpcre" >&5 $as_echo_n "checking for pcre_dfa_exec in -lpcre... " >&6; } if ${ac_cv_lib_pcre_pcre_dfa_exec+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcre $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 pcre_dfa_exec (); int main () { return pcre_dfa_exec (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcre_pcre_dfa_exec=yes else ac_cv_lib_pcre_pcre_dfa_exec=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_dfa_exec" >&5 $as_echo "$ac_cv_lib_pcre_pcre_dfa_exec" >&6; } if test "x$ac_cv_lib_pcre_pcre_dfa_exec" = xyes; then : $as_echo "#define HAVE_PCRE_DFA_EXEC 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pcre_dfa_exec not available" >&5 $as_echo "$as_me: WARNING: pcre_dfa_exec not available" >&2;} fi fi fi # Check whether --enable-process-check was given. if test "${enable_process_check+set}" = set; then : enableval=$enable_process_check; if test "x${enable_process_check}" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_getparam in -lrt" >&5 $as_echo_n "checking for sched_getparam in -lrt... " >&6; } if ${ac_cv_lib_rt_sched_getparam+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 sched_getparam (); int main () { return sched_getparam (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_sched_getparam=yes else ac_cv_lib_rt_sched_getparam=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_sched_getparam" >&5 $as_echo "$ac_cv_lib_rt_sched_getparam" >&6; } if test "x$ac_cv_lib_rt_sched_getparam" = xyes; then : sh_lrt=yes else sh_lrt=no fi if test x"$sh_lrt" = xyes; then LIBRT=-lrt else LIBRT= fi LIBS="$LIBS $LIBRT" $as_echo "#define SH_USE_PROCESSCHECK 1" >>confdefs.h fi fi # Check whether --enable-port-check was given. if test "${enable_port_check+set}" = set; then : enableval=$enable_port_check; if test "x${enable_port_check}" = xyes; then $as_echo "#define SH_USE_PORTCHECK 1" >>confdefs.h fi fi # Check whether --enable-userfiles was given. if test "${enable_userfiles+set}" = set; then : enableval=$enable_userfiles; if test "x${enableval}" = "xyes"; then $as_echo "#define SH_USE_USERFILES 1" >>confdefs.h fi fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; if test "x${enable_debug}" = "xyes"; then if test "x${mydebugflag}" != "xyes"; then $as_echo "#define MEM_DEBUG 1" >>confdefs.h fi $as_echo "#define WITH_TPT 1" >>confdefs.h $as_echo "#define SL_DEBUG 1" >>confdefs.h $as_echo "#define DNMALLOC_CHECKS 1" >>confdefs.h $as_echo "#define PARANOIA 0" >>confdefs.h $as_echo "#define SL_FAIL_ON_ERROR 1" >>confdefs.h if test "x${myneedg3}" = "xyes"; then mydebugdef="-g3" else mydebugdef="-g" fi mydebugit="yes" elif test "x${enable_debug}" = "xgdb"; then $as_echo "#define SH_ABORT_ON_ERROR 1" >>confdefs.h if test "x${myneedg3}" = "xyes"; then mydebugdef="-g3" else mydebugdef="-g" fi mydebugit="yes" fi fi if test "x${enable_asm_ok}" = "xyes"; then sh_enable_asm=yes else sh_enable_asm=no fi # Check whether --enable-asm was given. if test "${enable_asm+set}" = set; then : enableval=$enable_asm; if test "x${enable_asm}" = xno; then sh_enable_asm=no fi fi if test "x${samhain_64_asm}" = xyes; then if test "x${sh_enable_asm}" = xyes; then $as_echo "#define TIGER_OPT_ASM 1" >>confdefs.h fi fi # Check whether --enable-ipv6 was given. if test "${enable_ipv6+set}" = set; then : enableval=$enable_ipv6; if test "x${enable_ipv6}" = xno; then $as_echo "#define USE_IPV4 1" >>confdefs.h fi fi if test "x${dnmalloc_ok}" = "xyes"; then sh_dnmalloc_enabled=yes else sh_dnmalloc_enabled=no fi # Check whether --enable-dnmalloc was given. if test "${enable_dnmalloc+set}" = set; then : enableval=$enable_dnmalloc; if test "x${enable_dnmalloc}" = xno; then sh_dnmalloc_enabled=no else sh_dnmalloc_enabled=yes fi fi if test "x$sh_dnmalloc_enabled" = "xyes"; then if test x$enable_static = xyes; then if test "x$sh_no_gcc_static" = "xyes"; then sh_dnmalloc_enabled=no else if test "x$with_gnu_ld" = "xyes"; then LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition" else sh_dnmalloc_enabled=no fi fi fi fi if test "x${sh_dnmalloc_enabled}" = xno; then $as_echo "#define USE_SYSTEM_MALLOC 1" >>confdefs.h fi # Check whether --enable-ptrace was given. if test "${enable_ptrace+set}" = set; then : enableval=$enable_ptrace; if test "x${enable_ptrace}" = xyes; then if test "x$mydebugit" != "xyes"; then $as_echo "#define SCREW_IT_UP 1" >>confdefs.h fi fi fi if test "x$GCC" = "xyes"; then if test ! -z "`echo "$CFLAGS" | grep "\-g\ " 2> /dev/null`" ; then CFLAGS=`echo $CFLAGS | sed 's%\-g%%' ` fi if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then case "$host_os" in *solaris*) CFLAGS="$CFLAGS -Wall -W -Wno-missing-braces " ;; *) CFLAGS="$CFLAGS -Wall -W " ;; esac fi if test -z "`echo "$CFLAGS" | grep "\-fstrength\-reduce" 2> /dev/null`" then if test -z "`echo "$CFLAGS" | grep "\-fno\-strength\-reduce" 2> /dev/null`" then if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -fno-strength-reduce" >&5 $as_echo_n "checking whether ${CC} accepts -fno-strength-reduce... " >&6; } saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Werror -fno-strength-reduce" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_check_cv=yes else flag_check_cv=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" if test $flag_check_cv = yes; then CFLAGS="$CFLAGS -fno-strength-reduce" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi fi if test -z "`echo "$CFLAGS" | grep "\-fomit\-frame\-pointer" 2> /dev/null`" then if test -z "`echo "$CFLAGS" | grep "\-fno\-omit\-frame\-pointer" 2> /dev/null`" then if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -fno-omit-frame-pointer" >&5 $as_echo_n "checking whether ${CC} accepts -fno-omit-frame-pointer... " >&6; } saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Werror -fno-omit-frame-pointer" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_check_cv=yes else flag_check_cv=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" if test $flag_check_cv = yes; then CFLAGS="$CFLAGS -fno-omit-frame-pointer" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi fi fi if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -Wno-empty-body" >&5 $as_echo_n "checking whether ${CC} accepts -Wno-empty-body... " >&6; } saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Werror -Wno-empty-body" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_check_cv=yes else flag_check_cv=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" if test $flag_check_cv = yes; then CFLAGS="$CFLAGS -Wno-empty-body" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test "X$CC" != "X"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} accepts -Wno-invalid-source-encoding" >&5 $as_echo_n "checking whether ${CC} accepts -Wno-invalid-source-encoding... " >&6; } saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Werror -Wno-invalid-source-encoding" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_check_cv=yes else flag_check_cv=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" if test $flag_check_cv = yes; then CFLAGS="$CFLAGS -Wno-invalid-source-encoding" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking which random module to use" >&5 $as_echo_n "checking which random module to use... " >&6; } # Check whether --with-rnd was given. if test "${with_rnd+set}" = set; then : withval=$with_rnd; use_static_rnd=$withval else use_static_rnd=default fi if test "$use_static_rnd" = no; then use_static_rnd=default fi case "$use_static_rnd" in egd | dev | unix | default ) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_static_rnd" >&5 $as_echo "$use_static_rnd" >&6; } ;; * ) { $as_echo "$as_me:${as_lineno-$LINENO}: result: invalid argument" >&5 $as_echo "invalid argument" >&6; } as_fn_error $? "Option --with-rnd=module used with unsupported module ${use_static_rnd}" "$LINENO" 5 ;; esac # Check whether --with-egd-socket was given. if test "${with_egd_socket+set}" = set; then : withval=$with_egd_socket; egd_socket_name="$withval" else egd_socket_name="" fi cat >>confdefs.h <<_ACEOF #define EGD_SOCKET_NAME _("$egd_socket_name") _ACEOF try_dev_random=yes case "$use_static_rnd" in dev | default ) try_dev_random=yes ;; egd) $as_echo "#define HAVE_EGD_RANDOM 1" >>confdefs.h try_dev_random=no ;; unix) $as_echo "#define HAVE_UNIX_RANDOM 1" >>confdefs.h try_dev_random=no ;; esac if test "x$try_dev_random" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether /dev/random exists" >&5 $as_echo_n "checking whether /dev/random exists... " >&6; } if test -r "/dev/srandom" && test -c "/dev/srandom"; then $as_echo "#define HAVE_URANDOM 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define NAME_OF_DEV_RANDOM _("/dev/srandom") _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test -r "/dev/urandom" && test -c "/dev/urandom"; then cat >>confdefs.h <<_ACEOF #define NAME_OF_DEV_URANDOM _("/dev/urandom") _ACEOF fi else if test -r "/dev/random" && test -c "/dev/random"; then $as_echo "#define HAVE_URANDOM 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define NAME_OF_DEV_RANDOM _("/dev/random") _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test -r "/dev/urandom" && test -c "/dev/urandom"; then cat >>confdefs.h <<_ACEOF #define NAME_OF_DEV_URANDOM _("/dev/urandom") _ACEOF fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define HAVE_UNIX_RANDOM 1" >>confdefs.h fi fi fi # Check whether --enable-udp was given. if test "${enable_udp+set}" = set; then : enableval=$enable_udp; if test "x${enable_udp}" = xyes; then $as_echo "#define INET_SYSLOG 1" >>confdefs.h fi fi myencrypt=yes # Check whether --enable-encrypt was given. if test "${enable_encrypt+set}" = set; then : enableval=$enable_encrypt; if test "x${enable_encrypt}" = xno; then myencrypt=no fi fi if test "x${myencrypt}" = "xyes"; then $as_echo "#define SH_ENCRYPT 1" >>confdefs.h $as_echo "#define SH_ENCRYPT_2 1" >>confdefs.h fi sh_use_srp_proto=yes # Check whether --enable-srp was given. if test "${enable_srp+set}" = set; then : enableval=$enable_srp; if test "x${enable_srp}" = xno; then sh_use_srp_proto=no fi fi if test "x${sh_use_srp_proto}" = xyes; then $as_echo "#define USE_SRP_PROTOCOL 1" >>confdefs.h fi # Check whether --with-port was given. if test "${with_port+set}" = set; then : withval=$with_port; echo "${withval}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "For --with-port=PORT, PORT must be numeric." "$LINENO" 5 myport=${withval} else myport="49777" fi cat >>confdefs.h <<_ACEOF #define SH_DEFAULT_PORT ${myport} _ACEOF # Check whether --with-logserver was given. if test "${with_logserver+set}" = set; then : withval=$with_logserver; case "$withval" in *.* | localhost) mylogsrv="$withval" ;; *) mylogsrv="$withval" ;; esac else mylogsrv="NULL" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_LOGSERVER _("${mylogsrv}") _ACEOF # Check whether --with-altlogserver was given. if test "${with_altlogserver+set}" = set; then : withval=$with_altlogserver; case "$withval" in *.* | localhost) myaltlogsrv="$withval" ;; *) myaltlogsrv="$withval" ;; esac else myaltlogsrv="NULL" fi cat >>confdefs.h <<_ACEOF #define ALT_LOGSERVER _("${myaltlogsrv}") _ACEOF nocl_code= xor_code=0 # Check whether --enable-nocl was given. if test "${enable_nocl+set}" = set; then : enableval=$enable_nocl; if test "x${enableval}" != "x"; then $as_echo "#define SH_STEALTH_NOCL 1" >>confdefs.h fi if test "x${enableval}" = "xstop" || test "x${enableval}" = "xstart"; then as_fn_error $? "For --enable-nocl=PW start/stop/reload/restart/status are reserved words." "$LINENO" 5 fi if test "x${enableval}" = "xreload" || test "x${enableval}" = "xrestart"; then as_fn_error $? "For --enable-nocl=PW start/stop/reload/restart/status are reserved words." "$LINENO" 5 fi if test "x${enableval}" = "xstatus"; then as_fn_error $? "For --enable-nocl=PW start/stop/reload/restart/status are reserved words." "$LINENO" 5 fi if test "x${enableval}" = "xno"; then as_fn_error $? "With --enable-nocl=PW, the use of --enable-nocl=no is ambiguous." "$LINENO" 5 fi nocl_code="${enable_nocl}" fi cat >>confdefs.h <<_ACEOF #define NOCL_CODE _("${nocl_code}") _ACEOF # Check whether --enable-stealth was given. if test "${enable_stealth+set}" = set; then : enableval=$enable_stealth; $as_echo "#define SH_STEALTH 1" >>confdefs.h if test "x${enableval}" != "xyes"; then echo "${enableval}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "For --enable-stealth=XOR_VAL, XOR_VAL must be numeric." "$LINENO" 5 if test "${enableval}" -lt 127 || test "${enableval}" -gt 255; then if test x"${enableval}" = x0 then : else as_fn_error $? "For --enable-stealth=XOR_VAL, XOR_VAL must be in the range 127 to 255." "$LINENO" 5 fi fi xor_code="${enable_stealth}" else xor_code=0 fi stegin_prg="samhain_stealth" else stegin_prg= fi # Check whether --enable-micro-stealth was given. if test "${enable_micro_stealth+set}" = set; then : enableval=$enable_micro_stealth; $as_echo "#define SH_STEALTH 1" >>confdefs.h $as_echo "#define SH_STEALTH_MICRO 1" >>confdefs.h if test "x${enableval}" != "xyes"; then echo "${enableval}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "For --enable-micro-stealth=XOR_VAL, XOR_VAL must be numeric." "$LINENO" 5 if test "${enableval}" -lt 127 || test "${enableval}" -gt 255; then if test x"${enableval}" = x0 then : else as_fn_error $? "For --enable-micro-stealth=XOR_VAL, XOR_VAL must be in the range 127 to 255." "$LINENO" 5 fi fi xor_code="${enable_micro_stealth}" else xor_code=0 fi fi install_name="samhain" INSTALL_NAME="SAMHAIN" # Check whether --enable-install-name was given. if test "${enable_install_name+set}" = set; then : enableval=$enable_install_name; if test "x${enableval}" != "xyes"; then install_name="${enableval}" INSTALL_NAME=`echo "${enableval}" | tr a-z A-Z` else install_name="${sh_main_prg}" INSTALL_NAME=`echo "${sh_main_prg}" | tr a-z A-Z` fi else install_name="${sh_main_prg}" INSTALL_NAME=`echo "${sh_main_prg}" | tr a-z A-Z` fi need_user_install=0 # Check whether --enable-identity was given. if test "${enable_identity+set}" = set; then : enableval=$enable_identity; if test x"$enableval" = xno; then myident="daemon" else myident="$enableval" fi echo "${myident}" | grep '[^0123456789]' >/dev/null 2>&1 || \ as_fn_error $? "With --enable-identity=USER, please supply a username, not a UID." "$LINENO" 5 myident_uid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${myident}:" | awk -F: '{ print $3; }'` if test x"${myident_uid}" = x; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --enable-identity used, user ${myident} will be added upon install." >&5 $as_echo "$as_me: WARNING: Option --enable-identity used, user ${myident} will be added upon install." >&2;} need_user_install=1 fi else for myident in ${install_name} daemon nobody; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for user ${myident}" >&5 $as_echo_n "checking for user ${myident}... " >&6; } myident_uid=`(cat /etc/passwd; ypcat passwd) 2>/dev/null |\ grep "^${myident}:" | awk -F: '{ print $3; }'` if test x"${myident_uid}" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } break; else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi done if test x"${myident_uid}" = x; then myident=${install_name} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-identity: user ${myident} will be added upon install" >&5 $as_echo "$as_me: WARNING: --enable-identity: user ${myident} will be added upon install" >&2;} need_user_install=1 fi fi cat >>confdefs.h <<_ACEOF #define DEFAULT_IDENT _("${myident}") _ACEOF cat >>confdefs.h <<_ACEOF #define XOR_CODE ${xor_code} _ACEOF cat >>confdefs.h <<_ACEOF #define SH_SYSCALLTABLE ${sh_syscalltable} _ACEOF exepack_state0=`${srcdir}/c_random.sh 2>/dev/null` exepack_state1=`${srcdir}/c_random.sh 2>/dev/null` exepack_state2=`${srcdir}/c_random.sh 2>/dev/null` cat >>confdefs.h <<_ACEOF #define EXEPACK_STATE_0 ${exepack_state0} _ACEOF cat >>confdefs.h <<_ACEOF #define EXEPACK_STATE_1 ${exepack_state1} _ACEOF cat >>confdefs.h <<_ACEOF #define EXEPACK_STATE_2 ${exepack_state2} _ACEOF # Check whether --enable-suidcheck was given. if test "${enable_suidcheck+set}" = set; then : enableval=$enable_suidcheck; if test "x${enableval}" = "xyes"; then $as_echo "#define SH_USE_SUIDCHK 1" >>confdefs.h fi fi # Check whether --enable-base was given. if test "${enable_base+set}" = set; then : enableval=$enable_base; { $as_echo "$as_me:${as_lineno-$LINENO}: checking base key setting" >&5 $as_echo_n "checking base key setting... " >&6; } my_key_A=`echo ${enableval} | awk 'BEGIN{FS=","}{print $1}'` my_key_B=`echo ${enableval} | awk 'BEGIN{FS=","}{print $2}'` { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${my_key_A} ${my_key_B}" >&5 $as_echo "${my_key_A} ${my_key_B}" >&6; } if test "x${my_key_A}" = x; then as_fn_error $? "Option --enable-base=B1,B2 used with invalid first base key (zero length)." "$LINENO" 5 fi if test "x${my_key_B}" = x; then as_fn_error $? "Option --enable-base=B1,B2 used with invalid second base key (zero length)." "$LINENO" 5 fi echo "${my_key_A}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "For --enable-base=B1,B2, B1 and B2 must be numeric in the range 0 to 2147483647." "$LINENO" 5 echo "${my_key_B}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "For --enable-base=B1,B2, B1 and B2 must be numeric in the range 0 to 2147483647." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking base key setting .. collecting entropy" >&5 $as_echo_n "checking base key setting .. collecting entropy... " >&6; } my_key_1=`${srcdir}/c_random.sh 2>/dev/null` my_key_2=`${srcdir}/c_random.sh 2>/dev/null` my_key_3=`${srcdir}/c_random.sh 2>/dev/null` my_key_4=`${srcdir}/c_random.sh 2>/dev/null` my_key_A=`expr $my_key_1 \* 32767` my_key_A=`echo ${my_key_A} | sed 's%^0*%%g' 2>/dev/null` my_key_A=`expr $my_key_A \+ $my_key_2` my_key_B=`expr $my_key_3 \* 32767` my_key_B=`echo ${my_key_B} | sed 's%^0*%%g' 2>/dev/null` my_key_B=`expr $my_key_B \+ $my_key_4` { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${my_key_A} ${my_key_B}" >&5 $as_echo "${my_key_A} ${my_key_B}" >&6; } fi my_key_1=`expr $my_key_A \% 65536` my_key_2=`expr $my_key_A \/ 65536` my_key_3=`expr $my_key_B \% 65536` my_key_4=`expr $my_key_B \/ 65536` { $as_echo "$as_me:${as_lineno-$LINENO}: checking key position" >&5 $as_echo_n "checking key position... " >&6; } pos_tf_1=`${srcdir}/c_random.sh 2>/dev/null` pos_tf_2=`expr $pos_tf_1 \% 8` pos_tf=`expr $pos_tf_2 + 1` { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${pos_tf}" >&5 $as_echo "${pos_tf}" >&6; } cat >>confdefs.h <<_ACEOF #define POS_TF ${pos_tf} _ACEOF mykeybase=`echo ${my_key_A},${my_key_B}` cat >>confdefs.h <<_ACEOF #define DEFKEY ${mykeybase} _ACEOF # Check whether --with-gpg was given. if test "${with_gpg+set}" = set; then : withval=$with_gpg; if test "x${withval}" != "xno"; then if test "x${cross_compiling}" = xyes; then mygpg="${withval}" else if test -f "${withval}"; then mygpg="${withval}" mychk0=`${withval} --load-extension tiger --print-md TIGER192 ${withval} 2>/dev/null` if test "x$?" != "x0"; then mychktest=no for sampre in ./samhain ./yule /usr/local/sbin/samhain /usr/local/bin/samhain /usr/bin/samhain /usr/sbin/samhain /usr/local/sbin/yule /usr/local/bin/yule /usr/bin/yule /usr/sbin/yule; do if test x"${mychktest}" = xyes then : else if test -f ${sampre} then echo "use existing ${sampre} for gpg checksum" mychk0=`${sampre} -H ${withval} 2>/dev/null` if test "x$?" != "x0"; then if test "x${nocl_code}" != "x"; then mychk0=`echo -H ${withval} | ${sampre} ${nocl_code} 2>/dev/null` if test "x$?" != "x0"; then : else mychk="${mychk0}" mychktest=yes fi fi else mychk="${mychk0}" mychktest=yes fi fi fi done if test x${mychktest} = xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-gpg: cannot determine TIGER192 checksum of ${withval}" >&5 $as_echo "$as_me: WARNING: --with-gpg: cannot determine TIGER192 checksum of ${withval}" >&2;} echo "-------------------------------------------------------------" echo " Your gpg binary does not support the TIGER192 checksum, " echo " and I cannot find an existing samhain binary to use instead." echo " You can:" echo " (a) run make to compile a samhain binary, then repeat" echo " ./configure and make" echo " (b) ignore the failure. The checksum of the gpg binary" echo " will not get compiled in, thus allowing an attacker" echo " to replace gpg with a trojan and subverting the gpg" echo " signature verification of configure and database files." echo echo " PLEASE IGNORE THIS MESSAGE IF YOU ALSO USE --with-checksum" echo "-------------------------------------------------------------" fi else mychk="${mychk0}" fi else as_fn_error $? "--with-gpg: cannot find GnuPG PATH=${withval}" "$LINENO" 5 fi fi $as_echo "#define WITH_GPG 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define DEFAULT_GPG_PATH _("${mygpg}") _ACEOF fi fi # Check whether --with-keyid was given. if test "${with_keyid+set}" = set; then : withval=$with_keyid; if test "x${withval}" != "x"; then echo "${withval}" | awk '{if((length($0)==10)||(length($0)==18)){exit 2}else{exit 0}}' && as_fn_error $? "--with-keyid:${withval} must be \"0x\" + 8|16 hex digits" "$LINENO" 5 echo "${withval}" | grep '[^0][^x][^0123456789ABCDEFabcdef]' >/dev/null 2>&1 && as_fn_error $? "--with-keyid:${withval} must be \"0x\" + 8|16 hex digits" "$LINENO" 5 mykeyid="$withval" mykeytag="--default-key" else mykeyid="" mykeytag="" fi fi # Check whether --with-checksum was given. if test "${with_checksum+set}" = set; then : withval=$with_checksum; if test "x${withval}" != "xno"; then if test "x${withval}" != "xyes"; then if test "x${mychk}" != "x"; then if test "x${mychk}" != "x${withval}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-checksum: possible gpg CHKSUM problem" >&5 $as_echo "$as_me: WARNING: --with-checksum: possible gpg CHKSUM problem" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-checksum: CHKSUM=${withval}" >&5 $as_echo "$as_me: WARNING: --with-checksum: CHKSUM=${withval}" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-checksum: autodetected=${mychk}" >&5 $as_echo "$as_me: WARNING: --with-checksum: autodetected=${mychk}" >&2;} fi fi mychk="${withval}" else if test "x${mychk}" = "x"; then as_fn_error $? "Option --with-checksum=CHKSUM: checksum CHKSUM of the gpg binary not specified." "$LINENO" 5 fi fi $as_echo "#define HAVE_GPG_CHECKSUM 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define GPG_HASH _("${mychk}") _ACEOF echo "${mychk}" | sed 's,.*:,,g' | sed 's, ,,g' | sed 's,\(.\),\1:,g' | awk '{ split($0, arr, ":"); m = length($1)/2; print "#ifndef CHKSUM_H"; print "#define CHKSUM_H"; print "char gpgchk[50];"; for (i=1; i <= m; i++) printf "gpgchk[%d] = %c%s%c;\n", i-1, 39, arr[i], 39; printf "gpgchk[48] = %c%c0%c;\n", 39, 92, 39; print "#endif"; }' > sh_gpg_chksum.h fi else if test "x${mygpg}" != "x"; then if test "x${mychk}" != "x"; then $as_echo "#define HAVE_GPG_CHECKSUM 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define GPG_HASH _("${mychk}") _ACEOF echo "${mychk}" | sed 's,.*:,,g' | sed 's, ,,g' | sed 's,\(.\),\1:,g' | awk '{ split($0, arr, ":"); m = length($1)/2; print "#ifndef CHKSUM_H"; print "#define CHKSUM_H"; print "char gpgchk[50];"; for (i=1; i <= m; i++) printf "gpgchk[%d] = %c%s%c;\n", i-1, 39, arr[i], 39; printf "gpgchk[48] = %c%c0%c;\n", 39, 92, 39; print "#endif"; }' > sh_gpg_chksum.h fi fi fi # Check whether --with-fp was given. if test "${with_fp+set}" = set; then : withval=$with_fp; if test "x${withval}" != "xno"; then if test "x${withval}" != "xyes"; then withval0=`echo ${withval} | sed 's% %%g'` echo "${withval0}" | \ grep '[^0123456789abcdefABCDEF]' >/dev/null 2>&1 && as_fn_error $? "In option --with-fp=FINGERPRINT, there is an invalid character(s) in FINGERPRINT=${withval0}." "$LINENO" 5 sh_len=`echo ${withval0} | wc -c | sed 's% %%g'` sh_len0=`expr ${sh_len} \- 1` if test "x${sh_len0}" = "x40" || test "x${sh_len0}" = "x32" then myfp="${withval0}" $as_echo "#define USE_FINGERPRINT 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define SH_GPG_FP _("${myfp}") _ACEOF echo "${myfp}" | sed 's,.*:,,g' | sed 's, ,,g' | sed 's,\(.\),\1:,g' | awk '{ split($0, arr, ":"); m = length($1)/2; print "#ifndef FINGERPRINT_H"; print "#define FINGERPRINT_H"; printf "char gpgfp[%d];\n", m+1; for (i=1; i <= m; i++) printf "gpgfp[%d] = %c%s%c;\n", i-1, 39, arr[i], 39; printf "gpgfp[%d] = %c%c0%c;\n", m, 39, 92, 39; print "#endif"; }' > sh_gpg_fp.h else as_fn_error $? "In option --with-fp=FINGERPRINT, the length (${sh_len0}) of FINGERPRINT ${withval0} is incorrect." "$LINENO" 5 fi else as_fn_error $? "For option --with-fp=FINGERPRINT, FINGERPRINT=yes is invalid, please specify a valid key fingerprint." "$LINENO" 5 fi fi fi # Check whether --with-recipient was given. if test "${with_recipient+set}" = set; then : withval=$with_recipient; withval0=`echo ${withval} | sed 's%,% %g'` for sh_item in ${withval0} do case ${sh_item} in *@localhost) ;; *@*.*) sh_tmp=`echo ${sh_item} | awk '{ if ($1 ~ /^[a-zA-Z0-9][a-zA-Z0-9\-_\.]*@[a-zA-Z0-9\-\.]+\.([a-zA-Z]+|[0-9]+)$/) {print 1; } else { print 0}}'` if test "x${sh_tmp}" != "x1" then as_fn_error $? "Option --with-recipient=ADDR used with invalid mail address ${sh_item}." "$LINENO" 5 fi ;; *) as_fn_error $? "Option --with-recipient=ADDR used with invalid mail address ${sh_item}." "$LINENO" 5 ;; esac done myrcp="$withval0" else myrcp="NULL" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_MAILADDRESS _("${myrcp}") _ACEOF # Check whether --with-sender was given. if test "${with_sender+set}" = set; then : withval=$with_sender; mysender="${withval}" else mysender="daemon" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_SENDER _("${mysender}") _ACEOF # Check whether --with-trusted was given. if test "${with_trusted+set}" = set; then : withval=$with_trusted; sh_tmp_test=no sh_tmp=`echo ${withval} | sed 's%,% %g'` for sh_tmp1 in ${sh_tmp} do echo "${sh_tmp1}" | grep '[^0123456789]' >/dev/null 2>&1 && as_fn_error $? "Option --with-trusted=UID used with non-numeric UID in ${withval}." "$LINENO" 5 if test "x${sh_tmp1}" = "x0" then sh_tmp_test=yes fi done if test "x${sh_tmp_test}" = "xno" then withval="0,${withval}" fi mytrust="${withval}" else mytrust="0" fi cat >>confdefs.h <<_ACEOF #define SL_ALWAYS_TRUSTED ${mytrust} _ACEOF mytmpdir= # Check whether --with-tmp-dir was given. if test "${with_tmp_dir+set}" = set; then : withval=$with_tmp_dir; if test "x${cross_compiling}" = xyes; then mytmpdir="$withval" cat >>confdefs.h <<_ACEOF #define SH_TMPDIR _("${mytmpdir}") _ACEOF else if test -d "${withval}"; then mytmpdir="$withval" cat >>confdefs.h <<_ACEOF #define SH_TMPDIR _("${mytmpdir}") _ACEOF else mytmpdir="$withval" cat >>confdefs.h <<_ACEOF #define SH_TMPDIR _("${mytmpdir}") _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tmp-dir: tmp directory ${withval} does not exist" >&5 $as_echo "$as_me: WARNING: --with-tmp-dir: tmp directory ${withval} does not exist" >&2;} fi fi fi if test "x${ac_prefix_set}" = xyes then if test "x${exec_prefix}" = xNONE then exec_prefix="${prefix}" fi if test "x${prefix}" = xOPT then tmp_sbindir="/opt/${install_name}/bin" tmp_sysconfdir="/etc/opt" tmp_mandir="/opt/${install_name}/man" tmp_localstatedir="/var/opt/${install_name}" elif test "x${prefix}" = xUSR then tmp_sbindir="/usr/sbin" tmp_sysconfdir="/etc" tmp_mandir="/usr/share/man" tmp_localstatedir="/var" else tmp_sbindir=`eval echo ${sbindir}` tmp_sysconfdir=`eval echo ${sysconfdir}` tmp_mandir=`eval echo ${mandir}` tmp_localstatedir=`eval echo ${localstatedir}` fi else prefix="" if test "x${ac_exec_prefix_set}" = xyes then tmp_sbindir=`eval echo ${sbindir}` else tmp_sbindir="/usr/local/sbin" fi tmp_sysconfdir="/etc" # share/man -> man (FHS) 11.10.2002 tmp_mandir="/usr/local/man" tmp_localstatedir="/var" fi if test "x${ac_sbindir_set}" = xyes then : else sbindir=`eval echo ${tmp_sbindir}` fi if test "x${ac_sysconfdir_set}" = xyes then : else sysconfdir=`eval echo ${tmp_sysconfdir}` fi if test "x${ac_mandir_set}" = xyes then : else mandir=`eval echo ${tmp_mandir}` fi if test "x${ac_localstatedir_set}" = xyes then : else localstatedir=`eval echo ${tmp_localstatedir}` fi # Check whether --with-config-file was given. if test "${with_config_file+set}" = set; then : withval=$with_config_file; myconffile="${withval}" tmp=`echo ${withval} | sed 's%^REQ_FROM_SERVER%%'` sysconfdir=`echo ${tmp} | sed 's%/[^/][^/]*$%%'` myrpmconffile="${tmp}" else myconffile="${sysconfdir}/${install_name}rc" myrpmconffile="${myconffile}" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_CONFIGFILE _("${myconffile}") _ACEOF # Check whether --with-log-file was given. if test "${with_log_file+set}" = set; then : withval=$with_log_file; mylogfile="$withval" mylogdir=`echo ${withval} | sed 's%/[^/][^/]*$%%'` else if test "x${mytclient}" = "x-DSH_WITH_SERVER"; then mylogfile="${localstatedir}/log/${install_name}/${install_name}_log" mylogdir="${localstatedir}/log/${install_name}" else mylogfile="${localstatedir}/log/${install_name}_log" mylogdir="${localstatedir}/log" fi fi cat >>confdefs.h <<_ACEOF #define DEFAULT_ERRFILE _("${mylogfile}") _ACEOF cat >>confdefs.h <<_ACEOF #define DEFAULT_LOGDIR _("${mylogdir}") _ACEOF # Check whether --with-pid-file was given. if test "${with_pid_file+set}" = set; then : withval=$with_pid_file; mylockfile="$withval" mylockdir=`echo ${withval} | sed 's%/[^/][^/]*$%%'` else if test -h /var/run && test -d /run; then mylockfile="/run/${install_name}.pid" mylockdir="/run" else mylockfile="${localstatedir}/run/${install_name}.pid" mylockdir="${localstatedir}/run" fi fi cat >>confdefs.h <<_ACEOF #define DEFAULT_ERRLOCK _("${mylockfile}") _ACEOF cat >>confdefs.h <<_ACEOF #define DEFAULT_PIDDIR _("${mylockdir}") _ACEOF # Check whether --with-state-dir was given. if test "${with_state_dir+set}" = set; then : withval=$with_state_dir; mydataroot="$withval" else mydataroot="${localstatedir}/lib/${install_name}" fi # Check whether --with-data-file was given. if test "${with_data_file+set}" = set; then : withval=$with_data_file; mydatafile="$withval" tmp=`echo ${withval} | sed 's%^REQ_FROM_SERVER%%'` mydataroot=`echo ${tmp} | sed 's%/[^/][^/]*$%%'` myrpmdatafile="${tmp}" if test x"${tmp}" = x then echo "No local path in data file ${withval}" echo "This will not work for initializing the database." if test x"${withval}" = xREQ_FROM_SERVER then echo "It should be REQ_FROM_SERVER/some/local/path" fi as_fn_error $? "Option --with-data-file=FILE used with invalid path ${withval}." "$LINENO" 5 fi else mydatafile="${mydataroot}/${install_name}_file" myrpmdatafile="${mydatafile}" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_DATA_FILE _("${mydatafile}") _ACEOF cat >>confdefs.h <<_ACEOF #define DEFAULT_DATAROOT _("${mydataroot}") _ACEOF cat >>confdefs.h <<_ACEOF #define DEFAULT_QDIR _("${mydataroot}/.quarantine") _ACEOF # Check whether --with-html-file was given. if test "${with_html_file+set}" = set; then : withval=$with_html_file; myhtmlfile="$withval" else myhtmlfile="${mylogdir}/${install_name}.html" fi cat >>confdefs.h <<_ACEOF #define DEFAULT_HTML_FILE _("${myhtmlfile}") _ACEOF mydefargs=$ac_configure_args # if test -z "`echo "$mydefargs" | grep "\-\-enable\-static" 2> /dev/null`" # then # mydefargs="--enable-static $mydefargs" # fi if test -z "`echo "$mydefargs" | grep "\-\-enable\-base" 2> /dev/null`" then mydefargs="--enable-base=${mykeybase} $mydefargs" fi cat >>confdefs.h <<_ACEOF #define SH_INSTALL_DIR _("${sbindir}") _ACEOF cat >>confdefs.h <<_ACEOF #define SH_INSTALL_PATH _("${sbindir}/${install_name}") _ACEOF cat >>confdefs.h <<_ACEOF #define SH_INSTALL_NAME _("${install_name}") _ACEOF ac_config_headers="$ac_config_headers config.h" ac_config_files="$ac_config_files Makefile samhain-install.sh init/samhain.startLSB init/samhain.startLinux init/samhain.startGentoo init/samhain.startFreeBSD init/samhain.startSolaris init/samhain.startHPUX init/samhain.startIRIX init/samhain.startMACOSX samhain.spec rules.deb rules.deb-light hp_ux.psf scripts/logrotate scripts/samhain.spec scripts/redhat_i386.client.spec scripts/samhain.ebuild scripts/samhain.ebuild-light scripts/samhainadmin.pl scripts/yuleadmin.pl scripts/check_samhain.pl deploy.sh" ac_config_commands="$ac_config_commands default" 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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; 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 if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_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= U= 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=`$as_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. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $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} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } 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.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= 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 $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith 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 if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # 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 ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac 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 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_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 || $as_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" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # 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 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=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.69. 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 case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # 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_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent 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 the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 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' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. 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=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= 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 ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_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. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append 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 || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # 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" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "samhain-install.sh") CONFIG_FILES="$CONFIG_FILES samhain-install.sh" ;; "init/samhain.startLSB") CONFIG_FILES="$CONFIG_FILES init/samhain.startLSB" ;; "init/samhain.startLinux") CONFIG_FILES="$CONFIG_FILES init/samhain.startLinux" ;; "init/samhain.startGentoo") CONFIG_FILES="$CONFIG_FILES init/samhain.startGentoo" ;; "init/samhain.startFreeBSD") CONFIG_FILES="$CONFIG_FILES init/samhain.startFreeBSD" ;; "init/samhain.startSolaris") CONFIG_FILES="$CONFIG_FILES init/samhain.startSolaris" ;; "init/samhain.startHPUX") CONFIG_FILES="$CONFIG_FILES init/samhain.startHPUX" ;; "init/samhain.startIRIX") CONFIG_FILES="$CONFIG_FILES init/samhain.startIRIX" ;; "init/samhain.startMACOSX") CONFIG_FILES="$CONFIG_FILES init/samhain.startMACOSX" ;; "samhain.spec") CONFIG_FILES="$CONFIG_FILES samhain.spec" ;; "rules.deb") CONFIG_FILES="$CONFIG_FILES rules.deb" ;; "rules.deb-light") CONFIG_FILES="$CONFIG_FILES rules.deb-light" ;; "hp_ux.psf") CONFIG_FILES="$CONFIG_FILES hp_ux.psf" ;; "scripts/logrotate") CONFIG_FILES="$CONFIG_FILES scripts/logrotate" ;; "scripts/samhain.spec") CONFIG_FILES="$CONFIG_FILES scripts/samhain.spec" ;; "scripts/redhat_i386.client.spec") CONFIG_FILES="$CONFIG_FILES scripts/redhat_i386.client.spec" ;; "scripts/samhain.ebuild") CONFIG_FILES="$CONFIG_FILES scripts/samhain.ebuild" ;; "scripts/samhain.ebuild-light") CONFIG_FILES="$CONFIG_FILES scripts/samhain.ebuild-light" ;; "scripts/samhainadmin.pl") CONFIG_FILES="$CONFIG_FILES scripts/samhainadmin.pl" ;; "scripts/yuleadmin.pl") CONFIG_FILES="$CONFIG_FILES scripts/yuleadmin.pl" ;; "scripts/check_samhain.pl") CONFIG_FILES="$CONFIG_FILES scripts/check_samhain.pl" ;; "deploy.sh") CONFIG_FILES="$CONFIG_FILES deploy.sh" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; 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= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # 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. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[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="$ac_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 || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append 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 '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; 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 || $as_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"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_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 || ac_write_fail=1 # 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= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 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 || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;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 " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_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 "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "default":C) echo timestamp > stamp-h chmod +x samhain-install.sh chmod +x scripts/samhainadmin.pl chmod +x scripts/yuleadmin.pl chmod +x scripts/check_samhain.pl ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # 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 || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi chmod +x deploy.sh if test "x${cross_compiling}" = xyes then echo "--------------------------------------------------------------" echo echo "You are using a cross-compiler. The following system dependent" echo "values may have been set to default values that may be" echo "incorrect for your target system: " echo echo "ac_cv_c_bigendian bigendian byte order ${ac_cv_c_bigendian}" echo "ac_cv_c_long_double long double exists ${ac_cv_c_long_double}" echo "ac_cv_sizeof_char_p size of pointer to char ${ac_cv_sizeof_char_p}" echo "ac_cv_sizeof_char_p size of size_t ${ac_cv_sizeof_size_t}" echo "ac_cv_sizeof_unsigned_int size of unsigned int ${ac_cv_sizeof_unsigned_int}" echo "ac_cv_sizeof_unsigned_long size of unsigned long ${ac_cv_sizeof_unsigned_long}" echo "ac_cv_sizeof_unsigned_short size of unsigned short ${ac_cv_sizeof_unsigned_short}" echo echo "If these values are incorrect, change them in the file " echo "config.cache and run configure again." echo echo "--------------------------------------------------------------" fi if test x${silent} != xyes then # A=`eval echo ${sbindir}` ; A=`eval echo ${A}` # B=`eval echo ${myconffile}` ; B=`eval echo ${B}` # C=`eval echo ${mandir}` ; C=`eval echo ${C}` # D=`eval echo ${mylockfile}` ; D=`eval echo ${D}` # E=`eval echo ${mylogfile}` ; E=`eval echo ${E}` # F=`eval echo ${mydataroot}` ; F=`eval echo ${F}` echo echo " samhain has been configured as follows:" echo " System binaries: ${sbindir}" echo " Configuration file: ${myconffile}" echo " Manual pages: ${mandir}" echo " Data directory: ${mydataroot}" echo " Database file: ${mydatafile}" echo " PID file: ${mylockfile}" echo " Log file: ${mylogfile}" echo " Base key: ${mykeybase}" if test x"$mykeyid" != x then echo " target GPG/PGP key: ${mykeyid}" fi echo if test x"$mytclient" = x"-DSH_WITH_SERVER" then echo " Selected rc file: yulerc" else echo " Selected rc file: samhainrc.${selectconfig}" fi fi samhain-4.1.4/depend.dep0000664000175000017500000004544112724114744012032 00000000000000 # DO NOT DELETE THIS LINE samhain.o: $(srcsrc)/samhain.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_getopt.h $(srcinc)/sh_readconf.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_restrict.h $(srcinc)/sh_nmail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_mem.h $(srcinc)/sh_xfer.h $(srcinc)/sh_tools.h $(srcinc)/sh_hash.h $(srcinc)/sh_extern.h $(srcinc)/sh_modules.h $(srcinc)/sh_ignore.h $(srcinc)/sh_prelink.h $(srcinc)/sh_sem.h sh_MK.h $(srcinc)/sh_schedule.h sh_unix.o: $(srcsrc)/sh_unix.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_hash.h $(srcinc)/sh_tools.h $(srcinc)/sh_restrict.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_tiger.h $(srcinc)/sh_prelink.h $(srcinc)/sh_pthread.h $(srcinc)/sh_sem.h $(srcinc)/sh_static.h $(srcinc)/sh_prelude.h $(srcinc)/zAVLTree.h $(srcinc)/sh_ignore.h sh_utils.o: $(srcsrc)/sh_utils.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_entropy.h $(srcinc)/sh_pthread.h sh_error.o: $(srcsrc)/sh_error.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_database.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_nmail.h $(srcinc)/sh_xfer.h $(srcinc)/sh_prelude.h $(srcinc)/sh_pthread.h $(srcinc)/sh_tools.h $(srcinc)/sh_extern.h $(srcinc)/sh_checksum.h sh_files.o: $(srcsrc)/sh_files.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_tiger.h $(srcinc)/sh_hash.h $(srcinc)/sh_ignore.h $(srcinc)/sh_inotify.h $(srcinc)/zAVLTree.h $(srcinc)/sh_dbIO.h $(srcinc)/CuTest.h sh_getopt.o: $(srcsrc)/sh_getopt.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_getopt.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_utils.h $(srcinc)/sh_mail.h $(srcinc)/sh_xfer.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_dbCheck.h $(srcinc)/sh_dbCreate.h $(srcinc)/sh_sem.h $(srcinc)/sh_extern.h sh_readconf.o: $(srcsrc)/sh_readconf.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_calls.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_xfer.h $(srcinc)/sh_gpg.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_ignore.h $(srcinc)/sh_database.h $(srcinc)/sh_mail.h $(srcinc)/sh_modules.h $(srcinc)/sh_nmail.h $(srcinc)/sh_prelink.h $(srcinc)/sh_prelude.h $(srcinc)/sh_tiger.h $(srcinc)/sh_tools.h $(srcinc)/sh_utils.h $(srcinc)/sh_restrict.h $(srcinc)/sh_socket.h sh_tiger0.o: $(srcsrc)/sh_tiger0.c Makefile config_xor.h $(srcinc)/sh_tiger.h $(srcinc)/sh_unix.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_pthread.h $(srcinc)/sh_string.h $(srcinc)/sh_checksum.h sh_tiger1.o: $(srcsrc)/sh_tiger1.c Makefile config_xor.h sh_tiger2.o: $(srcsrc)/sh_tiger2.c Makefile config_xor.h sh_tiger1_64.o: $(srcsrc)/sh_tiger1_64.c Makefile config_xor.h sh_tiger2_64.o: $(srcsrc)/sh_tiger2_64.c Makefile config_xor.h sh_hash.o: $(srcsrc)/sh_hash.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_hash.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h $(srcinc)/sh_pthread.h $(srcinc)/sh_xfer.h $(srcinc)/sh_hash.h $(srcinc)/sh_checksum.h sh_mail.o: $(srcsrc)/sh_mail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_mail.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_pthread.h $(srcinc)/sh_filter.h $(srcinc)/sh_mail_int.h $(srcinc)/sh_nmail.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_static.h $(srcinc)/sh_tools.h sh_mem.o: $(srcsrc)/sh_mem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_pthread.h sh_entropy.o: $(srcsrc)/sh_entropy.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_calls.h $(srcinc)/sh_pthread.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h sh_forward.o: $(srcsrc)/sh_forward.c Makefile config_xor.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_forward.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/rijndael-api-fst.h $(srcinc)/sh_readconf.h $(srcinc)/zAVLTree.h $(srcinc)/sh_extern.h sh_modules.o: $(srcsrc)/sh_modules.c Makefile config_xor.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utmp.h $(srcinc)/sh_mounts.h $(srcinc)/sh_userfiles.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_portcheck.h $(srcinc)/sh_logmon.h $(srcinc)/sh_registry.h $(srcinc)/sh_fInotify.h sh_utmp.o: $(srcsrc)/sh_utmp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_utmp.h $(srcinc)/sh_pthread.h $(srcinc)/sh_inotify.h sh_kern.o: $(srcsrc)/sh_kern.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_kern.h sh_ks_xor.h $(srcinc)/sh_unix.h $(srcinc)/sh_hash.h sh_suidchk.o: $(srcsrc)/sh_suidchk.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_schedule.h $(srcinc)/sh_calls.h $(srcinc)/zAVLTree.h sh_srp.o: $(srcsrc)/sh_srp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_mem.h $(srcinc)/sh_utils.h $(srcinc)/sh_srp.h $(srcinc)/bignum.h $(srcinc)/CuTest.h sh_fifo.o: $(srcsrc)/sh_fifo.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_fifo.h $(srcinc)/CuTest.h sh_tools.o: $(srcsrc)/sh_tools.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error.h $(srcinc)/sh_tools.h $(srcinc)/sh_utils.h $(srcinc)/sh_tiger.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_ipvx.h $(srcinc)/rijndael-api-fst.h $(srcinc)/rijndael-api-fst.h sh_html.o: $(srcsrc)/sh_html.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_xfer.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_html.h $(srcinc)/zAVLTree.h sh_gpg.o: $(srcsrc)/sh_gpg.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_static.h $(srcinc)/sh_gpg.h sh_cat.o: $(srcsrc)/sh_cat.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_cat.h sh_calls.o: $(srcsrc)/sh_calls.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_calls.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_sub.h $(srcinc)/sh_utils.h sh_extern.o: $(srcsrc)/sh_extern.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_extern.h $(srcinc)/sh_calls.h $(srcinc)/sh_filter.h $(srcinc)/sh_static.h sh_database.o: $(srcsrc)/sh_database.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h sh_err_log.o: $(srcsrc)/sh_err_log.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_tiger.h sh_err_console.o: $(srcsrc)/sh_err_console.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_sem.h sh_err_syslog.o: $(srcsrc)/sh_err_syslog.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h sh_schedule.o: $(srcsrc)/sh_schedule.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error_min.h $(srcinc)/sh_schedule.h bignum.o: $(srcsrc)/bignum.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/bignum.h mkhdr.o: $(srcsrc)/mkhdr.c Makefile config.h samhain_setpwd.o: $(srcsrc)/samhain_setpwd.c Makefile config_xor.h samhain_stealth.o: $(srcsrc)/samhain_stealth.c Makefile config_xor.h encode.o: $(srcsrc)/encode.c Makefile sstrip.o: $(srcsrc)/sstrip.c Makefile config.h trustfile.o: $(srcsrc)/trustfile.c Makefile config_xor.h $(srcinc)/sh_calls.h $(srcinc)/slib.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h exepack.o: $(srcsrc)/exepack.c Makefile config.h $(srcinc)/minilzo.h $(srcinc)/exepack.data exepack_fill.o: $(srcsrc)/exepack_fill.c Makefile config.h config.h $(srcinc)/minilzo.h exepack_mkdata.o: $(srcsrc)/exepack_mkdata.c Makefile config.h $(srcinc)/minilzo.h minilzo.o: $(srcsrc)/minilzo.c Makefile $(srcinc)/minilzo.h slib.o: $(srcsrc)/slib.c Makefile config_xor.h $(srcinc)/slib.h $(srcinc)/sh_calls.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_string.h $(srcinc)/sh_mem.h rijndael-alg-fst.o: $(srcsrc)/rijndael-alg-fst.c Makefile config_xor.h $(srcinc)/rijndael-alg-fst.h rijndael-api-fst.o: $(srcsrc)/rijndael-api-fst.c Makefile config_xor.h $(srcinc)/rijndael-api-fst.h zAVLTree.o: $(srcsrc)/zAVLTree.c Makefile $(srcinc)/zAVLTree.h sh_socket.o: $(srcsrc)/sh_socket.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_socket.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_calls.h $(srcinc)/sh_guid.h $(srcinc)/sh_fifo.h $(srcinc)/sh_utils.h $(srcinc)/sh_utils.h $(srcinc)/zAVLTree.h $(srcinc)/sh_html.h $(srcinc)/sh_tools.h $(srcinc)/CuTest.h sh_ignore.o: $(srcsrc)/sh_ignore.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error.h $(srcinc)/CuTest.h yulectl.o: $(srcsrc)/yulectl.c Makefile config_xor.h sh_mounts.o: $(srcsrc)/sh_mounts.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_mounts.h sh_userfiles.o: $(srcsrc)/sh_userfiles.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_modules.h $(srcinc)/sh_userfiles.h $(srcinc)/sh_utils.h $(srcinc)/sh_schedule.h $(srcinc)/sh_error.h $(srcinc)/sh_hash.h $(srcinc)/sh_files.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h sh_prelude.o: $(srcsrc)/sh_prelude.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_error_min.h $(srcinc)/sh_prelude.h $(srcinc)/sh_static.h sh_prelink.o: $(srcsrc)/sh_prelink.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_extern.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h sh_static.o: $(srcsrc)/sh_static.c Makefile config_xor.h $(srcinc)/sh_pthread.h sh_portcheck.o: $(srcsrc)/sh_portcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_mem.h $(srcinc)/sh_calls.h $(srcinc)/sh_utils.h $(srcinc)/sh_modules.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_ipvx.h $(srcinc)/CuTest.h sh_processcheck.o: $(srcsrc)/sh_processcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_modules.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_calls.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h sh_prelude_old.o: $(srcsrc)/sh_prelude_old.c Makefile config_xor.h $(srcinc)/slib.h $(srcinc)/sh_mem.h $(srcinc)/sh_cat.h $(srcinc)/sh_error_min.h $(srcinc)/sh_prelude.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h sh_pthread.o: $(srcsrc)/sh_pthread.c Makefile config_xor.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_modules.h kern_head.o: $(srcsrc)/kern_head.c Makefile config.h $(srcinc)/kern_head.h $(srcinc)/kern_head.h sh_string.o: $(srcsrc)/sh_string.c Makefile config_xor.h $(srcinc)/sh_string.h $(srcinc)/sh_mem.h $(srcinc)/CuTest.h dnmalloc-1.0.beta5-rw.o: $(srcsrc)/dnmalloc-1.0.beta5-rw.c Makefile t-test1.o: $(srcsrc)/t-test1.c Makefile config.h $(srcinc)/malloc.h dnmalloc-portable.o: $(srcsrc)/dnmalloc-portable.c Makefile config.h dnmalloc.o: $(srcsrc)/dnmalloc.c Makefile config.h sh_port2proc.o: $(srcsrc)/sh_port2proc.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error_min.h $(srcinc)/sh_pthread.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_ipvx.h sh_log_parse_syslog.o: $(srcsrc)/sh_log_parse_syslog.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h sh_log_parse_pacct.o: $(srcsrc)/sh_log_parse_pacct.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h sh_log_parse_apache.o: $(srcsrc)/sh_log_parse_apache.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h sh_log_evalrule.o: $(srcsrc)/sh_log_evalrule.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/sh_log_correlate.h $(srcinc)/sh_log_mark.h $(srcinc)/sh_log_repeat.h $(srcinc)/zAVLTree.h sh_log_check.o: $(srcsrc)/sh_log_check.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/sh_log_correlate.h $(srcinc)/sh_log_mark.h $(srcinc)/sh_log_repeat.h $(srcinc)/sh_extern.h $(srcinc)/sh_modules.h sh_log_parse_samba.o: $(srcsrc)/sh_log_parse_samba.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_string.h sh_nmail.o: $(srcsrc)/sh_nmail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_mem.h $(srcinc)/sh_mail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_string.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_filter.h $(srcinc)/sh_mail_int.h $(srcinc)/zAVLTree.h sh_filter.o: $(srcsrc)/sh_filter.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_filter.h sh_inotify.o: $(srcsrc)/sh_inotify.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_inotify.h $(srcinc)/sh_mem.h $(srcinc)/sh_utils.h $(srcinc)/slib.h $(srcinc)/zAVLTree.h $(srcinc)/sh_calls.h $(srcinc)/sh_inotify.h $(srcinc)/CuTest.h sh_log_correlate.o: $(srcsrc)/sh_log_correlate.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h sh_log_mark.o: $(srcsrc)/sh_log_mark.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_mem.h $(srcinc)/sh_string.h $(srcinc)/sh_error_min.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/zAVLTree.h sh_log_repeat.o: $(srcsrc)/sh_log_repeat.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h sh_log_parse_generic.o: $(srcsrc)/sh_log_parse_generic.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_log_check.h $(srcinc)/sh_string.h sh_login_track.o: $(srcsrc)/sh_login_track.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_string.h $(srcinc)/sh_tools.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_error_min.h $(srcinc)/CuTest.h $(srcinc)/CuTest.h sh_audit.o: $(srcsrc)/sh_audit.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_utils.h sh_registry.o: $(srcsrc)/sh_registry.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_modules.h $(srcinc)/sh_hash.h $(srcinc)/sh_tiger.h sh_ipvx.o: $(srcsrc)/sh_ipvx.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_ipvx.h $(srcinc)/CuTest.h sh_restrict.o: $(srcsrc)/sh_restrict.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error_min.h $(srcinc)/sh_string.h $(srcinc)/sh_utils.h $(srcinc)/sh_restrict.h $(srcinc)/CuTest.h sh_filetype.o: $(srcsrc)/sh_filetype.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error_min.h $(srcinc)/sh_utils.h sh_sub.o: $(srcsrc)/sh_sub.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h sh_fInotify.o: $(srcsrc)/sh_fInotify.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/sh_inotify.h $(srcinc)/sh_unix.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h sh_checksum.o: $(srcsrc)/sh_checksum.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_checksum.h $(srcinc)/sh_utils.h $(srcinc)/CuTest.h sh_guid.o: $(srcsrc)/sh_guid.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/CuTest.h sh_dbIO.o: $(srcsrc)/sh_dbIO.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_gpg.h $(srcinc)/sh_tiger.h $(srcinc)/sh_xfer.h $(srcinc)/sh_pthread.h $(srcinc)/sh_socket.h $(srcinc)/sh_files.h $(srcinc)/zAVLTree.h sh_dbCheck.o: $(srcsrc)/sh_dbCheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_hash.h $(srcinc)/sh_files.h $(srcinc)/sh_tiger.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_pthread.h sh_dbCreate.o: $(srcsrc)/sh_dbCreate.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_hash.h $(srcinc)/sh_files.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_pthread.h $(srcinc)/sh_guid.h sh_xfer_client.o: $(srcsrc)/sh_xfer_client.c Makefile config_xor.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_xfer.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/rijndael-api-fst.h sh_xfer_server.o: $(srcsrc)/sh_xfer_server.c Makefile config_xor.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_xfer.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/sh_guid.h $(srcinc)/rijndael-api-fst.h $(srcinc)/sh_readconf.h $(srcinc)/zAVLTree.h $(srcinc)/sh_extern.h sh_xfer_syslog.o: $(srcsrc)/sh_xfer_syslog.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tools.h $(srcinc)/sh_utils.h $(srcinc)/sh_ipvx.h sh_xload_client.o: $(srcsrc)/sh_xload_client.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_guid.h sh_sem.o: $(srcsrc)/sh_sem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_sem.h $(srcinc)/sh_error_min.h samhain-4.1.4/scripts/0000755000175000017500000000000012724114744011636 500000000000000samhain-4.1.4/scripts/makeself/0000755000175000017500000000000012615253277013431 500000000000000samhain-4.1.4/scripts/makeself/makeself.sh0000755000175000017500000002357312543560174015506 00000000000000#!/bin/sh # # Makeself version 2.1.x # by Stephane Peter # # $Id: makeself.sh,v 1.44 2004/04/23 18:28:48 megastep Exp $ # # Utility to create self-extracting tar.gz archives. # The resulting archive is a file holding the tar.gz archive with # a small Shell script stub that uncompresses the archive to a temporary # directory and then executes a given script from withing that directory. # # Makeself home page: http://www.megastep.org/makeself/ # # Version 2.0 is a rewrite of version 1.0 to make the code easier to read and maintain. # # Version history : # - 1.0 : Initial public release # - 1.1 : The archive can be passed parameters that will be passed on to # the embedded script, thanks to John C. Quillan # - 1.2 : Package distribution, bzip2 compression, more command line options, # support for non-temporary archives. Ideas thanks to Francois Petitjean # - 1.3 : More patches from Bjarni R. Einarsson and Francois Petitjean: # Support for no compression (--nocomp), script is no longer mandatory, # automatic launch in an xterm, optional verbose output, and -target # archive option to indicate where to extract the files. # - 1.4 : Improved UNIX compatibility (Francois Petitjean) # Automatic integrity checking, support of LSM files (Francois Petitjean) # - 1.5 : Many bugfixes. Optionally disable xterm spawning. # - 1.5.1 : More bugfixes, added archive options -list and -check. # - 1.5.2 : Cosmetic changes to inform the user of what's going on with big # archives (Quake III demo) # - 1.5.3 : Check for validity of the DISPLAY variable before launching an xterm. # More verbosity in xterms and check for embedded command's return value. # Bugfix for Debian 2.0 systems that have a different "print" command. # - 1.5.4 : Many bugfixes. Print out a message if the extraction failed. # - 1.5.5 : More bugfixes. Added support for SETUP_NOCHECK environment variable to # bypass checksum verification of archives. # - 1.6.0 : Compute MD5 checksums with the md5sum command (patch from Ryan Gordon) # - 2.0 : Brand new rewrite, cleaner architecture, separated header and UNIX ports. # - 2.0.1 : Added --copy # - 2.1.0 : Allow multiple tarballs to be stored in one archive, and incremental updates. # Added --nochown for archives # Stopped doing redundant checksums when not necesary # - 2.1.1 : Work around insane behavior from certain Linux distros with no 'uncompress' command # Cleaned up the code to handle error codes from compress. Simplified the extraction code. # - 2.1.2 : Some bug fixes. Use head -n to avoid problems. # - 2.1.3 : Bug fixes with command line when spawning terminals. # Added --tar for archives, allowing to give arbitrary arguments to tar on the contents of the archive. # Added --noexec to prevent execution of embedded scripts. # Added --nomd5 and --nocrc to avoid creating checksums in archives. # Added command used to create the archive in --info output. # Run the embedded script through eval. # # (C) 1998-2004 by Stphane Peter # # This software is released under the terms of the GNU GPL # Please read the license at http://www.gnu.org/copyleft/gpl.html # MS_VERSION=2.1.3 # Procedures MS_Usage() { echo "Usage: $0 [params] archive_dir file_name label [startup_script] [args]" echo "params can be one or more of the following :" echo " --version | -v : Print out Makeself version number and exit" echo " --help | -h : Print out this help message" echo " --gzip : Compress using gzip (default if detected)" echo " --bzip2 : Compress using bzip2 instead of gzip" echo " --compress : Compress using the UNIX 'compress' command" echo " --nocomp : Do not compress the data" echo " --notemp : The archive will create archive_dir in the" echo " current directory and uncompress in ./archive_dir" echo " --copy : Upon extraction, the archive will first copy itself to" echo " a temporary directory" echo " --append : Append more files to an existing Makeself archive" echo " The label and startup scripts will then be ignored" echo " --current : Files will be extracted to the current directory." echo " Implies --notemp." echo " --nomd5 : Don't calculate an MD5 for archive" echo " --nocrc : Don't calculate a CRC for archive" echo " --header file : Specify location of the header script" echo " --follow : Follow the symlinks in the archive" echo " --nox11 : Disable automatic spawn of a xterm" echo " --nowait : Do not wait for user input after executing embedded" echo " program from an xterm" echo " --lsm file : LSM file describing the package" echo echo "Do not forget to give a fully qualified startup script name" echo "(i.e. with a ./ prefix if inside the archive)." exit 1 } # Default settings if type gzip 2>&1 > /dev/null; then COMPRESS=gzip else COMPRESS=Unix fi KEEP=n CURRENT=n NOX11=n APPEND=n COPY=none TAR_ARGS=cvf HEADER=`dirname $0`/makeself-header.sh # LSM file stuff LSM_CMD="echo No LSM. >> \"\$archname\"" while true do case "$1" in --version | -v) echo Makeself version $MS_VERSION exit 0 ;; --bzip2) COMPRESS=bzip2 shift ;; --gzip) COMPRESS=gzip shift ;; --compress) COMPRESS=Unix shift ;; --nocomp) COMPRESS=none shift ;; --notemp) KEEP=y shift ;; --copy) COPY=copy shift ;; --current) CURRENT=y KEEP=y shift ;; --header) HEADER="$2" shift 2 ;; --follow) TAR_ARGS=cvfh shift ;; --nox11) NOX11=y shift ;; --nowait) shift ;; --nomd5) NOMD5=y shift ;; --nocrc) NOCRC=y shift ;; --append) APPEND=y shift ;; --lsm) LSM_CMD="cat \"$2\" >> \"\$archname\"" shift 2 ;; -h | --help) MS_Usage ;; -*) echo Unrecognized flag : "$1" MS_Usage ;; *) break ;; esac done archdir="$1" archname="$2" MS_COMMAND="$0 $*" if test "$APPEND" = y; then if test $# -lt 2; then MS_Usage fi # Gather the info from the original archive OLDENV=`sh "$archname" --dumpconf` if test $? -ne 0; then echo "Unable to update archive: $archname" >&2 exit 1 else eval "$OLDENV" fi else if test "$KEEP" = n -a $# = 3; then echo "ERROR: Making a temporary archive with no embedded command does not make sense!" >&2 echo MS_Usage fi # We don't really want to create an absolute directory... if test "$CURRENT" = y; then archdirname="." else archdirname=`basename "$1"` fi if test $# -lt 3; then MS_Usage fi LABEL="$3" SCRIPT="$4" test x$SCRIPT = x || shift 1 shift 3 SCRIPTARGS="$*" fi if test "$KEEP" = n -a "$CURRENT" = y; then echo "ERROR: It is A VERY DANGEROUS IDEA to try to combine --notemp and --current." >&2 exit 1 fi case $COMPRESS in gzip) GZIP_CMD="gzip -c9" GUNZIP_CMD="gzip -cd" ;; bzip2) GZIP_CMD="bzip2 -9" GUNZIP_CMD="bzip2 -d" ;; Unix) GZIP_CMD="compress -cf" GUNZIP_CMD="exec 2>&-; uncompress -c || test \\\$? -eq 2 || gzip -cd" ;; none) GZIP_CMD="cat" GUNZIP_CMD="cat" ;; esac tmpfile="${TMPDIR:=/tmp}/mkself$$" if test -f $HEADER; then oldarchname="$archname" archname="$tmpfile" # Generate a fake header to count its lines SKIP=0 . $HEADER SKIP=`cat "$tmpfile" |wc -l` # Get rid of any spaces SKIP=`expr $SKIP` rm -f "$tmpfile" echo Header is $SKIP lines long >&2 archname="$oldarchname" else echo "Unable to open header file: $HEADER" >&2 exit 1 fi echo if test "$APPEND" = n; then if test -f "$archname"; then echo "WARNING: Overwriting existing file: $archname" >&2 fi fi test -d "$archdir" || { echo "Error: $archdir does not exist."; rm -f "$tmpfile"; exit 1; } USIZE=`du -ks $archdir | cut -f1` DATE=`LC_ALL=C date` echo About to compress $USIZE KB of data... echo Adding files to archive named \"$archname\"... (cd "$archdir"; tar $TAR_ARGS - * | eval "$GZIP_CMD" ) >> "$tmpfile" || { echo Aborting; rm -f "$tmpfile"; exit 1; } echo >> "$tmpfile" >&- # try to close the archive fsize=`cat "$tmpfile" | wc -c | tr -d " "` # Compute the checksums md5sum=00000000000000000000000000000000 crcsum=0000000000 if test "$NOCRC" = y; then echo "skipping crc at user request" else crcsum=`cat "$tmpfile" | cksum | sed -e 's/ /Z/' -e 's/ /Z/' | cut -dZ -f1` echo "CRC: $crcsum" fi # Try to locate a MD5 binary OLD_PATH=$PATH PATH=${GUESS_MD5_PATH:-"$OLD_PATH:/bin:/usr/bin:/sbin:/usr/local/ssl/bin:/usr/local/bin:/opt/openssl/bin"} MD5_PATH=`type -p md5sum` MD5_PATH=${MD5_PATH:-`type -p md5`} PATH=$OLD_PATH if test "$NOMD5" = y; then echo "skipping md5sum at user request" else if test -x "$MD5_PATH"; then md5sum=`cat "$tmpfile" | "$MD5_PATH" | cut -b-32`; echo "MD5: $md5sum" else echo "MD5: none, md5sum binary not found" fi fi if test "$APPEND" = y; then mv "$archname" "$archname".bak || exit # Prepare entry for new archive filesizes="$filesizes $fsize" CRCsum="$CRCsum $crcsum" MD5sum="$MD5sum $md5sum" USIZE=`expr $USIZE + $OLDUSIZE` # Generate the header . $HEADER # Append the original data tail -n +$OLDSKIP "$archname".bak >> "$archname" # Append the new data cat "$tmpfile" >> "$archname" chmod +x "$archname" rm -f "$archname".bak echo Self-extractible archive \"$archname\" successfully updated. else filesizes="$fsize" CRCsum="$crcsum" MD5sum="$md5sum" # Generate the header . $HEADER # Append the compressed tar data after the stub echo cat "$tmpfile" >> "$archname" chmod +x "$archname" echo Self-extractible archive \"$archname\" successfully created. fi rm -f "$tmpfile" samhain-4.1.4/scripts/makeself/makeself-header.sh0000755000175000017500000002077512543560174016735 00000000000000cat << EOF > "$archname" #!/bin/sh # This script was generated using Makeself $MS_VERSION CRCsum="$CRCsum" MD5="$MD5sum" TMPROOT=\${TMPDIR:=/tmp} label="$LABEL" script="$SCRIPT" scriptargs="$SCRIPTARGS" targetdir="$archdirname" filesizes="$filesizes" keep=$KEEP print_cmd_arg="" if type printf > /dev/null; then print_cmd="printf" elif test -x /usr/ucb/echo; then print_cmd="/usr/ucb/echo" else print_cmd="echo" fi MS_Printf() { \$print_cmd \$print_cmd_arg "\$1" } MS_Progress() { while read a; do MS_Printf . done } MS_dd() { blocks=\`expr \$3 / 1024\` bytes=\`expr \$3 % 1024\` dd if="\$1" ibs=\$2 skip=1 obs=1024 conv=sync 2> /dev/null | \\ { test \$blocks -gt 0 && dd ibs=1024 obs=1024 count=\$blocks ; \\ test \$bytes -gt 0 && dd ibs=1 obs=1024 count=\$bytes ; } 2> /dev/null } MS_Help() { cat << EOH >&2 Makeself version $MS_VERSION 1) Getting help or info about \$0 : \$0 --help Print this message \$0 --info Print embedded info : title, default target directory, embedded script ... \$0 --lsm Print embedded lsm entry (or no LSM) \$0 --list Print the list of files in the archive \$0 --check Checks integrity of the archive 2) Running \$0 : \$0 [options] [--] [additional arguments to embedded script] with following options (in that order) --confirm Ask before running embedded script --noexec Do not run embedded script --keep Do not erase target directory after running the embedded script --nox11 Do not spawn an xterm --nochown Do not give the extracted files to the current user --target NewDirectory Extract in NewDirectory --tar arg1 [arg2 ...] Access the contents of the archive through the tar command -- Following arguments will be passed to the embedded script EOH } MS_Check() { OLD_PATH=\$PATH PATH=\${GUESS_MD5_PATH:-"\$OLD_PATH:/bin:/usr/bin:/sbin:/usr/local/ssl/bin:/usr/local/bin:/opt/openssl/bin"} MD5_PATH=\`exec 2>&-; which md5sum || type md5sum\` MD5_PATH=\${MD5_PATH:-\`exec 2>&-; which md5 || type md5\`} PATH=\$OLD_PATH MS_Printf "Verifying archive integrity..." offset=\`head -n $SKIP "\$1" | wc -c | tr -d " "\` verb=\$2 i=1 for s in \$filesizes do crc=\`echo \$CRCsum | cut -d" " -f\$i\` if test -x "\$MD5_PATH"; then md5=\`echo \$MD5 | cut -d" " -f\$i\` if test \$md5 = "00000000000000000000000000000000"; then test x\$verb = xy && echo " \$1 does not contain an embedded MD5 checksum." >&2 else md5sum=\`MS_dd "\$1" \$offset \$s | "\$MD5_PATH" | cut -b-32\`; if test "\$md5sum" != "\$md5"; then echo "Error in MD5 checksums: \$md5sum is different from \$md5" >&2 exit 2 else test x\$verb = xy && MS_Printf " MD5 checksums are OK." >&2 fi crc="0000000000"; verb=n fi fi if test \$crc = "0000000000"; then test x\$verb = xy && echo " \$1 does not contain a CRC checksum." >&2 else sum1=\`MS_dd "\$1" \$offset \$s | cksum | awk '{print \$1}'\` if test "\$sum1" = "\$crc"; then test x\$verb = xy && MS_Printf " CRC checksums are OK." >&2 else echo "Error in checksums: \$sum1 is different from \$crc" exit 2; fi fi i=\`expr \$i + 1\` offset=\`expr \$offset + \$s\` done echo " All good." } UnTAR() { tar \$1vf - 2>&1 || { echo Extraction failed. > /dev/tty; kill -15 \$$; } } finish=true xterm_loop= nox11=$NOX11 copy=$COPY ownership=y verbose=n initargs="\$@" while true do case "\$1" in -h | --help) MS_Help exit 0 ;; --info) echo Identification: "\$label" echo Target directory: "\$targetdir" echo Uncompressed size: $USIZE KB echo Compression: $COMPRESS echo Date of packaging: $DATE echo Built with Makeself version $MS_VERSION on $OSTYPE echo Build command was: "$MS_COMMAND" if test x\$script != x; then echo Script run after extraction: echo " " \$script \$scriptargs fi if test x"$copy" = xcopy; then echo "Archive will copy itself to a temporary location" fi if test x"$KEEP" = xy; then echo "directory \$targetdir is permanent" else echo "\$targetdir will be removed after extraction" fi exit 0 ;; --dumpconf) echo LABEL=\"\$label\" echo SCRIPT=\"\$script\" echo SCRIPTARGS=\"\$scriptargs\" echo archdirname=\"$archdirname\" echo KEEP=$KEEP echo COMPRESS=$COMPRESS echo filesizes=\"\$filesizes\" echo CRCsum=\"\$CRCsum\" echo MD5sum=\"\$MD5\" echo OLDUSIZE=$USIZE echo OLDSKIP=`expr $SKIP + 1` exit 0 ;; --lsm) cat << EOLSM EOF eval "$LSM_CMD" cat << EOF >> "$archname" EOLSM exit 0 ;; --list) echo Target directory: \$targetdir offset=\`head -n $SKIP "\$0" | wc -c | tr -d " "\` for s in \$filesizes do MS_dd "\$0" \$offset \$s | eval "$GUNZIP_CMD" | UnTAR t offset=\`expr \$offset + \$s\` done exit 0 ;; --tar) offset=\`head -n $SKIP "\$0" | wc -c | tr -d " "\` arg1="\$2" shift 2 for s in \$filesizes do MS_dd "\$0" \$offset \$s | eval "$GUNZIP_CMD" | tar "\$arg1" - \$* offset=\`expr \$offset + \$s\` done exit 0 ;; --check) MS_Check "\$0" y exit 0 ;; --confirm) verbose=y shift ;; --noexec) script="" shift ;; --keep) keep=y shift ;; --target) keep=y targetdir=\${2:-.} shift 2 ;; --nox11) nox11=y shift ;; --nochown) ownership=n shift ;; --xwin) finish="echo Press Return to close this window...; read junk" xterm_loop=1 shift ;; --phase2) copy=phase2 shift ;; --) shift break ;; -*) echo Unrecognized flag : "\$1" >&2 MS_Help exit 1 ;; *) break ;; esac done case "\$copy" in copy) SCRIPT_COPY="\$TMPROOT/makeself\$\$" echo "Copying to a temporary location..." >&2 cp "\$0" "\$SCRIPT_COPY" chmod +x "\$SCRIPT_COPY" cd "\$TMPROOT" exec "\$SCRIPT_COPY" --phase2 ;; phase2) finish="\$finish ; rm -f \$0" ;; esac if test "\$nox11" = "n"; then if tty -s; then # Do we have a terminal? : else if test x"\$DISPLAY" != x -a x"\$xterm_loop" = x; then # No, but do we have X? if xset q > /dev/null 2>&1; then # Check for valid DISPLAY variable GUESS_XTERMS="xterm rxvt dtterm eterm Eterm kvt konsole aterm" for a in \$GUESS_XTERMS; do if type \$a >/dev/null 2>&1; then XTERM=\$a break fi done chmod a+x \$0 || echo Please add execution rights on \$0 if test \`echo "\$0" | cut -c1\` = "/"; then # Spawn a terminal! exec \$XTERM -title "\$label" -e "\$0" --xwin "\$initargs" else exec \$XTERM -title "\$label" -e "./\$0" --xwin "\$initargs" fi fi fi fi fi if test "\$targetdir" = "."; then tmpdir="." else if test "\$keep" = y; then echo "Creating directory \$targetdir" >&2 tmpdir="\$targetdir" else tmpdir="\$TMPROOT/selfgz\$\$" fi mkdir -p \$tmpdir || { echo 'Cannot create target directory' \$tmpdir >&2 echo 'You should try option --target OtherDirectory' >&2 eval \$finish exit 1 } fi location="\`pwd\`" if test x\$SETUP_NOCHECK != x1; then MS_Check "\$0" fi offset=\`head -n $SKIP "\$0" | wc -c | tr -d " "\` if test x"\$verbose" = xy; then MS_Printf "About to extract $USIZE KB in \$tmpdir ... Proceed ? [Y/n] " read yn if test x"\$yn" = xn; then eval \$finish; exit 1 fi fi MS_Printf "Uncompressing \$label" res=3 if test "\$keep" = n; then trap 'echo Signal caught, cleaning up >&2; cd \$TMPROOT; /bin/rm -rf \$tmpdir; eval \$finish; exit 15' 1 2 3 15 fi for s in \$filesizes do if MS_dd "\$0" \$offset \$s | eval "$GUNZIP_CMD" | ( cd "\$tmpdir"; UnTAR x ) | MS_Progress; then if test x"\$ownership" = xy; then (PATH=/usr/xpg4/bin:\$PATH; cd "\$tmpdir"; chown -R \`id -u\` .; chgrp -R \`id -g\` .) fi else echo echo "Unable to decompress \$0" >&2 eval \$finish; exit 1 fi offset=\`expr \$offset + \$s\` done echo cd "\$tmpdir" res=0 if test x"\$script" != x; then if test x"\$verbose" = xy; then MS_Printf "OK to execute: \$script \$scriptargs \$* ? [Y/n] " read yn if test x"\$yn" = x -o x"\$yn" = xy -o x"\$yn" = xY; then eval \$script \$scriptargs \$*; res=\$?; fi else eval \$script \$scriptargs \$*; res=\$? fi if test \$res -ne 0; then test x"\$verbose" = xy && echo "The program '\$script' returned an error code (\$res)" >&2 fi fi if test "\$keep" = n; then cd \$TMPROOT /bin/rm -rf \$tmpdir fi eval \$finish; exit \$res EOF samhain-4.1.4/scripts/example_pager.pl0000755000175000017500000001506512615253277014742 00000000000000#!/usr/bin/perl -w # # # Simple program to connect to: # http://www2.pagemart.com/cgi-bin/rbox/pglpage-cgi # and send a page. # # Modified 10/21/99 Will O'Brien willo@savvis.net # Originally Written by David Allen s2mdalle@titan.vcu.edu # http://opop.nols.com/ # # # Modified by R. Wichmann (read message from stdin) # # # - added config variables # - read MESSAGE from STDIN # # This file is released under the terms of the GNU General Public License. # Please see http://www.gnu.org for more details. # # This program still beta, but working better. # # Changelog: # 10/21/99: Modified original code and get paging to function. # 10/22/99: Fixed Error checking. Checks PIN length, outputs failure message. # # REQUIRES MODULES: strict and IO::Socket # # USAGE FROM COMMAND LINE: echo "message" | example_pager.pl PAGER_PIN # Where PAGER_PIN is the PIN of the pager you want to send MESSAGE to. # # This program will send the page using # www.pagemart.com/cgi-bin/rbox/pglpage-cgi # and will store the response in LASTRESPONSE.html when the server replies. # # If you are looking at this program for examples of code to make it work, # check out the page{} subroutine below - it is the meat of this program. ############################################################################## # use Socket; # INET use strict; use IO::Socket; # Socket work my $pagerid = shift; ########################## -- BEGIN CONFIGURATION -- ## set to 1 for verbose output my $verbose = 1; ## set to 1 if you want to save response my $save_response = 1; ## set to 1 to enable sending my $really_send = 0; ########################### -- END CONFIGURATION -- # previous #my $MESSAGE = join(' ', @ARGV); my $MESSAGE=''; undef $/; $MESSAGE=; $MESSAGE =~ s/\[EOF\]//g; die "Usage: echo \"message\" \| example_pager.pl PAGER_ID\n\n" unless $pagerid; die "Usage: echo \"message\" \| example_pager.pl PAGER_ID\n\n" unless $MESSAGE; page($pagerid, $MESSAGE); if ($verbose) { print "Done.\n"; } exit(0); ############################################################################ sub page{ my ($name, $text) = @_; my $TRUNCATED = 0; my $PAGE = ""; # The text sent to www.pagemart.com - appended later. $pagerid = $name; if ($verbose) { print STDERR "Processing pager ID...\n"; } # Eliminate everything but numbers from the pager id $pagerid =~ s/[^0-9]//g; # Check the pager id length and so on. if( (((length($pagerid)) < 7)) || ((length($pagerid)) > 10) ) { if ($verbose) { die "Bad pager ID number. A pager id number is 7 or 10 numbers.\n"; } else { exit (1); } } if ($verbose) { die "No message specified.\n" unless $text; } else { exit (1) unless $text; } # This is the format of the message we're going to send via the TCP # socket # POST /cgi-bin/rbox/pglpage-cgi HTTP/1.0 # User-Agent: Myprogram/1.00 # Accept: */* # Content-length: 35 # Content-type: application/x-www-form-urlencoded # # pin2=6807659&message1=stuff+and+nonsense if ($verbose) { print STDERR "Processing text of message...\n"; } # A bit of string pre-processing chomp $text; my $strdelim = "\r\n"; # At the end of each line. # Compress the text a bit - eliminate redundant characters - this # helps a lot for pages that have multiple spaces and so on. $text =~s/\n/ /g; # Linefeeds are spaces $text =~s/\r//g; # No carriage returns $text =~s/\s+/ /g; # Multiple whitespace -> one space. if(length($text)>=200) { $TRUNCATED = "True"; $text = substr($text, 0, 199); # 200 Character maximum } my $encodedmessage = urlencode($text); # The length of the request has to be TOTAL QUERY. If it's just # the length of the string you're sending, it will truncate the # hell out of the page. So the pager number is length($pagerid) # of course the length of the message, and add the length of the # parameter flags, (PIN= and ?MSSG=) and you're done. my $xxmsg = "pin2=$pagerid&"; $xxmsg .= "PAGELAUNCHERID=1&"; $xxmsg .= $encodedmessage; # my $pagelen=length($encodedmessage)+length("pin2=?message1=")+ # length($pagerid)+; my $pagelen = length($xxmsg); # Build the text we send to the server $PAGE = "POST /cgi-bin/rbox/pglpage-cgi HTTP/1.0$strdelim"; $PAGE .= "User-Agent: Pagent/5.4$strdelim"; $PAGE .= "Referer: http://www.weblinkwireless.com/productsnservices/sendingmessage/pssm-sendamessage.html$strdelim"; $PAGE .= "Accept: */*$strdelim"; $PAGE .= "Content-length: $pagelen$strdelim"; $PAGE .= "Content-type: application/x-www-form-urlencoded$strdelim"; $PAGE .= "$strdelim"; # $PAGE .= "pin2=$pagerid&message1=".$encodedmessage; $PAGE .= $xxmsg; if ($verbose) { print STDERR "Sending message...\n\n"; print STDERR "$PAGE\n\n"; } my $document=''; if ($really_send) { # Now we send our data. # Note that this is just quick and dirty, so I'm using a perl module # to do the network dirty work for me. my $sock = IO::Socket::INET->new(PeerAddr => 'www2.pagemart.com', PeerPort => 'http(80)', Proto => 'tcp'); if ($verbose) { die "Cannot create socket : $!" unless $sock; } else { exit (1) unless $sock; } $sock->autoflush(); $sock->print("$PAGE"); $document = join('', $sock->getlines()); } else { $document = " really_send was set to 0, page NOT sent"; } if ($save_response) { if ($verbose) { print STDERR "Saving response to tmp.html...\n\n"; } my $status = 0; open(TMP,">tmp.html") or $status=1; print TMP "$document\n" unless $status; close TMP unless $status; } if($document =~ m/NOT/g) { if ($verbose) { print STDERR "Page not sent. There was an error. \n"; print STDERR "See tmp.html for what the server sent back to me.\n"; } exit(0); } # End if else { if ($verbose) { $document =~ m/(\d{1,4}) character message out of/g; print STDERR "Page sent successfully to $pagerid.\n"; } exit(0); } # End else } # End sub page ############################################################################ sub urlencode{ my $text = shift; my $input = $text; chomp $input; # Translate all non-letter non-number characters into their %HEX_VAL # and return that string. $input =~ s/([^a-zA-Z0-9-_\.\/])/uc sprintf("%%%02x",ord($1))/eg; $input =~ s/%20/+/g; return $input; } # End sub urlencode samhain-4.1.4/scripts/redhat_i386.client.spec.in0000644000175000017500000001400112616325646016335 00000000000000# # Accepted parameters for 'rpmbuild': # # --with tests - make tests before building Summary: File integrity and host-based IDS Name: samhain-client Version: @VERSION@ Release: 5 License: GPL Group: System Environment/Base Source: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/samhain-client-%{version}-root Packager: Andre Oliveira da Costa Provides: %{name} %description samhain is an open source file integrity and host-based intrusion detection system for Linux and Unix. It can run as a daemon process, and and thus can remember file changes -- contrary to a tool that runs from cron, if a file is modified you will get only one report, while subsequent checks of that file will ignore the modification as it is already reported (unless the file is modified again). samhain can optionally be used as client/server system to provide centralized monitoring for multiple host. Logging to a (MySQL or PostgreSQL) database is supported. NOTE: for security reasons, if you distribute binary executables to third parties you should point out the use of the --add-key option to modify the key material within the executable. This spec file is intended to facilitate installation on YOUR system. If you use this spec file to build a SRPM for distribution to third parties, make sure to remove the --enable-base configure option below. %prep %setup -q %build %if %{?_with_tests:1}%{!?_with_tests:0} # test installation (test #7 is only included if --with gpg has been # specified) for i in `seq 6` %{?_with_gpg:7}; do ./test/test.sh $i; done %endif # #./configure --prefix=%{_usr} \ # --sysconfdir=%{_sysconfdir} \ # --localstatedir=%{_localstatedir} \ # --mandir=%{_mandir} # ./configure '--enable-network=client' \ '--with-port=@myport@' \ '--with-logserver=@mylogsrv@' \ '--with-data-file=REQ_FROM_SERVER/etc/samclient.data' \ '--with-config-file=REQ_FROM_SERVER/etc/samclient.conf' \ '--with-kcheck=/boot/System.map' \ '--enable-khide=/boot/System.map' \ '--enable-suidcheck' \ '--enable-static' \ '--enable-login-watch' \ '--enable-ptrace' \ '--enable-db-reload' \ '--enable-base=@my_key_A@,@my_key_B@' \ '--enable-xml-log' make %install rm -rf ${RPM_BUILD_ROOT} # sstrip shouldn't be used since binaries will be stripped later cat << EOF > sstrip #!/bin/sh echo "*** SSTRIP DISABLED ***" EOF make DESTDIR=${RPM_BUILD_ROOT} install # copy script files to /var/lib/samhain so that we can use them right # after the package is installed install -m 700 samhain-install.sh init/samhain.startLinux init/samhain.startLSB ${RPM_BUILD_ROOT}/etc install -m 640 -o 0 -g 0 samhain_kmem.ko ${RPM_BUILD_ROOT}/lib/modules/`uname -r`/samhain_kmem.ko install -m 640 -o 0 -g 0 samhain_hide.ko ${RPM_BUILD_ROOT}/lib/modules/`uname -r`/samhain_hide.ko install -m 700 -o 0 -g 0 samhain_setpwd ${RPM_BUILD_ROOT}/usr/local/sbin/samhain_setpwd %clean rm -rf ${RPM_BUILD_ROOT} %post if [ "$1" = 1 ]; then # Activate boot-time start up cd /etc ./samhain-install.sh --verbose install-boot if test -f /sbin/chkconfig; then /sbin/chkconfig --add samhain fi fi rm -rf /etc/samclient.conf rm -rf /etc/samhain.startLinux rm -rf /etc/samhain.startLSB cat << EOF Samhain is installed but is NOT running yet, and the database of file signatures is NOT initialized yet. Read the documentation, review configuration files, and then (i) initialize it (/usr/local/sbin/samhain -t init) and (ii) start it manually (/usr/local/sbin/samhain start). It is configured to start automatically on the next boot for runlevels [2-5]. EOF %preun # stop running instance of samhain, if any if [ -f /var/run/%{name}.pid ]; then /usr/local/sbin/samhain stop fi if [ "$1" = 0 ]; then # remove boot-time scripts and links cd /etc ./samhain-install.sh --verbose uninstall-boot fi %files %defattr(-,root,root) %dir /var/run %dir /var/log #%doc docs/BUGS COPYING docs/Changelog #%doc LICENSE docs/HOWTO* docs/MANUAL-2_4.* docs/README* /etc /usr/local/sbin/samhain /usr/local/sbin/samhain_setpwd /lib/modules %attr(644,root,root) /etc/logrotate.d/@install_name@ #%attr(644,root,root) /usr/local/man/man5/samhain* #%attr(644,root,root) /usr/local/man/man8/samhain* #%config(noreplace) REQ_FROM_SERVER/etc/samclient.conf %changelog * Thu Apr 3 2003 Rainer Wichmann - adapt for configure * Wed Mar 26 2003 Philipp Stadler - add samhain modules installation - stops installation of documentation to server - replace %config entry for /etc/samclient.conf - remove samhain.startLinux and samhain.startLSB after installation * Sun Jan 12 2003 Rainer Wichmann - replace %configure with ./configure * Tue Dec 24 2002 Rainer Wichmann - backported applicable changes to samhain.spec.in - warn user that database must be initialized - fix version of MANUAL in '%files' - test for chkconfig, use only if found * Sun Dec 22 2002 Andre Oliveira da Costa 1.7.0 - fixed typo with _usr macro on ./configure - stops running samhain before uninstall - implemented conditionals to allow proper uninstalls/upgrades - 'BuildPreReq: gpg' is considered only if '--with gpg' is provided - run 'chkconfig' to activate samhain after installation - warn user that samhain must be manually started after install/upgrade * Fri Dec 20 2002 Rainer Wichmann - backported to samhain.spec.in (take over user's choices from configure) - also save samhain.startLSB and samhain.startSuSE for install-boot * Thu Dec 19 2002 Andre Oliveira da Costa 1.6.6 - optional parameters '--with gpg' and '--with tests' - use of pre-defined macros whenever possible * Wed Dec 18 2002 Andre Oliveira da Costa 1.6.6 - Fixed installation process, avoiding hardcoded paths on the binaries (thks to samhain's author Rainer Wichmann) * Mon Dec 16 2002 Andre Oliveira da Costa 1.6.6 - First attempt to build from sources samhain-4.1.4/scripts/example_sms.pl0000755000175000017500000001254012615253277014441 00000000000000#!/usr/bin/perl -w use strict; use IO::Socket; # Socket work ############################################################################### ## ## example_sms.pl -- simple example script to send ## an SMS message via a web cgi ## Works with German pitcom powered free SMS sites ## - find one and look at the page source to set the ## pitcom variables (see below) ## - note that pitcom checks the referer, thus you should ## take care to set the proper value ## ## NOTE: while the 'big names' have implemented measures to prevent ## the use of automated scripts, and disallow such scripts ## explicitely in their TOS (Terms of Service), this is not ## neccesarily true for smaller websites. ## ## An example for the latter are German websites providing free ## SMS (to German nets only) powered by pitcom. ## With a suitable query, you may find such sites on (e.g.) Google. ## At the time of the writing of this script, the sites I found did not ## disallow the use of scripts, but check for yourself if you are ## using this. ## ## usage: example_sms.pl [NR] ## destination phone number ## message is read from STDIN ## ## (c) R. Wichmann Tue Jul 17 CEST 2001 ## Released under the Gnu Public License version 2.0 or later ## adapted from archpage ( (c) Rob Muhlestein ) ## and mpage.pl ( (c) David Allen ) ## ########################## -- BEGIN CONFIGURATION -- ## set to default phone number my $NR = ''; ## set to sender #my $VON = ''; my $VON = 'stupsel'; ## set to URL of form page my $REFERER = ''; ## set to cgi script URL without 'http://domain'; my $PAGE = ''; ## set to domain where cgi script lives; my $DOMAIN = ''; ## set to 1 if you want to save response my $save_response = 1; ## set to 1 for verbose output my $verbose = 1; ## set to 1 to enable sending my $really_send = 0; ## The PITCOM variables #my $ID = ''; # gateway-ID #my $WERBUNG = ''; # advertisement #my $QUITTUNG = ''; # return page #my $USER = ''; # customer #my $LIST = '0'; # message type ########################## -- END CONFIGURATION -- $NR = $ARGV[0] if $ARGV[0]; my $message=''; undef $/; $message=; $message =~ s/\[EOF\]//g; ## URL encode and remove line breaks $message =~ s/\n/ /g; $message =~ s/\r//g; $message =~s/\s+/ /g; # Multiple whitespace -> one space $message =~ s/([^a-zA-Z0-9-_\.\/])/uc sprintf("%%%02x",ord($1))/eg; $message =~ s/%20/+/g; $WERBUNG =~ s/([^a-zA-Z0-9-_\.\/])/uc sprintf("%%%02x",ord($1))/eg; $WERBUNG =~ s/%20/+/g; $QUITTUNG =~ s/([^a-zA-Z0-9-_\.\/])/uc sprintf("%%%02x",ord($1))/eg; $QUITTUNG =~ s/%20/+/g; $USER =~ s/([^a-zA-Z0-9-_\.\/])/uc sprintf("%%%02x",ord($1))/eg; $USER =~ s/%20/+/g; ## truncate my $maxChars = 153 - length($WERBUNG) - length($VON); if(length($message) >= $maxChars) { $message = substr($message, 0, $maxChars); } my $NR1 = substr($NR, 0, 4); my $NR2 = substr($NR, 4, length($NR)-4); my $msglen = length($message); my $overhead = "ID=$ID&"; $overhead .= "WERBUNG=$WERBUNG&"; $overhead .= "QUITTUNG=$QUITTUNG&"; $overhead .= "USER=$USER&"; $overhead .= "LIST=$LIST&"; $overhead .= "NR1=$NR1&"; $overhead .= "NR2=$NR2&"; $overhead .= "VON=$VON&"; $overhead .= "MESSAGE=$message&"; $overhead .= "CNT=$msglen"; my $smslen = length($overhead); my $llim = "\r\n"; # At the end of each line. my $SMS = "POST $PAGE HTTP/1.0$llim"; $SMS .= "User-Agent: EvilGenius/1.0$llim"; $SMS .= "Referer: $REFERER$llim"; $SMS .= "Accept: */*$llim"; $SMS .= "Content-length: $smslen$llim"; $SMS .= "Content-type: application/x-www-form-urlencoded$llim"; $SMS .= "$llim"; $SMS .= "$overhead"; if ($verbose) { print STDERR " Sending message...\n\n"; print STDERR "$SMS\n\n"; } my $document=''; if ($really_send) { my $sock = IO::Socket::INET->new(PeerAddr => $DOMAIN, PeerPort => 'http(80)', Proto => 'tcp'); if ($verbose) { die "Cannot create socket : $!" unless $sock; } else { exit (1) unless $sock; } $sock->autoflush(); $sock->print("$SMS"); $document = join('', $sock->getlines()); } else { $document = " really_send was set to 0, SMS not sent"; } if ($save_response) { if ($verbose) { print STDERR "Saving response to tmp.html...\n\n"; } my $status = 0; open(TMP,">tmp.html") or $status=1; print TMP "$document\n" unless $status; close TMP unless $status; } if ($document =~ m/SMS wird versendet/g) { if ($verbose) { print STDERR " SMS successfully sent to $NR.\n"; } exit (0); } else { if ($verbose) { print STDERR " SMS not sent. There was an error.\n"; print STDERR " Use save_response = 1 to save the response to\n"; print STDERR " tmp.html in order to see what the server sent back.\n"; } exit (1); } samhain-4.1.4/scripts/logrotate.in0000644000175000017500000000075112615253277014115 00000000000000@mylogfile@ { weekly rotate 52 nocreate missingok compress prerotate if test -f @mylockfile@; then \ PIN=`cat @mylockfile@`; \ /bin/kill -TTIN $PIN; \ sleep 1; \ AA=0; \ while test "x$AA" != "x120"; do \ AA=$(( AA + 1 )); \ if test -f @mylogfile@.lock; then \ sleep 1; \ else \ break; \ fi \ done; \ fi endscript }samhain-4.1.4/scripts/check_samhain.pl.in0000755000175000017500000001345112615253277015310 00000000000000#!/usr/bin/perl -w # check_samhain.pl - check to see how many policy violations are reported # by the samhain file integrity checker. # # Copyright Rainer Wichmann (2004, 2012) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # ############################################################################ # -------------------------------------------------------------------[ Uses ]-- use strict; use Getopt::Long; use vars qw($PROGNAME $SAMHAIN $opt_V $opt_h $opt_v $verbose $opt_w $opt_c $opt_t $status $msg $state $retval); use lib "/usr/local/nagios/libexec" ; use utils qw(%ERRORS &print_revision); #my $TIMEOUT = 15; #my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); #sub print_revision ($$); # ----------------------------------------------------[ Function Prototypes ]-- sub print_help (); sub print_usage (); sub process_arguments (); # ------------------------------------------------------------[ Environment ]-- $ENV{'PATH'}=''; $ENV{'BASH_ENV'}=''; $ENV{'ENV'}=''; # -----------------------------------------------------------------[ Global ]-- $PROGNAME = "check_@install_name@"; $SAMHAIN = "@sbindir@/@install_name@"; # ----------------------------------------------------------------[ options ]-- Getopt::Long::Configure('bundling'); $status = process_arguments(); if ($status){ print "ERROR: processing arguments\n"; exit $ERRORS{"UNKNOWN"}; } # ----------------------------------------------------------------[ timeout ]-- $SIG{'ALRM'} = sub { print ("ERROR: timed out waiting for $SAMHAIN\n"); exit $ERRORS{"WARNING"}; }; alarm($opt_t); # ----------------------------------------------------------[ start samhain ]-- if ( defined $SAMHAIN && -x $SAMHAIN ) { if (! open (SHPIPE, "$SAMHAIN -t check --foreground -p err -s none -l none -m none 2>&1 | " ) ) { print "ERROR: could not popen $SAMHAIN \n"; exit $ERRORS{'UNKNOWN'}; } }else{ print "ERROR: Could not find samhain executable!\n"; exit $ERRORS{'UNKNOWN'}; } # ---------------------------------------------------------[ read from pipe ]-- $status = 0; while () { if (/POLICY/) { ++$status; print $_ if $verbose; } } if ($status < $opt_w) { $msg = "OK: $status policy violations (threshold $opt_w/$opt_c)"; $state = $ERRORS{'OK'}; } elsif ($status >= $opt_w && $status < $opt_c) { $msg = "WARNING: $status policy violations (threshold w=$opt_w)"; $state = $ERRORS{'WARNING'}; } else { $msg = "CRITICAL: $status policy violations (threshold c=$opt_c)"; $state = $ERRORS{'CRITICAL'}; } # -------------------------------------------------------------[ close pipe ]-- close (SHPIPE); # declare an error if we also get a non-zero return code from samhain if ( $? ) { $retval = $? / 256; if ( $! ) { print "Error closing $SAMHAIN: $!\n" if $verbose; } else { print "$SAMHAIN returned exit status $retval\n" if $verbose; } if ($state == $ERRORS{"CRITICAL"}) { $state = $ERRORS{"CRITICAL"}; } else { print "ERROR: $SAMHAIN exit status $retval\n"; exit $ERRORS{'UNKNOWN'}; } } # -------------------------------------------------------------------[ exit ]-- print "$msg | 'policy violations'=$status;$opt_w;$opt_c\n"; exit $state; # ------------------------------------------------------------[ Subroutines ]-- sub process_arguments(){ GetOptions ("V" => \$opt_V, "version" => \$opt_V, "h" => \$opt_h, "help" => \$opt_h, "v" => \$opt_v, "verbose" => \$opt_v, "w=i" => \$opt_w, "warning=i" => \$opt_w, "c=i" => \$opt_c, "critical=i" => \$opt_c, "t=i" => \$opt_t, "timeout=i" => \$opt_t ); if ($opt_V) { print_revision($PROGNAME,'$Revision: 1.1 $ '); exit $ERRORS{'OK'}; } if ($opt_h) { print_help(); exit $ERRORS{'OK'}; } if (defined $opt_v ){ $verbose = $opt_v; } unless (defined $opt_t) { $opt_t = $utils::TIMEOUT ; # default timeout # $opt_t = $TIMEOUT ; } unless (defined $opt_w) { $opt_w = 1; } unless (defined $opt_c) { $opt_c = 1; } if ( $opt_w > $opt_c) { print "Warning cannot be greater than Critical!\n"; exit $ERRORS{'UNKNOWN'}; } return $ERRORS{'OK'}; } sub print_usage () { print "Usage: $PROGNAME [-w ] [-c ] [-t ]\n"; } sub print_help () { print_revision($PROGNAME, '1.1'); print "Copyright (c) 2004,2012 Rainer Wichmann This plugin checks the number of policy violations reported by the samhain file intgrity checker "; print_usage(); print " -w, --warning=INTEGER Minimum number of policy violations for which a WARNING status will result -c, --critical=INTEGER Minimum number of policy violations for which a CRITICAL status will result -t, --timeout=SECONDS The number of seconds after which a the plugin will timeout -v, --verbose Verbose output -h, --help Show this help message -V, --version Show the version of the plugin "; } #sub print_revision ($$) { # my $commandName = shift; # my $pluginRevision = shift; # $pluginRevision =~ s/^\$Revision: //; # $pluginRevision =~ s/ \$\s*$//; # print "$commandName (@PACKAGE@ @VERSION@) $pluginRevision\n"; #} samhain-4.1.4/scripts/samhain.ebuild.in0000644000175000017500000000552112615253277015000 00000000000000# Copyright 2004 Rainer Wichmann # Distributed under the terms of the GNU General Public License v2 inherit eutils MY_P="${PN}_signed-${PV}" SLOT="0" LICENSE="GPL-2" DESCRIPTION="Samhain is a file integrity checker with optional central logging" # This is a fake URI that allows us to do a 'make dist' and copy # the file to distdir. # The proper URI would be http://www.la-samhna.de/archive/${MY_P}.tar.gz, # but this would force us to do a 'make dist-sign' ... # Apparently, portage cannot handle the file:// scheme, # and not every user might be prepared to create a signed tarball. # # SRC_URI="http://www.la-samhna.de/archive/${MY_P}.tar.gz" SRC_URI="http://www.la-samhna.de/archive/${P}.tar.gz" HOMEPAGE="http://www.la-samhna.de/samhain/" KEYWORDS="x86" IUSE="" DEPEND="app-arch/gzip app-arch/tar" # mysql? (>=dev-db/mysql-3.23.58)" RDEPEND="" src_unpack() { unpack ${A} cd ${WORKDIR} if test -f ${P}.tar.gz; then gunzip -c ${P}.tar.gz | tar xf - || die cd ${P} elif test -d "samhain-${PV}"; then mv "samhain-${PV}" "@install_name@-${PV}" fi } src_compile() { local myconf="--with-trusted=0,250" # myconf="$myconf --enable-mounts-check" # myconf="$myconf --enable-userfiles" # use mysql && myconf="$myconf --with-database=mysql" # use postgres && myconf="$myconf --with-database=postgresql" # econf \ # --with-pid-file=/var/run/${PN}.pid \ # --with-state-dir=/var/lib/${PN} \ # --with-log-file=/var/log/${PN}.log \ ./configure ${myconf} @mydefargs@ || die emake || die echo '#!/bin/sh' > ./sstrip echo 'echo "*** SSTRIP DISABLED ***"' >> ./sstrip } src_install() { make DESTDIR=${D} install || die make DESTDIR=${D} install-boot || die dodoc docs/BUGS COPYING docs/Changelog LICENSE docs/README \ docs/README.UPGRADE docs/sh_mounts.txt docs/sh_userfiles.txt \ docs/MANUAL-2_4.ps docs/MANUAL-2_4.html.tar dohtml docs/HOWTO-client+server.html docs/HOWTO-samhain+GnuPG.html \ docs/HOWTO-write-modules.html docs/HOWTO-samhain-on-windows.html \ docs/HOWTO-client+server-troubleshooting.html docs/FAQ.html } pkg_prerm() { rc-update del @install_name@ einfo "Stopping service @install_name@" test -f /etc/init.d/@install_name@ && /etc/init.d/@install_name@ stop sleep 3 } pkg_postinst() { rc-update add @install_name@ default einfo einfo "@install_name@ is installed but is NOT running yet, and the database" einfo "of file signatures is NOT initialized yet." einfo einfo "You need to run \"@install_name@ -t init\" to initialize " einfo "the baseline database of file signatures." einfo einfo "After initializing the database, you can start @install_name@ " einfo "with \"/etc/init.d/@install_name@ start\". It is configured to start" einfo "automatically on the next boot for runlevel \"default\"" } samhain-4.1.4/scripts/samhain.ebuild-light.in0000644000175000017500000000476612615253277016117 00000000000000# Copyright 2004 Rainer Wichmann # Distributed under the terms of the GNU General Public License v2 inherit eutils MY_P="${PN}_signed-${PV}" SLOT="0" LICENSE="GPL-2" DESCRIPTION="Samhain is a file integrity checker with optional central logging" # This is a fake URI that allows us to do a 'make dist' and copy # the file to distdir. # The proper URI would be http://www.la-samhna.de/archive/${MY_P}.tar.gz, # but this would force us to do a 'make dist-sign' ... # Apparently, portage cannot handle the file:// scheme, # and not every user might be prepared to create a signed tarball. # # SRC_URI="http://www.la-samhna.de/archive/${MY_P}.tar.gz" SRC_URI="http://www.la-samhna.de/archive/${P}.tar.gz" HOMEPAGE="http://www.la-samhna.de/samhain/" KEYWORDS="x86" IUSE="" DEPEND="app-arch/gzip app-arch/tar" # mysql? (>=dev-db/mysql-3.23.58)" RDEPEND="" src_unpack() { unpack ${A} cd ${WORKDIR} if test -f ${P}.tar.gz; then gunzip -c ${P}.tar.gz | tar xf - || die cd ${P} elif test -d "samhain-${PV}"; then mv "samhain-${PV}" "@install_name@-${PV}" fi } src_compile() { local myconf="--with-trusted=0,250" # myconf="$myconf --enable-mounts-check" # myconf="$myconf --enable-userfiles" # use mysql && myconf="$myconf --with-database=mysql" # use postgres && myconf="$myconf --with-database=postgresql" # econf \ # --with-pid-file=/var/run/${PN}.pid \ # --with-state-dir=/var/lib/${PN} \ # --with-log-file=/var/log/${PN}.log \ ./configure ${myconf} @mydefargs@ || die emake || die echo '#!/bin/sh' > ./sstrip echo 'echo "*** SSTRIP DISABLED ***"' >> ./sstrip } src_install() { make DESTDIR=${D} install-light || die make DESTDIR=${D} install-boot || die rm -f ${D}/@sbindir@/@install_name@_stealth } pkg_prerm() { rc-update del @install_name@ einfo "Stopping service @install_name@" test -f /etc/init.d/@install_name@ && /etc/init.d/@install_name@ stop sleep 3 } pkg_postinst() { rc-update add @install_name@ default einfo einfo "@install_name@ is installed but is NOT running yet, and the database" einfo "of file signatures is NOT initialized yet." einfo einfo "You need to run \"@install_name@ -t init\" to initialize " einfo "the baseline database of file signatures." einfo einfo "After initializing the database, you can start @install_name@" einfo "with \"/etc/init.d/@install_name@ start\". It is configured to start" einfo "automatically on the next boot for runlevel \"default\"" } samhain-4.1.4/scripts/head.html0000644000175000017500000000343412615253277013355 00000000000000 Server status
S A M H A I N

Server Status

Current time: %T
Startup time: %S
Connections: (maximum %M simultaneously)
open %O
total %A
Last connection: %L

Clients

samhain-4.1.4/scripts/README0000644000175000017500000000557712615253277012460 00000000000000 This directory contains miscellaneous useful scripts, some of them contributed by various users. Additions and/or improvements are welcome. chroot.sh: prepare chroot environment for the log server --------- Usage: chroot.sh Tested on Debian Linux. Your mileage may vary. After running the script, review /etc/passwd to replace passwords with a *, and to fix the path to the home directory of the yule user. If using a signed configuration file, you need a working copy of GnuPG inside the chroot jail. This script will probably fail on systems other than Linux, mainly because of the mknod commands to create devices in the chroot jail. NO WARRANTY !!! samhainadmin.pl --------------- Perform various tasks useful if you are using signed configuration and database files. Run 'samhainadmin.pl -h' for usage instructions. yuleadmin.pl ------------ Perl script (by Riccardo Murri) to list, add, and remove clients from the yulerc file. Run 'yuleadmin.pl -h' for usage instructions. check_samhain.pl ---------------- Nagios plugin for samhain. Will execute samhain and report results in the way expected by nagios. Drop this into your nagios/libexec/ directory. samhain.logrotator: logrotate script ------------------ This is a logrotate script (contributed by Simon Bailey) concat.pl --------- Concatenate samhain file signature databases and write the resulting database file to stdout. Does not work on signed or otherwise modified file signature databases. samhain.{cgi|dtd|xsl}: display XML logfile in XML capable browser --------------------- (works with Mozilla 1.2, possibly Mozilla 1.0, IE 6) Usage: 1. review samhain.cgi (see remarks in file) 2. drop samhain.cgi, samhain.dtd, samhain.xsl in some directory on your webserver 3. use .htaccess to protect access to that directory 4. point your browser at samhain.cgi You may need to rename samhain.cgi to samhain.php if you use mod_php. Also, you will certainly need to edit the path to the logfile in samhain.cgi. CAVEAT: There is no built-in access restriction (use .htaccess to password-protect the directory). The XSL stylesheet is based on a contribution by Olivier Salaun. samhain.spec: RPM spec file for building a vanilla single-host RPM ------------ Contributed by Andre Oliveira da Costa This is a spec file to produce a vanilla single-host samhain RPM (no fancy options, standard directory layout :). Accepted parameters for 'rpmbuild': --with gpg - enables gpg support --with tests - make tests before building redhat_i386.client.spec: RPM spec file for building a RedHat client RPM ------------ Contributed by Philipp Stadler Does not install documentation or local config file. samhain-4.1.4/scripts/foot.html0000644000175000017500000000015112615253277013414 00000000000000
samhain-4.1.4/scripts/samhain.xsl0000644000175000017500000001242512615253277013736 00000000000000 Samhain Log

Logs Samhain



Date: Machine:


TYPE D'ALERTE CHEMIN MESSAGE DATE MACHINE

samhain-4.1.4/scripts/chroot.sh0000755000175000017500000000711512615253277013423 00000000000000#! /bin/sh # NOTE: tested on Debian Linux # # NO WARRANTY - may or may not work on your system # # Copyright Rainer Wichmann (2003) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # CHROOT=$1 SYSTEM=`uname -s` if test "x$SYSTEM" = xLinux; then : else echo "This script will fail on systems other than Linux," echo "mainly because of the mknod commands to create devices" echo "in the chroot jail." exit 1 fi if test "x$CHROOT" = x; then echo "Usage: chroot.sh chroot_dir" echo "Purpose: prepare a chroot jail for yule" echo echo "NOTE: tested on Debian Linux" echo "NO WARRANTY - may or may not work on your system" exit 1 fi # # Link configuration file # echo " Link configuration file:" echo " ln -s ${CHROOT}/etc/yulerc /etc/yulerc" ln -s -f ${CHROOT}/etc/yulerc /etc/yulerc echo # # Create passwd file # echo " Create passwd file" echo " grep root /etc/passwd > ${CHROOT}/etc/passwd" echo " grep daemon /etc/passwd >> ${CHROOT}/etc/passwd" echo " grep yule /etc/passwd >> ${CHROOT}/etc/passwd" grep root /etc/passwd > ${CHROOT}/etc/passwd grep daemon /etc/passwd >> ${CHROOT}/etc/passwd grep yule /etc/passwd >> ${CHROOT}/etc/passwd echo # # Create group file # echo " Create group file" echo " grep root /etc/group > ${CHROOT}/etc/group" echo " grep daemon /etc/group >> ${CHROOT}/etc/group" echo " grep yule /etc/group >> ${CHROOT}/etc/group" grep root /etc/group > ${CHROOT}/etc/group grep daemon /etc/group >> ${CHROOT}/etc/group grep yule /etc/group >> ${CHROOT}/etc/group echo # # Create devices # echo " Create devices" echo " mkdir ${CHROOT}/dev" echo " mknod -m 444 ${CHROOT}/dev/urandom c 1 9" echo " mknod -m 666 ${CHROOT}/dev/random c 1 8" echo " mknod -m 666 ${CHROOT}/dev/null c 1 3" echo " mknod -m 666 ${CHROOT}/dev/null c 1 5" mkdir ${CHROOT}/dev mknod -m 444 ${CHROOT}/dev/urandom c 1 9 mknod -m 666 ${CHROOT}/dev/random c 1 8 mknod -m 666 ${CHROOT}/dev/null c 1 3 mknod -m 666 ${CHROOT}/dev/zero c 1 5 echo # # DNS # echo " Copy files for DNS" echo " cp -p /etc/nsswitch.conf ${CHROOT}/etc/" echo " cp -p /etc/hosts ${CHROOT}/etc/" echo " cp -p /etc/host.conf ${CHROOT}/etc/" echo " cp -p /etc/resolv.conf ${CHROOT}/etc/" echo " cp -p /etc/services ${CHROOT}/etc/" echo " cp -p /etc/protocols ${CHROOT}/etc/" cp -p /etc/nsswitch.conf ${CHROOT}/etc/ cp -p /etc/hosts ${CHROOT}/etc/ cp -p /etc/host.conf ${CHROOT}/etc/ cp -p /etc/resolv.conf ${CHROOT}/etc/ cp -p /etc/services ${CHROOT}/etc/ cp -p /etc/protocols ${CHROOT}/etc/ echo "----------------------------------------------------" echo echo " You may want to review ${CHROOT}/etc/passwd" echo " to replace passwords with a *, and to fix the" echo " path to the home directory of the yule user." echo echo " If using a signed configuration file, you need" echo " a working copy of GnuPG inside the chroot jail." echo echo "----------------------------------------------------" samhain-4.1.4/scripts/yuleadmin.pl.in0000755000175000017500000001764112615253277014527 00000000000000#! /usr/bin/perl # Copyright (c) 2007 Riccardo Murri # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # use warnings; use strict; use Getopt::Long; use File::Basename; use File::Copy; use File::Temp qw/ tempfile /; use IO::File; # Do I/O to the data file in binary mode (so it # wouldn't complain about invalid UTF-8 characters). use bytes; File::Temp->safe_level( File::Temp::HIGH ); my %opts = (); my $outfile; my $verbose; my $base = basename($0); #my $cfgfile = "yulerc"; #my $yule = "./yule"; #my $gpg = "/usr/bin/gpg"; my $cfgfile = "@myconffile@"; my $yule = "@sbindir@/@install_name@"; my $gpg = "@mygpg@"; $cfgfile =~ s/^REQ_FROM_SERVER//; $gpg = "gpg" if ($gpg eq ""); sub usage() { print <<__END_OF_TEXT__ Usage: $base { -a | --add } [options] HOSTNAME [PASSWORD] Add client HOSTNAME to configuration file. If PASSWORD is omitted, it is read from stdin. If HOSTNAME already exists in the configuration file, an error is given. $base { -d | --delete } [options] HOSTNAME Remove client HOSTNAME from configuration file. $base { -l | --list } [options] List clients in the yule configuration file. $base { -r | --replace } [options] HOSTNAME [PASSWORD] Replace password of existing client HOSTNAME in configuration file. If PASSWORD is omitted, it is read from stdin. If HOSTNAME does not already exist in the configuration file, an error is given. $base { -u | --update } [options] HOSTNAME [PASSWORD] Add client HOSTNAME to config file or replace its password with a new one. If PASSWORD is omitted, it is read from stdin. Options: -c CFGFILE --cfgfile CFGFILE Select an alternate configuration file. (default: $cfgfile) -o OUTFILE --output OUTFILE Write modified configuration to OUTFILE. If this option is omitted, $base will rename the original configuration file to '$cfgfile.BAK' and overwrite it with the modified content. -Y YULECMD --yule YULECMD Use command YULECMD to generate the client key from the password. (default: $yule) -v --verbose Verbose output. __END_OF_TEXT__ ; return; } ## subroutines sub read_clients ($) { my $cfgfile = shift || '-'; my %clients; open INPUT, "<$cfgfile" or die ("Cannot read configuration file '$cfgfile'. Aborting"); my $section; while () { # skip comment and blank lines next if m{^\s*#}; next if m{^\s*$}; # match section headers $section = $1 if m{^\s*\[([a-z0-9 ]+)\]}i; # ok, list matching lines if ($section =~ m/Clients/) { if (m{^\s*Client=}i) { chomp; s{^\s*Client=}{}i; my ($client, $key) = split /@/,$_,2; $clients{lc($client)} = $key; } } } close INPUT; return \%clients; } sub write_clients ($$$) { my $cfgfile_in = shift || '-'; my $cfgfile_out = shift || $cfgfile_in; my $clients = shift; my @lines; my $in_clients_section; # copy-pass input file my $section = ''; open INPUT, "<$cfgfile_in" or die ("Cannot read configuration file '$cfgfile_in'. Aborting"); while () { # match section headers if (m{^\s*\[([a-z0-9 ]+)\]}i) { if ($in_clients_section and ($section ne $1)) { # exiting [Clients] section, output remaining ones foreach my $hostname (keys %{$clients}) { push @lines, 'Client=' . $hostname . '@' . $clients->{lc($hostname)} . "\n"; delete $clients->{lc($hostname)}; } } # update section title $section = $1; if ($section =~ m/Clients/i) { $in_clients_section = 1; } else { $in_clients_section = 0; } } # process entries in [Clients] section if ($in_clients_section) { if (m{^\s*Client=}i) { my ($hostname, undef) = split /@/,$_,2; $hostname =~ s{^\s*Client=}{}i; if (defined($clients->{lc($hostname)})) { # output (possibly) modified key $_ = 'Client=' . $hostname . '@' . $clients->{lc($hostname)} . "\n"; delete $clients->{lc($hostname)}; } else { # client deleted, skip this line from output $_ = ''; } } } # copy input to output push @lines, $_; } close INPUT; # if end-of-file reached within [Clients] section, output remaining ones if ($in_clients_section) { foreach my $hostname (keys %{$clients}) { push @lines, 'Client=' . $hostname . '@' . $clients->{lc($hostname)} . "\n"; } } # if necessary, replace input file with output file if ($cfgfile_in eq $cfgfile_out) { copy($cfgfile_in, $cfgfile_in . '.BAK') or die("Cannot backup config file '$cfgfile_in'. Aborting"); } open OUTPUT, ">$cfgfile_out" or die ("Cannot write to file '$cfgfile_out'. Aborting"); # overwrite config file line by line foreach my $line (@lines) { print OUTPUT $line; } close OUTPUT; } sub new_client_key ($) { my $password = shift; my $yulecmd = shift || $yule; my (undef, $key) = split /@/, `$yulecmd -P $password`, 2; chomp $key; return $key; } ## main Getopt::Long::Configure ("posix_default"); Getopt::Long::Configure ("bundling"); # Getopt::Long::Configure ("debug"); GetOptions (\%opts, 'Y|yule=s', 'a|add', 'c|cfgfile=s', 'd|delete', 'h|help', 'l|list', 'o|output=s', 'r|replace', 'u|update', 'v|verbose', ); if (defined ($opts{'h'})) { usage(); exit; } if (defined($opts{'c'})) { $cfgfile = $opts{'c'}; $outfile = $cfgfile unless defined($outfile); } if (defined($opts{'Y'})) { $yule = $opts{'Y'}; } if (defined($opts{'v'})) { $verbose = 1; } if (defined($opts{'o'})) { $outfile = $opts{'o'}; } if (defined($opts{'l'})) { # list contents my $clients = read_clients($cfgfile); foreach my $client (keys %{$clients}) { print "$client"; print " ${$clients}{$client}" if $verbose; print "\n"; } } elsif (defined($opts{'a'}) or defined($opts{'u'}) or defined($opts{'r'})) { # add HOSTNAME my $hostname = $ARGV[0] or die("Actions --add/--replace/--update require at least argument HOSTNAME. Aborting"); my $password; if (defined($ARGV[1])) { $password = uc($ARGV[1]); } else { $password = uc(); # remove leading and trailing space $password =~ s{\s*}{}g; } # sanity check die ("Argument PASSWORD must be a 16-digit hexadecimal string. Aborting") unless ($password =~ m/[[:xdigit:]]{16}/); my $add = defined($opts{'a'}); my $replace = defined($opts{'r'}); my $clients = read_clients($cfgfile); die ("Client '$hostname' already present in config file - cannot add. Aborting") if ($add and defined(${$clients}{$hostname})); die ("Client '$hostname' not already present in config file - cannot replace. Aborting") if ($replace and not defined(${$clients}{$hostname})); $clients->{$hostname} = new_client_key($password) or die ("Cannot get key for the given password. Aborting"); write_clients($cfgfile, $outfile, $clients); } elsif (defined($opts{'d'})) { # remove HOSTNAME my $hostname = $ARGV[0] or die("Action --delete requires one argument HOSTNAME. Aborting"); my $clients = read_clients($cfgfile); delete ${$clients}{$hostname}; write_clients($cfgfile, $outfile, $clients); } else { usage(); die ("You must specify one of --list, --add or --remove options. Aborting"); } samhain-4.1.4/scripts/samhain.dtd0000644000175000017500000000042712615253277013702 00000000000000 samhain-4.1.4/scripts/logrotate0000664000175000017500000000100412724114713013472 00000000000000/var/log/samhain_log { weekly rotate 52 nocreate missingok compress prerotate if test -f /run/samhain.pid; then \ PIN=`cat /run/samhain.pid`; \ /bin/kill -TTIN $PIN; \ sleep 1; \ AA=0; \ while test "x$AA" != "x120"; do \ AA=$(( AA + 1 )); \ if test -f /var/log/samhain_log.lock; then \ sleep 1; \ else \ break; \ fi \ done; \ fi endscript } samhain-4.1.4/scripts/concat.pl0000755000175000017500000000337312615253277013377 00000000000000#! /usr/bin/perl # Copyright Rainer Wichmann (2004) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # use warnings; use strict; my $fno = 0; my $file = ''; my @last2 = (); my $line = ''; sub usage () { print "Usage: concat.pl \n\n"; print " Will concatenate samhain file signature database files\n"; print " and print to stdout.\n"; print " Does not work on signed or otherwise modified\n"; print " file signature databases.\n"; } if ($#ARGV < 0) { # must be at least one file usage(); exit 1; } elsif ($ARGV[0] =~ /^-h$/ || $ARGV[0] =~ /^--?help$/) { usage(); exit 0; } for $file (@ARGV) { open FH, "< $file" or die "Cannot open $file: $!"; if ($fno != 0) { # search and read past the start-of-file marker while () { last if ($_ =~ /^\[SOF\]$/); } } @last2 = (); while () { push @last2, $_; if (@last2 > 2) { $line = shift @last2; print $line; } } close FH; ++$fno; } # last two lines of last file $line = shift @last2; print $line; $line = shift @last2; print $line; samhain-4.1.4/scripts/samhainadmin.pl.in0000755000175000017500000004656312615253277015176 00000000000000#! /usr/bin/perl # Copyright Rainer Wichmann (2004) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # use warnings; use strict; use Getopt::Long; use File::Basename; use File::Copy; use File::stat; use File::Temp qw/ tempfile tempdir unlink0 /; use IO::Handle; use Fcntl qw(:DEFAULT :flock); use Tie::File; # Do I/O to the data file in binary mode (so it # wouldn't complain about invalid UTF-8 characters). use bytes; File::Temp->safe_level( File::Temp::HIGH ); my %opts = (); my $action; my $file1; my $file2; my $passphrase; my $secretkeyring; my $return_from_sign = 0; my $no_print_examine = 0; my $no_remove_lock = 0; my $base = basename($0); my $cfgfile = "@myconffile@"; my $datafile = "@mydatafile@"; my $daemon = "@sbindir@/@install_name@"; my $gpg = "@mygpg@"; my $TARGETKEYID = "@mykeyid@"; my $KEYTAG = "@mykeytag@"; $cfgfile =~ s/^REQ_FROM_SERVER//; $datafile =~ s/^REQ_FROM_SERVER//; $gpg = "gpg" if ($gpg eq ""); sub check_gpg_agent() { my $gpgconf = "$ENV{'HOME'}/.gnupg/gpg.conf"; if (!-f "$gpgconf") { $gpgconf = "$ENV{'HOME'}/.gnupg/options"; } if (-f $gpgconf) { my @array = (); tie @array, 'Tie::File', $gpgconf or die "Cannot tie ${gpgconf}: $!"; my @grep = grep(/^\s*use-agent/, @array); # print "matches = $#grep\n"; if ($#grep >= 0) { if (exists $ENV{'GPG_AGENT_INFO'}) { my $socke = $ENV{'GPG_AGENT_INFO'}; $socke =~ s/:.*//; # print "socke = $socke\n"; if (! -S $socke) { print "--------------------------------------------------\n"; print "\n"; print " GPG is set to use gpg-agent, but GPG agent is"; print " not running, though GPG_AGENT_INFO is defined.\n\n"; print " Please restart gpg-agent, or remove the use-agent\n"; print " option from ${gpgconf} and unset GPG_AGENT_INFO\n\n"; print "--------------------------------------------------\n"; print "\n"; exit 1; } } else { print "--------------------------------------------------\n"; print "\n"; print " GPG is set to use gpg-agent, but "; print " GPG_AGENT_INFO is not defined.\n\n"; print " Please start gpg-agent, or remove the use-agent\n"; print " option from ${gpgconf}\n\n"; print "--------------------------------------------------\n"; print "\n"; exit 1; } } untie @array; } } sub usage() { print "Usage:\n"; print " $base { -m F | --create-cfgfile } [options] [in.cfgfile]\n"; print " Sign the configuration file. If in.cfgfile is given, sign it\n"; print " and install it as configuration file.\n\n"; print " $base { -m f | --print-cfgfile } [options] \n"; print " Print the configuration file to stdout. Signatures are removed.\n\n"; print " $base { -m D | --create-datafile } [options] [in.datafile]\n"; print " Sign the database file. If in.datafile is given, sign it\n"; print " and install it as database file.\n\n"; print " $base { -m d | --print-datafile } [options] \n"; print " Print the database file to stdout. Signatures are removed. Use\n"; print " option --list to list files in database rather than printing the raw file.\n\n"; print " $base { -m R | --remove-signature } [options] file1 [file2 ...]\n"; print " Remove cleartext signature from input file(s). The file\n"; print " is replaced by the non-signed file.\n\n"; print " $base { -m E | --sign } [options] file1 [file2 ...]\n"; print " Sign file(s) with a cleartext signature. The file\n"; print " is replaced by the signed file.\n\n"; print " $base { -m e | --examine } [options] file1 [file2 ...]\n"; print " Report signature status of file(s).\n\n"; print " $base { -m G | --generate-keys } [options] \n"; print " Generate a PGP keypair to use for signing.\n\n"; print "Options:\n"; print " -c cfgfile --cfgfile cfgfile\n"; print " Select an alternate configuration file.\n\n"; print " -d datafile --datafile datafile\n"; print " Select an alternate database file.\n\n"; print " -p passphrase --passphrase passphrase\n"; print " Set the passphrase for gpg. By default, gpg will ask.\n\n"; print " -s gnupg_homedir --secretkeyring gnupg_homedir\n"; print " Select an alternate gpg homedirectory to locate the secret keyring.\n"; print " Will use '$ENV{'HOME'}/.gnupg/' by default.\n\n"; print " -k keyid --keyid keyid\n"; print " Select the keyid to use for signing.\n\n"; print " -l --list\n"; print " List the files in database rather than printing the raw file.\n\n"; print " -v --verbose\n"; print " Verbose output.\n\n"; return; } sub check_gpg_uid () { if (0 != $>) { print "--------------------------------------------------\n"; print "\n"; print " You are not root. Please remember that samhain/yule\n"; print " will use the public keyring of root to verify a signature.\n"; print "\n"; print "--------------------------------------------------\n"; } else { if (!("@yulectl_prg@" =~ //)) { print "--------------------------------------------------\n"; print "\n"; print " Please remember that yule will drop root after startup. Signature\n"; print " verification on SIGHUP will fail if you do not import the public key\n"; print " into the keyring of the non-root yule user.\n"; print "\n"; print "--------------------------------------------------\n"; } } } sub check_gpg_sign () { if ( defined($secretkeyring)) { if ( (!-d "$secretkeyring")){ print "--------------------------------------------------\n"; print "\n"; print " Secret keyring $secretkeyring not found!\n"; print "\n"; print " Please check the path/name of the alternate secret keyring.\n"; print "\n"; print "--------------------------------------------------\n"; print "\n"; exit; } } else { if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/secring.gpg")) { print "--------------------------------------------------\n"; print "\n"; if (!-d "$ENV{'HOME'}/.gnupg") { print " Directory \$HOME/.gnupg not found!\n"; } else { print " Secret keyring \$HOME/.gnupg/secring.gpg not found!\n"; } print "\n"; print " This indicates that you have never created a \n"; print " public/private keypair, and thus cannot sign.\n"; print " \n"; print " Please use $0 --generate-keys or gpg --gen-key\n"; print " to generate a public/private keypair first.\n"; print "\n"; print "--------------------------------------------------\n"; print "\n"; exit; } } } sub check_gpg_verify () { if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/pubring.gpg")) { print "--------------------------------------------------\n"; print "\n"; if (!-d "$ENV{'HOME'}/.gnupg") { print " Directory \$HOME/.gnupg not found!\n"; } else { print " Public keyring \$HOME/.gnupg/pubring.gpg not found!\n"; } print "\n"; print " This indicates that you have never used gpg before \n"; print " and/or have no public keys to verify signatures.\n"; print " \n"; print " Please use 'gpg --export key_id' to export the public\n"; print " signing key of the user who is signing the\n"; print " configuration/database files.\n\n"; print " Then you can use 'gpg --import keyfile' to import the key\n"; print " into this user's public keyring.\n"; print "\n"; print "--------------------------------------------------\n"; print "\n"; exit; } } sub generate () { my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --gen-key"; check_gpg_uid(); system ($command) == 0 or die "system $command failed: $?"; exit; } sub examine () { my $iscfg = 0; my $have_fp = 0; my $have_sig = 0; my $message = ''; my $retval = 9; my $fh; my $filename; if (!($file1 =~ /^\-$/)) { die ("Cannot open $file1 for read: $!") unless ((-e $file1) && (-r _)); } open FIN, "<$file1" or die "Cannot open $file1 for read: $!"; my $dir = tempdir( CLEANUP => 1 ); $filename = $dir . "/exa_jhfdbilw." . $$; open $fh, ">$filename" or die "Cannot open $filename"; autoflush $fh 1; while () { print $fh $_; if ($_ =~ /^\s*\[Misc\]/) { $iscfg = 1; } } if ($iscfg == 1) { $message .= "File $file1 is a configuration file\n\n"; } else { $message .= "File $file1 is a database file\n\n"; } my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --status-fd 1 "; $command .= "--verbose " if (defined($opts{'v'})); $command .= "--verify $filename "; if (defined($opts{'v'})) { $command .= "2>&1"; } else { $command .= "2>/dev/null"; } print STDOUT "Using: $command\n\n" if (defined($opts{'v'})); open GPGIN, "$command |" or die "Cannot fork: $!"; while () { if ($_ =~ /^\[GNUPG:\] GOODSIG ([0-9A-F]+) (.*)$/) { $message .= "GOOD signature with key: $1\n"; $message .= "Key owner: $2\n"; $have_sig = 1; $retval = 0; } if ($_ =~ /^\[GNUPG:\] VALIDSIG ([0-9A-F]+) ([0-9\-]+)\s/) { $message .= "Key fingerprint: $1\n"; $message .= "Signature generated on: $2\n\n"; $have_fp = 1; $message .= "This file is signed with a valid signature.\n" if ($have_sig == 1); $have_sig = 1; $have_fp = 1; } if ($_ =~ /^\[GNUPG:\] NODATA 1/) { $message .= "NO signature found.\n\n"; $message .= "This file is not signed !!!\n"; $have_sig = 1; $have_fp = 1; $retval = 2; } if ($_ =~ /^\[GNUPG:\] BADSIG ([0-9A-F]+) (.*)$/) { $message .= "BAD signature with key: $1\n"; $message .= "Key owner: $2\n\n"; $message .= "This file is signed with an invalid signature !!!\n"; $have_sig = 1; $have_fp = 1; $retval = 1; } if ($_ =~ /^\[GNUPG:\] NO_PUBKEY ([0-9A-F]+)/) { $message .= "NOT CHECKED signature with key: $1\n\n"; $message .= "The signature of this file cannot be checked: no public key available !!!\n"; $have_sig = 1; $have_fp = 1; $retval = 1; } print STDOUT $_ if (defined($opts{'v'})); } close (GPGIN); print STDOUT "\n" if (defined($opts{'v'})); if ($have_sig == 0) { $message .= "NO valid signature found\n"; } elsif ($have_fp == 0) { $message .= "NO fingerprint found\n"; } close (FIN); if ($no_print_examine == 0) { print STDOUT $message; } unlink0( $fh, $filename ) or die "Cannot unlink $filename safely"; return $retval; } sub remove () { my $bodystart = 1; my $sigstart = 0; my $sigend = 0; my $filename = ""; my $fh; my $stats; open FH, "<$file1" or die "Cannot open file $file1 for read: $!"; if (!($file1 =~ /^\-$/)) { flock(FH, LOCK_EX) unless ($no_remove_lock == 1); my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed"; $filename = $dir . "/rem_iqegBCQb." . $$; open $fh, ">$filename" or die "Cannot open $filename"; $stats = stat($file1); # ($fh, $filename) = tempfile(UNLINK => 1); } else { open $fh, ">$file1" or die "Cannot open file $file1 for write: $!"; } autoflush $fh 1; while () { if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) { $sigstart = 1; $bodystart = 0; next; } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) { $sigstart = 0; $bodystart = 1; next; } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) { $bodystart = 0; $sigend = 1; next; } elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) { $sigend = 0; $bodystart = 1; next; } if ($bodystart == 1) { print $fh $_; } } if (!($file1 =~ /^\-$/)) { copy("$filename", "$file1") or die "Copy $filename to $file1 failed: $!"; chmod $stats->mode, $file1; chown $stats->uid, $stats->gid, $file1; flock(FH, LOCK_UN) unless ($no_remove_lock == 1); close FH; } unlink0( $fh, $filename ) or die "Cannot unlink $filename safely"; return; } sub print_cfgfile () { my $bodystart = 0; my $sigstart = 0; if (!defined($file2)) { $file2 = '-'; } open FH, "<$file1" or die "Cannot open file $file1 for read: $!"; open FO, ">$file2" or die "Cannot open file $file2 for write: $!"; while () { if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) { $sigstart = 1; next; } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) { $sigstart = 0; $bodystart = 1; next; } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) { $bodystart = 0; exit; } if ($bodystart == 1) { print FO $_; } } exit; } sub print_datafile () { die ("Cannot find program $daemon") unless (-e $daemon); if (defined($opts{'v'})) { open FH, "$daemon --full-detail -d $datafile |" or die "Cannot open datafile $datafile for read: $!"; } else { open FH, "$daemon -d $datafile |" or die "Cannot open datafile $datafile for read: $!"; } while () { print $_; } exit; } sub sign_file () { my $fileout = ''; my $bodystart = 1; my $sigstart = 0; my $sigend = 0; my $stats; my $fh1; my $filename1; my $flag1 = 0; check_gpg_uid(); check_gpg_agent(); if (!defined($file2)) { $file2 = $file1; } if ($file1 =~ /^\-$/) { my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed"; $filename1 = $dir . "/sig_vs8827sd." . $$; open $fh1, ">$filename1" or die "Cannot open $filename1"; $flag1 = 1; # my ($fh1, $filename1) = tempfile(UNLINK => 1); while () { if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) { $sigstart = 1; $bodystart = 0; next; } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) { $sigstart = 0; $bodystart = 1; next; } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) { $bodystart = 0; $sigend = 1; next; } elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) { $sigend = 0; $bodystart = 1; next; } if ($bodystart == 1) { print $fh1 $_; } # # print $fh1 $_; # } $file1 = $filename1; $fileout = '-'; } else { open (LOCKFILE, "<$file1") or die "Cannot open $file1: $!"; flock(LOCKFILE, LOCK_EX); $no_print_examine = 1; $no_remove_lock = 1; if (examine() < 2) { remove(); } $fileout = $file1 . ".asc"; $stats = stat($file1) or die "No file $file1: $!"; } if (defined($passphrase)) { local $SIG{PIPE} = 'IGNORE'; my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --passphrase-fd 0 -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped "; $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'})); $command .= "$file1"; open (FH, "|$command") or die "can't fork: $!"; print FH "$passphrase" or die "can't write: $!"; close FH or die "can't close: status=$?"; } else { my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped "; $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'})); $command .= "$file1"; system("$command") == 0 or die "system $command failed: $?"; } if (!($fileout =~ /^\-$/)) { my $st_old = stat($file1) or die "No file $file1: $!"; my $st_new = stat($fileout) or die "No file $fileout: $!"; die ("Signed file is smaller than unsigned file") unless ($st_new->size > $st_old->size); move("$fileout", "$file2") or die "Move $fileout to $file2 failed: $!"; chmod $stats->mode, $file2; chown $stats->uid, $stats->gid, $file2; flock(LOCKFILE, LOCK_UN); } if ($flag1 == 1) { unlink0( $fh1, $filename1 ) or die "Cannot unlink $filename1 safely"; } if ($return_from_sign == 1) { return; } exit; } Getopt::Long::Configure ("posix_default"); Getopt::Long::Configure ("bundling"); # Getopt::Long::Configure ("debug"); GetOptions (\%opts, 'm=s', 'h|help', 'v|verbose', 'l|list', 'c|cfgfile=s', 'd|datafile=s', 'p|passphrase=s', 's|secretkeyring=s', 'k|keyid=s', 'create-cfgfile', # -m F 'print-cfgfile', # -m f 'create-datafile', # -m D 'print-datafile', # -m d 'remove-signature',# -m R 'sign', # -m E 'examine', # -m e 'generate-keys'); # -m G if (defined ($opts{'h'})) { usage(); exit; } if (defined($opts{'k'})) { $TARGETKEYID = $opts{'k'}; $KEYTAG = "--default-key"; } if (defined($opts{'c'})) { $cfgfile = $opts{'c'}; } if (defined($opts{'d'})) { $datafile = $opts{'d'}; } if (defined($opts{'p'})) { $passphrase = $opts{'p'}; } if (defined($opts{'s'})) { $secretkeyring = $opts{'s'}; } if (defined ($opts{'m'}) && ($opts{'m'} =~ /[FfDdREeG]{1}/) ) { $action = $opts{'m'}; } elsif (defined ($opts{'create-cfgfile'})) { $action = 'F'; } elsif (defined ($opts{'print-cfgfile'})) { $action = 'f'; } elsif (defined ($opts{'create-datafile'})) { $action = 'D'; } elsif (defined ($opts{'print-datafile'})) { $action = 'd'; } elsif (defined ($opts{'remove-signature'})) { $action = 'R'; } elsif (defined ($opts{'sign'})) { $action = 'E'; } elsif (defined ($opts{'examine'})) { $action = 'e'; } elsif (defined ($opts{'generate-keys'})) { $action = 'G'; } else { usage(); die ("No valid action specified !"); } if (defined($ARGV[0])) { $file1 = $ARGV[0]; } if (defined($ARGV[1])) { $file2 = $ARGV[1]; } if (($action =~ /[REe]{1}/) && !defined($file1)) { usage(); die("Option -m $action requires a filename (or '-' for stdio)\n"); } if ($action =~ /^F$/) { if (!defined($file1)) { $file1 = $cfgfile; } $file2 = $cfgfile; sign_file (); } if ($action =~ /^D$/) { if (!defined($file1)) { $file1 = $datafile; } $file2 = $datafile; sign_file (); } if ($action =~ /^R$/) { # $file1 defined my $i = 0; while (defined($ARGV[$i])) { $file1 = $ARGV[$i]; remove (); ++$i; } } if ($action =~ /^E$/) { # $file1 defined # default: $file2 = $file1 check_gpg_sign(); my $i = 0; while (defined($ARGV[$i])) { $file1 = $ARGV[$i]; $file2 = $file1; $return_from_sign = 1; sign_file (); ++$i; } } if ($action =~ /^e$/) { # $file1 defined # default: $file2 = stdout check_gpg_verify(); my $i = 0; my $ret = 0; while (defined($ARGV[$i])) { print "\n"; $file1 = $ARGV[$i]; $ret += examine (); ++$i; print "\n--------------------------------\n" if (defined($ARGV[$i])); } exit($ret); } if ($action =~ /^f$/) { $file1 = $cfgfile; $file2 = "-"; print_cfgfile (); } if ($action =~ /^d$/) { # $file1 irrelevant if (defined($opts{'l'})) { print_datafile (); } else { $file1 = $datafile; $file2 = "-"; print_cfgfile (); } } samhain-4.1.4/scripts/samhain.spec.in0000644000175000017500000001163712616325622014466 00000000000000# # Accepted parameters for 'rpmbuild': # # --with gpg - enables gpg support # --with tests - make tests before building Summary: File integrity and host-based IDS Name: samhain Version: @VERSION@ Release: 1 License: GPL Group: System Environment/Base Source: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-root Packager: Andre Oliveira da Costa Provides: %{name} %if %{?_with_gpg:1}%{!?_with_gpg:0} BuildPreReq: gpg %endif %description samhain is an open source file integrity and host-based intrusion detection system for Linux and Unix. It can run as a daemon process, and and thus can remember file changes -- contrary to a tool that runs from cron, if a file is modified you will get only one report, while subsequent checks of that file will ignore the modification as it is already reported (unless the file is modified again). samhain can optionally be used as client/server system to provide centralized monitoring for multiple host. Logging to a (MySQL or PostgreSQL) database is supported. This package contains only the single host version. %prep %setup -q -n samhain-%{version} %build %if %{?_with_tests:1}%{!?_with_tests:0} # test installation (test #7 is only included if --with gpg has been # specified) for i in `seq 6` %{?_with_gpg:7}; do ./test/test.sh $i; done %endif ./configure --prefix=%{_usr} \ --sbindir=%{_sbindir} \ --sysconfdir=%{_sysconfdir} \ --localstatedir=%{_localstatedir} \ --mandir=%{_mandir} \ %{?_with_gpg: --with-gpg=`type -p gpg`} make %install rm -rf $RPM_BUILD_ROOT # sstrip shouldn't be used since binaries will be stripped later cat << EOF > sstrip #!/bin/sh echo "*** SSTRIP DISABLED ***" EOF make DESTDIR=${RPM_BUILD_ROOT} install # copy script files to /var/lib/samhain so that we can use them right # after the package is installed install -m 700 samhain-install.sh init/samhain.startLinux init/samhain.startLSB ${RPM_BUILD_ROOT}%{_localstatedir}/lib/%{name} %clean rm -rf ${RPM_BUILD_ROOT} %post if [ "$1" = 1 ]; then # Activate boot-time start up cd %{_localstatedir}/lib/%{name} /bin/sh ./samhain-install.sh --verbose install-boot if test -f /sbin/chkconfig; then /sbin/chkconfig --add samhain /sbin/chkconfig samhain on fi fi cat << EOF Samhain is installed but is NOT running yet, and the database of file signatures is NOT initialized yet. Read the documentation, review configuration files, and then (i) initialize it (%{_sbindir}/samhain -t init) and (ii) start it manually (%{_sysconfdir}/init.d/samhain start). It is configured to start automatically on the next boot for runlevels [2-5]. EOF %preun # stop running instance of samhain, if any if [ -f %{_localstatedir}/run/%{name}.pid ]; then %{_sysconfdir}/init.d/samhain stop fi if [ "$1" = 0 ]; then # remove boot-time scripts and links cd %{_localstatedir}/lib/samhain if [ -f ./samhain-install.sh ]; then /bin/sh ./samhain-install.sh --verbose uninstall-boot else if [ -f /sbin/chkconfig ]; then /sbin/chkconfig samhain off /sbin/chkconfig --del samhain fi fi fi %files %defattr(-,root,root) %dir %{_localstatedir}/run %dir %{_localstatedir}/log %doc docs/BUGS COPYING docs/Changelog %doc LICENSE docs/HOWTO* docs/MANUAL-2_4.* docs/README* %{_localstatedir}/lib/%{name} %{_sbindir}/%{name} %attr(644,root,root) %{_mandir}/man5/samhain* %attr(644,root,root) %{_mandir}/man8/samhain* %attr(644,root,root) /etc/logrotate.d/@install_name@ %config(noreplace) %{_sysconfdir}/samhainrc %changelog * Sat Jun 19 2004 Rainer Wichmann - replace ./test.sh $i with make test$i * Sat Jan 03 2004 Rainer Wichmann - Use /sbin/chkconfig as in ../samhain.spec.in * Thu Dec 11 2003 Christian Vanguers - Fixed typo in samhain.spec * Tue Dec 24 2002 Rainer Wichmann - warn user that database must be initialized - fix version of MANUAL in '%files' - test for chkconfig, use only if found * Sun Dec 22 2002 Andre Oliveira da Costa 1.7.0 - fixed typo with _usr macro on ./configure - stops running samhain before uninstall - implemented conditionals to allow proper uninstalls/upgrades - 'BuildPreReq: gpg' is considered only if '--with gpg' is provided - run 'chkconfig' to activate samhain after installation - warn user that samhain must be manually started after install/upgrade * Fri Dec 20 2002 Rainer Wichmann - use 'configure' to set version string - use standard macros for paths * Thu Dec 19 2002 Andre Oliveira da Costa 1.6.6 - optional parameters '--with gpg' and '--with tests' - use of pre-defined macros whenever possible * Wed Dec 18 2002 Andre Oliveira da Costa 1.6.6 - Fixed installation process, avoiding hardcoded paths on the binaries (thks to samhain's author Rainer Wichmann) * Mon Dec 16 2002 Andre Oliveira da Costa 1.6.6 - First attempt to build from sources samhain-4.1.4/scripts/samhain.logrotator0000644000175000017500000000067512615253277015330 00000000000000/var/log/samhain_log { size=1M nocreate compress mail root@mail maillast rotate 5 prerotate if test -f /var/run/samhain.pid; then \ PIN=`cat /var/run/samhain.pid`; \ /bin/kill -ABRT $PIN; \ sleep 1; \ AA=0; \ while test "x$AA" != "x120"; do \ let "AA = $AA + 1"; \ if test -f /var/run/samhain.pid; then \ sleep 1; \ else \ break; \ fi \ done; \ fi endscript samhain-4.1.4/scripts/samhain.cgi0000755000175000017500000000164212615253277013674 00000000000000#! /usr/local/bin/php \n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; $machine = $HTTP_POST_VARS["machine"]; print "$machine\n"; $date = $HTTP_POST_VARS["date"]; print "$date\n"; /* INSERT PATH TO YOUR LOGFILE !!! */ readfile("/var/log/yule/yule.log"); /* INSERT PATH TO YOUR PID FILE !!! * The final is only written when the * daemon exits, threfore we need to supply it here. */ if (TRUE == file_exists("/var/run/yule.pid")) { echo "\n"; fi echo "\n"; ?> samhain-4.1.4/Makefile.in0000644000175000017500000023141012620122045012121 00000000000000# # Copyright Rainer Wichmann (2006) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # --- boiler-plate stuff --- # SHELL = /bin/sh srcdir = @srcdir@ srcsrc = @srcdir@/src srcinc = @srcdir@/include top_srcdir = @top_srcdir@ # Don't use VPATH - it's a portability mess # # VPATH = $(top_srcdir)/src prefix = @prefix@ exec_prefix = @exec_prefix@ sbindir = @sbindir@ sysconfdir = @sysconfdir@ localstatedir = @localstatedir@ mandir = @mandir@ datarootdir = @datarootdir@ mytmpdir = @mytmpdir@ configfile = @myconffile@ mydatafile = @mydatafile@ mylockfile = @mylockfile@ mylogfile = @mylogfile@ mydatadir = @mydataroot@ mylogdir = @mylogdir@ mylockdir = @mylockdir@ selectconfig = @selectconfig@ top_builddir = . INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL@ -s -m 700 INSTALL_SHELL = @INSTALL@ -m 700 INSTALL_DATA = @INSTALL@ -m 600 INSTALL_MAN = @INSTALL@ -m 644 INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_NAME = @install_name@ INSTALL_DSYS = @INSTALL@ -m 755 PACKAGE = @PACKAGE@ VERSION = @VERSION@ BUILD_NUM = 1 DEFAULT_MAINTAINER = Nobody Nowhere VFLAG = @mytclient@ SETPWD = @setpwd_prg@ STEGIN = @stegin_prg@ SAMHAIN = @sh_main_prg@ YULECTL = @yulectl_prg@ SADMIN = @samhainadmin_prg@ XOR_CODE = @xor_code@ TIGER_SRC = @tiger_src@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CC = @CC@ BUILD_CC = @BUILD_CC@ # DBGDEF = -pg -DSH_PROFILE=1 DBGDEF = @mydebugdef@ DEFS = $(DBGDEF) @DEFS@ -I. -I$(top_srcdir)/include CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS_TRY = @LIBS@ LIBS_SOCK = @sh_libsocket@ LIBS_KVM = @sh_libkvm@ CFLAGS = @CFLAGS@ CUTEST = COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(CUTEST) LINK = $(CC) $(DBGDEF) -O $(LDFLAGS) -o $@ DESTDIR = TAR = tar GZIP = --best # For creating a packed client # CLIENTPASSWD = .SUFFIXES: # Delete the default suffixes # # --- Files ------- # HEADERS = samhain.h sh_unix.h sh_utils.h sh_error.h sh_error_min.h sh_files.h \ sh_getopt.h sh_readconf.h sh_tiger.h sh_hash.h \ sh_mail.h sh_mail_int.h sh_nmail.h sh_filter.h \ sh_mem.h sh_entropy.h sh_xfer.h sh_modules.h sh_utmp.h \ sh_suidchk.h sh_srp.h sh_fifo.h sh_html.h sh_tools.h \ sh_gpg.h sh_cat.h sh_calls.h sh_extern.h sh_database.h sh_trace.h \ sh_schedule.h bignum.h trustfile.h slib.h zAVLTree.h \ lzoconf.h minilzo.h rijndael-alg-fst.h rijndael-api-fst.h \ rijndael-boxes-fst.h sh_socket.h sh_ignore.h sh_prelude.h \ sh_mounts.h sh_userfiles.h sh_static.h sh_prelink.h \ sh_processcheck.h sh_portcheck.h sh_pthread.h sh_string.h \ sh_log_check.h sh_log_evalrule.h sh_log_correlate.h \ sh_log_mark.h sh_log_repeat.h sh_inotify.h sh_registry.h sh_ipvx.h \ sh_restrict.h sh_sub.h sh_fInotify.h sh_checksum.h \ sh_dbIO.h sh_dbIO_int.h sh_guid.h sh_dbCheck.h sh_dbCreate.h \ sh_sem.h SOURCES = $(srcsrc)/samhain.c $(srcsrc)/sh_unix.c \ $(srcsrc)/sh_utils.c $(srcsrc)/sh_error.c \ $(srcsrc)/sh_files.c $(srcsrc)/sh_getopt.c \ $(srcsrc)/sh_readconf.c $(srcsrc)/sh_tiger0.c \ $(srcsrc)/sh_tiger1.c $(srcsrc)/sh_tiger2.c \ $(srcsrc)/sh_tiger1_64.c $(srcsrc)/sh_tiger2_64.c \ $(srcsrc)/sh_hash.c $(srcsrc)/sh_mail.c $(srcsrc)/sh_nmail.c \ $(srcsrc)/sh_mem.c $(srcsrc)/sh_entropy.c \ $(srcsrc)/sh_xfer_client.c $(srcsrc)/sh_xfer_server.c \ $(srcsrc)/sh_xfer_syslog.c $(srcsrc)/sh_modules.c \ $(srcsrc)/sh_utmp.c $(srcsrc)/sh_login_track.c \ $(srcsrc)/sh_suidchk.c $(srcsrc)/sh_srp.c \ $(srcsrc)/sh_fifo.c $(srcsrc)/sh_tools.c \ $(srcsrc)/sh_html.c $(srcsrc)/sh_gpg.c \ $(srcsrc)/sh_cat.c $(srcsrc)/sh_calls.c \ $(srcsrc)/sh_extern.c $(srcsrc)/sh_database.c \ $(srcsrc)/sh_err_log.c $(srcsrc)/sh_err_console.c \ $(srcsrc)/sh_err_syslog.c $(srcsrc)/sh_schedule.c \ $(srcsrc)/bignum.c $(srcsrc)/mkhdr.c \ $(srcsrc)/samhain_setpwd.c $(srcsrc)/samhain_stealth.c \ $(srcsrc)/encode.c $(srcsrc)/sstrip.c \ $(srcsrc)/trustfile.c $(srcsrc)/exepack.c \ $(srcsrc)/exepack_fill.c $(srcsrc)/exepack_mkdata.c \ $(srcsrc)/minilzo.c $(srcsrc)/slib.c \ $(srcsrc)/rijndael-alg-fst.c $(srcsrc)/rijndael-api-fst.c \ $(srcsrc)/zAVLTree.c $(srcsrc)/bignum.c \ $(srcsrc)/sh_socket.c $(srcsrc)/sh_ignore.c \ $(srcsrc)/yulectl.c $(srcsrc)/sh_mounts.c \ $(srcsrc)/sh_userfiles.c $(srcsrc)/sh_prelude.c \ $(srcsrc)/sh_prelink.c $(srcsrc)/sh_static.c \ $(srcsrc)/sh_portcheck.c $(srcsrc)/sh_port2proc.c\ $(srcsrc)/sh_processcheck.c $(srcsrc)/sh_filter.c \ $(srcsrc)/sh_pthread.c $(srcsrc)/sh_string.c \ $(srcsrc)/sh_log_parse_syslog.c $(srcsrc)/sh_log_parse_pacct.c \ $(srcsrc)/sh_log_parse_samba.c $(srcsrc)/sh_log_parse_generic.c \ $(srcsrc)/sh_log_parse_apache.c $(srcsrc)/sh_log_evalrule.c \ $(srcsrc)/sh_log_correlate.c $(srcsrc)/sh_log_mark.c \ $(srcsrc)/sh_log_check.c $(srcsrc)/dnmalloc.c \ $(srcsrc)/sh_inotify.c $(srcsrc)/sh_log_repeat.c \ $(srcsrc)/sh_audit.c $(srcsrc)/sh_registry.c \ $(srcsrc)/sh_ipvx.c $(srcsrc)/sh_restrict.c \ $(srcsrc)/sh_filetype.c $(srcsrc)/sh_sub.c $(srcsrc)/sh_fInotify.c \ $(srcsrc)/sh_checksum.c $(srcsrc)/sh_guid.c $(srcsrc)/sh_sem.c \ $(srcsrc)/sh_dbIO.c $(srcsrc)/sh_dbCheck.c $(srcsrc)/sh_dbCreate.c \ $(srcsrc)/t-test1.c OBJECTS = sh_files.o sh_tiger0.o sh_tiger2.o sh_tiger2_64.o \ samhain.o sh_unix.o sh_utils.o sh_error.o \ sh_getopt.o sh_readconf.o sh_filter.o \ sh_hash.o sh_mail.o sh_nmail.o sh_mem.o sh_login_track.o \ sh_entropy.o sh_modules.o sh_utmp.o \ sh_xfer_client.o sh_xfer_server.o sh_xfer_syslog.o \ sh_suidchk.o sh_srp.o sh_fifo.o sh_tools.o sh_html.o sh_gpg.o \ sh_cat.o sh_calls.o sh_extern.o sh_database.o sh_err_log.o \ sh_err_console.o sh_err_syslog.o sh_schedule.o bignum.o \ trustfile.o rijndael-alg-fst.o rijndael-api-fst.o slib.o \ zAVLTree.o sh_socket.o sh_ignore.o sh_prelude.o \ sh_mounts.o sh_userfiles.o sh_prelink.o sh_static.o \ sh_processcheck.o sh_portcheck.o sh_port2proc.o \ sh_log_parse_syslog.o sh_log_parse_pacct.o sh_log_parse_apache.o \ sh_log_parse_samba.o sh_log_evalrule.o sh_log_check.o \ sh_log_parse_generic.o \ sh_log_correlate.o sh_log_mark.o sh_log_repeat.o \ sh_pthread.o sh_string.o sh_inotify.o dnmalloc.o \ sh_audit.o sh_registry.o sh_ipvx.o sh_restrict.o \ sh_filetype.o sh_sub.o sh_fInotify.o sh_checksum.o \ sh_guid.o sh_sem.o sh_dbIO.o sh_dbCheck.o sh_dbCreate.o TESTSUITE = test.sh testcompile.sh testhash.sh testtiger.txt \ testtimesrv.sh \ testext.sh testrc_1ext.in test_ext.c.in testrun_1d.sh \ testrun_1.sh testrun_1a.sh testrun_1b.sh testrun_1c.sh testrc_1 \ testrun_2.sh testrun_2a.sh testrun_2b.sh testrc_2.in \ testrun_2c.sh testrun_2d.sh DIST_COMMON = README COPYING LICENSE samhain.jpg \ samhainrc.linux samhainrc.solaris samhainrc.freebsd samhainrc.aix5.2.0 \ samhainrc.netbsd yulerc.template \ Install.sh DIST_NEEDED = Makefile.in deploy.sh.in samhain-install.sh.in \ samhain.spec.in rules.deb.in rules.deb-light.in samhain.spec hp_ux.psf.in \ stealth_template.jpg \ config.guess config.h.in stamp-h.in config.sub configure \ configure.ac acconfig.h aclocal.m4 install-sh missing mkinstalldirs \ c_random.sh c_bits.sh depend.sum depend.dep stamp-hdep DISTFILES = $(DIST_COMMON) $(DIST_NEEDED) \ src include man scripts init docs sql_init test dsys PROGRAMS = $(SETPWD) $(STEGIN) $(SAMHAIN) $(YULECTL) $(SADMIN) #---------------------------------------------------------- # # the first target is the default one # #---------------------------------------------------------- all: $(top_srcdir)/depend.sum $(SETPWD) $(STEGIN) $(SAMHAIN) $(YULECTL) sstrip #---------------------------------------------------------- # # rules for automatic updating of configuration information # after changing the configuration files # #---------------------------------------------------------- $(top_srcdir)/configure: $(top_srcdir)/configure.ac $(top_srcdir)/aclocal.m4 cd $(srcdir) && autoconf # autoheader might not change config.h.in, so touch a stamp file. $(top_srcdir)/config.h.in: $(top_srcdir)/stamp-h.in touch $(top_srcdir)/config.h.in $(top_srcdir)/stamp-h.in: $(top_srcdir)/configure.ac $(top_srcdir)/aclocal.m4 cd $(top_srcdir) && autoheader echo timestamp > $(top_srcdir)/stamp-h.in config.h: stamp-h @sleep 1; \ touch config.h stamp-h: $(top_srcdir)/config.h.in config.status ./config.status Makefile: $(top_srcdir)/Makefile.in config.status ./config.status samhain-install.sh: $(top_srcdir)/samhain-install.sh.in config.status ./config.status config.status: $(top_srcdir)/configure ./config.status --recheck #---------------------------------------------------------- # # rules for automatic dependency tracking # #---------------------------------------------------------- depend-gen: $(srcsrc)/depend-gen.c @echo "$(BUILD_CC) -I. -o depend-gen $(srcsrc)/depend-gen.c"; \ $(BUILD_CC) -I. -o depend-gen $(srcsrc)/depend-gen.c 2>/dev/null || \ echo "failed to compile ... hope depend.dep is ok" # redo if sources change # $(top_srcdir)/depend.dep: depend-gen $(SOURCES) @echo "update depend.dep ..."; \ test -f $(srcdir)/depend.dep || echo > $(srcdir)/depend.dep; \ if test -f depend-gen; then \ failfiles=""; \ for ff in $(SOURCES); do \ ./depend-gen -i '$$(srcinc)/' -o $(top_srcdir)/depend.dep $$ff || \ failfiles="$${failfiles} $$ff"; \ done; \ if test x"$${failfiles}" != x; then \ echo "--------------------------------------------------------";\ echo " depend-gen failed to update depend.dep. You can safely"; \ echo " ignore this error, unless you have modified the source"; \ echo " files and changed their dependencies."; \ echo "--------------------------------------------------------";\ else \ echo $(srcsrc) > $(top_srcdir)/stamp-dep; \ fi; \ else \ echo "depend-gen not found ... depend.dep not modified"; \ fi # only updated if depencies change # $(top_srcdir)/depend.sum: $(top_srcdir)/depend.dep @if test -f depend-gen; then \ nsum=`./depend-gen -c $(top_srcdir)/depend.dep|awk '{print $$1}'`; \ osum=`cat $(top_srcdir)/depend.sum 2>/dev/null`; \ if test "x$$osum" != "x$$nsum"; then \ echo "update $(top_srcdir)/depend.sum ..."; \ echo $$nsum > $(top_srcdir)/depend.sum; \ echo timestamp > $(top_srcdir)/stamp-hdep; \ fi; \ fi; $(top_srcdir)/stamp-hdep: touch $(top_srcdir)/stamp-hdep && touch $(top_srcdir)/Makefile.in $(top_srcdir)/Makefile.in: $(top_srcdir)/stamp-hdep @echo "update Makefile.in ..."; \ echo "cp Makefile.in Makefile.in.bak"; \ cp $(top_srcdir)/Makefile.in $(top_srcdir)/Makefile.in.bak; \ if test -f depend-gen; then \ failfiles=""; \ for ff in $(SOURCES); do \ ./depend-gen -i '$$(srcinc)/' -o $(top_srcdir)/Makefile.in $$ff || \ failfiles="$${failfiles} $$ff"; \ done; \ if test x"$${failfiles}" != x; then \ echo "--------------------------------------------------------";\ echo " depend-gen failed to update Makefile.in. You can safely"; \ echo " ignore this error, unless you have modified the source"; \ echo " files and changed their dependencies."; \ echo "--------------------------------------------------------";\ else \ echo $(srcsrc) > $(top_srcdir)/stamp-dep; \ fi; \ fi # do it manually # depend: depend-gen @echo "update Makefile.in ..."; \ for ff in $(SOURCES); do \ ./depend-gen -i '$$(srcinc)/' -o $(top_srcdir)/Makefile.in $$ff; \ echo $(srcsrc) > $(top_srcdir)/stamp-dep; \ done #---------------------------------------------------------- # # CLEAN rules # #---------------------------------------------------------- # everything created by make # CLEANFILES = encode config_xor.h depend-gen \ internal.h sh_MK.h trustfile sstrip samhain mkhdr encode cutest \ yule samhain_setpwd samhain_stealth samhainrc yulectl clean: -rm -f core *.o @-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) # everything created by (./configure && make) # DISTCLEANFILES = Makefile samhain.spec sh_gpg_checksum.h sh_gpg_fp.h \ init/samhain.startLinux init/samhain.startGentoo \ init/samhain.startLSB init/samhain.startFreeBSD \ init/samhain.startSolaris init/samhain.startHPUX \ init/samhain.startIRIX init/samhain.startMACOSX \ deploy.sh sh_MK.h samhain-install.sh sh_gpg_chksum.h sh_gpg_fp.h \ rules.deb rules.deb-light src/CuTestMain.c \ scripts/samhainadmin.pl scripts/check_samhain.pl \ scripts/samhain.ebuild scripts/samhain.ebuild-light \ scripts/yuleadmin.pl scripts/logrotate \ scripts/redhat_i386.client.spec scripts/samhain.spec hp_ux.psf TESTCLEANFILES = samhain.build samhain.new yule.html \ test_ext test_ext.c test_ext.res testhash.tmp \ testrc1.signed testrc_1ext testrc_2 testrc_2.signed \ test_dnmalloc distclean: clean -rm -f config.status config.log configure.lineno config.h config.cache @-test -z "$(TESTCLEANFILES)" || rm -f $(TESTCLEANFILES) @-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) #---------------------------------------------------------- # # TEST rules # #---------------------------------------------------------- test14: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 14 `hostname -f` test13: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 13 `hostname -f` test12: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 12 `hostname -f` test11: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 11 `hostname -f` test10: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 10 `hostname -f` test7: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 7 test6: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 6 test5: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 5 test4: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 4 test3: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 3 test2: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 2 test1: test @cd test && TOP_SRCDIR=$(top_srcdir) && \ export TOP_SRCDIR && ./test.sh 1 test: @if test -f test; then \ :; \ else \ cp -pr $(top_srcdir)/test .; \ cat $(top_srcdir)/test/test.sh | \ sed 's%XXXSRCXXX%$(top_srcdir)%' > test/test.sh; \ chmod +x test/test.sh; \ fi test_dnmalloc: $(srcsrc)/t-test1.c dnmalloc.o $(COMPILE) $(VFLAG) -o t-test1.o -c $(srcsrc)/t-test1.c; \ $(LINK) t-test1.o dnmalloc.o $(LIBS_TRY) #---------------------------------------------------------- # # INSTALL rules # #---------------------------------------------------------- install: install-program install-man install-data @echo; \ echo " You can use 'samhain-install.sh uninstall' for uninstalling"; \ echo " i.e. you might consider saving that script for future use";\ echo; \ echo " Use 'make install-boot' if you want @install_name@ to start on system boot"; \ echo install-light: install-program install-data @echo; \ echo " You can use 'samhain-install.sh uninstall' for uninstalling"; \ echo " i.e. you might consider saving that script for future use";\ echo; \ echo " Use 'make install-boot' if you want @install_name@ to start on system boot"; \ echo purge: uninstall-program uninstall-man @echo "./samhain-install.sh --destdir=$(DESTDIR) --force --verbose uninstall-data"; \ ./samhain-install.sh --destdir=$(DESTDIR) --force --verbose uninstall-data remove: uninstall uninstall: uninstall-program uninstall-man uninstall-data @echo; \ echo " Use 'make purge' if you also want to uninstall the configuration file"; \ echo " Use 'make uninstall-boot' to uninstall the runlevel scripts"; \ echo # # --- boot --- # install-boot: samhain-install.sh ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose install-boot uninstall-boot: samhain-install.sh ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-boot # # --- program --- # install-program: $(PROGRAMS) sstrip @$(mkinstalldirs) $(DESTDIR)$(sbindir) @if test x$(mytmpdir) != x; then \ $(mkinstalldirs) $(DESTDIR)$(mytmpdir); \ fi @list='$(PROGRAMS)'; for p in $$list; do \ if test -f $$p; then \ target=$(DESTDIR)$(sbindir)/`echo $$p|sed 's%samhain%@install_name@%'|sed 's%yule%@install_name@%'|sed 's%.*/%%'`; \ extension=`echo $$target|sed 's%.*\.%%'`; \ if test x$$extension = x; then \ echo " $(INSTALL_PROGRAM) $$p $$target"; \ $(INSTALL_PROGRAM) $$p $$target; \ chmod 0700 $$target; \ echo " ./sstrip $$target"; \ ./sstrip $$target; \ else \ echo " $(INSTALL_SHELL) $$p $$target"; \ $(INSTALL_SHELL) $$p $$target; \ chmod 0700 $$target; \ fi; \ else :; fi; \ done uninstall-program: @echo "./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-program";\ ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-program # # -- data files # install-user: @if test "x@need_user_install@" = x1; then \ echo "./samhain-install.sh --destdir=$(DESTDIR) --express --verbose install-user @myident@"; \ ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose install-user @myident@; \ fi @if test x"$(VFLAG)" = "x-DSH_WITH_SERVER"; then \ echo " chown root $(DESTDIR)$(mydatadir)"; \ chown root $(DESTDIR)$(mydatadir); \ echo " chmod 755 $(DESTDIR)$(mydatadir)"; \ chmod 755 $(DESTDIR)$(mydatadir); \ echo " chown @myident@ $(DESTDIR)$(configfile)"; \ chown @myident@ $(DESTDIR)$(configfile); \ if test x"$(mylogdir)" = "x/var/log"; then \ if test x"@myident@" = xroot; then \ :; \ else \ echo; \ echo " ----------------------------------------------------------------"; \ echo " Directory $(mylogdir) (log file) looks like a system directory."; \ echo " You may run into problems (need write access for user @myident@)."; \ echo " ----------------------------------------------------------------"; \ echo; \ fi; \ else \ echo " chown @myident@ $(DESTDIR)$(mylogdir)"; \ chown @myident@ $(DESTDIR)$(mylogdir); \ fi; \ fi install-data: trustfile @$(mkinstalldirs) $(DESTDIR)$(sysconfdir) @$(mkinstalldirs) $(DESTDIR)$(mylockdir) @$(mkinstalldirs) $(DESTDIR)$(mylogdir) @$(mkinstalldirs) $(DESTDIR)$(mydatadir); \ chmod 700 $(DESTDIR)$(mydatadir) @if test -f samhainrc.$(selectconfig); then \ :; \ else \ if test -f $(srcdir)/samhainrc.$(selectconfig); then \ cp $(srcdir)/samhainrc.$(selectconfig) . ; \ fi; \ fi; \ if test -f yulerc; then \ :; \ else \ if test -f $(srcdir)/yulerc.template; then \ cp $(srcdir)/yulerc.template yulerc; \ fi; \ fi; \ if test -f stealth_template.jpg; then \ :; \ else \ if test -f $(srcdir)/stealth_template.jpg; then \ cp $(srcdir)/stealth_template.jpg . ; \ fi; \ fi @if test -d /etc/logrotate.d; then \ if test ! -d $(DESTDIR)/etc/logrotate.d; then \ $(mkinstalldirs) $(DESTDIR)/etc/logrotate.d; \ fi; \ if test ! -f $(DESTDIR)/etc/logrotate.d/@install_name@; then \ if test -w $(DESTDIR)/etc/logrotate.d; then \ cp $(srcdir)/scripts/logrotate $(DESTDIR)/etc/logrotate.d/@install_name@; \ else \ echo "$(DESTDIR)/etc/logrotate.d not writable"; \ fi; \ else \ echo "$(DESTDIR)/etc/logrotate.d/@install_name@ exists, not overwriting"; \ fi; \ fi @echo "./samhain-install.sh --destdir=$(DESTDIR) --express --verbose install-data"; \ ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose install-data || \ echo " ERROR: Failed to install the configuration file to $(DESTDIR)$(configfile). You need to install the configuration file manually." @if test x"$(VFLAG)" = "x-DSH_WITH_SERVER"; then \ echo;\ echo " -----------------------------------------------------";\ echo " The server will run as user @myident@ if started with";\ echo " root privileges, otherwise as the user of the parent ";\ echo " process (use --enable-identity=USER to change).";\ echo;\ echo " You may want to use: make install-user";\ echo;\ echo " - to add the user @myident@ (if not existing already)";\ echo " - to chown the data directory $(mydatadir)";\ echo " - to chown the log file directory $(mylogdir)";\ echo " - to chown the configuration file $(configfile)";\ echo " -----------------------------------------------------";\ else \ if test "x@need_user_install@" = x1; then \ echo;\ echo " -----------------------------------------------------";\ echo " You may want to use: make install-user";\ echo;\ echo " - to add the user @myident@ (if not existing already)";\ echo " -----------------------------------------------------";\ fi; \ fi uninstall-data: @echo "./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-data"; \ ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-data # # -- man files # install-man: $(mkinstalldirs) $(DESTDIR)$(mandir)/man8 $(mkinstalldirs) $(DESTDIR)$(mandir)/man5 @if test -f $(top_srcdir)/man/samhain.8 ; then \ echo " $(INSTALL_MAN) $(top_srcdir)/man/samhain.8 $(DESTDIR)$(mandir)/man8/@install_name@.8"; \ $(INSTALL_MAN) $(top_srcdir)/man/samhain.8 $(DESTDIR)$(mandir)/man8/@install_name@.8; \ fi @if test -f $(top_srcdir)/man/samhainrc.5 ; then \ echo " $(INSTALL_MAN) $(top_srcdir)/man/samhainrc.5 $(DESTDIR)$(mandir)/man5/@install_name@rc.5"; \ $(INSTALL_MAN) $(top_srcdir)/man/samhainrc.5 $(DESTDIR)$(mandir)/man5/@install_name@rc.5; \ fi uninstall-man: @echo "./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-man";\ ./samhain-install.sh --destdir=$(DESTDIR) --express --verbose uninstall-man #---------------------------------------------------------- # # BUILD rules # #---------------------------------------------------------- run: run-light run-light: all @echo "Building $(PACKAGE)-$(VERSION).run"; \ STAGE=$(PACKAGE)-$(VERSION); \ mkdir $$STAGE; \ if test x"$$?" != x0; then \ echo "ERROR ... mkdir $$STAGE failed"; \ exit 1; \ fi; \ $(MAKE) DESTDIR=$$STAGE install-light; \ rm -f $$STAGE/@sbindir@/@install_name@_stealth; \ echo "#! /bin/sh" > $$STAGE/setup.sh; \ if test x$(mytmpdir) != x; then \ echo "./mkinstalldirs @mytmpdir@ || exit 1" >> $$STAGE/setup.sh; \ fi; \ echo "./mkinstalldirs @sbindir@ || exit 1" >> $$STAGE/setup.sh; \ echo "./mkinstalldirs @sysconfdir@ || exit 1" >> $$STAGE/setup.sh; \ echo "./mkinstalldirs @mylockdir@ || exit 1" >> $$STAGE/setup.sh; \ echo "./mkinstalldirs @mylogdir@ || exit 1" >> $$STAGE/setup.sh; \ echo "./mkinstalldirs @mydataroot@ || exit 1" >> $$STAGE/setup.sh; \ echo "chmod 700 @mydataroot@ || exit 1" >> $$STAGE/setup.sh; \ temp=`echo $(sbindir) | sed s,^/,,`; \ echo "chown root $$temp/*" >> $$STAGE/setup.sh; \ echo "cp -p $$temp/* $(sbindir) || exit 1" >> $$STAGE/setup.sh; \ temp=`echo $(sysconfdir) | sed s,^/,,`; \ echo "chown root $$temp/*" >> $$STAGE/setup.sh; \ configfile=`echo @myconffile@ | sed 's%^REQ_FROM_SERVER%%'`; \ echo "test -f $$configfile || cp -p $$temp/* $$configfile" >> $$STAGE/setup.sh; \ echo "./samhain-install.sh --express --verbose install-boot || echo 'Cannot install init script'" >> $$STAGE/setup.sh; \ cp $(top_srcdir)/mkinstalldirs $$STAGE/; \ cp $(top_srcdir)/install-sh $$STAGE/; \ cp ./samhain-install.sh $$STAGE/; \ cp -r init/ $$STAGE/; \ chmod +x $$STAGE/setup.sh; \ chmod +x $$STAGE/samhain-install.sh; \ chmod +x $$STAGE/mkinstalldirs; \ chmod +x $$STAGE/install-sh; \ $(top_srcdir)/scripts/makeself/makeself.sh --header $(top_srcdir)/scripts/makeself/makeself-header.sh --nocomp --nomd5 --notemp $$STAGE $(PACKAGE)-$(VERSION).run "$(PACKAGE)_$(VERSION)_self_extracting_installer" ./setup.sh && \ rm -r $(PACKAGE)-$(VERSION) emerge-prepare: dist @echo "Building $(PACKAGE)-$(VERSION)"; \ test -f /etc/make.globals && . /etc/make.globals; \ test -f /etc/make.conf && . /etc/make.conf; \ echo "$(INSTALL_MAN) $(PACKAGE)-$(VERSION).tar.gz $${DISTDIR}/@install_name@-$(VERSION).tar.gz"; \ $(INSTALL_MAN) $(PACKAGE)-$(VERSION).tar.gz $${DISTDIR}/@install_name@-$(VERSION).tar.gz; \ if test "x$${PORTDIR_OVERLAY}" = "x"; then \ COPY_TO="$${PORTDIR}"; \ else \ COPY_TO="$${PORTDIR_OVERLAY}"; \ fi; \ $(mkinstalldirs) $${COPY_TO}/app-admin/@install_name@; \ echo "$(INSTALL_MAN) scripts/samhain.ebuild $${COPY_TO}/app-admin/@install_name@/@install_name@-$(VERSION).ebuild";\ $(INSTALL_MAN) scripts/samhain.ebuild $${COPY_TO}/app-admin/@install_name@/@install_name@-$(VERSION).ebuild; \ test -f $${COPY_TO}/app-admin/@install_name@/files/digest-@install_name@-$(VERSION) && rm $${COPY_TO}/app-admin/@install_name@/files/digest-@install_name@-$(VERSION);\ ebuild $${COPY_TO}/app-admin/@install_name@/@install_name@-$(VERSION).ebuild digest; emerge-prepare-light: dist @echo "Building $(PACKAGE)-$(VERSION)"; \ test -f /etc/make.globals && . /etc/make.globals; \ test -f /etc/make.conf && . /etc/make.conf; \ echo "$(INSTALL_MAN) $(PACKAGE)-$(VERSION).tar.gz $${DISTDIR}/@install_name@-$(VERSION).tar.gz"; \ $(INSTALL_MAN) $(PACKAGE)-$(VERSION).tar.gz $${DISTDIR}/@install_name@-$(VERSION).tar.gz; \ if test "x$${PORTDIR_OVERLAY}" = "x"; then \ COPY_TO="$${PORTDIR}"; \ else \ COPY_TO="$${PORTDIR_OVERLAY}"; \ fi; \ $(mkinstalldirs) $${COPY_TO}/app-admin/@install_name@; \ echo "$(INSTALL_MAN) scripts/samhain.ebuild-light $${COPY_TO}/app-admin/@install_name@/@install_name@-$(VERSION).ebuild";\ $(INSTALL_MAN) scripts/samhain.ebuild-light $${COPY_TO}/app-admin/@install_name@/@install_name@-$(VERSION).ebuild; \ test -f $${COPY_TO}/app-admin/@install_name@/files/digest-@install_name@-$(VERSION) && rm $${COPY_TO}/app-admin/@install_name@/files/digest-@install_name@-$(VERSION);\ ebuild $${COPY_TO}/app-admin/@install_name@/@install_name@-$(VERSION).ebuild digest; tbz2: emerge-prepare @emerge --buildpkgonly @install_name@; \ test -f /etc/make.globals && . /etc/make.globals; \ test -f /etc/make.conf && . /etc/make.conf; \ echo; \ echo "@install_name@-$(VERSION).tbz2 should be in $${PKGDIR}/All"; \ if test -f $${PKGDIR}/All/@install_name@-$(VERSION).tbz2; then \ echo "Package $${PKGDIR}/All/@install_name@-$(VERSION).tbz2 built."; \ mv $${PKGDIR}/All/@install_name@-$(VERSION).tbz2 $(PACKAGE)-$(VERSION).tbz2; \ rm -f $${PKGDIR}/app-admin/@install_name@-$(VERSION).tbz2; \ rm -rf $${PORTAGE_TMPDIR}/portage/@install_name@-$(VERSION); \ else \ echo "Error ... cannot find package."; \ exit 1; \ fi; \ echo tbz2-light: emerge-prepare-light @emerge --buildpkgonly @install_name@; \ test -f /etc/make.globals && . /etc/make.globals; \ test -f /etc/make.conf && . /etc/make.conf; \ echo; \ if test -f $${PKGDIR}/All/@install_name@-$(VERSION).tbz2; then \ echo "Package $${PKGDIR}/All/@install_name@-$(VERSION).tbz2 built."; \ mv $${PKGDIR}/All/@install_name@-$(VERSION).tbz2 $(PACKAGE)-$(VERSION).tbz2; \ rm -f $${PKGDIR}/app-admin/@install_name@-$(VERSION).tbz2; \ rm -rf $${PORTAGE_TMPDIR}/portage/@install_name@-$(VERSION); \ else \ echo "Error ... cannot find package."; \ exit 1; \ fi; \ echo emerge: emerge $(PACKAGE); deb-light: @echo "creating subdirectory debian"; \ mkdir -p debian; \ cp rules.deb-light debian/rules; \ chmod +x debian/rules; \ echo $(sbindir) | sed s,^/,, > debian/dirs; \ if test x$(mytmpdir) != x; then \ echo $(mytmpdir) | sed s,^/,, >> debian/dirs; \ fi; \ echo $(sysconfdir) | sed s,^/,, >> debian/dirs; \ echo etc/init.d >> debian/dirs; \ echo $(mydatadir) | sed s,^/,, >> debian/dirs; \ echo $(mylogdir) | sed s,^/,, >> debian/dirs; \ echo $(mylockdir) | sed s,^/,, >> debian/dirs; \ $(MAKE) deb-run deb: @echo "creating subdirectory debian"; \ mkdir -p debian; \ cp rules.deb debian/rules; \ chmod +x debian/rules; \ echo $(sbindir) | sed s,^/,, > debian/dirs; \ if test x$(mytmpdir) != x; then \ echo $(mytmpdir) | sed s,^/,, >> debian/dirs; \ fi; \ echo $(sysconfdir) | sed s,^/,, >> debian/dirs; \ echo etc/init.d >> debian/dirs; \ echo $(mydatadir) | sed s,^/,, >> debian/dirs; \ echo $(mylogdir) | sed s,^/,, >> debian/dirs; \ echo $(mylockdir) | sed s,^/,, >> debian/dirs; \ echo $(mandir)/man5 | sed s,^/,, >> debian/dirs; \ echo $(mandir)/man8 | sed s,^/,, >> debian/dirs; \ echo usr/share/doc/$(PACKAGE) >> debian/dirs; \ echo $(top_srcdir)/README > debian/docs; \ echo $(top_srcdir)/test/testtiger.txt >> debian/docs; \ echo $(srcsrc)/simple-bignum.tar.bz2 >> debian/docs; \ echo $(top_srcdir)/scripts/head.html >> debian/docs; \ echo $(top_srcdir)/scripts/foot.html >> debian/docs; \ echo $(top_srcdir)/samhain.jpg >> debian/docs; \ echo $(top_srcdir)/docs/BUGS >> debian/docs; \ echo $(top_srcdir)/docs/HOWTO-client+server.html >> debian/docs; \ echo $(top_srcdir)/docs/HOWTO-samhain+GnuPG.html >> debian/docs; \ echo $(top_srcdir)/docs/MANUAL-2_4.html.tar >> debian/docs; \ echo $(top_srcdir)/docs/MANUAL-2_4.pdf >> debian/docs; \ echo $(top_srcdir)/docs/README.gcc_bug >> debian/docs; \ echo $(top_srcdir)/docs/README.LZO >> debian/docs; \ echo $(top_srcdir)/docs/README.sstrip >> debian/docs; \ echo $(top_srcdir)/docs/README.UPGRADE >> debian/docs; \ echo $(top_srcdir)/docs/README.win2K >> debian/docs; \ $(MAKE) deb-run deb-run: @maintainer=`gpg --list-secret-keys | grep 'uid ' | cut -d" " -f 5- | sed 's/^ *//' | sed q1`;\ if test "x$$maintainer" = x; then \ maintainer="$(DEFAULT_MAINTAINER)"; \ fi; \ echo "$(PACKAGE) ($(VERSION)-$(BUILD_NUM)) stable; urgency=low" > debian/changelog; \ echo >> debian/changelog; \ echo " * Initial release." >> debian/changelog; \ echo >> debian/changelog; \ echo " -- $$maintainer `date -R`" >> debian/changelog; \ echo >> debian/changelog; \ echo "Local variables:" >> debian/changelog; \ echo "mode: debian-changelog" >> debian/changelog; \ echo "End:" >> debian/changelog; \ cp $(top_srcdir)/COPYING debian/copyright; \ touch debian/README.debian; \ echo "Document: @install_name@-manual" > debian/@install_name@.doc-base; \ echo "Title: @install_name@ Manual" >> debian/@install_name@.doc-base; \ echo "Author: Rainer Wichmann" >> debian/@install_name@.doc-base; \ echo "Abstract: This manual describes what @install_name@ is" >> debian/@install_name@.doc-base; \ echo " and how it can be used to check the file integrity of your" >> debian/@install_name@.doc-base; \ echo " server." >> debian/@install_name@.doc-base; \ echo "Section: System/Security" >> debian/@install_name@.doc-base; \ echo >> debian/@install_name@.doc-base; \ echo >> debian/@install_name@.doc-base; \ echo "Format: Postscript" >> debian/@install_name@.doc-base; \ echo "Files: /usr/share/doc/@install_name@/manual.pdf.gz" >> debian/@install_name@.doc-base; \ echo >> debian/@install_name@.doc-base; \ echo "Format: HTML" >> debian/@install_name@.doc-base; \ echo "Index: /usr/share/doc/@install_name@/manual.html/index.html" >> debian/@install_name@.doc-base; \ echo "Files: /usr/share/doc/@install_name@/manual.html/*.html" >> debian/@install_name@.doc-base; \ if test -f /usr/lib/lsb/install_initd; then \ cp init/samhain.startLSB debian/@install_name@.init; \ else \ cp init/samhain.startLinux debian/@install_name@.init; \ fi; \ echo "Source: samhain" > debian/control; \ echo "Section: admin" >> debian/control; \ echo "Priority: optional" >> debian/control; \ echo "Maintainer: $$maintainer" >> debian/control; \ echo "Standards-Version: 3.2.1" >> debian/control; \ echo >> debian/control; \ echo "Package: @install_name@" >> debian/control; \ echo "Architecture: any" >> debian/control; \ echo "Depends: libc6" >> debian/control; \ echo "Description: File integrity checker" >> debian/control; \ echo " A file integrity checker" >> debian/control; \ echo "running debuild -us -uc"; \ debuild --preserve-envvar=PASSWORD -us -uc -b; \ DEBFILE=`find ../ -follow -maxdepth 1 -cnewer ./debian/control 2>/dev/null | grep '@install_name@_$(VERSION)' | grep '\.deb'`; \ if test x"$$DEBFILE" = x; then \ echo "Error ... cannot find package file"; \ exit 1; \ else \ echo "Package $$DEBFILE built."; \ cp $$DEBFILE ./$(PACKAGE)-$(VERSION)-$(BUILD_NUM).deb; \ ln -s ./$(PACKAGE)-$(VERSION)-$(BUILD_NUM).deb ./$(PACKAGE)-$(VERSION).deb; \ fi; \ echo # # Check samhain.spec # rpmspec-full: @grep 'install-light' samhain.spec >/dev/null 2>&1; \ if test x"$$?" = "x0"; then \ echo "Your samhain.spec is from rpm-light. Please run"; \ echo " .config.status to re-create the original samhain.spec"; \ exit 1; \ fi # when editing the spec file, make an additional blank after 'make' # to avoid that it matches on a second processing # rpmspec-light: samhain.spec @echo "Stripping docs from samhain.spec"; \ cat samhain.spec | sed 's,make DESTDIR=$${RPM_BUILD_ROOT} install,make DESTDIR=$${RPM_BUILD_ROOT} install-light,' | sed s,shkeep=yes,shkeep=no, | sed s,%doc.*,, | sed '/logrotate/! { s,%attr.*,, }' > samhain.spec-light; \ mv samhain.spec-light samhain.spec rpm-light: rpmspec-light distrpm rpmbuild -ta ./$(PACKAGE)-$(VERSION).tar.gz; @RPMTOP=`cat ~/.rpmmacros 2>/dev/null | grep '%_topdir' | awk '{ print $$2}'`; \ if test x"$$RPMTOP" = x; then RPMTOP=/usr/src; fi; \ if ! test -d "$$RPMTOP"; then \ RPMTOP=`echo $$HOME/rpmbuild`; \ fi; \ echo "Searching the RPM package below $$RPMTOP ..."; \ RPMFILE=`find $$RPMTOP -follow -maxdepth 4 -cnewer ./samhain.spec 2>/dev/null | grep '@install_name@-$(VERSION)' | grep '\.rpm' | grep -v '\.src\.'`; \ echo; \ if test x"$$RPMFILE" = x; then \ echo "Error ... cannot find package file"; \ exit 1; \ else \ echo "Package $$RPMFILE built."; \ echo "Copying it to ./$(PACKAGE)-$(VERSION).rpm"; \ cp $$RPMFILE ./$(PACKAGE)-$(VERSION).rpm; \ fi; \ echo rpm: rpmspec-full distrpm rpmbuild -ta ./$(PACKAGE)-$(VERSION).tar.gz; @RPMTOP=`cat ~/.rpmmacros 2>/dev/null | grep '%_topdir' | awk '{ print $$2}'`; \ if test x"$$RPMTOP" = x; then RPMTOP=/usr/src; fi; \ if ! test -d "$$RPMTOP"; then \ RPMTOP=`echo $$HOME/rpmbuild`; \ fi; \ echo "Searching the RPM package below $$RPMTOP ..."; \ RPMFILE=`find $$RPMTOP -follow -maxdepth 4 -cnewer ./samhain.spec 2>/dev/null | grep '@install_name@-$(VERSION)' | grep '\.rpm' | grep -v '\.src\.'`; \ echo; \ if test x"$$RPMFILE" = x; then \ echo "Error ... cannot find package file"; \ exit 1; \ else \ echo "Package $$RPMFILE built."; \ echo "Copying it to ./$(PACKAGE)-$(VERSION).rpm"; \ cp $$RPMFILE ./$(PACKAGE)-$(VERSION).rpm; \ fi; \ echo srpm-dist: rpmspec-full samhain.spec @cat samhain.spec | \ sed s%\-\-with\-base=.*\,[0123456789]*%% | \ sed s%\'\'%% > samhain.spec.m; \ mv samhain.spec.m samhain.spec $(MAKE) distrpm rpmbuild -ts ./$(PACKAGE)-$(VERSION).tar.gz srpm: rpmspec-full distrpm rpmbuild -ts ./$(PACKAGE)-$(VERSION).tar.gz solaris-pkg-light: all @STAGE=/tmp/samhain-pkg-staging; \ mkdir $$STAGE; \ if test x"$$?" != x0; then \ echo "ERROR ... mkdir $$STAGE failed"; \ exit 1; \ fi; \ $(MAKE) DESTDIR=$$STAGE install-light; $(MAKE) solaris-pkg-finish solaris-pkg: all @STAGE=/tmp/samhain-pkg-staging; \ mkdir $$STAGE; \ if test x"$$?" != x0; then \ echo "ERROR ... mkdir $$STAGE failed"; \ exit 1; \ fi; \ $(MAKE) DESTDIR=$$STAGE install; $(MAKE) solaris-pkg-finish solaris-pkg-finish: @STAGE=/tmp/samhain-pkg-staging; \ $(mkinstalldirs) $$STAGE/etc/init.d; \ $(INSTALL_SHELL) init/samhain.startSolaris $$STAGE/etc/init.d/@install_name@; \ (echo 'i pkginfo'; pkgproto $$STAGE=/ ) >prototype; \ user=`id | sed s,uid=[0123456789]*\(,, | sed s,\).*,,`; \ group=`id | sed s,.*gid=[0123456789]*\(,, | sed s,\).*,,`; \ cat prototype | grep -v 'none / ' | \ sed s,$$user\ $$group,root\ sys,g > prototype.1; \ rm -f prototype.2; \ while read line; do \ echo "$${line}" | egrep '^d none' >/dev/null 2>&1; \ if [ $$? = 0 ]; then \ dir=`echo "$${line}" | awk '{ print $$3 }'`; \ if [ -d "$$dir" ]; then \ echo "d none $${dir} ? ? ?" >> prototype.2; \ else \ echo "$${line}" >> prototype.2; \ fi; \ else \ echo "$${line}" >> prototype.2; \ fi; \ done < prototype.1; \ rm -f prototype && rm prototype.1 && mv prototype.2 prototype; \ echo "d none /etc/rc0.d ? ? ?" >> prototype; \ echo "d none /etc/rc1.d ? ? ?" >> prototype; \ echo "d none /etc/rc3.d ? ? ?" >> prototype; \ echo "l none /etc/rc3.d/S99@install_name@=/etc/init.d/@install_name@" >> prototype; \ echo "l none /etc/rc0.d/K10@install_name@=/etc/init.d/@install_name@" >> prototype; \ echo "l none /etc/rc1.d/K10@install_name@=/etc/init.d/@install_name@" >> prototype; \ ARCH=`uname -p`; \ PSTAMP=`date '+%c%y%m%d%H%M%S'`; \ echo "PKG=@install_name@" > pkginfo; \ echo "NAME=file integrity check" >> pkginfo; \ echo "VERSION=$(VERSION)" >> pkginfo; \ echo "CATEGORY=system" >> pkginfo; \ echo "CLASSES=none" >> pkginfo; \ echo "VENDOR=http://la-samhna.de/samhain" >> pkginfo; \ echo "EMAIL=support@la-samhna.de" >> pkginfo; \ echo "ARCH=$$ARCH" >> pkginfo; \ echo "PSTAMP=$$PSTAMP" >> pkginfo; \ pkgmk -o; \ pkgtrans -s /var/spool/pkg /tmp/samhain-pkg-staging/@install_name@.pkg @install_name@; \ if test -f /tmp/samhain-pkg-staging/@install_name@.pkg; then \ echo; \ cp /tmp/samhain-pkg-staging/@install_name@.pkg $(PACKAGE)-$(VERSION).pkg; \ echo "Package $(PACKAGE)-$(VERSION).pkg is ready for installation"; \ echo "to install, use: pkgadd -n -d $(PACKAGE)-$(VERSION).pkg all"; \ echo; \ rm -rf /var/spool/pkg/@install_name@ /tmp/samhain-pkg-staging; \ else \ echo; \ echo "**************************************************************"; \ echo "Error ... cannot find /tmp/samhain-pkg-staging/@install_name@.pkg."; \ echo "Keeping /var/spool/pkg/@install_name@ /tmp/samhain-pkg-staging"; \ if test -d /var/spool/pkg; then \ echo "**************************************************************"; \ else \ echo "************** /var/spool/pkg is missing *********************"; \ fi; \ echo; \ exit 1; \ fi depot-prep: all STAGE=/tmp/samhain-pkg-staging; \ mkdir $$STAGE; \ if test x"$$?" != x0; then \ echo "ERROR ... mkdir $$STAGE failed"; \ exit 1; \ fi; \ $(MAKE) DESTDIR=$$STAGE install; \ $(MAKE) DESTDIR=$$STAGE install-boot; \ cp hp_ux.psf $$STAGE; \ mkdir $$STAGE/sc; \ echo "#!/sbin/sh" > $$STAGE/sc/configure; \ echo "PATH=\$$SW_PATH; export PATH" >> $$STAGE/sc/configure; \ echo "chmod 555 /sbin/init.d/samhain; chown bin:bin /sbin/init.d/@install_name@; (cd /sbin; ln -f -s /sbin/init.d/@install_name@ rc2.d/S900@install_name@; ln -f -s /sbin/init.d/@install_name@ rc1.d/K100@install_name@; )" >> $$STAGE/sc/configure; \ chmod +x $$STAGE/sc/configure; \ echo "#!/sbin/sh" > $$STAGE/sc/unconfigure; \ echo "PATH=\$$SW_PATH; export PATH" >> $$STAGE/sc/unconfigure; \ echo "rm -f /sbin/rc2.d/S900@install_name@; rm -f /sbin/rc1.d/K100@install_name@" >> $$STAGE/sc/unconfigure; \ chmod +x $$STAGE/sc/unconfigure; \ echo "#!/sbin/sh" > $$STAGE/sc/preremove; \ echo "PATH=\$$SW_PATH; export PATH" >> $$STAGE/sc/preremove; \ echo "/sbin/init.d/@install_name@ stop" >> $$STAGE/sc/preremove; \ echo "exit 0" >> $$STAGE/sc/preremove; \ chmod +x $$STAGE/sc/preremove; depot: depot-prep (cd /tmp/samhain-pkg-staging && /usr/sbin/swpackage -v -s ./hp_ux.psf -x media_type=tape @ $(PACKAGE)-$(VERSION).depot) cp /tmp/samhain-pkg-staging/$(PACKAGE)-$(VERSION).depot . rm -rf /tmp/samhain-pkg-staging depot-light: depot #--------------------------------------------------------------- trustfile: $(srcsrc)/trustfile.c config.h $(COMPILE) $(VFLAG) -DSH_IDENT=\"@myident@\" -DTRUST_MAIN -DSL_ALWAYS_TRUSTED=@mytrust@ -o trustfile $(srcsrc)/trustfile.c sh_MK.h: config.h @echo "creating sh_MK.h"; \ echo "#ifndef SH_MK_H" > sh_MK.h; \ echo "#define SH_MK_H" >> sh_MK.h; \ $(top_srcdir)/c_bits.sh @my_key_1@ MKB >> sh_MK.h; \ $(top_srcdir)/c_bits.sh @my_key_2@ MKA >> sh_MK.h; \ $(top_srcdir)/c_bits.sh @my_key_3@ MKC >> sh_MK.h; \ $(top_srcdir)/c_bits.sh @my_key_4@ MKD >> sh_MK.h; \ echo "#endif" >> sh_MK.h sstrip: $(srcsrc)/sstrip.c Makefile $(BUILD_CC) -I. -o sstrip $(srcsrc)/sstrip.c encode: $(srcsrc)/encode.c Makefile $(BUILD_CC) -I. -o encode $(srcsrc)/encode.c config_xor.h: config.h encode @echo 'encode $(XOR_CODE) config.h'; \ ./encode $(XOR_CODE) config.h; \ mv x_config.h config_xor.h $(OBJECTS): encode internal.h config_xor.h @echo "./encode $(XOR_CODE) $(srcsrc)/`echo $@ |sed 's%\.o$$%%'`.c --> x_`echo $@ |sed 's%\.o$$%%'`.c"; \ ./encode $(XOR_CODE) $(srcsrc)/`echo $@ |sed 's%\.o$$%%'`.c; \ echo "$(COMPILE) $(VFLAG) -o `echo $@ |sed 's%.*/%%'` -c x_`echo $@ |sed 's%\.o$$%%'`.c"; \ $(COMPILE) $(VFLAG) -o `echo $@ |sed 's%.*/%%'` -c x_`echo $@ |sed 's%\.o$$%%'`.c && \ rm x_`echo $@ |sed 's%\.o$$%%'`.c sh_tiger_i.o: $(srcsrc)/$(TIGER_SRC) Makefile config_xor.h @echo "$(COMPILE) $(VFLAG) -o sh_tiger_i.o -c $(srcsrc)/$(TIGER_SRC)";\ $(COMPILE) $(VFLAG) -o sh_tiger_i.o -c $(srcsrc)/$(TIGER_SRC); samhain_setpwd: encode config_xor.h $(srcsrc)/samhain_setpwd.c @echo '$(COMPILE) -o samhain_setpwd $(srcsrc)/samhain_setpwd.c'; \ ./encode $(XOR_CODE) $(srcsrc)/samhain_setpwd.c; \ $(COMPILE) -o samhain_setpwd x_samhain_setpwd.c; \ rm x_samhain_setpwd.c samhain_stealth: encode config_xor.h $(srcsrc)/samhain_stealth.c @echo '$(COMPILE) -o samhain_stealth $(srcsrc)/samhain_stealth.c'; \ ./encode $(XOR_CODE) $(srcsrc)/samhain_stealth.c; \ $(COMPILE) -o samhain_stealth x_samhain_stealth.c; \ rm x_samhain_stealth.c yulectl: encode config_xor.h $(srcsrc)/yulectl.c @echo '$(COMPILE) -o yulectl $(srcsrc)/yulectl.c $(LIBS_SOCK)'; \ ./encode $(XOR_CODE) $(srcsrc)/yulectl.c; \ $(COMPILE) -o yulectl x_yulectl.c $(LIBS_SOCK); \ rm x_yulectl.c $(SAMHAIN): internal.h $(OBJECTS) sh_tiger_i.o @-rm -f $(SAMHAIN) @echo "$(LINK) sh_tiger_i.o $(OBJECTS) $(LIBS_TRY)"; \ $(LINK) sh_tiger_i.o $(OBJECTS) $(LIBS_TRY) CUTEST_SOURCES = $(srcsrc)/cutest_sh_tools.c \ $(srcsrc)/cutest_sh_utils.c \ $(srcsrc)/cutest_sh_unix.c \ $(srcsrc)/cutest_slib.c \ $(srcsrc)/cutest_zAVLTree.c \ $(srcsrc)/cutest_sh_hash.c \ $(srcsrc)/cutest_sh_tiger0.c CUTEST_OBJECTS = cutest_sh_tools.o \ cutest_sh_utils.o \ cutest_sh_unix.o \ cutest_slib.o \ cutest_zAVLTree.o \ cutest_sh_hash.o \ cutest_sh_tiger0.o $(CUTEST_OBJECTS): $(CUTEST_SOURCES) config_xor.h internal.h @echo "./encode $(XOR_CODE) $(srcsrc)/`echo $@ |sed 's%\.o$$%%'`.c --> x_`echo $@ |sed 's%\.o$$%%'`.c"; \ ./encode $(XOR_CODE) $(srcsrc)/`echo $@ |sed 's%\.o$$%%'`.c; \ echo "$(COMPILE) $(VFLAG) -o `echo $@ |sed 's%.*/%%'` -c x_`echo $@ |sed 's%\.o$$%%'`.c"; \ $(COMPILE) $(VFLAG) -o `echo $@ |sed 's%.*/%%'` -c x_`echo $@ |sed 's%\.o$$%%'`.c; \ rm x_`echo $@ |sed 's%\.o$$%%'`.c cutest: $(SOURCES) $(CUTEST_SOURCES) @$(MAKE) CUTEST='-DSH_CUTEST=1' intcutest $(srcsrc)/CuTestMain.c: $(SOURCES) $(CUTEST_SOURCES) $(srcsrc)/make-tests.sh cd $(srcsrc)/ && ./make-tests.sh >CuTestMain.c; intcutest: internal.h $(OBJECTS) $(CUTEST_OBJECTS) sh_tiger_i.o $(srcsrc)/CuTestMain.c @$(COMPILE) -o CuTestMain.o -c $(srcsrc)/CuTestMain.c; \ $(COMPILE) -o CuTest.o -c $(srcsrc)/CuTest.c; \ rm -f samhain.o; \ ./encode $(XOR_CODE) $(srcsrc)/samhain.c; \ $(COMPILE) $(VFLAG) -o samhain.o -c x_samhain.c; \ rm x_samhain.c; \ $(LINK) sh_tiger_i.o $(CUTEST_OBJECTS) CuTestMain.o CuTest.o $(OBJECTS) $(LIBS_TRY); \ test -f ./intcutest && mv ./intcutest ./cutest; \ ./cutest runcutest: gdb ./cutest # For bignum internal.h: mkhdr @sleep 1; \ ./mkhdr bignum.o: internal.h # If your compiler can't handle long identifiers (> 6 chars), move the `#' to # the other line. mkhdr: $(srcsrc)/mkhdr.c config.h @echo "$(BUILD_CC) -I. -o mkhdr $(srcsrc)/mkhdr.c"; \ sleep 1; \ $(BUILD_CC) -I. -o mkhdr $(srcsrc)/mkhdr.c # $(COMPILE) -DBIG_SHORT_NAMES -o mkhdr $(srcdir)/mkhdr.c #---------------------------------------------------------- # # EXE PACKER rules # #---------------------------------------------------------- minilzo.o: $(srcsrc)/minilzo.c $(srcinc)/lzoconf.h $(srcinc)/minilzo.h config.h @echo "$(COMPILE) -DMINILZO_HAVE_CONFIG_H -o minilzo.o -c $(srcsrc)/minilzo.c"; \ $(COMPILE) -DMINILZO_HAVE_CONFIG_H -o minilzo.o -c $(srcsrc)/minilzo.c exepack_mkdata: $(srcsrc)/exepack_mkdata.c $(srcinc)/lzoconf.h $(srcinc)/minilzo.h minilzo.o @echo "$(COMPILE) -o exepack_mkdata.o -c $(srcsrc)/exepack_mkdata.c"; \ $(COMPILE) -o exepack_mkdata.o -c $(srcsrc)/exepack_mkdata.c; \ echo "$(LINK) exepack_mkdata.o minilzo.o"; \ $(LINK) exepack_mkdata.o minilzo.o # # prepare the data to be packed # exepack.data: $(SAMHAIN) exepack_mkdata sstrip @echo "cp ./$(SAMHAIN) ./samhain.pk.data"; \ cp ./$(SAMHAIN) ./samhain.pk.data; \ echo "strip ./samhain.pk.data"; \ strip ./samhain.pk.data > /dev/null 2>&1 || echo "... is already stripped"; \ echo "./sstrip ./samhain.pk.data"; \ ./sstrip ./samhain.pk.data > /dev/null 2>&1 || echo "sstrip returned false"; \ echo "./exepack_mkdata ./samhain.pk.data ./exepack.data 0"; \ ./exepack_mkdata ./samhain.pk.data ./exepack.data 0; \ echo "rm -f ./samhain.pk.data"; \ rm -f ./samhain.pk.data; exepack: $(srcsrc)/exepack.c minilzo.o exepack.data @echo "$(COMPILE) -o exepack.o -c $(srcsrc)/exepack.c"; \ $(COMPILE) -o exepack.o -c $(srcsrc)/exepack.c; \ echo "$(LINK) exepack.o minilzo.o"; \ $(LINK) exepack.o minilzo.o; # # this program fills the data section with the binary # exepack_fill: $(srcsrc)/exepack_fill.c minilzo.o exepack @echo "$(COMPILE) -o exepack_fill.o -c $(srcsrc)/exepack_fill.c"; \ $(COMPILE) -o exepack_fill.o -c $(srcsrc)/exepack_fill.c; \ echo "$(LINK) exepack_fill.o minilzo.o"; \ $(LINK) exepack_fill.o minilzo.o samhain.pk: $(SAMHAIN) exepack exepack_fill sstrip @echo "cp ./$(SAMHAIN) ./samhain.pk.data"; \ cp ./$(SAMHAIN) ./samhain.pk.data; \ echo "strip ./samhain.pk.data"; \ strip ./samhain.pk.data > /dev/null 2>&1 || echo "... is already stripped"; \ echo "./sstrip ./samhain.pk.data"; \ ./sstrip ./samhain.pk.data > /dev/null 2>&1 || echo "sstrip returned false"; \ test -f exepack.out && rm exepack.out; \ echo "./exepack_fill exepack samhain.pk.data exepack.out"; \ ./exepack_fill exepack samhain.pk.data exepack.out; \ chmod +x exepack.out; \ echo "strip exepack.out"; \ strip exepack.out > /dev/null 2>&1 || echo "... is already stripped"; \ ./sstrip exepack.out > /dev/null 2>&1 || echo "sstrip returned false"; \ echo "mv exepack.out samhain.pk"; \ rm -f samhain.pk; mv exepack.out samhain.pk samhain-packed: $(SAMHAIN) samhain_setpwd @echo "samhain_setpwd samhain new $(CLIENTPASSWD)"; \ samhain_setpwd samhain new $(CLIENTPASSWD); \ echo "rm -f samhain; mv samhain.new samhain"; \ rm -f samhain; mv samhain.new samhain; \ $(MAKE) samhain.pk; \ echo "rm -f samhain; mv samhain.pk samhain"; \ rm -f samhain; mv samhain.pk samhain #---------------------------------------------------------- # # DEPLOY rules # #---------------------------------------------------------- uninstall-deploy: rm -rf $(mydatadir)/profiles/source rm -rf $(mydatadir)/profiles/archpkg rm -rf $(mydatadir)/profiles/libexec rm -rf $(mydatadir)/profiles/tmp rm -rf $(mydatadir)/profiles/private @if test -f $(sbindir)/deploy.sh; then \ old_deploy=`grep 'VERSION2' $(sbindir)/deploy.sh >/dev/null 2>&1 || echo old`; \ if test x"$$old_deploy" = xold; then \ echo "rm -f $(sbindir)/deploy2.sh"; \ rm -f $(sbindir)/deploy2.sh; \ else \ echo "rm -f $(sbindir)/deploy.sh"; \ rm -f $(sbindir)/deploy.sh; \ fi; \ fi EXECFILES= comCHECKSRC comDOWNLOAD comBUILD comCLEAN comINSTALL \ funcDIALOG funcEXE funcPRINT funcSETUP funcBUILD funcINSTALL \ funcDB comUNINSTALL \ preinstall postinstall initscript # $(mydatadir)/profiles/ # | # | # |-- source -------------> (tarballs) # | # |-- configs ------------> (default configs) # | # |-- archpkg # | | # | |-- architecture -> (package, setup script) # | # |-- hosts # | | # | |-- hostname -----> (config) # | # |-- libexec ------------> (scripts) # | # |-- private ------------> (gpg key) # | # |-- tmp # install-deploy: deploy.sh samhain_stealth @echo "Creating directory tree under $(mydatadir)/profiles/"; \ $(mkinstalldirs) $(sbindir); \ $(mkinstalldirs) $(mydatadir)/profiles/source; \ $(mkinstalldirs) $(mydatadir)/profiles/configs; \ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/debian_i386; \ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/gentoo_i386; \ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/redhat_i386; \ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/linux_i386; \ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/freebsd_i386;\ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/solaris; \ $(mkinstalldirs) $(mydatadir)/profiles/archpkg/aix; \ $(mkinstalldirs) $(mydatadir)/profiles/hosts; \ $(mkinstalldirs) $(mydatadir)/profiles/libexec; \ $(mkinstalldirs) $(mydatadir)/profiles/private; \ $(mkinstalldirs) $(mydatadir)/profiles/tmp; \ if test -f $(srcdir)/../$(PACKAGE)-$(VERSION).tar.gz.asc; then \ if test -f $(srcdir)/../$(PACKAGE)-$(VERSION).tar.gz; then \ echo "Installing source tarball"; \ $(INSTALL_DATA) $(srcdir)/../$(PACKAGE)-$(VERSION).tar.gz.asc \ $(mydatadir)/profiles/source/$(PACKAGE)-$(VERSION).tar.gz.asc; \ $(INSTALL_DATA) $(srcdir)/../$(PACKAGE)-$(VERSION).tar.gz \ $(mydatadir)/profiles/source/$(PACKAGE)-$(VERSION).tar.gz; \ fi; \ fi; \ echo "Installing default configs"; \ test -f $(mydatadir)/profiles/configs/freebsd_i386.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.freebsd \ $(mydatadir)/profiles/configs/freebsd_i386.samhainrc; \ test -f $(mydatadir)/profiles/configs/debian_i386.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.linux \ $(mydatadir)/profiles/configs/debian_i386.samhainrc; \ test -f $(mydatadir)/profiles/configs/gentoo_i386.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.linux \ $(mydatadir)/profiles/configs/gentoo_i386.samhainrc; \ test -f $(mydatadir)/profiles/configs/redhat_i386.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.linux \ $(mydatadir)/profiles/configs/redhat_i386.samhainrc; \ test -f $(mydatadir)/profiles/configs/linux_i386.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.linux \ $(mydatadir)/profiles/configs/linux_i386.samhainrc; \ test -f $(mydatadir)/profiles/configs/solaris.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.solaris \ $(mydatadir)/profiles/configs/solaris.samhainrc; \ test -f $(mydatadir)/profiles/configs/aix.samhainrc || \ $(INSTALL_DATA) $(srcdir)/samhainrc.aix5.2.0 \ $(mydatadir)/profiles/configs/aix.samhainrc; \ if test -f $(mydatadir)/profiles/configs/generic.configure; then \ :; \ else \ SH_FQDN_SYSTEM=`uname -n`; \ SH_FQDN_DOMAIN=`grep -i domain /etc/resolv.conf |grep -v "\#" |awk '{print $$2}' |head -1`; \ if test -n "$${SH_FQDN_SYSTEM}" -a -n "$${SH_FQDN_DOMAIN}"; then \ sh_thishost="$${SH_FQDN_SYSTEM}.$${SH_FQDN_DOMAIN}"; \ else \ sh_thishost="FQDN_MISSING"; \ fi; \ outfile=$(mydatadir)/profiles/configs/generic.configure; \ echo "'--enable-network=client'" > $$outfile; \ echo "'--with-logserver=$${sh_thishost}'" >> $$outfile; \ echo "'--with-data-file=REQ_FROM_SERVER/var/lib/samhain/samhain_file'" >> $$outfile; \ echo "'--with-config-file=REQ_FROM_SERVER/etc/samhainrc'" >> $$outfile; \ echo "'--enable-base=@mykeybase@'" >> $$outfile; \ fi; \ $(INSTALL_SHELL) $(srcdir)/mkinstalldirs \ $(mydatadir)/profiles/libexec; \ $(INSTALL_SHELL) $(srcdir)/install-sh \ $(mydatadir)/profiles/libexec; \ for ff in $(EXECFILES); do \ test -f $(srcdir)/dsys/$$ff && $(INSTALL_SHELL) $(srcdir)/dsys/$$ff \ $(mydatadir)/profiles/libexec; \ done; \ $(INSTALL_SHELL) samhain_stealth $(mydatadir)/profiles/libexec; \ test -f $(srcdir)/dsys/0F571F6C.asc && $(INSTALL_DATA) $(srcdir)/dsys/0F571F6C.asc \ $(mydatadir)/profiles/private; \ convert +compress $(srcdir)/stealth_template.jpg stealth_template.ps >/dev/null || \ { echo "*"; echo "* 'convert' not found or not working, not installing"; echo "* $(mydatadir)/profiles/private/stealth_template.ps"; echo "* (only required for installing packages built with --enable-stealth)"; echo "*"; }; \ if test -f stealth_template.ps; then \ if test -f $(mydatadir)/profiles/private/stealth_template.ps; then \ :; \ else \ $(INSTALL_DATA) stealth_template.ps $(mydatadir)/profiles/private; \ fi; \ fi; \ if test -f $(sbindir)/deploy.sh; then \ old_deploy=`grep 'VERSION2' $(sbindir)/deploy.sh >/dev/null 2>&1 || echo old`; \ if test x"$$old_deploy" = xold; then \ echo "*"; echo "* Version 1 of deploy.sh found"; echo "*"; \ echo "* Installing $(sbindir)/deploy2.sh"; echo "*"; \ $(INSTALL_SHELL) deploy.sh $(sbindir)/deploy2.sh; \ else \ echo "Installing $(sbindir)/deploy.sh"; \ $(INSTALL_SHELL) deploy.sh $(sbindir)/deploy.sh; \ fi; \ else \ echo "Installing $(sbindir)/deploy.sh"; \ $(INSTALL_SHELL) deploy.sh $(sbindir)/deploy.sh; \ fi #---------------------------------------------------------- # # DISTRIBUTION rules # #---------------------------------------------------------- distdir = $(PACKAGE)-$(VERSION) top_distdir = $(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. # # 1) make distribution tarfile # 2) unpack the tarfile into distdir # 3) create build and install directories # 4) do the build in the build dir, with sources from distdir # 5) check (there are no subdirs, thus does nothing) # 6) install # 7) installcheck (equal to check, does nothing) # distcheck: dist -rm -rf $(distdir) GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz mkdir $(distdir)/=build mkdir $(distdir)/=inst dc_install_base=`cd $(distdir)/=inst && pwd`; \ cd $(distdir)/=build \ && ../configure --srcdir=.. --prefix=$$dc_install_base \ && $(MAKE) \ && $(MAKE) install -rm -rf $(distdir) -rm -f $(distdir).tar.gz.asc @gpg -a --detach-sign $(distdir).tar.gz; \ $(TAR) chof $(distdir).tar $(distdir).tar.gz $(distdir).tar.gz.asc; \ rm -f $(distdir).tar.gz; \ rm -f $(distdir).tar.gz.asc; \ gzip --best $(distdir).tar mv $(distdir).tar.gz $(PACKAGE)_signed-$(VERSION).tar.gz @echo "========================"; \ echo "$(PACKAGE)_signed-$(VERSION).tar.gz is ready for distribution"; \ echo "========================" # # create a tarfile for the distibution # distrpm: distdirrpm -chmod -R a+r $(distdir) -rm -rf $(distdir).tar.gz -rm -rf $(distdir).tar $(TAR) chof $(distdir).tar $(distdir) gzip -c --best $(distdir).tar > $(distdir).tar.gz -rm -rf $(distdir) dist: distdir -chmod -R a+r $(distdir) -rm -rf $(distdir).tar.gz -rm -rf $(distdir).tar $(TAR) chof $(distdir).tar $(distdir) gzip -c --best $(distdir).tar > $(distdir).tar.gz -rm -rf $(distdir) # # create a tarfile for the distibution # dist-sign: distdir -rm -f $(distdir)/scripts/samhain.ebuild -rm -f $(distdir)/scripts/samhain.ebuild-light -chmod -R a+r $(distdir) -rm -rf $(distdir).tar.gz -rm -rf $(distdir).tar $(TAR) chof $(distdir).tar $(distdir) gzip --best $(distdir).tar -rm -rf $(distdir) -rm -f $(distdir).tar.gz.asc gpg -a --detach-sign $(distdir).tar.gz $(TAR) chof $(distdir).tar $(distdir).tar.gz $(distdir).tar.gz.asc -rm -f $(distdir).tar.gz -rm -f $(distdir).tar.gz.asc gzip --best $(distdir).tar mv $(distdir).tar.gz $(PACKAGE)_signed-$(VERSION).tar.gz # # same as dist # dist-all: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) # # create distribution directory and copy files into it # INITFILES=samhain.startIRIX samhain.startFreeBSD samhain.startSolaris \ samhain.startLSB samhain.startGentoo samhain.startLinux samhain.startHPUX \ samhain.startIRIX samhain.startMACOSX SCRIPTFILES=redhat_i386.client.spec check_samhain.pl samhainadmin.pl \ yuleadmin.pl samhain.ebuild samhain.ebuild-light samhain.spec distdir: distfilecheck -rm -f $(top_srcdir)/init/*~ -rm -f $(top_srcdir)/sql_init/*~ -rm -f $(top_srcdir)/dsys/*~ -rm -f $(top_srcdir)/docs/*~ -rm -f $(top_srcdir)/include/*~ -rm -f $(top_srcdir)/src/*~ -rm -f $(top_srcdir)/test/*~ -rm -f $(top_srcdir)/scripts/*~ (cd $(top_srcdir)/init && rm -f $(INITFILES)) -rm -rf $(distdir) mkdir $(distdir) -chmod 777 $(distdir) cp scripts/samhain.spec $(distdir)/samhain.spec; \ (cd $(top_srcdir)/scripts && rm -f $(SCRIPTFILES)) @for file in $(DISTFILES); do \ d=$(top_srcdir); \ if test -f $$d/$$file || test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ fi; \ done; \ rm -f $(distdir)/scripts/*.spec # # as distdir, but don't copy spec file from scripts # distdirrpm: distfilecheck -rm -rf $(distdir) mkdir $(distdir) -chmod 777 $(distdir) @if test -f ./samhain.spec; then \ :; \ else \ echo "Error: ./samhain.spec not found, please run configure"; \ exit 1; \ fi @cp -p samhain.spec $(distdir)/samhain.spec; \ for file in $(DISTFILES); do \ d=$(top_srcdir); \ if test -f $$d/$$file || test -d $$d/$$file; then \ if test x"$$file" = "xsamhain.spec"; then \ :; \ else \ cp -pr $$d/$$file $(distdir)/$$file; \ fi; \ fi; \ done; \ rm -f $(distdir)/scripts/*.spec distfilecheck: $(top_srcdir)/config.h.in $(top_srcdir)/depend.sum @for file in $(DISTFILES); do \ d=$(top_srcdir); \ if test -f $$d/$$file || test -d $$d/$$file; then \ : \ else \ echo "File not found: $$d/$$file"; \ fi; \ done @for file in $(SOURCES); do \ if test -f $$file; then \ : \ else \ echo "File not found: $$file"; \ fi; \ done # DO NOT DELETE THIS LINE samhain.o: $(srcsrc)/samhain.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_getopt.h $(srcinc)/sh_readconf.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_restrict.h $(srcinc)/sh_nmail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_mem.h $(srcinc)/sh_xfer.h $(srcinc)/sh_tools.h $(srcinc)/sh_hash.h $(srcinc)/sh_extern.h $(srcinc)/sh_modules.h $(srcinc)/sh_ignore.h $(srcinc)/sh_prelink.h $(srcinc)/sh_sem.h sh_MK.h $(srcinc)/sh_schedule.h sh_unix.o: $(srcsrc)/sh_unix.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_hash.h $(srcinc)/sh_tools.h $(srcinc)/sh_restrict.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_tiger.h $(srcinc)/sh_prelink.h $(srcinc)/sh_pthread.h $(srcinc)/sh_sem.h $(srcinc)/sh_static.h $(srcinc)/sh_prelude.h $(srcinc)/zAVLTree.h $(srcinc)/sh_ignore.h sh_utils.o: $(srcsrc)/sh_utils.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_entropy.h $(srcinc)/sh_pthread.h sh_error.o: $(srcsrc)/sh_error.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_database.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_nmail.h $(srcinc)/sh_xfer.h $(srcinc)/sh_prelude.h $(srcinc)/sh_pthread.h $(srcinc)/sh_tools.h $(srcinc)/sh_extern.h $(srcinc)/sh_checksum.h sh_files.o: $(srcsrc)/sh_files.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_tiger.h $(srcinc)/sh_hash.h $(srcinc)/sh_ignore.h $(srcinc)/sh_inotify.h $(srcinc)/zAVLTree.h $(srcinc)/sh_dbIO.h $(srcinc)/CuTest.h sh_getopt.o: $(srcsrc)/sh_getopt.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_getopt.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_utils.h $(srcinc)/sh_mail.h $(srcinc)/sh_xfer.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_dbCheck.h $(srcinc)/sh_dbCreate.h $(srcinc)/sh_sem.h $(srcinc)/sh_extern.h sh_readconf.o: $(srcsrc)/sh_readconf.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_calls.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_xfer.h $(srcinc)/sh_gpg.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_ignore.h $(srcinc)/sh_database.h $(srcinc)/sh_mail.h $(srcinc)/sh_modules.h $(srcinc)/sh_nmail.h $(srcinc)/sh_prelink.h $(srcinc)/sh_prelude.h $(srcinc)/sh_tiger.h $(srcinc)/sh_tools.h $(srcinc)/sh_utils.h $(srcinc)/sh_restrict.h $(srcinc)/sh_socket.h sh_tiger0.o: $(srcsrc)/sh_tiger0.c Makefile config_xor.h $(srcinc)/sh_tiger.h $(srcinc)/sh_unix.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_pthread.h $(srcinc)/sh_string.h $(srcinc)/sh_checksum.h sh_tiger1.o: $(srcsrc)/sh_tiger1.c Makefile config_xor.h sh_tiger2.o: $(srcsrc)/sh_tiger2.c Makefile config_xor.h sh_tiger1_64.o: $(srcsrc)/sh_tiger1_64.c Makefile config_xor.h sh_tiger2_64.o: $(srcsrc)/sh_tiger2_64.c Makefile config_xor.h sh_hash.o: $(srcsrc)/sh_hash.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_hash.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h $(srcinc)/sh_pthread.h $(srcinc)/sh_xfer.h $(srcinc)/sh_hash.h $(srcinc)/sh_checksum.h sh_mail.o: $(srcsrc)/sh_mail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_mail.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_pthread.h $(srcinc)/sh_filter.h $(srcinc)/sh_mail_int.h $(srcinc)/sh_nmail.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_static.h $(srcinc)/sh_tools.h sh_mem.o: $(srcsrc)/sh_mem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_pthread.h sh_entropy.o: $(srcsrc)/sh_entropy.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_calls.h $(srcinc)/sh_pthread.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h sh_forward.o: $(srcsrc)/sh_forward.c Makefile config_xor.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_forward.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/rijndael-api-fst.h $(srcinc)/sh_readconf.h $(srcinc)/zAVLTree.h $(srcinc)/sh_extern.h sh_modules.o: $(srcsrc)/sh_modules.c Makefile config_xor.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utmp.h $(srcinc)/sh_mounts.h $(srcinc)/sh_userfiles.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_portcheck.h $(srcinc)/sh_logmon.h $(srcinc)/sh_registry.h $(srcinc)/sh_fInotify.h sh_utmp.o: $(srcsrc)/sh_utmp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_utmp.h $(srcinc)/sh_pthread.h $(srcinc)/sh_inotify.h sh_kern.o: $(srcsrc)/sh_kern.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_kern.h sh_ks_xor.h $(srcinc)/sh_unix.h $(srcinc)/sh_hash.h sh_suidchk.o: $(srcsrc)/sh_suidchk.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_schedule.h $(srcinc)/sh_calls.h $(srcinc)/zAVLTree.h sh_srp.o: $(srcsrc)/sh_srp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_mem.h $(srcinc)/sh_utils.h $(srcinc)/sh_srp.h $(srcinc)/bignum.h $(srcinc)/CuTest.h sh_fifo.o: $(srcsrc)/sh_fifo.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_fifo.h $(srcinc)/CuTest.h sh_tools.o: $(srcsrc)/sh_tools.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error.h $(srcinc)/sh_tools.h $(srcinc)/sh_utils.h $(srcinc)/sh_tiger.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_ipvx.h $(srcinc)/rijndael-api-fst.h $(srcinc)/rijndael-api-fst.h sh_html.o: $(srcsrc)/sh_html.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_xfer.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_html.h $(srcinc)/zAVLTree.h sh_gpg.o: $(srcsrc)/sh_gpg.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_static.h $(srcinc)/sh_gpg.h sh_cat.o: $(srcsrc)/sh_cat.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_cat.h sh_calls.o: $(srcsrc)/sh_calls.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_calls.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_sub.h $(srcinc)/sh_utils.h sh_extern.o: $(srcsrc)/sh_extern.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_extern.h $(srcinc)/sh_calls.h $(srcinc)/sh_filter.h $(srcinc)/sh_static.h sh_database.o: $(srcsrc)/sh_database.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h sh_err_log.o: $(srcsrc)/sh_err_log.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_tiger.h sh_err_console.o: $(srcsrc)/sh_err_console.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_sem.h sh_err_syslog.o: $(srcsrc)/sh_err_syslog.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h sh_schedule.o: $(srcsrc)/sh_schedule.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error_min.h $(srcinc)/sh_schedule.h bignum.o: $(srcsrc)/bignum.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/bignum.h mkhdr.o: $(srcsrc)/mkhdr.c Makefile config.h samhain_setpwd.o: $(srcsrc)/samhain_setpwd.c Makefile config_xor.h samhain_stealth.o: $(srcsrc)/samhain_stealth.c Makefile config_xor.h encode.o: $(srcsrc)/encode.c Makefile sstrip.o: $(srcsrc)/sstrip.c Makefile config.h trustfile.o: $(srcsrc)/trustfile.c Makefile config_xor.h $(srcinc)/sh_calls.h $(srcinc)/slib.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h exepack.o: $(srcsrc)/exepack.c Makefile config.h $(srcinc)/minilzo.h $(srcinc)/exepack.data exepack_fill.o: $(srcsrc)/exepack_fill.c Makefile config.h config.h $(srcinc)/minilzo.h exepack_mkdata.o: $(srcsrc)/exepack_mkdata.c Makefile config.h $(srcinc)/minilzo.h minilzo.o: $(srcsrc)/minilzo.c Makefile $(srcinc)/minilzo.h slib.o: $(srcsrc)/slib.c Makefile config_xor.h $(srcinc)/slib.h $(srcinc)/sh_calls.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_string.h $(srcinc)/sh_mem.h rijndael-alg-fst.o: $(srcsrc)/rijndael-alg-fst.c Makefile config_xor.h $(srcinc)/rijndael-alg-fst.h rijndael-api-fst.o: $(srcsrc)/rijndael-api-fst.c Makefile config_xor.h $(srcinc)/rijndael-api-fst.h zAVLTree.o: $(srcsrc)/zAVLTree.c Makefile $(srcinc)/zAVLTree.h sh_socket.o: $(srcsrc)/sh_socket.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_socket.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_calls.h $(srcinc)/sh_guid.h $(srcinc)/sh_fifo.h $(srcinc)/sh_utils.h $(srcinc)/sh_utils.h $(srcinc)/zAVLTree.h $(srcinc)/sh_html.h $(srcinc)/sh_tools.h $(srcinc)/CuTest.h sh_ignore.o: $(srcsrc)/sh_ignore.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error.h $(srcinc)/CuTest.h yulectl.o: $(srcsrc)/yulectl.c Makefile config_xor.h sh_mounts.o: $(srcsrc)/sh_mounts.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_mounts.h sh_userfiles.o: $(srcsrc)/sh_userfiles.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_modules.h $(srcinc)/sh_userfiles.h $(srcinc)/sh_utils.h $(srcinc)/sh_schedule.h $(srcinc)/sh_error.h $(srcinc)/sh_hash.h $(srcinc)/sh_files.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h sh_prelude.o: $(srcsrc)/sh_prelude.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_error_min.h $(srcinc)/sh_prelude.h $(srcinc)/sh_static.h kern_head.o: $(srcsrc)/kern_head.c Makefile config.h $(srcinc)/kern_head.h $(srcinc)/kern_head.h sh_prelink.o: $(srcsrc)/sh_prelink.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_extern.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h sh_static.o: $(srcsrc)/sh_static.c Makefile config_xor.h $(srcinc)/sh_pthread.h sh_async.o: $(srcsrc)/sh_async.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_calls.h $(srcinc)/sh_error.h sh_processcheck.o: $(srcsrc)/sh_processcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_modules.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_calls.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h sh_portcheck.o: $(srcsrc)/sh_portcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_mem.h $(srcinc)/sh_calls.h $(srcinc)/sh_utils.h $(srcinc)/sh_modules.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_ipvx.h $(srcinc)/CuTest.h sh_pthread.o: $(srcsrc)/sh_pthread.c Makefile config_xor.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_modules.h sh_string.o: $(srcsrc)/sh_string.c Makefile config_xor.h $(srcinc)/sh_string.h $(srcinc)/sh_mem.h $(srcinc)/CuTest.h dnmalloc.o: $(srcsrc)/dnmalloc.c Makefile config.h t-test1.o: $(srcsrc)/t-test1.c Makefile config.h $(srcinc)/malloc.h sh_port2proc.o: $(srcsrc)/sh_port2proc.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error_min.h $(srcinc)/sh_pthread.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_ipvx.h sh_log_parse_syslog.o: $(srcsrc)/sh_log_parse_syslog.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h sh_log_parse_pacct.o: $(srcsrc)/sh_log_parse_pacct.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h sh_log_parse_apache.o: $(srcsrc)/sh_log_parse_apache.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h sh_log_evalrule.o: $(srcsrc)/sh_log_evalrule.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/sh_log_correlate.h $(srcinc)/sh_log_mark.h $(srcinc)/sh_log_repeat.h $(srcinc)/zAVLTree.h sh_log_check.o: $(srcsrc)/sh_log_check.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/sh_log_correlate.h $(srcinc)/sh_log_mark.h $(srcinc)/sh_log_repeat.h $(srcinc)/sh_extern.h $(srcinc)/sh_modules.h sh_log_parse_samba.o: $(srcsrc)/sh_log_parse_samba.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_string.h sh_nmail.o: $(srcsrc)/sh_nmail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_mem.h $(srcinc)/sh_mail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_string.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_filter.h $(srcinc)/sh_mail_int.h $(srcinc)/zAVLTree.h sh_filter.o: $(srcsrc)/sh_filter.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_filter.h sh_inotify.o: $(srcsrc)/sh_inotify.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_inotify.h $(srcinc)/sh_mem.h $(srcinc)/sh_utils.h $(srcinc)/slib.h $(srcinc)/zAVLTree.h $(srcinc)/sh_calls.h $(srcinc)/sh_inotify.h $(srcinc)/CuTest.h sh_log_correlate.o: $(srcsrc)/sh_log_correlate.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h sh_log_mark.o: $(srcsrc)/sh_log_mark.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_mem.h $(srcinc)/sh_string.h $(srcinc)/sh_error_min.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/zAVLTree.h sh_log_repeat.o: $(srcsrc)/sh_log_repeat.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h sh_log_parse_generic.o: $(srcsrc)/sh_log_parse_generic.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_log_check.h $(srcinc)/sh_string.h sh_login_track.o: $(srcsrc)/sh_login_track.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_string.h $(srcinc)/sh_tools.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_error_min.h $(srcinc)/CuTest.h $(srcinc)/CuTest.h sh_audit.o: $(srcsrc)/sh_audit.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_utils.h sh_registry.o: $(srcsrc)/sh_registry.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_modules.h $(srcinc)/sh_hash.h $(srcinc)/sh_tiger.h sh_ipvx.o: $(srcsrc)/sh_ipvx.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_ipvx.h $(srcinc)/CuTest.h sh_restrict.o: $(srcsrc)/sh_restrict.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error_min.h $(srcinc)/sh_string.h $(srcinc)/sh_utils.h $(srcinc)/sh_restrict.h $(srcinc)/CuTest.h sh_filetype.o: $(srcsrc)/sh_filetype.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_mem.h $(srcinc)/sh_error_min.h $(srcinc)/sh_utils.h sh_sub.o: $(srcsrc)/sh_sub.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h sh_fInotify.o: $(srcsrc)/sh_fInotify.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/sh_inotify.h $(srcinc)/sh_unix.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h sh_checksum.o: $(srcsrc)/sh_checksum.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_checksum.h $(srcinc)/sh_utils.h $(srcinc)/CuTest.h sh_guid.o: $(srcsrc)/sh_guid.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/CuTest.h sh_dbIO.o: $(srcsrc)/sh_dbIO.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_gpg.h $(srcinc)/sh_tiger.h $(srcinc)/sh_xfer.h $(srcinc)/sh_pthread.h $(srcinc)/sh_socket.h $(srcinc)/sh_files.h $(srcinc)/zAVLTree.h sh_dbCheck.o: $(srcsrc)/sh_dbCheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_hash.h $(srcinc)/sh_files.h $(srcinc)/sh_tiger.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_pthread.h sh_dbCreate.o: $(srcsrc)/sh_dbCreate.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_hash.h $(srcinc)/sh_files.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_dbIO_int.h $(srcinc)/sh_pthread.h $(srcinc)/sh_guid.h sh_xfer_client.o: $(srcsrc)/sh_xfer_client.c Makefile config_xor.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_xfer.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/rijndael-api-fst.h sh_xfer_server.o: $(srcsrc)/sh_xfer_server.c Makefile config_xor.h $(srcinc)/sh_ipvx.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_xfer.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/sh_guid.h $(srcinc)/rijndael-api-fst.h $(srcinc)/sh_readconf.h $(srcinc)/zAVLTree.h $(srcinc)/sh_extern.h sh_xfer_syslog.o: $(srcsrc)/sh_xfer_syslog.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tools.h $(srcinc)/sh_utils.h $(srcinc)/sh_ipvx.h sh_xload_client.o: $(srcsrc)/sh_xload_client.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_guid.h sh_sem.o: $(srcsrc)/sh_sem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_sem.h $(srcinc)/sh_error_min.h samhain-4.1.4/stealth_template.jpg0000644000175000017500000001625712615253270014140 00000000000000JFIFGGCreated with The GIMPC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"<!1"AQaq#23BRb$r4c*!1A"Qa2#3q ?<(+1Iܦ{}wNW3IsWS_n>:fKyY)g4fTn`*ţis*\KH{U쭒oް!:aP9`V w~OW^ԯD{|[zKNYibG'!CʭXE&[VAQ|S؏TFMW6B; ?O'^#qkm&h4xm,Oh듂3G}*ۖo|u2MҊ|m-4z1(ٕgLܜa&\#0EYmT?9֊ncTļϭ]t(@xqL AӍ\ʔ^gGkf3$kZQ+ yXC^pO=˔J*aRJJ*1J*EJ*=% qRV@NEQ[@D9U#Sb7w|VL#ԧ̠ղ ` .hmXýyi{`(I5>$"ZFpy,N?+m/2yfOwʬ]B΋SȺ2tLP]B$Ք;QhTeUD[ Hil0yٮYh.ʤhiTat}=gȑr 䌏qnǁ=x멾dQxɪ3rzx50jr {P7>k'G$3(`<{42f[ \֛MHJ 3WF+If%7U~_Wdh#\~mb]_$Nq)S=0ic`D<S]; :Lr7-Fc=TCwv1EtUĩsgmW}Ю[?ky<נiMT=WbJt!RJJ*bXtTRc&*jJhFOd,YB8+zPTu'f;=0yk)9὏J=Ò*6z3YwxiHHHOү]co^IsB8U7zۯ {t4X4]:++e,ǫԶ[zmB"Ut4p5:{xV"rhi.չ'$W$޵v{3çyOΠOhQ;~>uovɭ*uB2]-%R3,>曓[wupL Rߕ/YJZ΍;c>/#Ϊ٨7>Evò2sG./ƳU-'J\5z:3gLgubD12[dWqG4=4裸PQ..NI clcqxhoiؒO+.x3vU9kN|~B!QԒx֎'_jk>OVdfM{tz55,`Ti"I}q.ckltɨ#T$zc Lp[cdGgi#8jG zO`mc~irC[5WP>) Iɩypÿ,jY3ޜ$prWx{w ,N0˸ig8it|?,ks)NgXҧqmȸI]jtb;ynjB^>GVk+Yؖxt*!:ȶȋ㲺HF+#Nbm9կ61'MUgXc%e(cPp1mWzۮ ;<- N9(ԞW4EǷY r $Wh02mi-=kCvt2sRR{i f7l⍱cghm :GBLLQXBnrp~*Rxzy`̊ ɢ1GP@c4W4S*ܘ^{3ce1[gUw6y ¼@gԞi>g;8=p Y6i12˜x)5̞( sVK7xe\xUMvQE,FCÒ<֗}6^T%ƕm0|`mn%qTRοB-ubW/YdePC+{MlO5f8.cb,z3!Ǯ+p@d>kLr/lqRsXt*zKW4#޾`VAEaۖڜ`ezht-I&F<>ǃJ>,N98#I UDQ;A#wUn7͚٣ή-hTSX=ƣoYdQ I3N[7s&8JڃI)]`t⛹$DZ3Ango&<򇡦.P;hݗ״Պ+xaXacW$H퓌\1Ƥ>ݦ-\HCD_R*ˏ y3 :pW| zs=s]keS=zoT.dy @'VәmR١tAuΊ[$q 94UT dXԜ,G%-_@ #[Lл?Q(V6ܶee'[jVoQѷ[ W`==j\@OG!h%R)"][ml/qQf |!%f+5&݃d&6i<]|rlX85kL$SFsVy&Enyv&T󫜶 Y3.6'bS*qZ^b9:k6Gk}FpÐhdvFarC⤥(,ܩ^OpjI2Z>-2C 7j$]ϗ>ړ1M"Fyxzc2"6(ۓ([MfQF6OR(?Zk3ݏ1>Oj8O3kx废lJ]| dYv}QMSd`D r}8XnȒA<ƞ.-$I'GW=CRl`iwY,X5n$ew_=c[:ЄJߴX;m |hyUCYt[Zm6xed\GG["" UƷnQNZ5hHqCɤ˷>՛cYtm XH²0@w_UJFصGCzbd$StK[ JnQ"2!|8GQ?!S YArq_k)cw)2ipuZߜ['tFs5`UojVG.6v1M1w= J*/+.%|P[rGYfB T͌!XmS8r,PMi #/ڬ!(wkܥC~W8/v/^ j&(U D{ 4]+_U>$%d%驭 nէRŚ+V ΅pA8#_1+\lRKCI<K9)mJ9kTޤw^. (Օzz?[ ]X]9zO`r*eusB5%˟ % |*n+_=Ca^ej*Ȯe%t'C2 Ѿ+\/^U'%aW1v~ |[98SSk7, Provides: %{name} Requires(pre): shadow-utils # dummy (fix configure warning) # datarootdir = @datarootdir@ # no quotes here - aparently will be expanded literally %define password %(echo $PASSWORD) %define withpwd_prg x@clmytclient@ %define withstg_prg x@stegin_prg@ # disable automatic stripping of binaries upon installation %define __spec_install_post %{nil} # required because DeadRat wants to package some debug info otherwise # (this debug info would be created by debug_install_post called # from spec_install_post) %define debug_package %{nil} # Use internal dependency generator rather than external helpers? %define _use_internal_dependency_generator 0 %description @install_name@ is an open source file integrity and host-based intrusion detection system for Linux and Unix. It can run as a daemon process, and and thus can remember file changes -- contrary to a tool that runs from cron, if a file is modified you will get only one report, while subsequent checks of that file will ignore the modification as it is already reported (unless the file is modified again). @install_name@ can optionally be used as client/server system to provide centralized monitoring for multiple host. Logging to a (MySQL or PostgreSQL) database is supported. NOTE: for security reasons, if you distribute binary executables to third parties you should point out the use of the --add-key option to modify the key material within the executable. This spec file is intended to facilitate installation on YOUR system. If you use this spec file to build a SRPM for distribution to third parties, make sure to remove the --enable-base configure option below. %prep %setup -q -n samhain-%{version} %build %if %{?_with_tests:1}%{!?_with_tests:0} # test installation (test #7 is only included if --with gpg has been # specified) for i in `seq 6` %{?_with_gpg:7}; do ./test/test.sh $i; done %endif # # configure with the user-supplied arguments to './configure' # ./configure @mydefargs@ make %if "%{withpwd_prg}" == "xDSH_WITH_CLIENT" %if 0%{?password} ./samhain_setpwd samhain new %{password} mv samhain samhain.old mv samhain.new samhain %endif %endif %install rm -rf ${RPM_BUILD_ROOT} # sstrip shouldn't be used since binaries will be stripped later ## cat << EOF > sstrip ## #!/bin/sh ## echo "*** SSTRIP DISABLED ***" ## EOF make DESTDIR=${RPM_BUILD_ROOT} install # copy script files to /var/lib/samhain so that we can use them right # after the package is installed # install -m 700 samhain-install.sh init/samhain.startLinux init/samhain.startLSB ${RPM_BUILD_ROOT}@mydataroot@ # # file list (helpful advice from Lars Kellogg-Stedman) # echo "@sbindir@/@install_name@" > sh_file_list find %{buildroot}/lib/modules \! -type d -print | \ sed 's,%{buildroot},,' >> sh_file_list %clean rm -rf ${RPM_BUILD_ROOT} %pre if test "x@install_name@" = "xyule" then getent group samhain >/dev/null || groupadd -r samhain getent passwd yule >/dev/null || \ useradd -r -g samhain -d @mydataroot@ -s /sbin/nologin \ -c "samhain server daemon" yule fi exit 0 %post if test "x@sh_lkm@" = x; then : else if test -f /sbin/depmod; then /sbin/depmod -a fi fi if [ "$1" -ge 1 ]; then # Activate boot-time start up cd @mydataroot@ /bin/sh ./samhain-install.sh --verbose install-boot rm -f ./samhain.startLSB rm -f ./samhain.startLinux if [ -f @sbindir@/@install_name@_stealth ]; then rm -f samhain-install.sh fi shkeep=yes if test x"$shkeep" = xno; then rm -f ./samhain-install.sh rm -f @sbindir@/@install_name@_stealth fi fi if [ "$1" = 1 ]; then if test -f /usr/lib/lsb/install_initd; then /usr/lib/lsb/install_initd /etc/init.d/@install_name@ fi fi %if "%{name}" != "yule" cat << EOF Samhain is installed but is NOT running yet, and the database of file signatures is NOT initialized yet. Read the documentation, review configuration files, and then (i) initialize it (@sbindir@/samhain -t init) and (ii) start it manually (@sbindir@/samhain start). It is configured to start automatically on the next boot for runlevels [2-5]. EOF %endif %if "%{name}" == "yule" cat << EOF Yule is installed but is NOT running yet, read the documentation, review configuration files, and then start it (@sbindir@/yule) It is configured to start automatically on the next boot for runlevels [2-5]. EOF %endif %preun # stop running instance of samhain, if any if [ -f @mylockdir@/%{name}.pid ]; then @sbindir@/@install_name@ stop fi if [ "$1" = 0 ]; then # remove boot-time scripts and links cd @mydataroot@ if [ -f ./samhain-install.sh ]; then /bin/sh ./samhain-install.sh --verbose uninstall-boot else if test -f /usr/lib/lsb/remove_initd; then /usr/lib/lsb/remove_initd /etc/init.d/@install_name@ fi rm -f /etc/init.d/@install_name@ fi fi %files -f sh_file_list %defattr(-,root,root) %dir @mylockdir@ %dir @mylogdir@ %doc docs/BUGS COPYING docs/Changelog %doc LICENSE docs/FAQ.html docs/HOWTO* docs/MANUAL-2_4.* docs/README* @mydataroot@ %if "%{withstg_prg}" == "xsamhain_stealth" @sbindir@/@install_name@_stealth %endif %if "%{withpwd_prg}" == "xDSH_WITH_CLIENT" @sbindir@/@install_name@_setpwd %endif %if "%{withpwd_prg}" == "xDSH_WITH_SERVER" @sbindir@/@install_name@ctl %exclude @sbindir@/@install_name@_setpwd %endif %attr(644,root,root) @mandir@/man5/@install_name@* %attr(644,root,root) @mandir@/man8/@install_name@* %attr(644,root,root) /etc/logrotate.d/@install_name@ %if "%{name}" == "yule" %attr(750,root,samhain) @mydataroot@ %attr(750,yule,samhain) @mylogdir@ %endif %config(noreplace) @myrpmconffile@ %changelog * Tue Oct 23 2012 Rainer Wichmann - fixes for yule installation * Tue May 16 2006 Rainer Wichmann - fix manual version, noticed by Imre Gergely * Tue Apr 05 2005 Rainer Wichmann - disable automatic stripping, use sstrip * Thu Mar 17 2005 Rainer Wichmann - fixes for enable-khide * Wed Oct 20 2004 Rainer Wichmann - more fixes for client/server detection - fix for samhain_stealth * Sun Aug 15 2004 Rainer Wichmann - fix detection of client/server * Sat Jun 19 2004 Rainer Wichmann - replace ./test.sh $i with make test$i - add logic for rpm-light (remove some more files after install) - make postun posix compliant (avoid empty argument list for rm -f) * Wed Dec 31 2003 Stijn Jonker - Fixed correctly build of yule-*-rpm - Fixed excluding of yule_setpwd, and including of yulectl on yule build - Fixed including of samhain_setpwd in samhain client build - Above changes required for correct build in newer rpms, with defaults for abort on unpacked files due to %_unpackaged_files_terminate_build 1 setting - Fixed installation text for yule, not to display samhain text - Added /sbin/chkconfig install_name on to enable the rc scripts * Thu Dec 11 2003 Christian Vanguers - Fixed typo in samhain.spec - Compiled on RedHat Enterprise Linux ES 3 * Thu Mar 26 2003 Rainer Wichmann - strip REQ_FROM_SERVER in config file path (%config(noreplace) ...) * Sun Jan 12 2003 Rainer Wichmann - replace %configure with ./configure * Tue Dec 24 2002 Rainer Wichmann - backported applicable changes to samhain.spec.in - warn user that database must be initialized - fix version of MANUAL in '%files' - test for chkconfig, use only if found * Sun Dec 22 2002 Andre Oliveira da Costa 1.7.0 - fixed typo with _usr macro on ./configure - stops running samhain before uninstall - implemented conditionals to allow proper uninstalls/upgrades - 'BuildPreReq: gpg' is considered only if '--with gpg' is provided - run 'chkconfig' to activate samhain after installation - warn user that samhain must be manually started after install/upgrade * Fri Dec 20 2002 Rainer Wichmann - backported to samhain.spec.in (take over user's choices from configure) - also save samhain.startLSB and samhain.startSuSE for install-boot * Thu Dec 19 2002 Andre Oliveira da Costa 1.6.6 - optional parameters '--with gpg' and '--with tests' - use of pre-defined macros whenever possible * Wed Dec 18 2002 Andre Oliveira da Costa 1.6.6 - Fixed installation process, avoiding hardcoded paths on the binaries (thks to samhain's author Rainer Wichmann) * Mon Dec 16 2002 Andre Oliveira da Costa 1.6.6 - First attempt to build from sources samhain-4.1.4/stamp-h.in0000644000175000017500000000001212724114667011765 00000000000000timestamp samhain-4.1.4/samhainrc.solaris0000644000175000017500000003542712615253270013442 00000000000000##################################################################### # # SOLARIS Configuration file for samhain. # # Based on a contribution by Sean Boran (sean [at] boran d.o.t com) # # HISTORY: # 16.Aug.03 rw add plenty of comments # 24.Jun.02 rw remove linux stuff, clean up a bit # 06.Jun.02 sb <3>, add LOTS more Solaris stuff. Also and comment at bottom # of this file. # 03.Jun.02 sb Separate Linux & Solaris # 24.Apr.02 sb Use Samhain v.15 template and tune for Solaris. # # To do: logs /var/adm/messages and /var/cron/log are # pruned weekly. ##################################################################### # # -- empty lines and lines starting with '#', ';' or '//' are ignored # -- boolean options can be Yes/No or True/False or 1/0 # -- you can PGP clearsign this file -- samhain will check (if compiled # with support) or otherwise ignore the signature # -- CHECK mail address # # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). # ##################################################################### # SETUP for file system checking: # (i) There are several policies, each has its own section. Put files # into the section for the appropriate policy (see below). # (ii) Section [EventSeverity]: # To each policy, you can assign a severity (further below). # (iii) Section [Log]: # To each log facility, you can assign a threshold severity. Only # reports with at least the threshold severity will be logged # to the respective facility (even further below). ##################################################################### ##################################################################### # # Files are defined with: file = /absolute/path # # Directories are defined with: dir = /absolute/path # or with an optional recursion depth (N <= 99): dir = N/absolute/path # # Directory inodes are checked. If you only want to check files # in a directory, but not the directory inode itself, use (e.g.): # # [ReadOnly] # dir = /some/directory # [IgnoreAll] # file = /some/directory # # You can use shell-style globbing patterns, like: file = /path/foo* # ###################################################################### [Misc] ## ## Add or subtract tests from the policies ## - if you want to change their definitions, ## you need to do that before using the policies ## # RedefReadOnly = (no default) # RedefAttributes=(no default) # RedefLogFiles=(no default) # RedefGrowingLogFiles=(no default) # RedefIgnoreAll=(no default) # RedefIgnoreNone=(no default) # RedefUser0=(no default) # RedefUser1=(no default) [Attributes] ## ## for these files, only changes in permissions and ownership are checked ## file=/etc/ssh/ssh_random_seed file=/etc/resolv.conf # There are files in /etc that might change, thus changing the directory # timestamps. Put it here as 'file', and in the ReadOnly section as 'dir'. file=/etc file=/etc/skip/randseed file=/etc/cron.d/FIFO file=/etc/devlink.tab file=/etc/.syslog_door file=/etc/syslog.pid file=/etc/.name_service_door file=/etc/mnttab file=/etc/cron.d file=/etc/mail file=/etc/inet dir=/secure/tmp dir=/etc/sysevent dir=/usr/local/imap/spool/user dir=/usr/local/imap/proc dir=/usr/local/imap/quota dir=/usr/local/qmail/queue dir=/usr/local/qmail/alias/Mailbox dir=/usr/tmp dir=/usr/aset/tmp dir=/usr/oasys/tmp dir=/var/spool/lp/tmp dir=/var/tmp dir=/var/dt/tmp dir=/tmp dir=/etc/osa [LogFiles] ## ## for these files, changes in signature, timestamps, and size are ignored ## #file=/var/run/utmp file=/etc/motd file=/var/cron/log file=/var/adm/wtmpx file=/var/adm/wtmp file=/var/adm/utmpx file=/var/adm/lastlog [GrowingLogFiles] ## ## for these files, changes in signature, timestamps, and increase in size ## are ignored ## file=/var/adm/messages [IgnoreAll] ## ## for these files, no modifications are reported ## file=/etc/utmppipe file=/usr/dt/bin/ttsnoop file=/dev/mem dir=/etc/saf # dir=/secure/tmp dir=/usr/share/man dir=/usr/share/lib/terminfo dir=/usr/demo dir=/usr/lib/adb dir=/usr/local/man dir=/usr/local/doc dir=/usr/dt/share/man dir=/usr/openwin/lib/locale dir=/usr/openwin/share/man dir=/usr/openwin/share/src dir=/usr/openwin/lib/X11/fonts dir=/var/snort dir=/var/log/snort dir=/etc/snort/rules dir=/opt/oracle/doc dir=/usr/dt/share/examples dir=/opt/SUNWebnfs/javadoc dir=/usr/local/mysql/var dir=/jumpstart/Flash dir=/jumpstart/OS dir=/jumpstart/Patches dir=/etc/opt/SUNWicg/SunScreen/.active dir=/etc/opt/SUNWicg/SunScreen/.old [IgnoreNone] ## ## for these files, all modifications (even access time) are reported ## - you may create some interesting-looking file (like /etc/safe_passwd), ## just to watch whether someone will access it ... ## [ReadOnly] ## ## for these files, only access time is ignored ## dir=/usr/bin dir=/usr/sbin dir=/usr/lib # SuSE (old) has the boot init scripts in /sbin/init.d/*, # so we go 3 levels deep dir=3/sbin # RedHat and Debian have the bootinit scripts in /etc/init.d/* or /etc/rc.d/*, # so we go 3 levels deep there too dir=3/etc # Various directories / files that may include / be SUID/SGID binaries # dir=/usr/openwin/bin dir=/usr/dt/bin #dir=/opt/install dir=/opt/OBSDssh dir=/root # Critical devices file=/dev/dsk file=/dev/rdsk file=/dev/null file=/dev/zero [User0] [User1] ## User0 and User1 are sections for files/dirs with user-definable checking ## (see the manual) [EventSeverity] ## ## Here you can assign severities to policy violations. ## If this severity exceeds the treshold of a log facility (see below), ## a policy violation will be logged to that facility. # Severity for verification failures. # # SeverityReadOnly=crit # SeverityLogFiles=crit # SeverityGrowingLogs=crit # SeverityIgnoreNone=crit # SeverityAttributes=crit # SeverityUser0=crit # SeverityUser1=crit # We have a file in IgnoreAll that might or might not be present. # Setting the severity to 'info' prevents messages about deleted/new file. # # SeverityIgnoreAll=crit SeverityIgnoreAll=info # Files : file access problems # SeverityFiles=crit # Dirs : directory access problems # SeverityDirs=crit # Names : suspect (non-printable) characters in a pathname # SeverityNames=crit [Log] ## ## Switch on/OFF log facilities and set their threshold severity ## ## Values: debug, info, notice, warn, mark, err, crit, alert, none. ## 'mark' is used for timestamps. ## ## Use 'none' to SWITCH OFF a log facility ## ## By default, everything equal to and above the threshold is logged. ## The specifiers '*', '!', and '=' are interpreted as ## 'all', 'all but', and 'only', respectively (like syslogd(8) does, ## at least on Linux). Examples: ## MailSeverity=* ## MailSeverity=!warn ## MailSeverity==crit ## E-mail ## # MailSeverity=none ## Console ## # PrintSeverity=info ## Logfile ## # LogSeverity=mark ## Syslog ## # SyslogSeverity=none ## Remote server (yule) ## # ExportSeverity=none ## External script or program ## # ExternalSeverity = none ## Logging to a database ## # DatabaseSeverity = none ## Logging to a Prelude-IDS ## # PreludeSeverity = crit ##################################################### # # Optional modules # ##################################################### # [SuidCheck] ## ## --- Check the filesystem for SUID/SGID binaries ## ## Switch on # # SuidCheckActive = yes ## Interval for check (seconds) # # SuidCheckInterval = 7200 ## Alternative: crontab-like schedule # # SuidCheckSchedule = NULL ## Directory to exclude # # SuidCheckExclude = NULL ## Limit on files per second (0 == no limit) # # SuidCheckFps = 0 ## Alternative: yield after every file # # SuidCheckYield = no ## Severity of a detection # # SeveritySuidCheck = crit ## Quarantine SUID/SGID files if found # # SuidCheckQuarantineFiles = yes ## Method for Quarantining files: # 0 - Delete the file. # 1 - Remove SUID/SGID permissions from file. # 2 - Move SUID/SGID file to quarantine dir. # # SuidCheckQuarantineMethod = 0 ## For method 1 and 3, really delete instead of truncating # # [Utmp] ## ## --- Logging of login/logout events ## ## Switch on/off # # LoginCheckActive = True ## Severity for logins, multiple logins, logouts # # SeverityLogin=info # SeverityLoginMulti=warn # SeverityLogout=info ## Interval for login/logout checks # # LoginCheckInterval = 300 # [Database] ## ## --- Logging to a relational database ## ## Database name # # SetDBName = samhain ## Database table # # SetDBTable = log ## Database user # # SetDBUser = samhain ## Database password # # SetDBPassword = (default: none) ## Database host # # SetDBHost = localhost ## Log the server timestamp for received messages # # SetDBServerTstamp = True ## Use a persistent connection # # UsePersistent = True # [External] ## ## Interface to call external scripts/programs for logging ## ## The absolute path to the command ## - Each invocation of this directive will end the definition of the ## preceding command, and start the definition of ## an additional, new command # # OpenCommand = (no default) ## Type (log or rv) ## - log for log messages, srv for messages received by the server # # SetType = log ## The command (full command line) to execute # # SetCommandLine = (no default) ## The environment (KEY=value; repeat for more) # # SetEnviron = TZ=(your timezone) ## The TIGER192 checksum (optional) # # SetChecksum = (no default) ## User who runs the command # # SetCredentials = (default: samhain process uid) ## Words not allowed in message # # SetFilterNot = (none) ## Words required (ALL of them) # # SetFilterAnd = (none) ## Words required (at least one) # # SetFilterOr = (none) ## Deadtime between consecutive calls # # SetDeadtime = 0 ## Add default environment (HOME, PATH, SHELL) # # SetDefault = no ##################################################### # # Miscellaneous configuration options # ##################################################### [Misc] ## whether to become a daemon process ## (this is not honoured on database initialisation) # # Daemon = no Daemon = yes ## whether to test signature of files (init/check/none) ## - if 'none', then we have to decide this on the command line - # # ChecksumTest = none ChecksumTest=check ## Set nice level (-19 to 19, see 'man nice'), ## and I/O limit (kilobytes per second; 0 == off) ## to reduce load on host. # # SetNiceLevel = 0 # SetIOLimit = 0 ## The version string to embed in file signature databases # # VersionString = NULL ## Interval between time stamp messages # # SetLoopTime = 60 SetLoopTime = 600 ## Interval between file checks # # SetFileCheckTime = 600 SetFileCheckTime = 7200 ## Alternative: crontab-like schedule # # FileCheckScheduleOne = NULL ## Alternative: crontab-like schedule(2) # # FileCheckScheduleTwo = NULL ## Report only once on modified files ## Setting this to 'FALSE' will generate a report for any policy ## violation (old and new ones) each time the daemon checks the file system. # # ReportOnlyOnce = True ## Report in full detail # # ReportFullDetail = False ## Report file timestamps in local time rather than GMT # # UseLocalTime = No ## The console device (can also be a file or named pipe) ## - There are two console devices. Accordingly, you can use ## this directive a second time to set the second console device. ## If you have not defined the second device at compile time, ## and you don't want to use it, then: ## setting it to /dev/null is less effective than just leaving ## it alone (setting to /dev/null will waste time by opening ## /dev/null and writing to it) # # SetConsole = /dev/console ## Activate the SysV IPC message queue # # MessageQueueActive = False ## If false, skip reverse lookup when connecting to a host known ## by name rather than IP address (i.e. trust the DNS) # # SetReverseLookup = True ## --- E-Mail --- # Only highest-level (alert) reports will be mailed immediately, # others will be queued. Here you can define, when the queue will # be flushed (Note: the queue is automatically flushed after # completing a file check). # # SetMailTime = 86400 ## Maximum number of mails to queue # # SetMailNum = 10 ## Recipient (max. 8) # # SetMailAddress=root@localhost ## Mail relay (IP address) # # SetMailRelay = NULL ## Custom subject format # # MailSubject = NULL ## --- end E-Mail --- ## Path to the executable. If set, will be checksummed after startup ## and before exit. # # SamhainPath = (no default) ## The IP address of the log server # # SetLogServer = (default: compiled-in) ## The IP address of the time server # # SetTimeServer = (default: compiled-in) ## Trusted Users (comma delimited list of user names) # # TrustedUser = (no default; this adds to the compiled-in list) ## Path to the file signature database # # SetDatabasePath = (default: compiled-in) ## Path to the log file # # SetLogfilePath = (default: compiled-in) ## Path to the PID file # # SetLockfilePath = (default: compiled-in) ## The digest/checksum/hash algorithm # # DigestAlgo = TIGER192 ## Custom format for message header. ## CAREFUL if you use XML logfile format. ## ## %S severity ## %T timestamp ## %C class ## ## %F source file ## %L source line # # MessageHeader="%S %T " ## Don't log path to config/database file on startup # # HideSetup = False ## The syslog facility, if you log to syslog # # SyslogFacility = LOG_AUTHPRIV SyslogFacility=LOG_LOCAL2 ## The message authentication method ## - If you change this, you *must* change it ## on client *and* server # # MACType = HMAC-TIGER ## The Prelude-IDS profile to use for reporting ## default value is "samhain" # # PreludeProfile = samhain ## Map these samhain severities to impact severity 'info' severity # # PreludeMapToInfo = ## Map these samhain severities to impact severity 'low' severity # # PreludeMapToLow = debug info ## Map these samhain severities to impact severity 'medium' severity # # PreludeMapToMedium = notice warn err ## Map these samhain severities to impact severity 'high' severity # # PreludeMapToHigh = crit alert # everything below is ignored [EOF] ##################################################################### # This would be the proper syntax for parts that should only be # included for certain hosts. # You may enclose anything in a @HOSTNAME/@end bracket, as long as the # result still has the proper syntax for the config file. # You may have any number of @HOSTNAME/@end brackets. # HOSTNAME should be the fully qualified 'official' name # (e.g. 'nixon.watergate.com', not 'nixon'), no aliases. # No IP number - except if samhain cannot determine the # fully qualified hostname. # # @HOSTNAME # file=/foo/bar # @end # # These are two examples for conditional inclusion/exclusion # of a machine based on the output from 'uname -srm' # $Linux:2.*.7:i666 # file=/foo/bar3 # $end # # !$Linux:2.*.7:i686 # file=/foo/bar2 # $end # ##################################################################### samhain-4.1.4/aclocal.m40000644000175000017500000017753312633647322011751 00000000000000dnl aclocal.m4 generated automatically by aclocal 1.3 dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. dnl This Makefile.in is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A dnl PARTICULAR PURPOSE. # # Check to make sure that the build environment is sane. # AC_DEFUN([AM_INIT_AUTOMAKE], [ AC_REQUIRE([AC_PROG_INSTALL]) PACKAGE=[$1] AC_SUBST(PACKAGE) VERSION=[$2] AC_SUBST(VERSION) 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 ifelse([$3],, AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") AC_DEFINE_UNQUOTED(VERSION, "$VERSION")) AC_REQUIRE([AC_PROG_MAKE_SET])]) # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_SUBST($1_TRUE) AC_SUBST($1_FALSE) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi]) AC_DEFUN([sh_run_prog], [if test "$cross_compiling" = "yes"; then AC_MSG_ERROR([Can not probe non-portable values when cross compiling]) fi cat > conftest.$ac_ext </dev/null)` then dnl Don't remove the temporary files here, so they can be examined. ifelse([$3], , :, [$3]) else echo "configure: failed program was:" >&AC_FD_CC cat conftest.$ac_ext >&AC_FD_CC ifelse([$4], , , [ rm -fr conftest* $4 ]) fi rm -fr conftest* ]) dnl fs type number of the proc filing system AC_DEFUN([sh_procfs_id], [AC_MSG_CHECKING([f_type of /proc]) AC_CACHE_VAL([sh_cv_proc_fstype], [sh_run_prog( changequote(<<, >>)dnl <<#include #ifdef HAVE_STDLIB_H #include #endif /* HAVE_STDLIB_H */ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #ifdef HAVE_SYS_VFS_H #include #endif #ifndef Q #define __Q(x) #x #define Q(x) __Q(x) #endif int main(void) { struct statfs fsbuf; long ft; if (statfs("/", &fsbuf)!=0) exit(1); ft=fsbuf.f_type; if (statfs("/proc/1", &fsbuf)!=0) exit(1); if (ft!=fsbuf.f_type) printf("0x%08lx", fsbuf.f_type); else puts("statfs useless"); exit(0); } >> changequote([, ]), sh_cv_proc_fstype,, sh_cv_proc_fstype="a fatal error occured")]) AC_MSG_RESULT($sh_cv_proc_fstype) if test "${sh_cv_proc_fstype}" = "a fatal error occured"; then $1=$2 $4 else if test "${sh_cv_proc_fstype}" = "statfs useless"; then $1=$2 $4 else $1=$sh_cv_proc_fstype $3 fi; fi ]) # Check whether mlock is broken (hpux 10.20 raises a SIGBUS if mlock # is not called from uid 0 (not tested whether uid 0 works) dnl AC_CHECK_MLOCK dnl define([AC_CHECK_MLOCK], [ AC_CHECK_FUNCS(mlock) if test "$ac_cv_func_mlock" = "yes"; then AC_MSG_CHECKING(whether mlock is broken) AC_CACHE_VAL(ac_cv_have_broken_mlock, AC_TRY_RUN([ #include #include #include #include #include #include int main() { char *pool; int err; long int pgsize = getpagesize(); pool = malloc( 4096 + pgsize ); if( !pool ) return 2; pool += (pgsize - ((long int)pool % pgsize)); err = mlock( pool, 4096 ); if( !err || errno == EPERM ) return 0; /* okay */ return 1; /* hmmm */ } ], ac_cv_have_broken_mlock="no", ac_cv_have_broken_mlock="yes", ac_cv_have_broken_mlock="assume-no" ) ) if test "$ac_cv_have_broken_mlock" = "yes"; then AC_DEFINE(HAVE_BROKEN_MLOCK) AC_MSG_RESULT(yes) else if test "$ac_cv_have_broken_mlock" = "no"; then AC_MSG_RESULT(no) else AC_MSG_RESULT(assuming no) fi fi fi ]) dnl @synopsis AC_FUNC_VSNPRINTF dnl dnl Check whether there is a reasonably sane vsnprintf() function installed. dnl "Reasonably sane" in this context means never clobbering memory beyond dnl the buffer supplied, and having a sensible return value. It is dnl explicitly allowed not to NUL-terminate the return value, however. dnl dnl @version $Id: ac_func_vsnprintf.m4,v 1.1 2001/07/26 02:00:21 guidod Exp $ dnl @author Gaute Strokkenes dnl AC_DEFUN([SL_CHECK_VSNPRINTF], [AC_CACHE_CHECK(for working vsnprintf, ac_cv_func_vsnprintf, [AC_TRY_RUN( [#include #include int doit(char * s, ...) { char buffer[32]; va_list args; int r; buffer[5] = 'X'; va_start(args, s); r = vsnprintf(buffer, 5, s, args); va_end(args); /* -1 is pre-C99, 7 is C99. R.W. 17.01.2003 disallow -1 */ if (r != 7) exit(1); /* We deliberately do not care if the result is NUL-terminated or not, since this is easy to work around like this. */ buffer[4] = 0; /* Simple sanity check. */ if (strcmp(buffer, "1234")) exit(1); if (buffer[5] != 'X') exit(1); exit(0); } int main(void) { doit("1234567"); exit(1); }], ac_cv_func_vsnprintf=yes, ac_cv_func_vsnprintf=no, ac_cv_func_vsnprintf=no)]) dnl Note that the default is to be pessimistic in the case dnl of cross compilation. dnl If you know that the target has a sensible vsnprintf(), dnl you can get around this dnl by setting ac_func_vsnprintf to yes, as described in the Autoconf manual. if test $ac_cv_func_vsnprintf = yes; then : else AC_DEFINE(HAVE_BROKEN_VSNPRINTF, 1, [Define if you have a broken version of the `vsnprintf' function.]) fi ])# AC_FUNC_VSNPRINTF dnl SH_CHECK_TYPEDEF(TYPE, HAVE_NAME) dnl Check whether a typedef exists and create a #define $2 if it exists dnl AC_DEFUN([SH_CHECK_TYPEDEF], [ AC_MSG_CHECKING(for $1 typedef) sh_cv_typedef_foo=`echo sh_cv_typedef_$1 | sed -e 's% %_%g'` AC_CACHE_VAL( $sh_cv_typedef_foo, [AC_TRY_COMPILE([ #include #include #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif], [ #undef $1 int a = sizeof($1); ], sh_cv_typedef=yes, sh_cv_typedef=no )]) AC_MSG_RESULT($sh_cv_typedef) if test "$sh_cv_typedef" = yes; then AC_DEFINE([$2], [1], [Define if type is defined in stdint.h or inttypes.h]) sh_$2=yes else sh_$2=no fi ]) dnl ********************** dnl *** va_copy checks *** dnl ********************** AC_DEFUN([SL_CHECK_VA_COPY], [AC_MSG_CHECKING(for va_copy()) AC_CACHE_VAL(sh_cv_va_copy,[ AC_TRY_RUN([ #include void f (int i, ...) { va_list args1, args2; va_start (args1, i); va_copy (args2, args1); if (va_arg (args2, int) != 42) exit (1); if (va_arg (args1, int) != 42) exit (1); va_end (args1); va_end (args2); } int main() { f (0, 42); return 0; }], sh_cv_va_copy=yes , sh_cv_va_copy=no , sh_cv_va_copy=no) ]) AC_MSG_RESULT($sh_cv_va_copy) AC_MSG_CHECKING(for __va_copy()) AC_CACHE_VAL(sh_cv___va_copy,[ AC_TRY_RUN([ #include void f (int i, ...) { va_list args1, args2; va_start (args1, i); __va_copy (args2, args1); if (va_arg (args2, int) != 42) exit (1); if (va_arg (args1, int) != 42) exit (1); va_end (args1); va_end (args2); } int main() { f (0, 42); return 0; }], sh_cv___va_copy=yes , sh_cv___va_copy=no , sh_cv___va_copy=no) ]) AC_MSG_RESULT($sh_cv___va_copy) AC_MSG_CHECKING(whether va_lists can be copied by value) AC_CACHE_VAL(sh_cv_va_val_copy,[ AC_TRY_RUN([ #include void f (int i, ...) { va_list args1, args2; va_start (args1, i); args2 = args1; if (va_arg (args2, int) != 42) exit (1); if (va_arg (args1, int) != 42) exit (1); va_end (args1); va_end (args2); } int main() { f (0, 42); return 0; }], sh_cv_va_val_copy=yes , sh_cv_va_val_copy=no , sh_cv_va_val_copy=no) ]) if test "x$sh_cv_va_copy" = "xyes"; then AC_DEFINE(VA_COPY, va_copy) else if test "x$sh_cv___va_copy" = "xyes"; then AC_DEFINE(VA_COPY, __va_copy) fi fi if test "x$sh_cv_va_val_copy" = "xno"; then AC_DEFINE(VA_COPY_AS_ARRAY) fi AC_MSG_RESULT($sh_cv_va_val_copy) ]) dnl SH_INIT_PARSE_ARGS() m4_define([SH_INIT_PARSE_ARGS], [ m4_divert_push([PARSE_ARGS])dnl 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 # Sed expression to map a string onto a valid CPP name. as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[[^_$as_cr_alnum]]%_%g" as_tr_sh="eval sed 'y%*+%pp%;s%[[^_$as_cr_alnum]]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } # 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 AC_SUBST(exec_prefix, NONE)dnl no_create= no_recursion= AC_SUBST(prefix, NONE)dnl program_prefix=NONE program_suffix=NONE AC_SUBST(program_transform_name, [s,x,x,])dnl silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE DESTDIR= SH_ENABLE_OPTS="selinux posix-acl asm ssp db-reload xml-log message-queue login-watch process-check port-check mounts-check logfile-monitor userfiles debug ptrace static network udp nocl stealth micro-stealth install-name identity khide suidcheck base largefile mail external-scripts encrypt srp dnmalloc ipv6 shellexpand suid" SH_WITH_OPTS="prelude libprelude-prefix database libwrap cflags libs console altconsole timeserver alttimeserver rnd egd-socket port logserver altlogserver kcheck gpg keyid checksum fp recipient sender trusted tmp-dir config-file log-file pid-file state-dir data-file html-file" # 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. dnl Use braces instead of parens because sh, perl, etc. also accept them. sbindir='${exec_prefix}/sbin' sysconfdir='${prefix}/etc' localstatedir='${prefix}/var' mandir='${prefix}/share/man' AC_SUBST([sbindir], ['${exec_prefix}/sbin'])dnl AC_SUBST([sysconfdir], ['${prefix}/etc'])dnl AC_SUBST([localstatedir], ['${prefix}/var'])dnl AC_SUBST([mandir], ['${prefix}/share/man'])dnl # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= 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 changequote(, )dnl *=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; changequote([, ])dnl *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -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 ;; -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 && AC_MSG_ERROR([invalid feature name: $ac_feature]) ac_feature=`echo $ac_feature | sed 's/-/_/g'` ac_enable_check_opt=no for f in ${SH_ENABLE_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_feature}" then ac_enable_check_opt=yes fi done if test x${ac_enable_check_opt} = xno then AC_MSG_ERROR([unrecognized option: $ac_option Try `$[0] --help' for more information.]) fi eval "enable_$ac_feature=no" ;; -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 && AC_MSG_ERROR([invalid feature name: $ac_feature]) ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac ac_enable_check_opt=no for f in ${SH_ENABLE_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_feature}" then ac_enable_check_opt=yes fi done if test x${ac_enable_check_opt} = xno then AC_MSG_ERROR([unrecognized option: $ac_option Try `$[0] --help' for more information.]) fi 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 ac_exec_prefix_set="yes" ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ac_exec_prefix_set="yes" ;; -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" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ac_localstatedir_set="yes" ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ac_localstatedir_set="yes" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ac_mandir_set="yes" ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ac_mandir_set="yes" ;; -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 ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ac_prefix_set="yes" ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ac_prefix_set="yes" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ac_sbindir_set="yes" ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ac_sbindir_set="yes" ;; -bindir | --bindir | --bindi | --bind | --bin | --bi | --b) echo "WARNING: bindir will be ignored, use sbindir" ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* \ | --bi=* | --b=*) echo "WARNING: bindir will be ignored, use sbindir" ;; -datadir | --datadir) echo "WARNING: datadir will be ignored" ;; -datadir=* | --datadir=*) echo "WARNING: datadir will be ignored" ;; -includedir | --includedir) echo "WARNING: includedir will be ignored" ;; -includedir=* | --includedir=*) echo "WARNING: includedir will be ignored" ;; -infodir | --infodir) echo "WARNING: infodir will be ignored" ;; -infodir=* | --infodir=*) echo "WARNING: infodir will be ignored" ;; -libdir | --libdir) echo "WARNING: libdir will be ignored" ;; -libdir=* | --libdir=*) echo "WARNING: libdir will be ignored" ;; -libexecdir | --libexecdir) echo "WARNING: libexecdir will be ignored" ;; -libexecdir=* | --libexecdir=*) echo "WARNING: libexecdir will be ignored" ;; -sharedstatedir | --sharedstatedir) echo "WARNING: sharedstatedir will be ignored" ;; -sharedstatedir=* | --sharedstatedir=*) echo "WARNING: sharedstatedir will be ignored" ;; -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 ac_sysconfdir_set="yes" ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ac_sysconfdir_set="yes" ;; -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) 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 && AC_MSG_ERROR([invalid package name: $ac_package]) ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac ac_with_check_opt=no for f in ${SH_WITH_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_package}" then ac_with_check_opt=yes fi done if test x${ac_with_check_opt} = xno then AC_MSG_ERROR([unrecognized option: $ac_option Try `$[0] --help' for more information.]) fi 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 && AC_MSG_ERROR([invalid package name: $ac_package]) ac_package=`echo $ac_package | sed 's/-/_/g'` ac_with_check_opt=no for f in ${SH_WITH_OPTS} do f=`echo $f | sed 's/-/_/g'` if test x${f} = x"${ac_package}" then ac_with_check_opt=yes fi done if test x${ac_with_check_opt} = xno then AC_MSG_ERROR([unrecognized option: $ac_option Try `$[0] --help' for more information.]) fi eval "with_$ac_package=no" ;; -*) AC_MSG_ERROR([unrecognized option: $ac_option Try `$[0] --help' for more information.]) ;; *=*) 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 && AC_MSG_ERROR([invalid variable name: $ac_envvar]) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. AC_MSG_WARN([you should use --build, --host, --target]) expr "x$ac_option" : "[.*[^-._$as_cr_alnum]]" >/dev/null && AC_MSG_WARN([invalid host type: $ac_option]) : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then AC_MSG_ERROR(missing argument to --`echo $ac_prev | sed 's/_/-/g'`) fi # Be sure to have absolute paths. for ac_var in prefix exec_prefix do eval ac_val=$`echo $ac_var` case $ac_val in [[\\/$]]* | ?:[[\\/]]* | NONE | '' | OPT | USR ) ;; *) AC_MSG_ERROR([expected an absolute directory name for --$ac_var: $ac_val]);; esac done # Be sure to have absolute paths. for ac_var in sbindir sysconfdir localstatedir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [[\\/$]]* | ?:[[\\/]]* ) ;; *) AC_MSG_ERROR([expected an absolute directory name for --$ac_var: $ac_val]);; esac 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 AC_MSG_WARN([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.]) 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 AS_MESSAGE_FD>/dev/null m4_divert_pop([PARSE_ARGS])dnl ])# SH_INIT_PARSE_ARGS m4_define([SH_INIT_HELP], [m4_divert_push([HELP_BEGIN])dnl # # 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 m4_ifset([AC_PACKAGE_STRING], [AC_PACKAGE_STRING], [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 \`..'] _ACEOF cat <<_ACEOF 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 binaries in \`/usr/local/sbin', the config file in \`/etc', manpage in \`/usr/local/share/man', and state data in \`/var/lib/INSTALL_NAME' (FSH layout). You can specify other FSH compliant layouts with \`--prefix=OPT' or \`--prefix=USR', or you can specify a directory with \`--prefix=DIR' to install in \`DIR/sbin', \`DIR/etc', etc. For better control, use the options below. Fine tuning of the installation directories: --sbindir=DIR system admin executables [EPREFIX/sbin] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --mandir=DIR man documentation [PREFIX/man] For even finer tuning, paths can be specified for individual files (see below) _ACEOF cat <<\_ACEOF] m4_divert_pop([HELP_BEGIN])dnl dnl The order of the diversions here is dnl - HELP_BEGIN dnl which may be prolongated by extra generic options such as with X or dnl AC_ARG_PROGRAM. Displayed only in long --help. dnl dnl - HELP_CANON dnl Support for cross compilation (--build, --host and --target). dnl Display only in long --help. dnl dnl - HELP_ENABLE dnl which starts with the trailer of the HELP_BEGIN, HELP_CANON section, dnl then implements the header of the non generic options. dnl dnl - HELP_WITH dnl dnl - HELP_VAR dnl dnl - HELP_VAR_END dnl dnl - HELP_END dnl initialized below, in which we dump the trailer (handling of the dnl recursion for instance). m4_divert_push([HELP_ENABLE])dnl _ACEOF fi if test -n "$ac_init_help"; then m4_ifset([AC_PACKAGE_STRING], [ case $ac_init_help in short | recursive ) echo "Configuration of AC_PACKAGE_STRING:";; esac]) cat <<\_ACEOF m4_divert_pop([HELP_ENABLE])dnl m4_divert_push([HELP_END])dnl m4_ifset([AC_PACKAGE_BUGREPORT], [ Report bugs to .]) _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue _AC_SRCPATHS(["$ac_dir"]) cd $ac_dir # Check for guested configure; otherwise get Cygnus style 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 elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else AC_MSG_WARN([no configuration information is in $ac_dir]) fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 m4_divert_pop([HELP_END])dnl ])# SH_INIT_HELP # Check whether sa_sigaction works. # Rainer Wichmann , 2003. # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License. # serial 1 AC_DEFUN([AM_SA_SIGACTION_WORKS], [ am_cv_val_SA_SIGACTION=no AC_CHECK_HEADER(signal.h, [ AM_SI_USER AM_SA_SIGINFO if test $am_cv_val_SI_USER = yes && test $am_cv_val_SA_SIGINFO = yes then AC_TRY_RUN([ #include #include #include #include volatile int xnum = 0; volatile int xcode = 0; jmp_buf Buf; int xsig = SIGSEGV; void sighandler (int xsignam, siginfo_t * xsiginfo, void * xsigadd) { static sigset_t x; if (xsiginfo == NULL) exit(__LINE__); if (xsiginfo->si_signo != xsignam) exit(__LINE__); ++xnum; xcode = xsiginfo->si_code; sigemptyset (&x); sigprocmask(SIG_SETMASK, &x, NULL); longjmp ( Buf, 1); } int main () { struct sigaction newact; newact.sa_sigaction = sighandler; sigemptyset (&newact.sa_mask); newact.sa_flags = SA_SIGINFO; if (0 != sigaction (xsig, &newact, NULL)) exit (__LINE__); if(setjmp ( Buf)) { if (xnum > 1) goto Third; goto Second; } memcpy((void *) 0x0, "test", 5); Second: if (xcode == SI_USER) exit (__LINE__); raise(xsig); Third: if (xcode != SI_USER) exit (__LINE__); if (xnum != 2) exit (__LINE__); return (0); }], am_cv_val_SA_SIGACTION=yes, am_cv_val_SA_SIGACTION=no, am_cv_val_SA_SIGACTION=no) fi ]) AC_MSG_CHECKING([whether sa_sigaction is supported]) if test $am_cv_val_SA_SIGACTION = yes then AC_MSG_RESULT(yes) AC_DEFINE([SA_SIGACTION_WORKS], 1, [Define if sa_sigaction works]) else AC_MSG_RESULT(no) fi ]) # Check whether SI_USER is available in . # Rainer Wichmann , 2003. # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License. # serial 1 AC_DEFUN([AM_SI_USER], [if test $ac_cv_header_signal_h = yes; then AC_CACHE_CHECK([for SI_USER in signal.h], am_cv_val_SI_USER, [AC_TRY_LINK([#include ], [return SI_USER], am_cv_val_SI_USER=yes, am_cv_val_SI_USER=no)]) if test $am_cv_val_SI_USER = yes; then AC_DEFINE([HAVE_SI_USER], 1, [Define if you have SI_USER]) fi fi]) # Check whether SA_SIGINFO is available in . # Rainer Wichmann , 2003. # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License. # serial 1 AC_DEFUN([AM_SA_SIGINFO], [if test $ac_cv_header_signal_h = yes; then AC_CACHE_CHECK([for SA_SIGINFO in signal.h], am_cv_val_SA_SIGINFO, [AC_TRY_LINK([#include ], [return SA_SIGINFO], am_cv_val_SA_SIGINFO=yes, am_cv_val_SA_SIGINFO=no)]) if test $am_cv_val_SA_SIGINFO = yes; then AC_DEFINE([HAVE_SA_SIGINFO], 1, [Define if you have SA_SIGINFO]) fi fi]) dnl dnl Useful macros for autoconf to check for ssp-patched gcc dnl 1.0 - September 2003 - Tiago Sousa dnl 1.1 - August 2006 - Ted Percival dnl * Stricter language checking (C or C++) dnl * Adds GCC_STACK_PROTECT_LIB to add -lssp to LDFLAGS as necessary dnl * Caches all results dnl * Uses macros to ensure correct ouput in quiet/silent mode dnl 1.2 - April 2007 - Ted Percival dnl * Added GCC_STACK_PROTECTOR macro for simpler (one-line) invocation dnl * GCC_STACK_PROTECT_LIB now adds -lssp to LIBS rather than LDFLAGS dnl dnl About ssp: dnl GCC extension for protecting applications from stack-smashing attacks dnl http://www.research.ibm.com/trl/projects/security/ssp/ dnl dnl Usage: dnl Most people will simply call GCC_STACK_PROTECTOR. dnl If you only use one of C or C++, you can save time by only calling the dnl macro appropriate for that language. In that case you should also call dnl GCC_STACK_PROTECT_LIB first. dnl dnl GCC_STACK_PROTECTOR dnl Tries to turn on stack protection for C and C++ by calling the following dnl three macros with the right languages. dnl dnl GCC_STACK_PROTECT_CC dnl checks -fstack-protector with the C compiler, if it exists then updates dnl CFLAGS and defines ENABLE_SSP_CC dnl dnl GCC_STACK_PROTECT_CXX dnl checks -fstack-protector with the C++ compiler, if it exists then updates dnl CXXFLAGS and defines ENABLE_SSP_CXX dnl dnl GCC_STACK_PROTECT_LIB dnl adds -lssp to LIBS if it is available dnl ssp is usually provided as part of libc, but was previously a separate lib dnl It does not hurt to add -lssp even if libc provides SSP - in that case dnl libssp will simply be ignored. dnl AC_DEFUN([GCC_STACK_PROTECT_LIB],[ AC_CACHE_CHECK([whether libssp exists], ssp_cv_lib, [ssp_old_libs="$LIBS" LIBS="$LIBS -lssp" AC_TRY_LINK(,, ssp_cv_lib=yes, ssp_cv_lib=no) LIBS="$ssp_old_libs" ]) if test $ssp_cv_lib = yes; then LIBS="$LIBS -lssp" fi ]) AC_DEFUN([GCC_STACK_PROTECT_CC],[ AC_LANG_ASSERT(C) if test "X$CC" != "X"; then AC_CACHE_CHECK([whether ${CC} accepts -fstack-protector-all], ssp_cv_cc, [ssp_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -fstack-protector-all" AC_TRY_COMPILE(,, ssp_cv_cc=yes, ssp_cv_cc=no) CFLAGS="$ssp_old_cflags" ]) if test $ssp_cv_cc = no; then AC_CACHE_CHECK([whether ${CC} accepts -fstack-protector], ssp_cv_cc, [ssp_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -fstack-protector" AC_TRY_COMPILE(,, ssp_cv_cc=yes, ssp_cv_cc=no) CFLAGS="$ssp_old_cflags" ]) if test $ssp_cv_cc = yes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector" LDFLAGS="$LDFLAGS -fstack-protector" AC_DEFINE([ENABLE_SSP_CC], 1, [Define if SSP C support is enabled.]) fi else if test $ssp_cv_cc = yes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector-all" LDFLAGS="$LDFLAGS -fstack-protector-all" AC_DEFINE([ENABLE_SSP_CC], 1, [Define if SSP C support is enabled.]) fi fi fi ]) AC_DEFUN([GCC_STACK_PROTECT_CXX],[ AC_LANG_ASSERT(C++) if test "X$CXX" != "X"; then AC_CACHE_CHECK([whether ${CXX} accepts -fstack-protector], ssp_cv_cxx, [ssp_old_cxxflags="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fstack-protector" AC_TRY_COMPILE(,, ssp_cv_cxx=yes, ssp_cv_cxx=no) CXXFLAGS="$ssp_old_cxxflags" ]) if test $ssp_cv_cxx = yes; then CXXFLAGS="$CXXFLAGS -fstack-protector" AC_DEFINE([ENABLE_SSP_CXX], 1, [Define if SSP C++ support is enabled.]) fi fi ]) AC_DEFUN([GCC_STACK_PROTECTOR],[ GCC_STACK_PROTECT_LIB AC_LANG_PUSH([C]) GCC_STACK_PROTECT_CC AC_LANG_POP([C]) AC_LANG_PUSH([C++]) GCC_STACK_PROTECT_CXX AC_LANG_POP([C++]) ]) AC_DEFUN([GCC_PIE_CC],[ AC_LANG_ASSERT(C) if test "X$CC" != "X"; then AC_CACHE_CHECK([whether ${CC} accepts -pie -fPIE], pie_cv_cc, [pie_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -pie -fPIE" AC_TRY_COMPILE(,, pie_cv_cc=yes, pie_cv_cc=no) CFLAGS="$pie_old_cflags" ]) if test $pie_cv_cc = yes; then case "$host_os" in *cygwin*) ;; *) PIE_CFLAGS="-fPIE" PIE_LDFLAGS="-pie" ;; esac fi fi ]) AC_DEFUN([GCC_STACK_CHECK_CC],[ AC_LANG_ASSERT(C) if test "X$CC" != "X"; then AC_CACHE_CHECK([whether ${CC} accepts -fstack-check], stackcheck_cv_cc, [stackcheck_old_cflags="$CFLAGS" CFLAGS="$CFLAGS -fstack-check" AC_TRY_COMPILE(,, stackcheck_cv_cc=yes, stackcheck_cv_cc=no) CFLAGS="$stackcheck_old_cflags" ]) if test $stackcheck_cv_cc = yes; then CFLAGS="$CFLAGS -fstack-check" fi fi ]) AC_DEFUN([GCC_FLAG_CHECK],[ AC_LANG_ASSERT(C) if test "X$CC" != "X"; then AC_MSG_CHECKING([whether ${CC} accepts $1]) saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Werror $1" AC_TRY_COMPILE(,, flag_check_cv=yes, flag_check_cv=no) CFLAGS="$saved_cflags" if test $flag_check_cv = yes; then CFLAGS="$CFLAGS $1" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi ]) AC_DEFUN([SAMHAIN_POSIX],[ AC_MSG_CHECKING([whether _POSIX_SOURCE is necessary]) AC_TRY_COMPILE([#include void fileno(int);int fdopen(int, char *); ],, [ AC_MSG_RESULT(yes) AC_DEFINE([_POSIX_SOURCE],1,[Define if POSIX functions are required]) ], [AC_MSG_RESULT(no)]) ])dnl dnl checks for a known 64 bit programming environment dnl AC_RUN_IFELSE(PROGRAM, dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE], dnl [ACTION-IF-CROSS-COMPILING = RUNTIME-ERROR]) dnl AC_DEFUN([SAMHAIN_PRG_ENV],[ AC_MSG_CHECKING([for a known 64 bit programming environment]) # Compile and run a program that determines the programming environment AC_RUN_IFELSE([ AC_LANG_SOURCE([[ #include int main(int argc,char **argv) { if (argc > 1) { #if defined(__arch64__) printf("__arch64__\n"); #elif defined(__ia64__) printf("__ia64__\n"); #elif defined(__x86_64__) printf("__x86_64__\n"); #elif defined(__LP64__) printf("__LP64__\n"); #elif defined(__64BIT__) printf("__64BIT__\n"); #elif defined(_LP64) printf("_LP64\n"); #elif defined(_M_IA64) printf("_M_IA64\n"); #elif defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64) printf("_MIPS_64\n"); #else choke me #endif } return 0; } ]]) ],[ # Program compiled and ran, so get version by adding argument. samhain_prg_ENV=`./conftest$ac_exeext x` samhain_64=yes AC_MSG_RESULT([$samhain_prg_ENV]) ],[ AC_MSG_RESULT([none]) ],[ AC_MSG_RESULT([none]) ]) ])dnl AC_DEFUN([SAMHAIN_X86_64],[ AC_MSG_CHECKING([for x86_64]) AC_TRY_RUN([ int main() { __asm__ volatile ( "movq %rax, %rax" ); return 0; } ], [ AC_MSG_RESULT(yes) samhain_64=yes tiger_src=sh_tiger1_64.c samhain_64_asm=yes ], [ AC_MSG_RESULT([no]) ],[ AC_MSG_RESULT([no]) ]) ])dnl AC_DEFUN([SAMHAIN_64],[ samhain_64=no tiger_src=sh_tiger1.c samhain_64_asm=no # # if sizeof(unsigned long) = 4, try compiler macros for 64bit # if test "x$ac_cv_sizeof_unsigned_long" = x4; then if test "x$ac_cv_sizeof_unsigned_long_long" = x8; then SAMHAIN_PRG_ENV if test "x$samhain_64" = xyes; then tiger_src=sh_tiger1_64.c fi # # if GCC and __i386__, use precompiled assembler # if test "x$GCC" = xyes; then AC_MSG_CHECKING([for non-apple non-cygwin i386]) samhain_i386=no $CC -E -dM - < /dev/null | egrep '__i386__' >/dev/null 2>&1 if test $? = 0; then case "$host_os" in *linux*) # apples gcc does not understand the assembly we provide $CC -E -dM - < /dev/null | egrep '(__sun__|__APPLE__|__CYGWIN__)' >/dev/null 2>&1 || samhain_i386=yes ;; *) ;; esac fi AC_MSG_RESULT([$samhain_i386]) if test "x$samhain_i386" = xyes; then GCC_PIE_CC if test $pie_cv_cc = yes; then tiger_src=sh_tiger1.s AC_DEFINE([TIGER_32_BIT_S],1,[Define to use tiger 32 bit i386 assembler]) fi fi fi # # # else samhain_64=no tiger_src=sh_tiger1.c fi else # # sizeof(unsigned long) = 8 # tiger_src=sh_tiger1_64.c samhain_64=yes # # check for x86_64 (enables assembly optimizations) # if test "x$GCC" = xyes; then $CC -E -dM - < /dev/null | egrep '__clang__' >/dev/null 2>&1 if ! test $? = 0; then case "$host_os" in *linux*) SAMHAIN_X86_64 ;; *bsd*) SAMHAIN_X86_64 ;; *) SAMHAIN_X86_64 ;; esac fi fi fi if test "x$samhain_64" = xyes; then AC_DEFINE([TIGER_64_BIT],1,[Define to use tiger 64 bit implementation]) fi AC_MSG_CHECKING([for 64 bit environment]) AC_MSG_RESULT([$samhain_64]) AC_MSG_CHECKING([for tiger source to use]) AC_MSG_RESULT([$tiger_src]) AC_SUBST(tiger_src) ])dnl AC_DEFUN([sh_CHECK_POSIX_ACL], [ AC_CHECK_HEADERS(sys/acl.h) if test $ac_cv_header_sys_acl_h = yes; then AC_CHECK_LIB([acl], [acl_get_file], sh_lacl=yes, sh_lacl=no) if test x"$sh_lacl" = xyes; then LIBACL=-lacl else LIBACL= fi OLDLIBS="$LIBS" LIBS="$LIBS $LIBACL" AC_CHECK_FUNCS([acl_free acl_get_file acl_get_fd], [sh_facl=yes],[sh_facl=no]) LIBS="$OLDLIBS" fi if test x"$sh_facl" = xyes; then AC_DEFINE(USE_ACL, 1, [Define if you want ACL support.]) LIBS="$LIBS $LIBACL" else if test "x$enable_posix_acl" != xcheck; then AC_MSG_FAILURE([--enable-posix-acl was given, but test for acl support failed]) fi fi ]) AC_DEFUN([sh_CHECK_XATTR], [ AC_CHECK_HEADERS(attr/xattr.h) if test $ac_cv_header_attr_xattr_h = yes; then AC_CHECK_LIB([attr], [getxattr], sh_lattr=yes, sh_lattr=no) if test x"$sh_lattr" = xyes; then LIBATTR=-lattr else LIBATTR= fi OLDLIBS="$LIBS" LIBS="$LIBS $LIBATTR" AC_CHECK_FUNCS([getxattr lgetxattr fgetxattr], [sh_fattr=yes],[sh_fattr=no]) LIBS="$OLDLIBS" fi if test x"$sh_fattr" = xyes; then AC_DEFINE(USE_XATTR, 1, [Define if you want extended attributes support.]) LIBS="$LIBS $LIBATTR" else if test "x$enable_selinux" != xcheck; then AC_MSG_FAILURE([--enable-selinux was given, but test for selinux support failed]) fi fi ]) dnl Autoconf macros for libprelude dnl $id$ # Modified for LIBPRELUDE -- Yoann Vandoorselaere # Modified for LIBGNUTLS -- nmav # Configure paths for LIBGCRYPT # Shamelessly stolen from the one of XDELTA by Owen Taylor # Werner Koch 99-12-09 dnl AM_PATH_LIBPRELUDE([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libprelude, and define LIBPRELUDE_PREFIX, LIBPRELUDE_CFLAGS, LIBPRELUDE_PTHREAD_CFLAGS, dnl LIBPRELUDE_LDFLAGS, and LIBPRELUDE_LIBS dnl AC_DEFUN([AM_PATH_LIBPRELUDE], [dnl dnl Get the cflags and libraries from the libprelude-config script dnl dnl AC_ARG_WITH(libprelude-prefix, dnl [ --with-libprelude-prefix=PFX Prefix where libprelude is installed (optional)], dnl libprelude_config_prefix="$withval", libprelude_config_prefix="") dnl dnl if test x$libprelude_config_prefix != x ; then dnl if test x${LIBPRELUDE_CONFIG+set} != xset ; then dnl LIBPRELUDE_CONFIG=$libprelude_config_prefix/bin/libprelude-config dnl fi dnl fi dnl dnl AC_PATH_PROG(LIBPRELUDE_CONFIG, libprelude-config, no) min_libprelude_version=ifelse([$1], ,0.1.0,$1) AC_MSG_CHECKING(for libprelude - version >= $min_libprelude_version) no_libprelude="" if test "$LIBPRELUDE_CONFIG" = "no" ; then no_libprelude=yes else LIBPRELUDE_CFLAGS=`$LIBPRELUDE_CONFIG $libprelude_config_args --cflags` LIBPRELUDE_PTHREAD_CFLAGS=`$LIBPRELUDE_CONFIG $libprelude_config_args --pthread-cflags` LIBPRELUDE_LDFLAGS=`$LIBPRELUDE_CONFIG $libprelude_config_args --ldflags` LIBPRELUDE_LIBS=`$LIBPRELUDE_CONFIG $libprelude_config_args --libs` LIBPRELUDE_PREFIX=`$LIBPRELUDE_CONFIG $libprelude_config_args --prefix` LIBPRELUDE_CONFIG_PREFIX=`$LIBPRELUDE_CONFIG $libprelude_config_args --config-prefix` libprelude_config_version=`$LIBPRELUDE_CONFIG $libprelude_config_args --version` ac_save_CFLAGS="$CFLAGS" ac_save_LDFLAGS="$LDFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $LIBPRELUDE_CFLAGS" LDFLAGS="$LDFLAGS $LIBPRELUDE_LDFLAGS" LIBS="$LIBS $LIBPRELUDE_LIBS" dnl dnl Now check if the installed libprelude is sufficiently new. Also sanity dnl checks the results of libprelude-config to some extent dnl rm -f conf.libpreludetest AC_TRY_RUN([ #include #include #include #include int main () { system ("touch conf.libpreludetest"); if( strcmp( prelude_check_version(NULL), "$libprelude_config_version" ) ) { printf("\n*** 'libprelude-config --version' returned %s, but LIBPRELUDE (%s)\n", "$libprelude_config_version", prelude_check_version(NULL) ); printf("*** was found! If libprelude-config was correct, then it is best\n"); printf("*** to remove the old version of LIBPRELUDE. You may also be able to fix the error\n"); printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); printf("*** required on your system.\n"); printf("*** If libprelude-config was wrong, set the environment variable LIBPRELUDE_CONFIG\n"); printf("*** to point to the correct copy of libprelude-config, and remove the file config.cache\n"); printf("*** before re-running configure\n"); } else if ( strcmp(prelude_check_version(NULL), LIBPRELUDE_VERSION ) ) { printf("\n*** LIBPRELUDE header file (version %s) does not match\n", LIBPRELUDE_VERSION); printf("*** library (version %s)\n", prelude_check_version(NULL) ); } else { if ( prelude_check_version( "$min_libprelude_version" ) ) { return 0; } else { printf("no\n*** An old version of LIBPRELUDE (%s) was found.\n", prelude_check_version(NULL) ); printf("*** You need a version of LIBPRELUDE newer than %s. The latest version of\n", "$min_libprelude_version" ); printf("*** LIBPRELUDE is always available from http://www.prelude-ids.org/download/releases.\n"); printf("*** \n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the libprelude-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of LIBPRELUDE, but you can also set the LIBPRELUDE_CONFIG environment to point to the\n"); printf("*** correct copy of libprelude-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time))\n"); } } return 1; } ],, no_libprelude=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" LDFLAGS="$ac_save_LDFLAGS" fi if test "x$no_libprelude" = x ; then AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) else if test -f conf.libpreludetest ; then : else AC_MSG_RESULT(no) fi if test "$LIBPRELUDE_CONFIG" = "no" ; then echo "*** The libprelude-config script installed by LIBPRELUDE could not be found" echo "*** If LIBPRELUDE was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the LIBPRELUDE_CONFIG environment variable to the" echo "*** full path to libprelude-config." else if test -f conf.libpreludetest ; then : else echo "*** Could not run libprelude test program, checking why..." CFLAGS="$CFLAGS $LIBPRELUDE_CFLAGS" LDFLAGS="$LDFLAGS $LIBPRELUDE_LDFLAGS" LIBS="$LIBS $LIBPRELUDE_LIBS" AC_TRY_LINK([ #include #include #include #include ], [ return !!prelude_check_version(NULL); ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding LIBPRELUDE or finding the wrong" echo "*** version of LIBPRELUDE. If it is not finding LIBPRELUDE, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" echo "***" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means LIBPRELUDE was incorrectly installed" echo "*** or that you have moved LIBPRELUDE since it was installed. In the latter case, you" echo "*** may want to edit the libprelude-config script: $LIBPRELUDE_CONFIG" ]) CFLAGS="$ac_save_CFLAGS" LDFLAGS="$ac_save_LDFLAGS" LIBS="$ac_save_LIBS" fi fi LIBPRELUDE_CFLAGS="" LIBPRELUDE_LDFLAGS="" LIBPRELUDE_LIBS="" ifelse([$3], , :, [$3]) fi rm -f conf.libpreludetest AC_SUBST(LIBPRELUDE_CFLAGS) AC_SUBST(LIBPRELUDE_PTHREAD_CFLAGS) AC_SUBST(LIBPRELUDE_LDFLAGS) AC_SUBST(LIBPRELUDE_LIBS) AC_SUBST(LIBPRELUDE_PREFIX) AC_SUBST(LIBPRELUDE_CONFIG_PREFIX) ]) ##### http://autoconf-archive.cryp.to/acx_pthread.html # # SYNOPSIS # # ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. # It sets the PTHREAD_LIBS output variable to the threads library and # linker flags, and the PTHREAD_CFLAGS output variable to any special # C compiler flags that are needed. (The user can also force certain # compiler flags/libs to be tested by setting these environment # variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). # (This is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these # flags, but also link it with them as well. e.g. you should link # with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS # $LIBS # # If you are only building threads programs, you may wish to use # these variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute # constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # ACTION-IF-FOUND is a list of shell commands to run if a threads # library is found, and ACTION-IF-NOT-FOUND is a list of commands to # run it if it is not found. If ACTION-IF-FOUND is not specified, the # default action will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or # if you have any other suggestions or comments. This macro was based # on work by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) # (with help from M. Frigo), as well as ac_pthread and hb_pthread # macros posted by Alejandro Forero Cuervo to the autoconf macro # repository. We are also grateful for the helpful feedback of # numerous users. # # LAST MODIFICATION # # 2007-07-29 # # COPYLEFT # # Copyright (c) 2007 Steven G. Johnson # # 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 3 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, see # . # # As a special exception, the respective Autoconf Macro's copyright # owner gives unlimited permission to copy, distribute and modify the # configure scripts that are the output of Autoconf when processing # the Macro. You need not follow the terms of the GNU General Public # License when using or distributing such scripts, even though # portions of the text of the Macro appear in them. The GNU General # Public License (GPL) does govern all other use of the material that # constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the # Autoconf Macro released by the Autoconf Macro Archive. When you # make and distribute a modified version of the Autoconf Macro, you # may extend this special exception to the GPL to apply to your # modified version as well. AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -pthread) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi # Solaris lossage: default is obsolete semantics for getpwnam_r, # getpwuid_r, getgrgid_r, unless _POSIX_PTHREAD_SEMANTICS is defined AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *-osf* | *-hpux*) flag="-D_REENTRANT";; *solaris*) flag="-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi # Detect PTHREAD_MUTEX_RECURSIVE AC_MSG_CHECKING([for recursive mutexes]) mutex_recursive=no AC_TRY_LINK([ #define _XOPEN_SOURCE 500 #include ], [ pthread_mutexattr_t mta; pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); return 0;],[mutex_recursive=yes]) if test "x$mutex_recursive" = "xyes" then AC_DEFINE(HAVE_PTHREAD_MUTEX_RECURSIVE,1,[Define if you have recursive mutexes.]) fi AC_MSG_RESULT($mutex_recursive) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi if test x"$acx_pthread_ok" = xyes; then PTHREAD_CFLAGS="${PTHREAD_CFLAGS} -DUSE_MALLOC_LOCK=1" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_LDFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD dnl Copyright © 2004 Loic Dachary dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or (at dnl your option) any later version. dnl dnl Use ZLIB_HOME instead of option AC_DEFUN([CHECK_ZLIB],[ if test "x${ZLIB_HOME}" = "x"; then ZLIB_HOME=/usr/local if test ! -f "${ZLIB_HOME}/include/zlib.h" then ZLIB_HOME=/usr fi fi zlib_found=no ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$LDFLAGS if test "x${ZLIB_HOME}" = "x/usr"; then : else LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" fi AC_LANG_SAVE AC_LANG_C AC_CHECK_LIB(z, inflateEnd, [zlib_cv_libz=yes], [zlib_cv_libz=no]) AC_CHECK_HEADER(zlib.h, [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no]) AC_LANG_RESTORE if test "$zlib_cv_libz" = "yes" -a "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, use them # AC_CHECK_LIB(z, inflateEnd) AC_MSG_CHECKING([zlib in ${ZLIB_HOME}]) AC_MSG_RESULT(ok) AC_CHECK_FUNCS([compressBound]) zlib_found=yes else # # If either header or library was not found, revert and bomb # AC_MSG_CHECKING(zlib in ${ZLIB_HOME}) LDFLAGS="$ZLIB_OLD_LDFLAGS" CPPFLAGS="$ZLIB_OLD_CPPFLAGS" AC_MSG_RESULT(failed) AC_MSG_WARN([zlib not found in ZLIB_HOME, /usr/local, or /usr]) fi ]) # SH_PROG_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([SH_PROG_LD], [ AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac else AC_MSG_CHECKING([for ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 #include int main() { struct tm tm; char tt[64]; memset(&tm, 0, sizeof(tm)); strftime(tt, sizeof(tt), "%z", &tm); if (strlen(tt) != 5) return 1; return 0; } ], [ AC_MSG_RESULT([yes]) AC_DEFINE(HAVE_STRFTIME_Z, 1, [strftime supports %z]) ], [ AC_MSG_RESULT([no]) ],[ AC_MSG_RESULT([no]) ])]) AC_DEFUN([SH_GCC_VERSION], [ GCC_VERSION="" gcc_VERSION_MAJOR=0 gcc_VERSION_MINOR=0 AC_MSG_CHECKING([for gcc version]) if test "x$GCC" = "xyes" then $CC -dumpversion >/dev/null 2>&1 if test $? -eq 0 then GCC_VERSION=`$CC -dumpversion` gcc_VERSION_MAJOR=`echo $GCC_VERSION | cut -d'.' -f1` gcc_VERSION_MINOR=`echo $GCC_VERSION | cut -d'.' -f2` AC_DEFINE_UNQUOTED(GCC_VERSION_MAJOR, [${gcc_VERSION_MAJOR}], [gcc version major]) AC_DEFINE_UNQUOTED(GCC_VERSION_MINOR, [${gcc_VERSION_MINOR}], [gcc version minor]) AC_MSG_RESULT([$GCC_VERSION]) else AC_MSG_RESULT([$CC -dumpversion working]) fi else AC_MSG_RESULT([compiler is not gcc]) fi ]) dnl *-*wedit:notab*-* Please keep this as the last line. samhain-4.1.4/deploy.sh.in0000644000175000017500000007406012615253270012330 00000000000000#! /bin/sh # # Copyright Rainer Wichmann (2005) # # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # #VERSION2.0 # ----------------------------------------------------------------------- # Be Bourne compatible # ----------------------------------------------------------------------- if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi # ----------------------------------------------------------------------- # Make sure we support functions (from the autoconf manual) # ----------------------------------------------------------------------- SHELL="${SHELL-/bin/sh}" if test x"$1" = "x--re-executed" then shift elif "$SHELL" -c 'foo () { (exit 0); exit 0; }; foo' 2>/dev/null then : else for cmd in sh bash ash bsh ksh zsh sh5; do X="$PATH:/bin:/usr/bin:/usr/afsws/bin:/usr/ucb"; OLD_IFS=${IFS} IFS=':'; export IFS for dir in $X; do shell="$dir/$cmd" if (test -f "$shell" || test -f "$shell.exe") then if "$shell" -c 'foo () { (exit 0); exit 0; }; foo' 2>/dev/null then SHELL="$shell"; export SHELL IFS=${OLD_IFS}; export IFS exec "$shell" "$0" --re-executed ${1+"$@"} fi fi done IFS=${OLD_IFS}; export IFS done echo "-----------------------------------------------------------------" echo "ERROR: Unable to locate a shell interpreter with function support" >&2 echo "-----------------------------------------------------------------" { (exit 1); exit 1; } fi # ----------------------------------------------------------------------- # Test for 'echo -n' # ----------------------------------------------------------------------- case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,* ) ECHO_N=-n ECHO_C= ;; *) ECHO_N= ECHO_C='\c' ;; esac 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 ######################################################################### # # Configuration section # ######################################################################### # ----------------------------------------------------------------------- # The following part will be cut and saved to ~/.deploy.conf # ----------------------------------------------------------------------- #__BEGIN_CUT__ ######################################################################### # # This file is sourced by a Bourne shell script. # Thus you need to take care of proper shell syntax. # ######################################################################### # if you need, you can expand your PATH environment variable here # just uncomment and replace /opt/contrib/bin with whatever you need # # PATH="/opt/contrib/bin:${PATH}"; export PATH # the base directory of the deployment system # CLI option: --basedir=... # defbasedir="@mydataroot@/profiles" # the name of the database of installed clients # no CLI option # defdatabase="yulerc.install.db" # be quiet; 0 = false, 1 = true, 2 = very quiet # CLI option: --quiet | --quiet=2 # silent=0; # assume yes as answer to all prompts and run non-interactively # 0 = false, 1 = true # CLI option: --yes # assumeyes=0; # which 'dialog' to use (e.g. "Xdialog") # "no" for plain text; empty ("") lets the program search for dialog # CLI option: --dialog=... # prefdialog="" # operating system; no default # CLI option: --arch=... # arch="" # Format for binary packages (run | deb | rpm | tbz2 | solaris-pkg | depot) # CLI option: --format=... # format="" # logfile; default is none # CLI option: --logfile=... # logfile="" # The path to the yule (samhain server) executable. # CLI option: --yule_exec=... # yule_exec="@sbindir@/yule" # The path to the yule (samhain server) configuration file. # CLI option: --yule_conf=... # yule_conf="@sysconfdir@/yulerc" # The path to the data directory of yule (samhain server). # This is the directory where client configuration/database files # are stored. # CLI option: --yule_data=... # yule_data="@mydataroot@" # The temporary directory to use. Default is '/tmp', but some # sites may mount this 'noexec'. # temp_dir="/tmp" #__END_CUT__ # ----------------------------------------------------------------------- # Write configuration file to user home directory/Read configuration file # ----------------------------------------------------------------------- if test -f ~/.deploy.conf then . ~/.deploy.conf else # # From the autoconf configure script - search ourselves # case $0 in *[\\/]* ) as_myself=$0 ;; *) old_IFS=$IFS; IFS=: for as_dir in $PATH do IFS=$old_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; 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 "ERROR: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi cat "$as_myself" | sed -n -e '/^#__BEGIN_CUT__/,/^#__END_CUT__/ p ' >~/.deploy.conf && { echo echo "-----------------------------------------------------" echo " Configuration file ~/.deploy.conf created" echo " You may want to edit it to adapt it to your needs" echo "-----------------------------------------------------" echo } fi export silent export assumeyes export arch export logfile export format export yule_exec export yule_conf export yule_data export temp_dir # dialog # DIALOG="${prefdialog}"; export DIALOG # base directory # basedir="$defbasedir"; export basedir # simulate only; 0 = false, 1 = true # simulate=0; export simulate # version # version=2.0; export version # host; no default # host= export host # hostgroup; empty default # hostgroup= export hostgroup # action; no default # action= export action # the 'log.lastrun' logfile # logOpen=0 export logOpen # source version; default = current # src_version="" export src_version # checksrc; do you want to delete if PGP signature check fails ? # cs_delete=0 export cs_delete # build; do you want to pack the executable ? # bd_packed='' export bd_packed bd_user='root' export bd_user # addpath # bd_addpath="" export bd_addpath # Install; do you want to initialize the database ? # is_init=y export is_init # Install; do you want to replace the rc.host file ? # is_rcfile=y export is_rcfile # Install; do you want to start the client ? # is_startup=y export is_startup # Install; optional local command ? # local_command=""; export local_command # Info on packages ? # showpkg=n export showpkg ######################################################################### # # Help Subroutines # ######################################################################### # ----------------------------------------------------------------------- # We cannot source these, because we don't know yet the base directory # ----------------------------------------------------------------------- showUNINSTALL() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] uninstall" echo echo "Uninstall the samhain client from the specified host. Can only be" echo "used if the client has been installed with deploy.sh version 2." echo echo "Options:" echo echo " --host= The host where you want to uninstall." echo " --tmpdir= Temporary directory to use on the this host." echo { (exit 0); exit 0; } } showINFO() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] info" echo echo "Show info for hosts in client database (default), or for available" echo "binary installer packages." echo echo "Options:" echo echo " --packages Show info on packages." echo { (exit 0); exit 0; } } showCLEAN() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] clean" echo echo "Remove all files that are no longer needed:" echo " - Source tarballs in ${basedir}/source" echo " - Unused installer packages in ${basedir}/archpkg" echo { (exit 0); exit 0; } } showCHECKSRC() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] checksrc" echo echo "Check PGP signatures of source tarballs in the source/ subdirectory" echo "of the deploy system." echo "You must have gpg (GnuPG) in your PATH, and you should have imported" echo "the samhain release PGP key (Key ID 0F571F6C, Rainer Wichmann)." echo "To import the key, simply execute the command" echo "\"gpg --keyserver blackhole.pca.dfn.de --recv-keys 0F571F6C\"" echo echo "Options:" echo echo " --delete Delete source tarballs if PGP signature" echo " cannot be verified." echo { (exit 0); exit 0; } } showDOWNLOAD() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] download" echo echo "Download a samhain source tarball from http://www.la-samhna.de," echo "check its PGP signature, and install it into the source/ subdirectory" echo "of the deploy system." echo "You must have gpg (GnuPG) in your PATH, and you should have imported" echo "the samhain release PGP key (Key ID 0F571F6C, Rainer Wichmann)." echo "To import the key, simply execute the command" echo "\"gpg --keyserver blackhole.pca.dfn.de --recv-keys 0F571F6C\"" echo echo "Options:" echo echo " --version= Version of samhain to download. The" echo " default is \"current\" to download the current version." echo { (exit 0); exit 0; } } showBUILD() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] build" echo echo "Copy a source tarball to a build machine, build a binary package, and fetch" echo "the package. Will bail out if not running under ssh-agent. If you are sure" echo "that you don't need ssh-agent, set the environment variable SSH_AGENT_PID" echo "to some arbitrary string before launching the deploy.sh command." echo echo "Options:" echo echo " --host= The build host." echo " --arch= The architecture/operating system to build for." echo " This is used to get the \"./configure\" options from the file" echo " \${basedir}/configs/\${arch}.configure." echo " --version= The version of samhain you want to build." echo " --format=" echo " The format of the package. \"run\" is a portable tar" echo " package, \"deb\" is for Debian, \"tbz2\" for Gentoo," echo " \"rpm\" for any RPM-based Linux, \"solaris-pkg\"" echo " for Sun Solaris, and \"depot\" for HP-UX" echo " --packed= The client password, if you want to" echo " create a packed executable. Defaults to empty (don't pack)" echo " --user= Login as to the build host (root)." echo " --add-path= Append 'path' to the PATH variable on the build host." echo " --tmpdir= Temporary directory to use on the build host." { (exit 0); exit 0; } } showINSTALL() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] install" echo echo "Copy a pre-built binary installer package to a remote host, stop the client" echo "running there (if any), install the (new) client, optionally initialize" echo "the file signature database and fetch it from the remote host, update" echo "the server configuration file and reload the server." echo echo "Options:" echo echo " --host= The host where you want to install." echo " --group= Optional group the host belongs to." echo " --arch= The architecture/operating system of this host." echo " This is used to get the correct binary package." echo " --version= The version of samhain you want to install." echo " --format=" echo " The format of the binary package." echo " --yule_exec= The path to the 'yule' executable." echo " --yule_conf= The path to the 'yule' configuration file." echo " --yule_data= The path to the 'yule' data directory." echo " --no-init Do not initialize the file signature database." echo " --no-rcfile Do not replace the rc.host file on server." echo " --no-start Do not start the client after installation." echo " --local= Local command (executed twice: " echo " after config installation and before client startup)." echo " --tmpdir= Temporary directory to use on the this host." { (exit 0); exit 0; } } showUSAGE() { echo "deploy.sh $version" echo "USAGE: deploy.sh [options] command" echo echo "Commands: info | clean | download | checksrc | build | install | uninstall" echo echo "Options:" echo " -h | --help Print general usage information." echo " -h | --help Print usage information for \"command\"." echo " --basedir= Set the basedir for the deployment system." echo " The default is ${defbasedir}." echo " -q | --quiet Produce output suitable for logging." echo " You can also use -q=# to set the quiet level up to" echo " a maximum of 2. Note that -q=2 implies --yes (see below)." echo " -s | --simulate Perform a simulation of events that" echo " would occur but do not actually change the system." echo " -y | --yes Assume "yes" as answer to" echo " all prompts and run non-interactively." echo " -o | --logfile=" echo " Specify an output file for messages that would go to stdout" echo " otherwise. Has no effect on stderr (error messages)." echo " -d | --dialog= Specify your preferred \"dialog\"" echo " clone (e.g. Xdialog). Use \"no\" to force plain text." if test x"$1" = x then { (exit 0); exit 0; } else { (exit $1); exit $1; } fi } ######################################################################### # # Command line # ######################################################################### for option do # If the previous option needs an argument, assign it. # if test -n "$opt_prev"; then eval "$opt_prev=\$option" eval export "$opt_prev" opt_prev= continue fi case "$option" in -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case "$option" in # Info --packages | -packages) showpkg=y; export showpkg; ;; # Install --yule_exec | -yule_exec | --yule-exec | -yule-exec) opt_prev=yule_exec ;; --yule_exec=* | -yule_exec=* | --yule-exec=* | -yule-exec=*) yule_exec="$optarg"; export yule_exec ;; --yule_conf | -yule_conf | --yule-conf | -yule-conf) opt_prev=yule_conf ;; --yule_conf=* | -yule_conf=* | --yule-conf=* | -yule-conf=*) yule_conf="$optarg"; export yule_conf ;; --yule_data | -yule_data | --yule-data | -yule-data) opt_prev=yule_data ;; --yule_data=* | -yule_data=* | --yule-data=* | -yule-data=*) yule_data="$optarg"; export yule_data ;; --no-init | -no-init) is_init=n; export is_init ;; --no-rcfile | -no-rcfile) is_rcfile=n; export is_rcfile ;; --no-start | -no-start) is_startup=n; export is_startup ;; --local | -local) opt_prev=local_command ;; --local=* | -local=*) local_command="$optarg"; export local_command ;; --group | -group) opt_prev=hostgroup ;; --group=* | -group=*) hostgroup="$optarg"; export hostgroup ;; # Build --format | -format) opt_prev=format ;; --format=* | -format=*) format="$optarg"; export format ;; --packed | --pack | -packed | -pack) opt_prev=bd_packed ;; --packed=* | -packed=*) bd_packed="$optarg"; export bd_packed ;; --user | -user) opt_prev=bd_user ;; --user=* | -user=*) bd_user="$optarg"; export bd_user ;; --add-path | -add-path | --addpath | -addpath) opt_prev=bd_addpath ;; --add-path=* | -add-path=* | --addpath=* | -addpath=*) bd_addpath="$optarg"; export bd_addpath ;; # Checksource --delete | -delete) cs_delete=1; export cs_delete ;; # Download --version | -version) opt_prev=src_version ;; --version=* | -version=*) src_version="$optarg"; export src_version ;; # Generic --basedir | -basedir) opt_prev=basedir ;; --basedir=* | -basedir=*) basedir="$optarg"; export basedir ;; --host | -host) opt_prev=host ;; --host=* | -host=*) host="$optarg"; export host ;; --arch | -arch) opt_prev=arch ;; --arch=* | -arch=*) arch="$optarg"; export arch ;; --tmpdir | -tmpdir) opt_prev=temp_dir ;; --tmpdir=* | -tmpdir=*) temp_dir="$optarg"; export temp_dir ;; -o | --logfile | -logfile) opt_prev=logfile ;; -o=* | --logfile=* | -logfile=*) logfile="$optarg"; export logfile ;; -h | --h | --help | -help | help) if test $# -gt 1 then if test x"$2" = xdownload then showDOWNLOAD elif test x"$2" = xinfo then showINFO elif test x"$2" = xchecksrc then showCHECKSRC elif test x"$2" = xclean then showCLEAN elif test x"$2" = xbuild then showBUILD elif test x"$2" = xinstall then showINSTALL elif test x"$2" = xuninstall then showUNINSTALL else showUSAGE 1 fi fi showUSAGE ;; -q | --quiet | -quiet | --silent | -silent) if test x"$silent" = x0 then silent=1; export silent else silent=2; export silent fi ;; -q=* | --quiet=* | --silent=* | -silent=*) silent="$optarg"; export silent ;; -s | --simulate | -simulate | --dry-run | -dry-run | --recon | -recon | --just-print | -just-print | --no-act | -no-act) simulate=1; export simulate ;; -y | --yes | -yes) assumeyes=1; export assumeyes ;; -d | --dialog | -dialog) opt_prev=DIALOG ;; -d=* | --dialog=* | -dialog=*) DIALOG="$optarg"; export DIALOG ;; -*) showUSAGE 1 ;; clean | download | checksrc | build | install | info | uninstall) action="$option"; export action break ;; esac done ######################################################################### # # Subroutines # ######################################################################### # ----------------------------------------------------------------------- # Printing/logging Subroutines # ----------------------------------------------------------------------- . ${basedir}/libexec/funcPRINT # ----------------------------------------------------------------------- # Interaction Subroutines # ----------------------------------------------------------------------- . ${basedir}/libexec/funcDIALOG # ----------------------------------------------------------------------- # Setup test Subroutines # ----------------------------------------------------------------------- . ${basedir}/libexec/funcSETUP # ----------------------------------------------------------------------- # Subroutines for determining existence of / path to executables # ----------------------------------------------------------------------- . ${basedir}/libexec/funcEXE # ----------------------------------------------------------------------- # Subroutines for building # ----------------------------------------------------------------------- . ${basedir}/libexec/funcBUILD # ----------------------------------------------------------------------- # Subroutines for installing # ----------------------------------------------------------------------- . ${basedir}/libexec/funcINSTALL # ----------------------------------------------------------------------- # Subroutines for client database # ----------------------------------------------------------------------- . ${basedir}/libexec/funcDB # ----------------------------------------------------------------------- # Subroutine for the 'download' command # ----------------------------------------------------------------------- . ${basedir}/libexec/comDOWNLOAD # ----------------------------------------------------------------------- # Subroutine for the 'checksrc' command # ----------------------------------------------------------------------- . ${basedir}/libexec/comCHECKSRC # ----------------------------------------------------------------------- # Subroutine for the 'clean' command # ----------------------------------------------------------------------- . ${basedir}/libexec/comCLEAN # ----------------------------------------------------------------------- # Subroutine for the 'build' command # ----------------------------------------------------------------------- . ${basedir}/libexec/comBUILD # ----------------------------------------------------------------------- # Subroutine for the 'install' command # ----------------------------------------------------------------------- . ${basedir}/libexec/comINSTALL # ----------------------------------------------------------------------- # Subroutine for the 'install' command # ----------------------------------------------------------------------- . ${basedir}/libexec/comUNINSTALL ######################################################################### # # Main # ######################################################################### main_exit_status=0 tmpdir= # Find a dialog clone # findDIALOG # Check for basedir and tmpdir # testSETUP1 # Logfile setup # exec 5>${basedir}/tmp/logfile.lastrun now=`date` echo "$now: $0 " ${1+"$@"} >&5 lastlog="${basedir}/tmp/logfile.lastrun"; export lastlog logOpen=1 # Temporary directory/file setup # tmpD="$tmpdir/build.gui.$$" mkdir "$tmpD" || printFATAL "Cannot create temporary directory $tmpD" export tmpD tmpF="$tmpD/tmpF.$$" touch $tmpF || printFATAL "Cannot create temporary file $tmpF" export tmpF tmpERR="$tmpD/tmpERR.$$" echo '0' > $tmpERR || printFATAL "Cannot create temporary file $tmpERR" export tmpERR # Trap exit and cleanup # trap "exit_status=$?; rm -rf $tmpD; exit ${exit_status};" 0 trap "(exit 1); exit 1;" 1 2 13 15 # Check for action to perform, and host, if required # testSETUP2 if test x"$action" = xdownload then if test x"$src_version" = x then src_version="current"; export src_version fi #--------------------------------------------------------------------- # Vodoo code to tee both stdout and stderr, but keep them seperate. #--------------------------------------------------------------------- if test x"$DIALOG" = x then ((commandDOWNLOAD | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else commandDOWNLOAD 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version DOWNLOAD logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi elif test x"$action" = xinfo then if test x"${showpkg}" = xn then if test x"$DIALOG" = x then ((dbSHOWHOSTS "${host}" | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else dbSHOWHOSTS "${host}" 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version INFO logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi else if test x"$DIALOG" = x then ((dbSHOWPKG show | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else dbSHOWPKG show 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version INFO logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi fi elif test x"$action" = xchecksrc then if test x"$DIALOG" = x then ((commandCHECKSRC | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else commandCHECKSRC 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version CHECKSRC logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi elif test x"$action" = xclean then if test x"$DIALOG" = x then ((commandCLEAN | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else commandCLEAN 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version CLEAN logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi elif test x"$action" = xbuild then #--------------------------------------------------------------------- # Make sure we are running under ssh-agent. #--------------------------------------------------------------------- if test x"$SSH_AGENT_PID" = x then if test x"$assumeyes" = x1 then printFATAL "Not running under ssh-agent, and not running interactive: cannot continue." else promptYESNO "Not running under ssh-agent, continue anyway" "no" test "x$YESNO" = xn && { (exit 0; ); exit 0; } fi fi #--------------------------------------------------------------------- # Setup. #--------------------------------------------------------------------- selBVERSION selBARCH selBFORMAT if test x"$DIALOG" = x then ((commandBUILD | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else commandBUILD 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version BUILD logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi elif test x"$action" = xinstall then needEXE ssh scp ssh-agent #--------------------------------------------------------------------- # Make sure we are running under ssh-agent. #--------------------------------------------------------------------- if test x"$SSH_AGENT_PID" = x then if test x"$assumeyes" = x1 then printFATAL "Not running under ssh-agent, and not running interactive: cannot continue." else promptYESNO "Not running under ssh-agent, continue anyway" "no" test "x$YESNO" = xn && { (exit 0; ); exit 0; } fi fi #--------------------------------------------------------------------- # Setup. #--------------------------------------------------------------------- is_root=`id -u 2>/dev/null` if test "x$?" = x0 && test "x${is_root}" != x0 then promptYESNO "You are not root, continue anyway" "no" test "x$YESNO" = xn && { (exit 0; ); exit 0; } else is_root=0 fi pathYULE pathYDATA selbinARCH selbinVERSION if test "x${is_init}" = xy then promptYESNO "Initialize database" "yes" is_init=$YESNO fi if test "x${is_rcfile}" = xy then promptYESNO "Replace rc.host file on server" "yes" is_rcfile=$YESNO fi if test "x${is_startup}" = xy then promptYESNO "Start client after installation" "yes" is_startup=$YESNO fi if test -f "${yule_conf}" then : else promptINPUT "Please enter the path to the yule configuration file" yule_conf="$INPUT"; export yule_conf if test -f "${yule_conf}" then : else printFATAL "Cannot find ${yule_conf}" fi fi if test x"$DIALOG" = x then ((commandINSTALL | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else commandINSTALL 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version INSTALL logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi elif test x"$action" = xuninstall then needEXE ssh scp ssh-agent #--------------------------------------------------------------------- # Make sure we are running under ssh-agent. #--------------------------------------------------------------------- if test x"$SSH_AGENT_PID" = x then if test x"$assumeyes" = x1 then printFATAL "Not running under ssh-agent, and not running interactive: cannot continue." else promptYESNO "Not running under ssh-agent, continue anyway" "no" test "x$YESNO" = xn && { (exit 0; ); exit 0; } fi fi #--------------------------------------------------------------------- # Setup. #--------------------------------------------------------------------- dbINFO "$host" if test x"$?" = x0 then if test x"${DB_status}" = "xD2_installed" then : else if test x"${DB_status}" = "xD2_removed" then promptYESNO "Already uninstalled on host $host, continue" "no" test "x$YESNO" = xn && { (exit 0; ); exit 0; } else printFATAL "No deploy version 2 installation on host $host: ${DB_status}" fi fi else printFATAL "Cannot uninstall on host $host" fi if test x"$DIALOG" = x then ((commandUNINSTALL | tee -a "$lastlog") 6>&1 1>&2 2>&6 | \ tee -a "$lastlog") 6>&1 1>&2 2>&6 else commandUNINSTALL 2>&1 | tee -a "$lastlog" >/dev/null | $DIALOG \ --title "deploy.sh $version UNINSTALL logfile" \ --backtitle "Logfile: $lastlog" \ --tailbox "$lastlog" 19 75 fi fi if test x"${main_exit_status}" = x0 then test -f "$tmpERR" && main_exit_status=`cat "$tmpERR" | tr -d '\n'` fi (exit ${main_exit_status}); exit ${main_exit_status}; samhain-4.1.4/hp_ux.psf.in0000644000175000017500000000356612615253270012340 00000000000000# PSF depot layout_version 1.0 # Product definition: product tag @install_name@ revision @VERSION@ is_patch false title @install_name@ Client description "Client for the @install_name@ system" machine_type * os_name HP-UX os_release ?.11.* os_version ? directory / is_locatable false # Dummy for configure warning # datarootdir = @datarootdir@ # Specify a checkremove script that executes during the # swremove analysis phase. (This script prevents the # removal of the SD product and returns an ERROR. # checkremove scripts/checkremove.sd configure ./sc/configure unconfigure ./sc/unconfigure preremove ./sc/preremove # Fileset definitions: fileset tag basic title Core system revision @VERSION@ file_permissions -m 0700 -o root -g sys # # Files: # directory ./sbin/init.d=/sbin/init.d file -m 0555 -o bin -g bin @install_name@ # directory .@prefix@=@prefix@ file -m 0555 -o bin -g bin . # directory .@sysconfdir@=@sysconfdir@ file -v -m 0600 @install_name@rc file -m 0555 -o bin -g bin . # directory .@sbindir@=@sbindir@ file * file -m 0555 -o bin -g bin . file -m 0750 -o bin -g bin @install_name@ # directory .@mydataroot@=@mydataroot@ file -m 0555 -o bin -g bin . # directory .@mylogdir@=@mylogdir@ file -m 0755 -o adm -g adm . # directory .@mylockdir@=@mylockdir@ file -m 0555 -o bin -g bin . end # Manpage fileset definitions: #fileset # tag man # title Manual pages for samhain # revision 2.05 # directory .@mandir@/man8=@mandir@/man8 # file * # directory .@mandir@/man5=@mandir@/man5 # file * #end #man end # samhain-4.1.4/src/0000755000175000017500000000000012724114744010736 500000000000000samhain-4.1.4/src/sh_nmail.c0000644000175000017500000005444112615253277012630 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2008 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #if defined(HAVE_PTHREAD_MUTEX_RECURSIVE) #define _XOPEN_SOURCE 500 #endif #if defined(GCC_VERSION_MAJOR) && !defined(__clang__) #if (GCC_VERSION_MAJOR > 4) || ((GCC_VERSION_MAJOR == 4) && (GCC_VERSION_MINOR > 8)) #pragma GCC diagnostic ignored "-Wclobbered" #endif #endif #include #include #if defined(SH_WITH_MAIL) #undef FIL__ #define FIL__ _("sh_nmail.c") #include "samhain.h" #include "sh_pthread.h" #include "sh_mem.h" #include "sh_mail.h" #include "sh_tiger.h" #include "sh_string.h" #include "sh_utils.h" #include "sh_fifo.h" #include "sh_filter.h" #include "sh_mail_int.h" SH_MUTEX_INIT(mutex_listall, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_INIT(mutex_flush_l, PTHREAD_MUTEX_INITIALIZER); /* Pointer to last address */ static struct alias * last = NULL; /* List of mail recipients */ static struct alias * recipient_list = NULL; static struct alias * compiled_recipient_list = NULL; static sh_filter_type compiled_mail_filter = SH_FILT_INIT; /* List of mail aliases */ static struct alias * alias_list = NULL; /* List of all recipients */ struct alias * all_recipients = NULL; /* Check if addr is in list. If list is all_recipients, * must iterate over ->all_next instead of ->next */ static int check_double (const char * str, struct alias * list, int isAll) { if (str && list) { struct alias * item = list; while (item) { if (0 == strcmp(sh_string_str(item->recipient), str)) return -1; if (isAll) item = item->all_next; else item = item->next; } } return 0; } /* Add recipient to 'list' AND to all_recipients. If * it already is in all_recipients, mark it as an alias * (isAlias = 1). */ struct alias * add_recipient_intern(const char * str, struct alias * list) { if (str) { struct alias * new = SH_ALLOC(sizeof(struct alias)); new->next = list; new->mx_list = NULL; new->mail_filter = NULL; new->recipient_list = NULL; new->severity = (-1); new->send_mail = 0; new->isAlias = 0; new->recipient = sh_string_new_from_lchar(str, strlen(str)); list = new; SH_MUTEX_LOCK_UNSAFE(mutex_listall); if (0 != check_double(str, all_recipients, S_TRUE)) { new->isAlias = 1; } new->all_next = all_recipients; all_recipients = new; SH_MUTEX_UNLOCK_UNSAFE(mutex_listall); } return list; } int sh_nmail_close_recipient(const char * str) { (void) str; if (last) { last = NULL; return 0; } return -1; } /* Add a single recipient. Must not be in in * recipient_list already, and not in all_recipients. */ int sh_nmail_add_recipient(const char * str) { /* return error if duplicate, or * already defined within an alias list. */ if (0 == check_double(str, recipient_list, S_FALSE) && 0 == check_double(str, all_recipients, S_TRUE)) { recipient_list = add_recipient_intern(str, recipient_list); last = recipient_list; return 0; } return -1; } /* Add a compiled-in address. These share the compiled_mail_filter */ int sh_nmail_add_compiled_recipient(const char * str) { if (0 == check_double(str, compiled_recipient_list, S_FALSE)) { compiled_recipient_list = add_recipient_intern(str, compiled_recipient_list); if (compiled_recipient_list) compiled_recipient_list->mail_filter = &compiled_mail_filter; last = compiled_recipient_list; return 0; } return -1; } /* Add an alias; format is name ":" comma-delimited_list_of_recipients */ int sh_nmail_add_alias(const char * str) { #define SH_ALIASES_RECP_NUM 256 size_t lengths[SH_ALIASES_RECP_NUM]; unsigned int nfields = SH_ALIASES_RECP_NUM; char * new = sh_util_strdup(str); char * p = strchr(new, ':'); char * q; if (p && strlen(p) > 1) { unsigned int i; char ** array; *p = '\0'; q = p; ++p; if (strlen(new) > 0) { /* strip trailing space */ --q; while ((q != new) && *q == ' ') { *q = '\0'; --q; } } else { goto err; } if (0 == check_double(new, alias_list, S_FALSE)) { array = split_array_list(p, &nfields, lengths); if (array && nfields > 0) { struct alias * newalias = NULL; /* Enforce that all list members are defined already */ int nflag = 0; for (i = 0; i < nfields; ++i) { if (0 == check_double(array[i], all_recipients, S_TRUE)) nflag = 1; /* not in all_recipients --> bad */ } if (nflag == 0) { newalias = SH_ALLOC(sizeof(struct alias)); newalias->recipient_list = NULL; newalias->mail_filter = NULL; newalias->mx_list = NULL; newalias->severity = (-1); /* This is the alias */ newalias->recipient = sh_string_new_from_lchar(new, strlen(new)); for (i = 0; i < nfields; ++i) { if (lengths[i] > 0 && 0 == check_double(array[i], newalias->recipient_list, S_FALSE)) { newalias->recipient_list = add_recipient_intern(array[i], newalias->recipient_list); } } } SH_FREE(array); if (newalias == NULL || newalias->recipient_list == NULL) { if (newalias) SH_FREE(newalias); goto err; } newalias->next = alias_list; alias_list = newalias; last = alias_list; SH_FREE(new); return 0; } } } err: SH_FREE(new); return -1; } /* <<<<<<<<<<<<<<< Recipient List >>>>>>>>>>>>>>>>>>>>>> */ static struct alias * find_list (const char * alias, int * single) { struct alias * list = NULL; *single = 0; if (!alias) { list = all_recipients; } else { struct alias * test = alias_list; while (test) { if (0 == strcmp(alias, sh_string_str(test->recipient))) { list = test->recipient_list; break; } test = test->next; } if (!list) { test = recipient_list; while (test) { if (0 == strcmp(alias, sh_string_str(test->recipient))) { list = test; *single = 1; break; } test = test->next; } } if (!list) { test = compiled_recipient_list; while (test) { if (0 == strcmp(alias, sh_string_str(test->recipient))) { list = test; *single = 1; break; } test = test->next; } } } return list; } /* Returns zero (no) or one (yes). Used to tag messages that are * valid for a given recipient (or mailing list alias). */ int sh_nmail_valid_message_for_alias (int level, const char * message, const char * alias, const void * rcv_info) { const struct alias * rcv = (const struct alias *) rcv_info; if (!alias || 0 == strcmp(alias, sh_string_str(rcv->recipient))) { if ((level & rcv->severity) == 0) { return 0; } if (rcv->mail_filter) { if (0 != sh_filter_filter(message, rcv->mail_filter)) { return 0; } } } return 1; } /* Returns number of recipients */ static int sh_nmail_compute_recipients (int level, const char * message, const char * alias, int flagit) { struct alias * list = NULL; int single = 0; int retval = 0; if (flagit) { list = all_recipients; while (list) { list->send_mail = 0; list = list->all_next; } list = NULL; } if (message) { int flag = 0; list = find_list (alias, &single); if (list == all_recipients) flag = 1; while (list) { /* Check severity */ if ((list->severity & level) == 0) { if (single) break; if (flag) list = list->all_next; else list = list->next; continue; } /* Check filter */ if (list->mail_filter && 0 != sh_filter_filter(message, list->mail_filter)) { if (single) break; if (flag) list = list->all_next; else list = list->next; continue; } /* Mark the entry */ if (flag) { /* Don't mark aliases */ if (flagit && list->isAlias == 0) { list->send_mail = 1; } list = list->all_next; } else { if (flagit) list->send_mail = 1; list = list->next; } ++retval; } } return retval; } /* Is not called from same(recursively) or different thread */ static int sh_nmail_flag_recipients (int level, const char * message, const char * alias) { int retval = 0; if (message) { SH_MUTEX_LOCK_UNSAFE(mutex_listall); retval = sh_nmail_compute_recipients (level, message, alias, 1); SH_MUTEX_UNLOCK_UNSAFE(mutex_listall); } return retval; } /* Can be called from same thread with mutex_listall held via sh_nmail_flush() */ static int sh_nmail_test_recipients (int level, const char * message, const char * alias) { int retval = 0; if (message) { if (0 == SH_MUTEX_TRYLOCK_UNSAFE(mutex_flush_l)) { SH_MUTEX_LOCK_UNSAFE(mutex_listall); retval = sh_nmail_compute_recipients (level, message, alias, 0); SH_MUTEX_UNLOCK_UNSAFE(mutex_listall); SH_MUTEX_UNLOCK_UNSAFE(mutex_flush_l); } } return retval; } /* <<<<<<<<<<<<<<<<<<< Mail the message >>>>>>>>>>>>>>>>>>>>>> */ SH_MUTEX_RECURSIVE(mutex_nmail_msg); SH_MUTEX_STATIC(nmail_lock, PTHREAD_MUTEX_INITIALIZER); /* * First test list of recipients, then call sh_mail_pushstack(). */ int sh_nmail_pushstack (int level, const char * message, const char * alias) { int retval = 0; if (0 != sh_nmail_test_recipients (level, message, alias)) { retval = sh_mail_pushstack(level, message, alias); } return retval; } static int nmail_count = 0; /* * First mark list of recipients, then call sh_mail_msg(). */ int sh_nmail_msg (int level, const char * message, const char * alias) { volatile int retval = 0; /* Need to: * -- wait if different thread, and * -- fail if same thread. */ SH_MUTEX_RECURSIVE_INIT(mutex_nmail_msg); SH_MUTEX_RECURSIVE_LOCK(mutex_nmail_msg); /* Only same thread beyond this point. We fail * if count > 0 already. */ if (0 == SH_MUTEX_TRYLOCK_UNSAFE(nmail_lock)) { ++nmail_count; if (nmail_count != 1) { --nmail_count; SH_MUTEX_UNLOCK_UNSAFE(nmail_lock); goto cleanup; } SH_MUTEX_UNLOCK_UNSAFE(nmail_lock); if (0 != sh_nmail_flag_recipients (level, message, alias)) { /* Need to keep info for sh_nmail_pushstack() */ SH_MUTEX_LOCK(mutex_listall); retval = sh_mail_msg(message); SH_MUTEX_UNLOCK(mutex_listall); if (retval != 0) { sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, retval, MSG_E_SUBGEN, _("could not mail immediately"), _("sh_nmail_msg") ); sh_mail_pushstack(level, message, alias); } } SH_MUTEX_LOCK_UNSAFE(nmail_lock); --nmail_count; SH_MUTEX_UNLOCK_UNSAFE(nmail_lock); } cleanup: ; /* label at end of compound statement */ SH_MUTEX_RECURSIVE_UNLOCK(mutex_nmail_msg); return retval; } static int sh_nmail_flush_int (void); int sh_nmail_flush () { int retval = 0; if (0 == SH_MUTEX_TRYLOCK_UNSAFE(nmail_lock)) { ++nmail_count; if (nmail_count != 1) { --nmail_count; SH_MUTEX_UNLOCK_UNSAFE(nmail_lock); return retval; } SH_MUTEX_UNLOCK_UNSAFE(nmail_lock); retval = sh_nmail_flush_int (); SH_MUTEX_LOCK_UNSAFE(nmail_lock); --nmail_count; SH_MUTEX_UNLOCK_UNSAFE(nmail_lock); } return retval; } /* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/ static struct alias ** list_dummy; /* * Loop over all recipients in stack. * For each distinct one, mark all messages for sending. * Then call sh_mail_msg(). */ static int sh_nmail_flush_int () { int retval = 0; sh_string * msg = NULL; sh_string * smsg = NULL; struct alias * list; struct alias * dlist; /* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/ list_dummy = &list; SH_MUTEX_LOCK(mutex_listall); /* Reset recipient list */ list = all_recipients; while (list) { list->send_mail = 0; list = list->all_next; } /* Check (i) compiled recipients, (b) aliases, (c) single recipients. * For each, tag all messages, then call sh_mail_msg with * appropriate address list. */ reset_list(fifo_mail); /* Compiled recipients. These share threshold and filter, * hence only the first recipient needs to be tested. */ list = compiled_recipient_list; if (list) { msg = tag_list(fifo_mail, sh_string_str(list->recipient), sh_nmail_valid_message_for_alias, list, S_TRUE); } if (msg) { while (list) { list->send_mail = 1; list = list->next; } list = compiled_recipient_list; SH_MUTEX_LOCK(mutex_flush_l); (void) sh_mail_msg(sh_string_str(msg)); SH_MUTEX_UNLOCK(mutex_flush_l); sh_string_destroy(&msg); list = compiled_recipient_list; while (list) { list->send_mail = 0; list = list->next; } } /* Aliases */ list = alias_list; while (list) { /* Work through the recipient list. As smsg stores last msg, * we send a batch whenever msg != smsg, and continue from * that point in the recipient list. */ struct alias * lnew; while (list) { msg = tag_list(fifo_mail, sh_string_str(list->recipient), sh_nmail_valid_message_for_alias, list, S_FALSE); if (msg) { if (!smsg) /* init */ { smsg = sh_string_copy(msg); } else { if (0 != strcmp(sh_string_str(smsg), sh_string_str(msg))) { /* * Don't set list = list->next here, since we want * to continue with this recipient in the next batch. */ sh_string_destroy(&msg); break; } } lnew = list->recipient_list; while (lnew) { lnew->send_mail = 1; lnew= lnew->next; } sh_string_destroy(&msg); } list = list->next; } /* Continue here if smsg != msg */ if (smsg) { SH_MUTEX_LOCK(mutex_flush_l); (void) sh_mail_msg(sh_string_str(smsg)); SH_MUTEX_UNLOCK(mutex_flush_l); sh_string_destroy(&smsg); } /* Reset old list of recipients (up to current point in list) * and then continue with list from current point on. */ dlist = alias_list; while (dlist) { lnew = dlist->recipient_list; while (lnew) { lnew->send_mail = 0; lnew = lnew->next; } dlist = dlist->next; } } /* Single recipients */ list = recipient_list; while (list) { /* Work through the recipient list. As smsg stores last msg, * we send a batch whenever msg != smsg, and continue from * that point in the recipient list. */ while (list) { msg = tag_list(fifo_mail, sh_string_str(list->recipient), sh_nmail_valid_message_for_alias, list, S_TRUE); if (msg) { if (!smsg) /* init */ { smsg = sh_string_copy(msg); } else { if (0 != strcmp(sh_string_str(smsg), sh_string_str(msg))) { /* * Don't set list = list->next here, since we want * to continue with this recipient in the next batch. */ sh_string_destroy(&msg); break; } } list->send_mail = 1; sh_string_destroy(&msg); } list = list->next; } /* Continue here if smsg != msg */ if (smsg) { SH_MUTEX_LOCK(mutex_flush_l); (void) sh_mail_msg(sh_string_str(smsg)); SH_MUTEX_UNLOCK(mutex_flush_l); sh_string_destroy(&smsg); } /* Reset old list of recipients (up to current point in list) * and then continue with list from current point on. */ dlist = recipient_list; while (dlist) { dlist->send_mail = 0; dlist = dlist->next; } } /* Remove all mails for which no recipient failed */ sh.mailNum.alarm_last -= commit_list(fifo_mail); SH_MUTEX_UNLOCK(mutex_listall); return retval; } /* <<<<<<<<<<<<<<<<<<< Severity >>>>>>>>>>>>>>>>>>>>>> */ /* * -- set severity threshold for recipient or alias */ int sh_nmail_set_severity (const char * str) { if (last == recipient_list || last == alias_list) { if (0 == sh_error_set_level(str, &(last->severity))) { /* All recipients in alias share the severity */ if (last == alias_list) { struct alias * ptr = last->recipient_list; while (ptr) { ptr->severity = last->severity; ptr = ptr->next; } } return 0; } } return (-1); } /* <<<<<<<<<<<<<<<<<<< Filters >>>>>>>>>>>>>>>>>>>>>> */ int sh_nmail_add_generic (const char * str, int flag) { if (last) { if (NULL == last->mail_filter) last->mail_filter = sh_filter_alloc(); /* All recipients in alias share the mail filter */ if (last == alias_list) { struct alias * ptr = last->recipient_list; while (ptr) { ptr->mail_filter = last->mail_filter; ptr = ptr->next; } } return (sh_filter_add (str, last->mail_filter, flag)); } return (-1); } /* * -- add keywords to the OR filter */ int sh_nmail_add_or (const char * str) { return sh_nmail_add_generic(str, SH_FILT_OR); } /* * -- add keywords to the AND filter */ int sh_nmail_add_and (const char * str) { return sh_nmail_add_generic(str, SH_FILT_AND); } /* * -- add keywords to the NOT filter */ int sh_nmail_add_not (const char * str) { return sh_nmail_add_generic(str, SH_FILT_NOT); } /* <<<<<<<<<<<<<<<<<<< Mailkey per Alias >>>>>>>>>>>>>>>>>>>>>>>>> */ #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #include #endif #include "zAVLTree.h" zAVLTree * mailkeys = NULL; struct alias_mailkey { char * alias; unsigned int mailcount; time_t id_audit; char mailkey_old[KEY_LEN+1]; char mailkey_new[KEY_LEN+1]; }; static zAVLKey sh_nmail_getkey(void const *item) { const struct alias_mailkey * t = (const struct alias_mailkey *) item; return (zAVLKey) t->alias; } /* Return mailkey for alias. If there's no key yet, create it and * store it in the AVL tree. * This is called from sh_mail_msg, * which is called from sh_nmail_msg, * which is protected by a mutex. */ int sh_nmail_get_mailkey (const char * alias, char * buf, size_t bufsiz, time_t * id_audit) { char hashbuf[KEYBUF_SIZE]; start: if (mailkeys) { struct alias_mailkey * t; if (!alias) t = (struct alias_mailkey *) zAVLSearch (mailkeys, _("(null)")); else t = (struct alias_mailkey *) zAVLSearch (mailkeys, alias); if (t) { /* iterate the key */ (void) sl_strlcpy(t->mailkey_new, sh_tiger_hash (t->mailkey_old, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); (void) sl_strlcpy(buf, t->mailkey_new, bufsiz); ++(t->mailcount); } else { t = SH_ALLOC(sizeof(struct alias_mailkey)); MLOCK(t, sizeof(struct alias_mailkey)); if (!alias) t->alias = sh_util_strdup(_("(null)")); else t->alias = sh_util_strdup(alias); t->mailcount = 0; t->id_audit = time(NULL); BREAKEXIT(sh_util_keyinit); (void) sh_util_keyinit (t->mailkey_old, KEY_LEN+1); /* iterate the key */ (void) sl_strlcpy(t->mailkey_new, sh_tiger_hash (t->mailkey_old, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); (void) sl_strlcpy(buf, t->mailkey_new, bufsiz); (void) zAVLInsert(mailkeys, t); } /* X(n) -> X(n-1) */ (void) sl_strlcpy (t->mailkey_old, t->mailkey_new, KEY_LEN+1); *id_audit = t->id_audit; return (t->mailcount); } mailkeys = zAVLAllocTree (sh_nmail_getkey, zAVL_KEY_STRING); goto start; } /* <<<<<<<<<<<<<<<<<<< Free for Reconfigure >>>>>>>>>>>>>>>>>>>>>> */ static void free_recipient_list(struct alias * list) { struct alias * new; sh_filter_type * p = NULL; while (list) { new = list; list = new->next; if (new->mx_list) free_mx(new->mx_list); if (new->mail_filter) { sh_filter_free(new->mail_filter); if (!p || p != new->mail_filter) { p = new->mail_filter; SH_FREE(new->mail_filter); } } sh_string_destroy(&(new->recipient)); SH_FREE(new); } } /* Free everything to prepare for reconfigure */ void sh_nmail_free() { SH_MUTEX_LOCK_UNSAFE(mutex_listall); all_recipients = NULL; SH_MUTEX_UNLOCK_UNSAFE(mutex_listall); free_recipient_list(recipient_list); recipient_list = NULL; sh_filter_free(&compiled_mail_filter); while (alias_list) { struct alias * item = alias_list; alias_list = item->next; sh_string_destroy(&(item->recipient)); free_recipient_list(item->recipient_list); if (item->mail_filter) { sh_filter_free(item->mail_filter); /* SH_FREE(item->mail_filter); */ } SH_FREE(item); } alias_list = NULL; last = compiled_recipient_list; return; } /* defined(SH_WITH_MAIL) */ #endif samhain-4.1.4/src/sh_xfer_server.c0000644000175000017500000027217312615253277014066 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include /* Must be early on FreeBSD */ #include /* must be .le. than (1020 * 64) * (see sh_tools.c -- put_header) * * also: must be (N * 16), otherwise * binary files cannot be transferred encrypted * * 65280 = (1020*64) * #define TRANS_BYTES 8000 V0.8 */ #ifdef SH_ENCRYPT #define TRANS_BYTES 65120 #else #define TRANS_BYTES 65280 #endif /* timeout for session key */ #define TIMEOUT_KEY 7200 /* max time between connection attempts */ #define TIMEOUT_CON 2048 /* #undef SRP_DEBUG */ /* #define SRP_DEBUG */ #ifdef HAVE_MEMORY_H #include #endif #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif /* #ifdef TM_IN_SYS_TIME #include #else #include #endif */ #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_UNISTD_H #include #include #include #include #include #include #include #include #include #include #endif #ifndef FD_SET #define NFDBITS 32 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #endif /* !FD_SET */ #ifndef FD_SETSIZE #define FD_SETSIZE 32 #endif #ifndef FD_ZERO #define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p))) #endif #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #include #endif #include #include #include #include #ifndef S_SPLINT_S #include #endif #include "sh_ipvx.h" #include "samhain.h" #include "sh_tiger.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_xfer.h" #include "sh_srp.h" #include "sh_fifo.h" #include "sh_tools.h" #include "sh_entropy.h" #include "sh_html.h" #include "sh_nmail.h" #include "sh_socket.h" #define SH_NEED_GETHOSTBYXXX #include "sh_static.h" #include "sh_guid.h" #ifdef SH_ENCRYPT #include "rijndael-api-fst.h" char * sh_tools_makePack (unsigned char * header, int flag, char * payload, unsigned long payload_size, keyInstance * keyInstE); char * sh_tools_revertPack (unsigned char * header, int flag, char * message, keyInstance * keyInstE, unsigned long message_size); #endif /* define this if you want to debug the client/server communication */ /* #define SH_DBG_PROT 1 */ #ifdef SH_DBG_PROT #define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d)) #else #define SH_SHOWPROT(c,d) #endif /* the port client will be connecting to */ #ifndef SH_DEFAULT_PORT #define SH_DEFAULT_PORT 49777 #endif #ifndef SH_SELECT_REPEAT #define SH_SELECT_REPEAT 60 #endif #ifndef SH_HEADER_SIZE #define SH_HEADER_SIZE 7 #endif #ifndef SH_CHALLENGE_SIZE #define SH_CHALLENGE_SIZE 9 #endif #undef FIL__ #define FIL__ _("sh_xfer_server.c") int clt_class = (-1); extern int flag_err_debug; extern int flag_err_info; #if defined (SH_WITH_SERVER) #if defined(WITH_TRACE) || defined(WITH_TPT) extern char * hu_trans(const char * ihu); #endif extern unsigned int ServerPort; #if !defined(USE_SRP_PROTOCOL) extern void sh_passwd (char * salt, char * password, char * nounce, char *hash); #endif static int StripDomain = S_TRUE; int sh_xfer_set_strip (const char * str) { static int fromcl = 0; if (fromcl == 1) return 0; else return (sh_util_flagval(str, &StripDomain)); } static char * sh_strip_domain (char *name) { char * out = NULL; SL_ENTER(_("sh_strip_domain")); if (StripDomain == S_FALSE || strchr(name, '.') == NULL) { out = sh_util_strdup(name); SL_RETURN( out, _("sh_strip_domain")); } else { /* check whether it is in dotted number format * --> last part must be kept */ if (0 != sh_ipvx_is_numeric(name)) { out = sh_util_strdup(name); SL_RETURN( out, _("sh_strip_domain")); } else { char * p; out = sh_util_strdup(name); p = strchr(out, '.'); if (p) *p = '\0'; SL_RETURN( out, _("sh_strip_domain")); } } SL_RETURN( out, _("sh_strip_domain")); } #ifndef USE_SRP_PROTOCOL int sh_xfer_make_client (const char * str) { /* char * safer; */ char key[KEY_LEN+1]; unsigned char in[PW_LEN+1]; int i = 0, j, k, l = 0; char hashbuf[KEYBUF_SIZE]; if (sl_strlen(str) != (PW_LEN * 2)) { fprintf(stderr, _("Input must be a %d digit hexadecimal number"\ " (only 0-9, a-f, A-F allowed in input)\n"), (PW_LEN * 2)); _exit(EXIT_FAILURE); } while (i < (PW_LEN * 2)) { k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); if (k != -1 && j != -1) { in[l] = (k * 16 + j); ++l; i+= 2; } else { fprintf(stderr, _("Invalid char %c\n"), str[i]); _exit(EXIT_FAILURE); } } in[PW_LEN] = '\0'; sl_strlcpy ((char *)key, sh_tiger_hash ((char*)in, TIGER_DATA, PW_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); key[KEY_LEN] = '\0'; fprintf(stdout, _("Client entry: Client=HOSTNAME@00000000@%s\n"), key); fflush(stdout); _exit(EXIT_SUCCESS); return 0; } #else int sh_xfer_make_client (const char * str) { char * foo_v; char salt[17]; char key[KEY_LEN+1]; char in[PW_LEN]; int i = 0, j, k, l = 0; char hashbuf[KEYBUF_SIZE]; if (sl_strlen(str) != (PW_LEN*2)) { fprintf(stderr, _("Input must be a %d digit hexadecimal number"\ " (only 0-9, a-f, A-F allowed in input)\n"), (PW_LEN*2)); _exit(EXIT_FAILURE); } while (i < (PW_LEN*2)) { k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); if (k != -1 && j != -1) { in[l] = (k * 16 + j); ++l; i+= 2; } else { fprintf(stderr, _("Invalid char %c\n"), str[i]); _exit(EXIT_FAILURE); } } if (0 == sh_srp_init()) { sh_util_keyinit(key, KEY_LEN); sl_strlcpy(salt, sh_tiger_hash(key, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), 17); sh_srp_x (salt, in); foo_v = sh_srp_verifier (); fprintf(stdout, _("Client=HOSTNAME@%s@%s\n"), salt, foo_v); fflush(stdout); SH_FREE(foo_v); sh_srp_exit(); _exit(EXIT_SUCCESS); } fprintf(stdout, "%s",_("ERROR initializing BigNum library.\n")); fflush (stdout); _exit(EXIT_FAILURE); return -1; } #endif int sh_xfer_create_password (const char * dummy) { UINT32 val[2]; char output[KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; val[0] = taus_get (); val[1] = taus_get (); sl_strlcpy (output, sh_tiger_hash((char *)(&val[0]), TIGER_DATA, 2*sizeof(UINT32), hashbuf, sizeof(hashbuf)), KEY_LEN); output[16] = '\0'; fprintf(stdout, _("%s\n"), output); fflush (stdout); if (dummy) _exit(EXIT_SUCCESS); else _exit(EXIT_SUCCESS); return (0); /* avoid compiler warning */ } /* #if defined (SH_WITH_SERVER) */ #endif /************************************************** * * * S E R V E R * * ***************************************************/ #ifdef SH_WITH_SERVER #include "sh_readconf.h" #define CONN_FREE 0 #define CONN_READING 1 #define CONN_SENDING 2 #define CONN_PAUSE 3 #define CONN_BUSY 4 char * clt_stat[] = { N_("Inactive"), N_("Started"), N_("ILLEGAL"), N_("FAILED"), N_("Exited"), N_("PANIC"), N_("POLICY"), N_("File_transfer"), N_("Message"), N_("TIMEOUT_EXCEEDED"), N_("Suspended"), N_("Filecheck"), }; #include /* in sh_html.h: * typedef struct client_entry { * } client_t; */ #include "zAVLTree.h" static char * sh_tolower (char * s) { char * ret = s; if (s) { for (; *s; ++s) { *s = tolower((unsigned char) *s); } } return ret; } /* Function to return the key for indexing * the argument */ zAVLKey sh_avl_key (void const * arg) { const client_t * sa = (const client_t *) arg; return (zAVLKey) sa->hostname; } zAVLTree * all_clients = NULL; void sh_xfer_html_write() { SL_ENTER(_("sh_xfer_html_write")); sh_html_write(all_clients); SL_RET0(_("sh_xfer_html_write")); } int sh_xfer_use_clt_class (const char * c) { int i; SL_ENTER(_("sh_xfer_use_clt_class")); i = sh_util_flagval(c, &(sh.flag.client_class)); SL_RETURN(i, _("sh_xfer_use_clt_class")); } int sh_xfer_use_clt_sev (const char * c) { int i; SL_ENTER(_("sh_xfer_use_clt_sev")); i = sh_util_flagval(c, &(sh.flag.client_severity)); SL_RETURN(i, _("sh_xfer_use_clt_sev")); } /* the destructor */ void free_client(void * inptr) { client_t * here; SL_ENTER(_("free_client")); if (inptr == NULL) SL_RET0(_("free_client")); else here = (client_t *) inptr; if (here->hostname != NULL) SH_FREE(here->hostname); if (here->salt != NULL) SH_FREE(here->salt); if (here->verifier != NULL) SH_FREE(here->verifier); SH_FREE(here); SL_RET0(_("free_client")); } int sh_xfer_register_client (const char * str) { client_t * newclt; client_t * testclt; const char * ptr; int sepnum = 0; int sep[2]; register int i = 0; int siz_str = 0; SL_ENTER(_("sh_xfer_register_client")); ptr = str; while (*ptr) { if (*ptr == '@' && sepnum < 2 ) { sep[sepnum] = i; ++sepnum; } ++ptr; ++i; } if (all_clients == NULL) { all_clients = zAVLAllocTree (sh_avl_key, zAVL_KEY_STRING); if (all_clients == NULL) { (void) safe_logger (0, 0, NULL); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } } if ((sepnum == 2) && (sep[0] > 0) && (sep[1] > sep[0])) { newclt = SH_ALLOC (sizeof(client_t)); newclt->hostname = SH_ALLOC (sep[0]+1); newclt->salt = SH_ALLOC (sep[1]-sep[0]); newclt->verifier = SH_ALLOC (sl_strlen(str)-sep[1]+1); newclt->exit_flag = 0; newclt->dead_flag = 0; #ifdef SH_ENCRYPT newclt->encf_flag = SH_PROTO_ENC; newclt->ency_flag = SH_PROTO_ENC; #else newclt->encf_flag = 0; newclt->ency_flag = 0; #endif newclt->ivst_flag = 0; newclt->session_key[0] = '\0'; newclt->last_connect = (time_t) 0; newclt->session_key_timer = (time_t) 0; newclt->status_now = CLT_INACTIVE; for (i = 0; i < CLT_MAX; ++i) newclt->status_arr[i] = CLT_INACTIVE; (void) sh_unix_time(0, newclt->timestamp[CLT_INACTIVE], TIM_MAX); /* truncate */ sl_strlcpy(newclt->hostname, &str[0], sep[0]+1); sh_tolower(newclt->hostname); /* truncate */ sl_strlcpy(newclt->salt, &str[sep[0]+1], sep[1]-sep[0]); sl_strlcpy(newclt->verifier, &str[sep[1]+1], sl_strlen(str)-sep[1]+1); testclt = (client_t *) zAVLSearch (all_clients, newclt->hostname); if (testclt != NULL) { SH_FREE(testclt->verifier); siz_str = strlen (newclt->verifier) + 1; testclt->verifier = SH_ALLOC (siz_str); sl_strlcpy(testclt->verifier, newclt->verifier, siz_str); SH_FREE(testclt->salt); siz_str = strlen (newclt->salt) + 1; testclt->salt = SH_ALLOC (siz_str); sl_strlcpy(testclt->salt, newclt->salt, siz_str); testclt->dead_flag = 0; free_client(newclt); SL_RETURN( 0, _("sh_xfer_register_client")); } else { if (0 == zAVLInsert (all_clients, newclt)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CREG, newclt->hostname, newclt->salt, newclt->verifier); SL_RETURN( 0, _("sh_xfer_register_client")); } } } SL_RETURN (-1, _("sh_xfer_register_client")); } typedef struct { int state; int fd; char * buf; unsigned char head[SH_HEADER_SIZE]; char challenge[SH_CHALLENGE_SIZE]; char peer[SH_MINIBUF+1]; client_t * client_entry; char * K; char * M1; char * A; int headcount; unsigned long bytecount; unsigned long bytes_to_send; unsigned long bytes_to_get; int pass; unsigned long timer; char * FileName; unsigned long FileLength; unsigned long FileSent; char FileType[5]; struct sh_sockaddr addr_peer; } sh_conn_t; static char zap_challenge[SH_CHALLENGE_SIZE] = { 0 }; void sh_xfer_do_free (sh_conn_t * conn) { SL_ENTER(_("sh_xfer_do_free")); if (conn->K != NULL) { SH_FREE(conn->K); conn->K = NULL; } if (conn->A != NULL) { SH_FREE(conn->A); conn->A = NULL; } if (conn->M1 != NULL) { SH_FREE(conn->M1); conn->M1 = NULL; } if (conn->buf != NULL) { SH_FREE(conn->buf); conn->buf = NULL; } if (conn->fd != (-1)) { sl_close_fd (FIL__, __LINE__, conn->fd); conn->fd = -1; } memcpy(conn->challenge, zap_challenge, SH_CHALLENGE_SIZE); conn->state = CONN_FREE; conn->headcount = 0; conn->bytecount = 0; conn->bytes_to_send = 0; conn->bytes_to_get = 0; conn->pass = 0; conn->timer = 0; conn->client_entry = NULL; if (conn->FileName != NULL) { SH_FREE(conn->FileName); conn->FileName = NULL; } conn->FileLength = 0; conn->FileSent = 0; conn->FileType[0] = '\0'; conn->FileType[1] = '\0'; conn->FileType[2] = '\0'; conn->FileType[3] = '\0'; conn->FileType[4] = '\0'; --server_status.conn_open; SL_RET0(_("sh_xfer_do_free")); } /**************************************** * * -- Reconfiguration. -- * * (1) Mark all clients as 'dead'. * (2) Reload configuration - clients * in config are non-dead now. * (3) Remove all clients still * marked as 'dead'. */ /* -- Mark all clients as dead. */ void sh_xfer_mark_dead (void) { zAVLCursor avlcursor; client_t * item; SL_ENTER(_("sh_xfer_mark_dead")); for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item; item = (client_t *) zAVLNext(&avlcursor)) { item->dead_flag = 1; } SL_RET0(_("sh_xfer_mark_dead")); } /* -- Clean tree from dead clients. */ void sh_xfer_clean_tree (void) { zAVLCursor avlcursor; client_t * item; SL_ENTER(_("sh_xfer_clean_tree")); repeat_search: for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item; item = (client_t *) zAVLNext(&avlcursor)) { if (item->dead_flag == 1) { zAVLDelete (all_clients, item->hostname); free_client (item); goto repeat_search; } } SL_RET0(_("sh_xfer_clean_tree")); } /* * **********************************************/ /* -- SERVER SEND FUNCTION. -- */ void sh_xfer_prep_send_int (sh_conn_t * conn, char * msg, unsigned long length, char * u, char protocol, int docrypt) { /* register unsigned long i; */ unsigned long length2; #if !defined(SH_ENCRYPT) (void) docrypt; #endif SL_ENTER(_("sh_xfer_prep_send_int")); TPT((0, FIL__, __LINE__, _("msg=<%s>, docrypt=<%d>\n"), msg, docrypt )); length2 = length; conn->headcount = 0; conn->bytecount = 0; conn->bytes_to_send = 0; conn->bytes_to_get = 0; if (conn->buf != NULL) { SH_FREE(conn->buf); conn->buf = NULL; } put_header (conn->head, protocol, &length2, u); SH_SHOWPROT(conn->head,'>'); TPT((0, FIL__, __LINE__, _("msg=\n") )); if (msg == NULL) length2 = 0; #ifdef SH_ENCRYPT if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0)) { TPT((0, FIL__, __LINE__, _("encrypting (version 2)\n"))); conn->buf = sh_tools_makePack (conn->head, conn->client_entry->ivst_flag, msg, length2, &(conn->client_entry->keyInstE)); } else if (msg == NULL) { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("msg is NULL"), _("sh_xfer_prep_send_int: cipherInit")); } else { if ((length2 + 1) < length2) --length2; conn->buf = SH_ALLOC(length2 + 1); memcpy(conn->buf, msg, length2); conn->buf[length2] = '\0'; TPT((0, FIL__, __LINE__, _("msg=\n") )); } #else if ((length2 + 1) < length2) --length2; conn->buf = SH_ALLOC(length2 + 1); memcpy(conn->buf, msg, length2); conn->buf[length2] = '\0'; TPT((0, FIL__, __LINE__, _("msg=\n") )); #endif conn->state = CONN_SENDING; SL_RET0(_("sh_xfer_prep_send_int")); } /* -- Send/Receive. -- */ void sh_xfer_prep_send (sh_conn_t * conn, char * msg, unsigned long length, char * u, char protocol) { SL_ENTER(_("sh_xfer_prep_send")); sh_xfer_prep_send_int (conn, msg, length, u, protocol, S_FALSE); SL_RET0(_("sh_xfer_prep_send")); } void sh_xfer_send_crypt (sh_conn_t * conn, char * msg, unsigned long length, char * u, char protocol) { SL_ENTER(_("sh_xfer_send_crypt")); sh_xfer_prep_send_int (conn, msg, length, u, protocol, S_TRUE); SL_RET0(_("sh_xfer_send_crypt")); } /* #include */ #if defined(WITH_EXTERNAL) #include "sh_extern.h" #endif /* -- Update the client status. -- * * Update the status array for the client, * and eventually call external program. */ static void status_update (client_t * conn, int status) { #if defined(WITH_EXTERNAL) char msg[2 * SH_MINIBUF + TIM_MAX + 3]; #endif SL_ENTER(_("status_update")); if (conn == NULL || status < 0 || status >= CLT_MAX) SL_RET0(_("status_update")); conn->status_now = status; conn->status_arr[status] = status; (void) sh_unix_time(0, conn->timestamp[status], TIM_MAX); #if defined(WITH_EXTERNAL) sl_snprintf(msg, sizeof(msg), _("%s %s %s"), conn->hostname, conn->timestamp[status], _(clt_stat[status])); sh_ext_execute('s', 'r', 'v', msg, 0); #endif SL_RET0(_("status_update")); } static time_t time_client_limit = 86400; int sh_xfer_set_time_limit (const char * c) { long val; SL_ENTER(_("sh_xfer_set_time_limit")); val = strtol (c, (char **)NULL, 10); if (val <= 0) SL_RETURN( (-1), _("sh_xfer_set_time_limit")); time_client_limit = (time_t) val; SL_RETURN( (0), _("sh_xfer_set_time_limit")); } /* -- Check for time limit exceeded. -- */ static int client_time_check(void) { zAVLCursor avlcursor; client_t * item; SL_ENTER(_("client_time_check")); if (time_client_limit == (time_t) 0) SL_RETURN( 0, _("client_time_check")); for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item; item = (client_t *) zAVLNext(&avlcursor)) { if (item->exit_flag == 0 && item->last_connect != (time_t) 0) { if ( (time(NULL) - item->last_connect) > time_client_limit) { if (item->status_now != CLT_TOOLONG) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMEXC, item->hostname); status_update (item, CLT_TOOLONG); } } } } SL_RETURN( 0, _("client_time_check")); } static int lookup_err = SH_ERR_SEVERE; int sh_xfer_lookup_level (const char * c) { int ci = sh_error_convert_level (c); SL_ENTER(_("sh_xfer_lookup_level")); if (ci >= 0) { lookup_err = ci; SL_RETURN( 0, _("sh_xfer_lookup_level")); } else SL_RETURN( (-1), _("sh_xfer_lookup_level")); } #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 127 #endif int check_addr (const char * claim, struct sh_sockaddr * addr_peer) { char h_name[MAXHOSTNAMELEN + 1]; char h_peer[MAXHOSTNAMELEN + 1]; char h_peer_IP[SH_IP_BUF]; char tmp_peer_IP[SH_IP_BUF]; char * canonical; char numeric[SH_IP_BUF]; SL_ENTER(_("check_addr")); if (claim == NULL) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("NULL input"), _("check_addr")); SL_RETURN ((-1), _("check_addr")); } /* Make sure we have the canonical name for the client */ canonical = sh_ipvx_canonical(claim, numeric, sizeof(numeric)); /* copy canonical name into h_name */ if (canonical != NULL) { sl_strlcpy(h_name, canonical, MAXHOSTNAMELEN + 1); SH_FREE(canonical); } else { sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESCLT, claim); SL_RETURN ((0), _("check_addr")); } /* get canonical name of socket peer */ canonical = sh_ipvx_addrtoname(addr_peer); if (canonical) { if (0 == sl_strcmp(canonical, _("localhost"))) sl_strlcpy(h_peer, sh.host.name, MAXHOSTNAMELEN + 1); else sl_strlcpy(h_peer, canonical, MAXHOSTNAMELEN + 1); SH_FREE(canonical); } else { sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer); sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESPEER, claim, tmp_peer_IP); SL_RETURN ((0), _("check_addr")); } sh_ipvx_ntoa (h_peer_IP, sizeof(h_peer_IP), addr_peer); /* reverse lookup */ if (0 == sh_ipvx_reverse_check_ok (h_peer, ServerPort, addr_peer)) { sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer); sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKERS, claim, h_peer, tmp_peer_IP); SL_RETURN ((0), _("check_addr")); } /* Check whether claim and peer are identical */ sh_tolower(h_peer); /* Canonical name of what the peer is */ sh_tolower(h_name); /* Canonical name of what the peer claims */ if ((0 == sl_strcmp(h_peer, h_name)) || (0 == sl_strcmp(h_peer_IP, h_name))) { SL_RETURN ((0), _("check_addr")); } #if !defined(USE_IPVX) else { struct hostent * he = sh_gethostbyname(h_peer); int i = 0; int flag = 0; while (he->h_aliases[i] != NULL) { if (0 == sl_strcmp(sh_tolower(he->h_aliases[i]), h_name)) { flag = 1; break; } ++i; } if (flag == 0) sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKUP, claim, h_peer); } #endif SL_RETURN ((0), _("check_addr")); } static int UseSocketPeer = S_FALSE; int set_socket_peer (const char * c) { return sh_util_flagval(c, &UseSocketPeer); } /* -- Search register. -- */ client_t * search_register(sh_conn_t * conn, int pos) { client_t * this_client; char peer_ip[SH_IP_BUF]; char numerical[SH_IP_BUF]; char peer_name[MAXHOSTNAMELEN+1]; char * search_string; struct sh_sockaddr peer_addr; char * canonical; SL_ENTER(_("search_register")); if (UseSocketPeer == S_TRUE) { memcpy(&peer_addr, &(conn->addr_peer), sizeof(struct sh_sockaddr)); sh_ipvx_ntoa (peer_ip, sizeof(peer_ip), &peer_addr); /* get canonical name of socket peer */ canonical = sh_ipvx_canonical(peer_ip, numerical, sizeof(numerical)); if (canonical != NULL) { if (0 == sl_strcmp(canonical, _("localhost"))) sl_strlcpy(peer_name, sh.host.name, MAXHOSTNAMELEN + 1); else sl_strlcpy(peer_name, canonical, MAXHOSTNAMELEN + 1); SH_FREE(canonical); } if (0 == sh_ipvx_reverse_check_ok (peer_name, ServerPort, &peer_addr)) { sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1); } search_string = peer_name; } else { search_string = &(conn->buf[pos]); if (0 != check_addr (search_string, &(conn->addr_peer))) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Reverse lookup failed"), search_string); sh_xfer_do_free (conn); SL_RETURN( NULL, _("search_register")); } } sh_tolower(search_string); /* ---- search the register ----- */ this_client = zAVLSearch(all_clients, search_string); if (this_client == NULL) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Not in client list"), search_string); sh_xfer_do_free (conn); SL_RETURN( NULL, _("search_register")); } if (this_client->exit_flag == 1) { TPT((0, FIL__, __LINE__, _("msg=exit_flag == 1>\n"))); this_client->session_key_timer = (time_t) 0; this_client->session_key[0] = '\0'; this_client->exit_flag = 0; } TPT((0, FIL__, __LINE__, _("msg=\n"), this_client->hostname)); TPT((0, FIL__, __LINE__, _("msg=\n"), this_client->session_key)); SL_RETURN( this_client, _("search_register")); } client_t * do_check_client(sh_conn_t * conn, int * retval) { client_t * this_client = NULL; char sigbuf[KEYBUF_SIZE]; *retval = 0; TPT(( 0, FIL__, __LINE__, _("msg=\n"))); if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT); sh_xfer_do_free (conn); return NULL; } /* ---- search the register ----- */ this_client = search_register (conn, KEY_LEN); if (this_client == NULL) return NULL; /* ---- force authentication ----- */ if (this_client->session_key[0] == '\0' || (time(NULL) - this_client->session_key_timer) > (time_t) TIMEOUT_KEY ) { size_t len; /* fake an auth request and jump there */ conn->head[0] = (conn->head[0] | SH_PROTO_SRP); conn->head[3] = 'S'; conn->head[4] = 'A'; conn->head[5] = 'L'; conn->head[6] = 'T'; if (flag_err_info == S_TRUE) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH, &(conn->buf[KEY_LEN])); len = sl_strlen(&(conn->buf[KEY_LEN])) + 1; /* may overlap, thus only memmove is correct */ memmove(conn->buf, &(conn->buf[KEY_LEN]), len); this_client->session_key[0] = '\0'; this_client->session_key_timer = (time_t) 1; *retval = -1; return NULL; } /* --- check whether hostname is properly signed --- */ if (conn->K != NULL) { SH_FREE(conn->K); conn->K = NULL; } conn->K = SH_ALLOC(KEY_LEN+1); sl_strlcpy (conn->K, sh_util_siggen(this_client->session_key, &(conn->buf[KEY_LEN]), sl_strlen(&(conn->buf[KEY_LEN])), sigbuf, sizeof(sigbuf)), KEY_LEN+1); if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN)) { TPT((0, FIL__, __LINE__, _("msg=\n"), conn->buf)); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->K)); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Signature mismatch"), &(conn->buf[KEY_LEN])); this_client->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); return NULL; } SH_FREE(conn->K); conn->K = NULL; return this_client; } /* ------------------------------------------------------ * * FILE TRANSFER * * ------------------------------------------------------ */ static void do_file_send_data(sh_conn_t * conn) { char * read_buf = 0; char * send_buf; int bytes; SL_TICKET sfd = -1; #ifdef SH_ENCRYPT int blkfac; int rem; int send_bytes; #endif if (conn == NULL || conn->FileName == NULL) { sh_error_handle((-1), FIL__, __LINE__, sfd, MSG_TCP_NFILE, conn->peer, (conn->FileName == NULL) ? _("(NULL)") : conn->FileName); status_update (conn->client_entry, CLT_FAILED); sh_xfer_do_free (conn); return; } if (conn->FileSent == conn->FileLength) { send_buf = hash_me(conn->K, conn->peer, sl_strlen(conn->peer)); #ifdef SH_ENCRYPT sh_xfer_send_crypt (conn, send_buf, sl_strlen(conn->peer)+KEY_LEN, _("EEOT"), SH_PROTO_BIG|conn->client_entry->encf_flag); #else sh_xfer_send_crypt (conn, send_buf, sl_strlen(conn->peer)+KEY_LEN, _("EEOT"), SH_PROTO_BIG); #endif SH_FREE(send_buf); } else { bytes = -1; sfd = sl_open_read(FIL__, __LINE__, conn->FileName, SL_YESPRIV); if (!SL_ISERROR(sfd)) { read_buf = SH_ALLOC(TRANS_BYTES); if (conn->FileSent > 0) sl_seek (sfd, (off_t) conn->FileSent); bytes = sl_read (sfd, read_buf, TRANS_BYTES); sl_close(sfd); } else { sh_error_handle((-1), FIL__, __LINE__, sfd, MSG_E_ACCESS, (long) geteuid(), conn->FileName); } if (bytes >= 0) { #ifdef SH_ENCRYPT /* need to send N * B_SIZ bytes */ blkfac = bytes / B_SIZ; rem = bytes - (blkfac * B_SIZ); if (rem != 0) { memset(&read_buf[bytes], '\n', (B_SIZ-rem)); ++blkfac; send_bytes = blkfac * B_SIZ; } else send_bytes = bytes; send_buf = hash_me(conn->K, read_buf, send_bytes); sh_xfer_send_crypt (conn, send_buf, send_bytes+KEY_LEN, _("FILE"), SH_PROTO_BIG|conn->client_entry->encf_flag); #else send_buf = hash_me(conn->K, read_buf, bytes); sh_xfer_send_crypt (conn, send_buf, bytes+KEY_LEN, _("FILE"), SH_PROTO_BIG); #endif conn->FileSent += bytes; if (send_buf) /* hash_me() *may* return NULL */ SH_FREE(send_buf); SH_FREE(read_buf); } else { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NFILE, conn->peer, (conn->FileName == NULL) ? _("(NULL)") : conn->FileName); status_update (conn->client_entry, CLT_FAILED); sh_xfer_do_free (conn); } } return; } static void do_file_initial(sh_conn_t * conn) { char * ptok; char hashbuf[KEYBUF_SIZE]; /* --- get client nonce and compute hash --- * * K = H(NSRV, NCLT, session_key) */ if (conn->A != NULL) { SH_FREE(conn->A); conn->A = NULL; } conn->A = SH_ALLOC(3*KEY_LEN+1); sl_strlcpy (conn->A, conn->K, KEY_LEN+1); sl_strlcat(conn->A, conn->buf, /* truncate */ 2*KEY_LEN+1); sl_strlcat(conn->A, conn->client_entry->session_key, 3*KEY_LEN+1); sl_strlcpy (conn->K, sh_tiger_hash(conn->A,TIGER_DATA,3*KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); SH_FREE(conn->A); conn->A = NULL; /* Warn about encryption mismatch */ #ifdef SH_ENCRYPT if ((conn->client_entry->encf_flag != 0) && /* server */ ((conn->head[0] & SH_PROTO_ENC) == 0)) /* client */ { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC, _("file download"), _("version2"), _("none")); } else if ((conn->client_entry->encf_flag != 0) && /* server */ ((conn->head[0] & SH_MASK_ENC) != /* client */ conn->client_entry->encf_flag)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC, _("file download"), _("version2"), ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid")); conn->client_entry->encf_flag = (conn->head[0] & SH_MASK_ENC); } #else if ((conn->head[0] & SH_PROTO_ENC) != 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC, _("file download"), _("none"), ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid")); } #endif if (conn->FileName != NULL) { SH_FREE(conn->FileName); conn->FileName = NULL; } /* Determine what to send */ if (0 == sl_strncmp (_("CONF"), &(conn->buf[KEY_LEN]), 4)) { strcpy(conn->FileType, _("CONF")); /* known to fit */ conn->FileName = get_client_conf_file(conn->peer, &(conn->FileLength)); conn->FileSent = 0; } else if (0 == sl_strncmp (_("DATA"), &(conn->buf[KEY_LEN]), 4)) { strcpy(conn->FileType, _("DATA")); /* known to fit */ conn->FileName = get_client_data_file(conn->peer, &(conn->FileLength)); conn->FileSent = 0; } else if (0 == sh_uuid_check(&(conn->buf[KEY_LEN]))) { char * uuid = &(conn->buf[KEY_LEN]); strcpy(conn->FileType, _("UUID")); /* known to fit */ conn->FileName = get_client_uuid_file(conn->peer, &(conn->FileLength), uuid); conn->FileSent = 0; } else { ptok = sh_util_safe_name(&(conn->buf[KEY_LEN])); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FFILE, conn->peer, ptok); SH_FREE(ptok); status_update (conn->client_entry, CLT_FAILED); sh_xfer_do_free (conn); } return; } static int do_file_transfer(sh_conn_t * conn, int state) { client_t * this_client; UINT32 ticks; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("do_file_transfer")); if (state == SH_DO_READ) /* finished reading */ { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); /* -- Client requests challenge. -- */ if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO"))) { int client_state; this_client = do_check_client(conn, &client_state); if (!this_client) SL_RETURN(client_state, _("do_file_transfer")); /* --- create and send a nonce --- */ conn->client_entry = this_client; sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1); ticks = (UINT32) taus_get (); if (conn->K != NULL) { SH_FREE(conn->K); conn->K = NULL; } conn->K = SH_ALLOC(KEY_LEN+1); sl_strlcpy (conn->K, sh_tiger_hash ((char *) &ticks, TIGER_DATA, sizeof(UINT32), hashbuf, sizeof(hashbuf)), KEY_LEN+1); TPT((0, FIL__, __LINE__, _("msg=\n"))); sh_xfer_prep_send (conn, conn->K, KEY_LEN+1, _("NSRV"), SH_PROTO_BIG); } /* --- Client has send a message. Check state and message. --- */ else if (0 == check_request_nerr((char *)&(conn->head[3]), _("NCLT")) && conn->client_entry != NULL && sl_strlen(conn->buf) > KEY_LEN && conn->K != NULL) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); do_file_initial(conn); do_file_send_data(conn); } else if (0 == check_request_nerr((char *)&(conn->head[3]), _("RECV")) && conn->client_entry != NULL && conn->K != NULL && conn->FileName != NULL) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); do_file_send_data(conn); } else if (0 == check_request_nerr((char *)&(conn->head[3]), _("EOTE")) && conn->client_entry != NULL) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); if (flag_err_info == S_TRUE) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKFILE, conn->peer); if ((conn->client_entry->status_now != CLT_SUSPEND) && (conn->client_entry->status_now != CLT_TOOLONG)) { status_update (conn->client_entry, CLT_FILE); } else { conn->client_entry->session_key[0] = '\0'; } conn->client_entry->last_connect = time (NULL); sh_xfer_do_free (conn); } /* client does something unexpected */ else /* ---- ??? ----- */ { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV, 1, conn->pass, conn->peer, '\\', conn->head[3], '\\',conn->head[4], '\\', conn->head[5], '\\',conn->head[6]); status_update (conn->client_entry, CLT_FAILED); sh_xfer_do_free (conn); } } else if (state == SH_DO_WRITE) /* finished writing */ { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); /* challenge is sent, now wait for message from client */ conn->headcount = 0; conn->bytecount = 0; conn->bytes_to_send = 0; conn->bytes_to_get = 0; if (conn->buf != NULL) { SH_FREE(conn->buf); conn->buf = NULL; } conn->state = CONN_READING; } SL_RETURN(0, _("do_file_transfer")); } /* ------------------------------------------------------ * * MESSAGE TRANSFER * * ------------------------------------------------------ */ static int do_message_transfer(sh_conn_t * conn, int state) { client_t * this_client; char * cmd; char hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1]; char * buffer; int clt_sev; char * ptok; UINT32 ticks; size_t len; int i; char * test; char sigbuf[KEYBUF_SIZE]; SL_ENTER(_("do_message_transfer")); if (state == SH_DO_READ) /* finished reading */ { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); /* -- Client requests challenge. -- */ if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO"))) { int client_state; this_client = do_check_client(conn, &client_state); if (!this_client) SL_RETURN(client_state, _("do_message_transfer")); /* -- create a nonce and send it -- */ conn->client_entry = this_client; sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1); ticks = (UINT32) taus_get (); test = (char *) &ticks; sh_util_cpylong (conn->challenge, test, 4); conn->challenge[4] = '\0'; for (i = 0; i < 4; ++i) if (conn->challenge[i] == '\0') conn->challenge[i] = 0x01; sh_xfer_prep_send (conn, conn->challenge, 5, _("TALK"), SH_PROTO_MSG); TPT(( 0, FIL__, __LINE__, _("msg=\n"), hu_trans(conn->challenge))); } /* Client has send a message. Check whether we are in proper * state, and verify message. */ else if (0 == check_request_nerr((char *)&(conn->head[3]), _("MESG")) && conn->client_entry != NULL && conn->client_entry->session_key[0] != '\0' && (len = sl_strlen(conn->buf) - KEY_LEN) > 0 && sl_strlen(conn->challenge) == 4) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); #ifdef SH_ENCRYPT if (conn->client_entry->encf_flag == 0) { conn->client_entry->ency_flag = 0; } if ((conn->client_entry->ency_flag != 0) && ((conn->head[0] & SH_PROTO_ENC) == 0)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC, _("message transfer"), _("version2"), _("none")); } else if ((conn->client_entry->ency_flag != 0) && ((conn->head[0] & SH_MASK_ENC) != conn->client_entry->ency_flag)) { sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_TCP_MISENC, _("message transfer"), _("version2"), ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid")); conn->client_entry->ency_flag = (conn->head[0] & SH_MASK_ENC); } #else if ((conn->head[0] & SH_PROTO_ENC) != 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC, _("message transfer"), _("none"), ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid")); } #endif TPT(( 0, FIL__, __LINE__, _("msg=\n"), conn->buf)); /* get hash from message end, truncate message */ sl_strlcpy(hash, &(conn->buf[len]), KEY_LEN+1); conn->buf[len] = '\0'; /* verify hash */ buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL); i = sl_strncmp(hash, sh_util_siggen(conn->client_entry->session_key, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)), KEY_LEN); TPT((0, FIL__, __LINE__, _("msg=\n"), sh_util_siggen(conn->client_entry->session_key, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)))); if (0 != i) { TPT((0, FIL__, __LINE__, _("msg=\n"))); status_update (conn->client_entry, CLT_FAILED); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Msg signature mismatch"), conn->peer); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); SL_RETURN(0, _("do_message_transfer")); } else { conn->client_entry->last_connect = time (NULL); if (NULL != sl_strstr(conn->buf, _("EXIT"))) { TPT((0, FIL__, __LINE__, _("msg=\n"))); conn->client_entry->exit_flag = 1; status_update (conn->client_entry, CLT_EXITED); } else if (NULL != sl_strstr(conn->buf, _("PANIC"))) { TPT((0, FIL__, __LINE__, _("msg=\n"))); status_update (conn->client_entry, CLT_PANIC); } else if (NULL != sl_strstr(conn->buf, _("SUSPEND"))) { TPT((0, FIL__, __LINE__, _("msg=\n"))); status_update (conn->client_entry, CLT_SUSPEND); } else if (NULL != sl_strstr(conn->buf, _("POLICY"))) { TPT((0, FIL__, __LINE__, _("msg=\n"))); status_update (conn->client_entry, CLT_POLICY); } else if (NULL != sl_strstr(conn->buf, _("File check completed"))) { TPT((0, FIL__, __LINE__, _("msg=\n"))); status_update (conn->client_entry, CLT_CHECK); } else if (NULL != sl_strstr(conn->buf, _("START"))) { TPT((0, FIL__, __LINE__, _("msg=\n"))); sh_socket_add2reload (conn->client_entry->hostname); if (conn->client_entry->status_now == CLT_SUSPEND) { status_update (conn->client_entry, CLT_ILLEGAL); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL, conn->peer); } else status_update (conn->client_entry, CLT_STARTED); } else { TPT((0, FIL__, __LINE__, _("msg=\n"))); if (NULL != sl_strstr(conn->buf, _("Runtime configuration reloaded"))) { sh_socket_add2reload (conn->client_entry->hostname); } status_update (conn->client_entry, CLT_MSG); } TPT((0, FIL__, __LINE__, _("msg=\n"))); clt_sev = atoi(conn->buf); clt_class = (-1); ptok = strchr(conn->buf, '?'); if (ptok != NULL) { ++ptok; if (ptok != NULL && sh.flag.client_class == S_TRUE) clt_class = atoi(ptok); /* is a global */ ptok = strchr(ptok, '?'); if (ptok != NULL) ++ptok; } if (sh.flag.client_severity == S_FALSE) clt_sev = (-1); /* here we expect an xml formatted message, thus we don't escape xml special chars (flag == 0) */ ptok = sh_tools_safe_name ((ptok!=NULL) ? ptok : conn->buf, 0); /* push client name to error routine */ #if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE) { char peer_ip[SH_IP_BUF]; sh_ipvx_ntoa(peer_ip, sizeof(peer_ip), &(conn->addr_peer)); sh_error_set_peer_ip( peer_ip ); } #endif { char * pstrip = sh_strip_domain (conn->peer); sh_error_set_peer(pstrip); sh_error_handle(clt_sev, FIL__, __LINE__, 0, MSG_TCP_MSG, pstrip, ptok); SH_FREE(pstrip); sh_error_set_peer(NULL); } #if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE) sh_error_set_peer_ip(NULL); #endif TPT((0, FIL__, __LINE__, _("msg=<%s>\n"), ptok)); SH_FREE(ptok); clt_class = (-1); } memset(buffer, '\0', sl_strlen(buffer)); SH_FREE(buffer); /* SERVER CONF SEND */ buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL); sl_strlcpy(hash, sh_util_siggen ( conn->client_entry->session_key, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)), KEY_LEN+1); /* --- SERVER CMD --- */ cmd = sh_socket_check (conn->peer); if (cmd != NULL) { /* max cmd size is SH_MAXMSGLEN bytes */ sl_strlcpy(&hash[KEY_LEN], cmd, SH_MAXMSGLEN); sl_strlcat(&hash[KEY_LEN], sh_util_siggen ( conn->client_entry->session_key, &hash[KEY_LEN], sl_strlen(&hash[KEY_LEN]), sigbuf, sizeof(sigbuf)), SH_MAXMSGLEN+KEY_LEN+1); TPT((0, FIL__, __LINE__, _("CONF SEND <0> <%s>\n"), &hash[KEY_LEN])); } else { TPT((0, FIL__, __LINE__, _("CONF SEND <0> <[NULL]>\n"))); } /* --- SERVER CMD END --- */ TPT((0, FIL__, __LINE__, _("msg=\n"), sh_util_siggen(conn->client_entry->session_key, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)))); #ifdef SH_ENCRYPT sh_xfer_send_crypt (conn, hash, sl_strlen(hash) /* KEY_LEN */, _("CONF"), SH_PROTO_MSG|SH_PROTO_END|conn->client_entry->ency_flag); #else sh_xfer_send_crypt (conn, hash, sl_strlen(hash) /* KEY_LEN */, _("CONF"), SH_PROTO_MSG|SH_PROTO_END); #endif memset(buffer, '\0', sl_strlen(buffer)); SH_FREE(buffer); /* sh_xfer_do_free (conn); */ } /* client does something unexpected */ else /* ---- ??? ----- */ { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV, 2, conn->pass, conn->peer, '\\', conn->head[3], '\\',conn->head[4], '\\', conn->head[5], '\\',conn->head[6]); status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); } } else if (state == SH_DO_WRITE) /* finished writing */ { if (0 != (conn->head[0] & SH_PROTO_END)) { if (flag_err_debug == S_TRUE) { char * pstrip = sh_strip_domain (conn->peer); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKMSG, pstrip); SH_FREE(pstrip); } sh_xfer_do_free (conn); SL_RETURN(0, _("do_message_transfer")); } TPT(( 0, FIL__, __LINE__, _("msg=\n"))); /* challenge is sent, now wait for message from client */ conn->headcount = 0; conn->bytecount = 0; conn->bytes_to_send = 0; conn->bytes_to_get = 0; if (conn->buf != NULL) { SH_FREE(conn->buf); conn->buf = NULL; } conn->state = CONN_READING; } TPT((0, FIL__, __LINE__, _("msg=\n") )); SL_RETURN(0, _("do_message_transfer")); } /* ------------------------------------------------------ * * AUTHENTICATION * * ------------------------------------------------------ */ static void check_probe(sh_conn_t * conn) { if (conn && conn->client_entry) { /* If client has sent probe, change ivst_flag and clear probe in head[0]. */ conn->head[0] = sh_tools_probe_store(conn->head[0], &(conn->client_entry->ivst_flag)); } } client_t * do_auth_start(sh_conn_t * conn) { client_t * this_client; TPT((0, FIL__, __LINE__, _("msg=\n"))); if (conn->buf == NULL || sl_strlen(conn->buf) == 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT); sh_xfer_do_free (conn); return NULL; } /* search the register */ this_client = search_register (conn, 0); if (NULL == this_client) return NULL; conn->client_entry = this_client; sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1); if (0 != check_request_s((char *)&(conn->head[3]), _("SALT"),conn->peer)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("No salt requested"), conn->peer); status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); return NULL; } check_probe(conn); return this_client; } #if !defined(USE_SRP_PROTOCOL) int do_auth(sh_conn_t * conn) { client_t * this_client; UINT32 ticks; char u[5] = "OOOO"; #ifdef SH_ENCRYPT int err_num; char expbuf[SH_ERRBUF_SIZE]; #endif char hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1]; char hashbuf[KEYBUF_SIZE]; /* first pass -- client request salt */ if (conn->pass == 1) { this_client = do_auth_start(conn); if (!this_client) return -1; /* -- create server nounce v -- */ ticks = (UINT32) taus_get (); if (conn->A != NULL) { SH_FREE(conn->A); conn->A = NULL; } conn->A = SH_ALLOC(KEY_LEN+1); sl_strlcpy(conn->A, sh_tiger_hash((char *) &ticks, TIGER_DATA, sizeof(UINT32), hashbuf, sizeof(hashbuf)), KEY_LEN+1); u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0'; if (conn->M1 != NULL) { SH_FREE(conn->M1); conn->M1 = NULL; } conn->M1 = SH_ALLOC(2*KEY_LEN+1); /* compute hash key H(v(server), P)v(server) */ sh_passwd (conn->A, conn->client_entry->verifier, NULL, conn->M1); sl_strlcat(conn->M1, conn->A, 2*KEY_LEN+1); /* --- send H(v(server), P)v(server) ---- */ sh_xfer_prep_send (conn, conn->M1, sl_strlen(conn->M1), u, (conn->head[0]|SH_PROTO_SRP)); SH_FREE(conn->M1); conn->M1 = NULL; } /* client -- third pass * Message is H(H(u,v),P)u * * A := v, verifier := H(password), */ else if (conn->pass == 3 && conn->client_entry != NULL) { TPT((0, FIL__, __LINE__, _("msg=\n"))); if (0 != check_request_s((char *) &(conn->head[3]), _("PASS"), conn->peer) || sl_strlen(conn->buf) <= KEY_LEN || conn->A == NULL) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Invalid client request"), conn->peer); status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); return -1; } check_probe(conn); /* store random nonce u from client */ if (conn->K != NULL) { SH_FREE(conn->K); conn->K = NULL; } conn->K = SH_ALLOC(KEY_LEN+1); sl_strlcpy(conn->K, &(conn->buf[KEY_LEN]), KEY_LEN+1); /* verify random nonce u from client */ if (conn->M1 != NULL) { SH_FREE(conn->M1); conn->M1 = NULL; } conn->M1 = sh_util_strconcat(conn->K, conn->A, NULL); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->K)); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->A)); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->M1)); sl_strlcpy(hash, sh_tiger_hash (conn->M1, TIGER_DATA, sl_strlen(conn->M1), hashbuf, sizeof(hashbuf)), KEY_LEN+1); sh_passwd (hash, conn->client_entry->verifier, NULL, conn->M1); TPT((0, FIL__, __LINE__, _("msg=\n"), hash)); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->M1)); if ( 0 != sl_strncmp(conn->M1, conn->buf, KEY_LEN)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Session key mismatch"), conn->peer); status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); return -1; } /* ---- compute hash key H(v, P, u) ---- */ sh_passwd (conn->A, conn->client_entry->verifier, conn->K, conn->M1); sl_strlcpy(conn->client_entry->session_key, conn->M1, KEY_LEN+1); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->client_entry->session_key)); #ifdef SH_ENCRYPT err_num = rijndael_makeKey(&(conn->client_entry->keyInstE), DIR_ENCRYPT, 192, conn->client_entry->session_key); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("check_protocol: makeKey")); err_num = rijndael_makeKey(&(conn->client_entry->keyInstD), DIR_DECRYPT, 192, conn->client_entry->session_key); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("check_protocol: makeKey")); #endif if (conn->K != NULL) SH_FREE (conn->K); conn->K = NULL; if (conn->A != NULL) SH_FREE (conn->A); conn->A = NULL; if (conn->M1 != NULL) SH_FREE (conn->M1); conn->M1 = NULL; /* if (conn->client_entry->status_now == CLT_STARTED */ if (((conn->client_entry->status_now != CLT_INACTIVE) && (conn->client_entry->status_now != CLT_EXITED) && (conn->client_entry->status_now != CLT_SUSPEND)) && conn->client_entry->session_key_timer > (time_t) 1) { status_update (conn->client_entry, CLT_ILLEGAL); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL, conn->peer); } else if (conn->client_entry->session_key_timer == (time_t) 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NEW, conn->peer); if (conn->client_entry->status_now != CLT_SUSPEND) status_update (conn->client_entry, CLT_STARTED); } conn->client_entry->session_key_timer = time (NULL); conn->client_entry->last_connect = time (NULL); /* put in read state */ sh_xfer_prep_send (conn, _("AUTH"), 5, _("AUTH"), (conn->head[0]|SH_PROTO_SRP)); } else { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV, 3, conn->pass, conn->peer, '\\', conn->head[3], '\\', conn->head[4], '\\', conn->head[5], '\\', conn->head[6]); sh_xfer_do_free (conn); } return 0; } #else static void noise() { UINT32 n = taus_get(); retry_msleep(0, (n & 0x0000007F)); return; } /* use SRP */ int do_auth(sh_conn_t * conn) { client_t * this_client; UINT32 ticks; char u[5] = "OOOO"; #ifdef SH_ENCRYPT int err_num; char expbuf[SH_ERRBUF_SIZE]; #endif size_t len; char * test; char * foo_B; char * foo_Ss; char hashbuf[KEYBUF_SIZE]; /* use SRP */ if (conn->pass == 1) { this_client = do_auth_start(conn); if (!this_client) return -1; u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0'; sh_xfer_prep_send (conn, conn->client_entry->salt, sl_strlen(conn->client_entry->salt), u, (conn->head[0]|SH_PROTO_SRP)); } /* client has sent A -- third pass */ else if (conn->pass == 3 && conn->client_entry != NULL) { TPT((0, FIL__, __LINE__, _("msg=\n"))); if (0 != check_request_s((char *)&(conn->head[3]),_("PC01"),conn->peer)|| conn->buf == NULL ) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Invalid client request"), conn->peer); status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); return -1; } check_probe(conn); noise(); if (0 != sh_srp_init()) { status_update (conn->client_entry, CLT_FAILED); sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_TCP_EBGN); sh_xfer_do_free (conn); return -1; } /* check A, only send B if correct */ if ( sl_strlen(conn->buf) < SH_BUFSIZE && 0 == sh_srp_check_zero (conn->buf) ) { len = sl_strlen(conn->buf)+1; if (conn->A != NULL) { SH_FREE(conn->A); conn->A = NULL; } conn->A = SH_ALLOC(len); sl_strlcpy (conn->A, conn->buf, len); /* * compute B */ if (0 != sh_srp_make_a ()) /* b random number */ { status_update (conn->client_entry, CLT_FAILED); sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_TCP_EBGN); sh_srp_exit(); sh_xfer_do_free (conn); return -1; } foo_B = sh_srp_B /* B = v + g^b */ (conn->client_entry->verifier); if (foo_B == NULL) { status_update (conn->client_entry, CLT_FAILED); sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_TCP_EBGN); sh_srp_exit(); sh_xfer_do_free (conn); return -1; } TPT((0, FIL__, __LINE__, _("msg=\n"), conn->A)); TPT((0, FIL__, __LINE__, _("msg=\n"), foo_B)); /* * create nonce u */ ticks = (UINT32) taus_get (); test = (char *) &ticks; sh_util_cpylong (u, test, 4); /* u nounce */ u[4] = '\0'; sl_strlcpy(conn->challenge, sh_tiger_hash(u, TIGER_DATA, 4, hashbuf, sizeof(hashbuf)), SH_CHALLENGE_SIZE); TPT((0, FIL__, __LINE__, _("msg=\n"), u[0], u[1], u[2], u[3])); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->challenge)); /* * compute the session key K and M1 = Hash(A,B,K) */ foo_Ss = sh_srp_S_s (conn->challenge, conn->A, conn->client_entry->verifier); if (foo_Ss == NULL || 0 != sh_srp_check_zero (foo_Ss)) { status_update (conn->client_entry, CLT_FAILED); sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_TCP_EBGN); sh_srp_exit(); sh_xfer_do_free (conn); return -1; } if (conn->K != NULL) { SH_FREE(conn->K); conn->K = NULL; } conn->K = SH_ALLOC(KEY_LEN+1); sl_strlcpy(conn->K, sh_tiger_hash(foo_Ss, TIGER_DATA, sl_strlen(foo_Ss), hashbuf, sizeof(hashbuf)), KEY_LEN+1); if (conn->M1 != NULL) { SH_FREE(conn->M1); conn->M1 = NULL; } conn->M1 = SH_ALLOC(KEY_LEN+1); sh_srp_M (conn->A, foo_B, conn->K, conn->M1, KEY_LEN+1); TPT((0, FIL__, __LINE__, _("msg=\n"), foo_Ss)); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->K)); TPT((0, FIL__, __LINE__, _("msg=\n"),conn->M1)); /* * send B */ sh_xfer_prep_send (conn, foo_B, sl_strlen(foo_B)+1, u, (conn->head[0]|SH_PROTO_SRP)); if (foo_Ss != NULL) { SH_FREE(foo_Ss); foo_Ss = NULL; } if (foo_B != NULL) { SH_FREE(foo_B); foo_B = NULL; } } else { status_update (conn->client_entry, CLT_FAILED); sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_TCP_EZERO); sh_xfer_do_free (conn); } sh_srp_exit(); } /* client has sent M1 -- fifth pass */ else if (conn->pass == 5 && conn->client_entry != NULL) { TPT((0, FIL__, __LINE__, _("msg=\n"))); /* check that the state is valid */ if (0 != check_request_s((char *)&(conn->head[3]), _("PC02"), conn->peer) || conn->A == NULL || conn->K == NULL || conn->M1 == NULL) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Invalid client request"), conn->peer); status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_xfer_do_free (conn); return -1; } check_probe(conn); noise(); /* ------ verify M1 = H(A, B, K) ------- * ----- send M2 = H(A, M1, K) ------- */ if (conn->buf != NULL && sl_strncmp(conn->buf, conn->M1, KEY_LEN) == 0) { /* * send M2 */ char M_buf[KEY_LEN+1]; sh_xfer_prep_send (conn, sh_srp_M (conn->A, conn->M1, conn->K, M_buf, sizeof(M_buf)), KEY_LEN+1, _("PARP"), (conn->head[0]|SH_PROTO_SRP)); if (conn->A != NULL) SH_FREE(conn->A); conn->A = NULL; if (conn->M1 != NULL) SH_FREE(conn->M1); conn->M1 = NULL; sl_strlcpy(conn->client_entry->session_key, conn->K, KEY_LEN+1); TPT((0, FIL__, __LINE__, _("msg=\n"), conn->client_entry->session_key)); #ifdef SH_ENCRYPT err_num = rijndael_makeKey(&(conn->client_entry->keyInstE), DIR_ENCRYPT, 192, conn->client_entry->session_key); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("sh_xfer_prep_send_int: makeKey")); err_num = rijndael_makeKey(&(conn->client_entry->keyInstD), DIR_DECRYPT, 192, conn->client_entry->session_key); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("sh_xfer_prep_send_int: makeKey")); #endif if (conn->K != NULL) SH_FREE(conn->K); conn->K = NULL; conn->client_entry->last_connect = time (NULL); if (((conn->client_entry->status_now != CLT_INACTIVE) && (conn->client_entry->status_now != CLT_EXITED) && (conn->client_entry->status_now != CLT_SUSPEND)) && conn->client_entry->session_key_timer > (time_t) 1) { status_update (conn->client_entry, CLT_ILLEGAL); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL, conn->peer); } else if (conn->client_entry->session_key_timer == (time_t) 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NEW, conn->peer); if (conn->client_entry->status_now != CLT_SUSPEND) status_update (conn->client_entry, CLT_STARTED); } conn->client_entry->session_key_timer = time (NULL); } else { status_update (conn->client_entry, CLT_FAILED); conn->client_entry->session_key_timer = time(NULL) - (2*TIMEOUT_KEY); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN, _("Session key mismatch"), conn->peer); sh_xfer_do_free (conn); } } else { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV, 4, conn->pass, conn->peer, '\\', conn->head[3], '\\', conn->head[4], '\\', conn->head[5], '\\', conn->head[6]); sh_xfer_do_free (conn); } return 0; } #endif /************************************************************************ * * Here we check the message received, and decide on the answer to send * (if any). The connection is in CONN_PAUSED state, thus we must: * (i) define the proper reaction * (ii) reset to CONN_READING or CONN_WRITING or CONN_FREE * (iii) eventually reset the connection entry * *************************************************************************/ static void check_protocol(sh_conn_t * conn, int state) { SL_ENTER(_("check_protocol")); /* seed / re-seed the PRNG if required */ (void) taus_seed(); /* protocols: * -- (iii) file transfer * -- (ii) authenticated message transfer * -- (i) SRP key exchange */ /* --------- FILE TRANSFER ----------- */ if ( (conn->head[0] & SH_PROTO_SRP) == 0 && (conn->head[0] & SH_PROTO_BIG) != 0 /* is set */ ) { /* nonzero means re-authentication is required */ if (0 == do_file_transfer(conn, state)) SL_RET0(_("check_protocol")); } /* --------- END FILE TRANSFER ----------- */ /* --------- message exchange ----------- */ else if ((conn->head[0] & SH_PROTO_SRP) == 0 && (conn->head[0] & SH_PROTO_MSG) != 0 /* is set */ ) { /* nonzero means re-authentication is required */ if (0 == do_message_transfer(conn, state)) SL_RET0(_("check_protocol")); } /* --------- END MESSAGE TRANSFER ------ */ /* --------- authentication ----------- */ if ( (conn->head[0] & SH_PROTO_SRP) != 0 /* is set */ ) { if (state == SH_DO_READ) /* finished reading */ { do_auth(conn); } else if (state == SH_DO_WRITE) /* finished writing */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); conn->headcount = 0; conn->bytecount = 0; conn->bytes_to_send = 0; conn->bytes_to_get = 0; if (conn->buf != NULL) { SH_FREE(conn->buf); conn->buf = NULL; } conn->state = CONN_READING; } } SL_RET0(_("check_protocol")); } /*********************************************************** * * SERVER RECEIVE FUNCTION * *********************************************************** */ int sh_xfer_do_read (sh_conn_t * conn) { unsigned long byteread; /* bytes read */ SL_ENTER(_("sh_xfer_do_read")); if (conn->state == CONN_SENDING) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_SYNC, conn->peer); SL_RETURN( (-1), _("sh_xfer_do_read")); } if (conn->headcount < SH_HEADER_SIZE) { conn->bytes_to_get = SH_HEADER_SIZE - conn->headcount; byteread = read (conn->fd, &(conn->head[conn->headcount]), conn->bytes_to_get); if (byteread > 0 || errno == EINTR) { if (byteread > 0) conn->headcount += byteread; if (conn->headcount == SH_HEADER_SIZE) { conn->bytes_to_get = (256 * (unsigned int)conn->head[1] + (unsigned int)conn->head[2]); SH_SHOWPROT(conn->head, '<'); conn->bytecount = 0; } } else goto conn_reset; SL_RETURN( (0), _("sh_xfer_do_read")); } /* limit message size */ conn->bytes_to_get = (conn->bytes_to_get > TRANS_BYTES) ? TRANS_BYTES : conn->bytes_to_get; if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get > 0) { if ( conn->bytecount == 0) { if (conn->buf != NULL) SH_FREE (conn->buf); conn->buf = SH_ALLOC(conn->bytes_to_get + 1); /* <= TRANS_BYTES+1 */ } byteread = read (conn->fd, &(conn->buf[conn->bytecount]), conn->bytes_to_get - conn->bytecount); if (byteread > 0 || errno == EINTR) { if (byteread > 0) conn->bytecount += byteread; if (conn->bytecount == conn->bytes_to_get) { ++conn->pass; /* always terminate with NULL - we might use sl_strcmp() */ conn->buf[conn->bytecount] = '\0'; conn->state = CONN_PAUSE; #ifdef SH_ENCRYPT if ((conn->head[0] & SH_PROTO_ENC) != 0) { conn->buf = sh_tools_revertPack (conn->head, conn->client_entry->ivst_flag, conn->buf, &(conn->client_entry->keyInstD), conn->bytecount); } #endif /* ------ HERE CALL check_protocol(conn) ------- */ check_protocol(conn, SH_DO_READ); } } else goto conn_reset; } else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get == 0) { if (conn->buf != NULL) SH_FREE (conn->buf); conn->buf = NULL; conn->bytecount = 0; ++conn->pass; conn->state = CONN_PAUSE; /* ------ HERE CALL check_protocol(conn) ------- */ check_protocol(conn, SH_DO_READ); } SL_RETURN( (0), _("sh_xfer_do_read")); conn_reset: sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET, conn->peer); sh_xfer_do_free ( conn ); SL_RETURN( (-1), _("sh_xfer_do_read")); } #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif /* send to the client */ int sh_xfer_do_write (sh_conn_t * conn) { int flags; long arg = 0; long bytesent; /* bytes read */ SL_ENTER(_("sh_xfer_do_write")); /* ---- consistency check ------ */ if (conn->state == CONN_READING) { sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_SYNC, conn->peer); SL_RETURN( (-1), _("sh_xfer_do_write")); } flags = retry_fcntl (FIL__, __LINE__, conn->fd, F_GETFL, arg); retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL, flags|O_NONBLOCK); /* ---- send the header ------ */ if (conn->headcount < SH_HEADER_SIZE) { conn->bytes_to_send = SH_HEADER_SIZE - conn->headcount; bytesent = write (conn->fd, &(conn->head[conn->headcount]), conn->bytes_to_send); if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) { if (bytesent > 0) conn->headcount += bytesent; if (conn->headcount == SH_HEADER_SIZE) conn->bytes_to_send = (256 * (int)conn->head[1] + (int)conn->head[2]); } else goto conn_reset_w; if (conn->fd >= 0) retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL, flags); SL_RETURN( (0), _("sh_xfer_do_write")); } /* ---- send the body ------ */ if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send > 0 && conn->buf != NULL) { bytesent = write (conn->fd, &(conn->buf[conn->bytecount]), conn->bytes_to_send - conn->bytecount); if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) { if (bytesent > 0) conn->bytecount += bytesent; if (conn->bytecount == conn->bytes_to_send) { ++conn->pass; conn->state = CONN_PAUSE; /* ------ HERE CALL check_protocol(conn) ------- */ check_protocol(conn, SH_DO_WRITE); } } else goto conn_reset_w; } else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send == 0) { ++conn->pass; conn->state = CONN_PAUSE; /* ------ HERE CALL check_protocol(conn) ------- */ check_protocol(conn, SH_DO_WRITE); } if (conn->fd >= 0) retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL, flags); SL_RETURN( (0), _("sh_xfer_do_write")); conn_reset_w: sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET, conn->peer); sh_xfer_do_free ( conn ); SL_RETURN( (-1), _("sh_xfer_do_write")); } /* accept a connection from a client */ #include #ifdef SH_USE_LIBWRAP #include #ifndef ALLOW_SEVERITY #define ALLOW_SEVERITY LOG_INFO #define DENY_SEVERITY LOG_WARNING #endif int allow_severity; int deny_severity; #endif #ifdef SH_USE_LIBWRAP static int check_libwrap(int rc, sh_conn_t * newconn) { struct request_info request; char errbuf[128]; char daemon[128]; sl_strlcpy(daemon, SH_INSTALL_NAME, sizeof(daemon)); request_init(&request, RQ_DAEMON, daemon, RQ_FILE, rc, 0); fromhost(&request); if (!hosts_access(&request)) { sl_strlcpy(errbuf, _("Refused connection from "), sizeof(errbuf)); sl_strlcat(errbuf, eval_client(&request), sizeof(errbuf)); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, errbuf, _("libwrap")); newconn->fd = -1; newconn->state = CONN_FREE; sl_close_fd(FIL__, __LINE__, rc); return -1; } return 0; } #endif int sh_xfer_accept (int sock, sh_conn_t * newconn) { int errflag; int rc; struct sh_sockaddr addr; /* handle AIX (size_t addrlen) in wrapper */ int addrlen = sizeof(addr); SL_ENTER(_("sh_xfer_accept")); rc = retry_accept(FIL__, __LINE__, sock, &addr, &addrlen); if (rc < 0) { char err_buf[SH_ERRBUF_SIZE]; errflag = errno; sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_error_message(errflag,err_buf, sizeof(err_buf)), _("accept")); newconn->fd = -1; newconn->state = CONN_FREE; SL_RETURN( (-1), _("sh_xfer_accept")); } if (addrlen == 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Connecting entity unknown"), _("accept")); newconn->fd = -1; newconn->state = CONN_FREE; sl_close_fd(FIL__, __LINE__, rc); SL_RETURN( (-1), _("sh_xfer_accept")); } #ifdef SH_USE_LIBWRAP if (check_libwrap(rc, newconn) < 0) SL_RETURN( (-1), _("sh_xfer_accept")); #endif memcpy (&(newconn->addr_peer), &addr, sizeof(struct sh_sockaddr)); /* prepare for usage of connection */ (void) retry_fcntl( FIL__, __LINE__, rc, F_SETFD, 1 ); newconn->fd = rc; newconn->state = CONN_READING; newconn->timer = (unsigned long) time (NULL); if (flag_err_info == S_TRUE) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CNEW, newconn->fd); SL_RETURN( (0), _("sh_xfer_accept")); } extern char sh_sig_msg[64]; /* defined in sh_unix.c */ /* ------------ port and interface ------- */ static unsigned int server_port = SH_DEFAULT_PORT; int sh_xfer_set_port (const char * str) { int retval = 0; unsigned long i; char * endptr; SL_ENTER(_("sh_xfer_set_port")); i = strtoul (str, &endptr, 0); if (endptr == str) { retval = -1; } else if (i > 65535) { retval = -1; } else { server_port = i; } SL_RETURN( (retval), _("sh_xfer_set_port")); } static struct sh_sockaddr server_interface; static int use_server_interface = 0; int sh_xfer_set_interface (const char * str) { if (0 == strcmp(str, _("INADDR_ANY"))) { use_server_interface = 0; return 0; } if (0 == sh_ipvx_aton(str, &server_interface)) { use_server_interface = 0; return -1; } use_server_interface = 1; return 0; } /* ------------ print error -------------- */ struct sock_err_st { char msg[128]; int errnum; int port; int line; int euid; }; static struct sock_err_st sock_err[2]; void sh_xfer_printerr(char * str, int errnum, unsigned int port, int line) { int slot = 0; if (port != server_port) slot = 1; if (str == NULL) sock_err[slot].msg[0] = '\0'; else sl_strlcpy(sock_err[slot].msg, str, 128); sock_err[slot].errnum = errnum; sock_err[slot].port = port; sock_err[slot].line = line; sock_err[slot].euid = (int) geteuid(); } int sh_xfer_printerr_final(int slot) { char errbuf[SH_ERRBUF_SIZE]; SL_ENTER(_("sh_xfer_printerr_final")); if (sock_err[slot].msg[0] != '\0') { dlog(1, FIL__, __LINE__, _("Could not set up the listening socket for the server because of the\nfollowing error: %s\nPossible reasons include:\n - insufficient privilege for UID %d, or\n - the port %d is already used by another program.\n"), sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)), sock_err[slot].euid, sock_err[slot].port); sh_error_handle((-1), FIL__, sock_err[slot].line, sock_err[slot].errnum, MSG_EXIT_ABORTS, sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)), sh.prg_name, sock_err[slot].msg); SL_RETURN((-1), _("sh_xfer_printerr_final")); } SL_RETURN(0, _("sh_xfer_printerr_final")); } #define TIME_OUT_DEF 900 static unsigned long time_out_val = TIME_OUT_DEF; int sh_xfer_set_timeout (const char * c) { long val; SL_ENTER(_("sh_xfer_set_time_out")); val = strtol (c, (char **)NULL, 10); if (val == 0) { val = TIME_OUT_DEF; } else if (val < 0) { time_out_val = TIME_OUT_DEF; SL_RETURN( (-1), _("sh_xfer_set_time_out")); } time_out_val = (unsigned long) val; SL_RETURN( (0), _("sh_xfer_set_time_out")); } static sh_conn_t * conns = NULL; static int maxconn = 0; /* maximum number of simultaneous connections */ #ifdef INET_SYSLOG #define INET_SUSPEND_TIME 180 /* equal to 3 minutes */ #define SH_MINSOCK_DEFAULT 3 int sh_xfer_syslog_sock[SH_SOCKMAX] = { -1 }; extern int sh_xfer_recv_syslog_socket (int fd); int sh_xfer_syslog_sock_n = 0; #else #define SH_MINSOCK_DEFAULT 2 #endif int SH_MINSOCK = SH_MINSOCK_DEFAULT; extern int pf_unix_fd; /* the tcp socket, and the function to establish it */ static int sh_tcp_sock[SH_SOCKMAX] = { -1 }; static int sh_tcp_sock_n = 0; static int do_socket(int domain, int type, int protocol, struct sockaddr * sa, int salen) { int sock = -1; int errnum = 0; int flag = 1; /* non-zero to enable an option */ /* create the socket, bind() it and listen() */ if ((sock = socket(domain, type, protocol)) < 0 ) { errnum = errno; sh_xfer_printerr (_("socket"), errnum, server_port, __LINE__); return -1; } (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 ); if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &flag, sizeof(flag)) < 0 ) { errnum = errno; sh_xfer_printerr (_("setsockopt"), errnum, server_port, __LINE__); sl_close_fd (FIL__, __LINE__, sock); return -1; } if ( bind(sock, (struct sockaddr *) sa, salen) < 0) { if (errno != EADDRINUSE) { errnum = errno; sh_xfer_printerr (_("bind"), errnum, server_port, __LINE__); sl_close_fd (FIL__, __LINE__, sock); return -1; } else { sl_close_fd (FIL__, __LINE__, sock); return -2; } } if ( retry_fcntl( FIL__, __LINE__, sock, F_SETFL, O_NONBLOCK ) < 0 ) { errnum = errno; sh_xfer_printerr (_("fcntl"), errnum, server_port, __LINE__); sl_close_fd (FIL__, __LINE__, sock); return -1; } if ( listen(sock, 64) < 0) { errnum = errno; sh_xfer_printerr (_("listen"), errnum, server_port, __LINE__); sl_close_fd (FIL__, __LINE__, sock); return -1; } return sock; } int sh_create_tcp_socket (void) { #if defined(USE_IPVX) struct addrinfo *ai; struct addrinfo *p; struct addrinfo hints; char port[32]; #else struct sockaddr_in addr; int addrlen = sizeof(addr); #endif int sock = -1; SL_ENTER(_("sh_create_tcp_socket")); sh_xfer_printerr (NULL, 0, server_port, __LINE__); #if defined(USE_IPVX) if (use_server_interface == 0) /* INADDR_ANY, listen on all interfaces */ { memset (&hints, '\0', sizeof (hints)); hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; sl_snprintf(port, sizeof(port), "%d", server_port); if (getaddrinfo (NULL, port, &hints, &ai) != 0) { int errnum = errno; sh_xfer_printerr (_("getaddrinfo"), errnum, server_port, __LINE__); sl_close_fd (FIL__, __LINE__, sock); SL_RETURN((-1), _("sl_create_tcp_socket")); } p = ai; while (p != NULL && sh_tcp_sock_n < SH_SOCKMAX) { sock = do_socket(p->ai_family, p->ai_socktype, p->ai_protocol, p->ai_addr, p->ai_addrlen); if (sock >= 0) { if (sh_tcp_sock_n < SH_SOCKMAX) { sh_tcp_sock[sh_tcp_sock_n] = sock; ++sh_tcp_sock_n; } else { sl_close_fd (FIL__, __LINE__, sock); } } else if (sock == -1) { freeaddrinfo (ai); goto end; } p = p->ai_next; } freeaddrinfo (ai); } else { sh_ipvx_set_port(&server_interface, server_port); sock = do_socket(server_interface.ss_family, SOCK_STREAM, 0, sh_ipvx_sockaddr_cast(&server_interface), SH_SS_LEN(server_interface)); if (sock >= 0) { sh_tcp_sock[0] = sock; sh_tcp_sock_n = 1; } } #else if (use_server_interface == 0) addr.sin_addr.s_addr = INADDR_ANY; else memcpy(&addr, sh_ipvx_sockaddr_cast(&server_interface), addrlen); addr.sin_family = AF_INET; addr.sin_port = htons(server_port); sock = do_socket(AF_INET, SOCK_STREAM, 0, (struct sockaddr *) &addr, addrlen); if (sock >= 0) { sh_tcp_sock[0] = sock; sh_tcp_sock_n = 1; } #endif #if defined(USE_IPVX) end: #endif if (sh_tcp_sock_n > 1) SH_MINSOCK += (sh_tcp_sock_n - 1); SL_RETURN((sh_tcp_sock_n), _("sl_create_tcp_socket")); } /***************************************** * * This is the server main loop. * * The server is set up for listening, and * and starts a select() loop. * *****************************************/ void sh_xfer_start_server() { #ifdef SH_USE_XML extern int sh_log_file (char * message, char * inet_peer); #endif /* Use volatile to circumvent a gcc4 problem on RH/CentOS 4.8 (?) */ volatile int sock = -1; sh_conn_t * cx; fd_set readset; fd_set writeset; struct timeval tv; int num_sel; int errnum; int nowconn; int status; int high_fd = -1; register int i; long dummy = 0; unsigned long time_now; unsigned long time_last = 0; unsigned long time_out = time_out_val; time_t told; time_t tcurrent; unsigned long tchkold; int setsize_fd; int sock_tcp[2]; int sock_unix; #ifdef INET_SYSLOG int sock_log[2]; #endif SL_ENTER(_("sh_xfer_start_server")); if ( sh_xfer_printerr_final(0) < 0) { aud_exit(FIL__, __LINE__, EXIT_FAILURE); } sock = sh_tcp_sock[0]; /* **************************************************************** * * This is a non-forking server. We use select() on the listen() * socket to watch for new connections. For new connections, accept() * will return a new socket that is put in the read/write filesets. * Data about active connections are kept in the 'conns' table. * ******************************************************************/ /* The table to hold info on sockets. * We reserve 6 file descriptors for misc. use. * The POSIX lower limit on open files seems to be eight. */ maxconn = get_open_max() - 6; /* ugly fix for FreeBSD compiler warning; casting FD_SETSIZE in the * conditional expression does not suppress the warning... */ setsize_fd = (int)FD_SETSIZE; maxconn = (setsize_fd < maxconn) ? setsize_fd : maxconn; if (maxconn < 0 || !sl_ok_muls(maxconn, sizeof(sh_conn_t))) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV, 0, sock); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } conns = SH_ALLOC (sizeof(sh_conn_t) * maxconn); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV, (maxconn-1), sock); /* timer */ tcurrent = (unsigned long) time (NULL); told = tcurrent; tchkold = tcurrent; for (i = SH_MINSOCK; i < maxconn; ++i) { conns[i].buf = NULL; conns[i].K = NULL; conns[i].A = NULL; conns[i].M1 = NULL; conns[i].FileName = NULL; conns[i].fd = -1; sh_xfer_do_free ( &conns[i]); } /* status init */ server_status.conn_open = 0; server_status.conn_total = 0; server_status.conn_max = maxconn-1; server_status.start = time (NULL); server_status.last = (time_t) 0; nowconn = 1; tv.tv_sec = 5; tv.tv_usec = 0; /* conns[0] is the listen() socket. Always in read mode. */ sock = 0; sock_tcp[0] = 0; while (sock < sh_tcp_sock_n) { conns[sock].fd = sh_tcp_sock[sock]; conns[sock].state = CONN_READING; /* high_fd = (sh_tcp_sock[sock] > high_fd) ? sh_tcp_sock[sock] : high_fd; */ ++sock; } sock_tcp[1] = sock; conns[sock].fd = pf_unix_fd; conns[sock].state = CONN_READING; /* high_fd = (pf_unix_fd > high_fd) ? pf_unix_fd : high_fd; */ sock_unix = sock; ++sock; #ifdef INET_SYSLOG conns[sock].fd = -1; if ( sh_xfer_printerr_final(1) < 0) { SH_FREE(conns); conns = NULL; aud_exit(FIL__, __LINE__, EXIT_FAILURE); } sock_log[0] = sock; sock_log[1] = sock; if (sh_xfer_syslog_sock_n > 0) { int s2; for (s2 = 0; s2 < sh_xfer_syslog_sock_n; ++s2) { conns[sock].fd = sh_xfer_syslog_sock[s2]; conns[sock].state = CONN_READING; /* high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; */ ++sock; } sock_log[1] = sock; } #endif sh_html_write(all_clients); /* This is the select() loop. */ while (1 == 1) { if (sig_raised > 0) { TPT((0, FIL__, __LINE__, _("msg=\n"))) if (sig_termfast == 1) /* SIGTERM */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); strncpy (sh_sig_msg, _("SIGTERM"), 20); --sig_raised; --sig_urgent; aud_exit (FIL__, __LINE__, EXIT_SUCCESS); } if (sig_config_read_again == 1) { TPT((0, FIL__, __LINE__, _("msg=\n"))); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF); /* -- Delete the name server cache. -- */ delete_cache(); #if defined(WITH_EXTERNAL) /* -- Delete list of external tasks. -- */ (void) sh_ext_cleanup(); #endif #if defined(SH_WITH_MAIL) sh_nmail_free(); #endif /* - mark all clients dead * - read configuration file * - remove clients still dead */ sh_xfer_mark_dead (); reset_count_dev_console(); reset_count_dev_time(); sl_trust_purge_user(); (void) sh_readconf_read (); for (i = SH_MINSOCK; i < maxconn; ++i) if (conns[i].state != CONN_FREE && conns[i].client_entry != NULL && conns[i].client_entry->dead_flag == 1) sh_xfer_do_free ( &conns[i]); sh_xfer_clean_tree (); sig_config_read_again = 0; --sig_raised; } if (sig_fresh_trail == 1) /* SIGIOT */ { /* Logfile access */ #ifdef SH_USE_XML sh_log_file (NULL, NULL); #endif TPT((0, FIL__, __LINE__, _("msg=\n"))); sh_error_only_stderr (S_TRUE); sh_unix_rm_lock_file(sh.srvlog.name); retry_msleep(3, 0); sh.flag.log_start = S_TRUE; sh_error_only_stderr (S_FALSE); sig_fresh_trail = 0; --sig_raised; } if (sig_terminate == 1 && nowconn < 2) /* SIGQUIT */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); strncpy (sh_sig_msg, _("SIGQUIT"), 20); --sig_raised; --sig_urgent; aud_exit (FIL__, __LINE__, EXIT_SUCCESS); } if (sig_debug_switch == 1) /* SIGUSR1 */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); sh_error_dbg_switch(); sig_debug_switch = 0; --sig_raised; } if (sig_suspend_switch > 0) /* SIGUSR2 */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); if (sh_global_suspend_flag == 1) { sh_global_suspend_flag = 0; } else { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, sh.prg_name); sh_global_suspend_flag = 1; } --sig_suspend_switch; --sig_raised; --sig_urgent; } sig_raised = (sig_raised < 0) ? 0 : sig_raised; sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent; TPT((0, FIL__, __LINE__, _("msg=\n"))); } if (sh_global_suspend_flag == 1) { (void) retry_msleep (1, 0); continue; } /* Recompute the descriptor set. select() modifies it, * thus we update it using the info from the connection table. * Also recompute the number of open connections. */ FD_ZERO( &readset ); FD_ZERO( &writeset ); high_fd = conns[0].fd; for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock) { FD_SET(conns[sock].fd, &readset ); high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; } if (conns[sock_unix].fd > -1) { FD_SET(conns[sock_unix].fd, &readset ); high_fd = (high_fd > conns[sock_unix].fd) ? high_fd : conns[sock_unix].fd; } #ifdef INET_SYSLOG for (sock = sock_log[0]; sock < sock_log[1]; ++sock) { if (conns[sock].fd > -1) { FD_SET(conns[sock].fd, &readset ); high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; } } #endif time_now = (unsigned long) time (NULL); nowconn = 1; for (i = SH_MINSOCK; i < maxconn; ++i) { /* eliminate timed out connections */ if (conns[i].state != CONN_FREE) { if (time_now-conns[i].timer > time_out) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMOUT, conns[i].peer); sh_xfer_do_free ( &conns[i]); } else ++nowconn; } if (conns[i].state == CONN_READING) { FD_SET(conns[i].fd, &readset); high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd); } else if (conns[i].state == CONN_SENDING) { FD_SET(conns[i].fd, &writeset); high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd); } } /* -- Exponentially reduce timeout limit if more than 1/2 full. -- */ /* Eliminate this, will cause problems when too much clients are * starting up. */ #if 0 if (nowconn > (maxconn/2)) time_out = ( (time_out/2) > 1) ? (time_out/2) : 1; else time_out = time_out_val; #endif /* -- Do the select(). -- */ num_sel = select(high_fd+1, &readset, &writeset, NULL, &tv); errnum = errno; /* reset timeout - modified by select() on some systems */ tv.tv_sec = 5; tv.tv_usec = 0; if ( (time_now - time_last) > 2L) { time_last = time_now; if (sh_html_write(all_clients) < 0) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML); } /* Error handling. */ if ( num_sel < 0 ) /* some error */ { char errbuf[SH_ERRBUF_SIZE]; if (sig_raised == 1) { sig_raised = 2; continue; } if ( errnum == EINTR) continue; /* try again */ if ( errnum == EBADF) { /* seek and destroy the bad fd */ for (i = SH_MINSOCK; i < high_fd; ++i) { if ((conns[i].state == CONN_READING) || (conns[i].state == CONN_SENDING)) { if (-1 == retry_fcntl(FIL__, __LINE__, conns[i].fd, F_GETFL, dummy)) sh_xfer_do_free ( &conns[i]); } } continue; } sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_EXIT_ABORTS, sh_error_message(errnum, errbuf, sizeof(errbuf)), sh.prg_name, _("select")); aud_exit(FIL__, __LINE__, EXIT_FAILURE ); } /* log the timestamp */ if ((tcurrent - told) > sh.looptime ) { told = tcurrent; #ifdef MEM_DEBUG sh_mem_check(); sh_unix_count_mlock(); #else sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP); #endif } #if defined(SH_WITH_MAIL) /* * flush the mail queue */ if (tcurrent - sh.mailTime.alarm_last > sh.mailTime.alarm_interval) { TPT((0, FIL__, __LINE__, _("msg=\n"))) (void) sh_nmail_flush (); sh.mailTime.alarm_last = tcurrent; } #endif #ifdef MEM_DEBUG sh_mem_dump(); #endif tcurrent = (unsigned long) time (NULL); /* check for time limit exceeded */ if ((tcurrent - tchkold) > (unsigned int) 3 ) { tchkold = tcurrent; client_time_check(/* all_clients */); /* reset cache */ sh_userid_destroy(); } /* seed / re-seed the PRNG if required */ (void) taus_seed(); /* select() timeout handling. */ if ( num_sel == 0 ) /* timeout - no connection */ { if (sh_html_write(all_clients) < 0) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML); continue; } /* New connection. */ for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock) { if ( FD_ISSET(conns[sock].fd , &readset )) /* a new connection */ { --num_sel; status = 0; if (nowconn < maxconn && sig_terminate == 0 && sig_termfast == 0) { /* Find a free slot to accept the connection */ i = SH_MINSOCK; while (i < maxconn) { if (conns[i].state == CONN_FREE) { /* Here we run the accept() and copy the peer to * the free slot. */ status = sh_xfer_accept(conns[sock].fd, &conns[i]); if (status == 0) { high_fd = (high_fd > conns[i].fd ? high_fd : conns[i].fd); ++server_status.conn_open; ++server_status.conn_total; server_status.last = time (NULL); } break; } ++i; } } /* This re-runs select to accept data on the new * connection, rather than first dealing with old * connections. */ if (status == 0) continue; } } /* check for commands on the socket */ if (conns[sock_unix].fd > (-1) && FD_ISSET(conns[sock_unix].fd , &readset )) { sh_socket_poll(); } #ifdef INET_SYSLOG for (sock = sock_log[0]; sock < sock_log[1]; ++sock) { if (conns[sock].fd > (-1) && FD_ISSET(conns[sock].fd , &readset )) { sh_xfer_recv_syslog_socket (conns[sock].fd); } } #endif /* Check for pending read/write on the rest of the sockets. */ for ( i = SH_MINSOCK; num_sel > 0 && i < maxconn; ++i ) { if (sig_termfast == 1) break; cx = &conns[i]; if ( cx->state == CONN_READING && FD_ISSET( cx->fd, &readset ) ) { --num_sel; sh_xfer_do_read ( cx ); } else if ( cx->state == CONN_SENDING && FD_ISSET( cx->fd, &writeset ) ) { --num_sel; sh_xfer_do_write ( cx ); } } /* continue */ } /* notreached */ } void free_client_tree (void) { SL_ENTER(_("free_client_tree")); zAVLFreeTree (all_clients, free_client); SL_RET0(_("free_client_tree")); } void sh_xfer_free_all () { register int i; SL_ENTER(_("sh_xfer_free_all")); if (conns != NULL) for (i = SH_MINSOCK; i < maxconn; ++i) { sh_xfer_do_free ( &conns[i]); } free_client_tree (); if (conns != NULL) SH_FREE (conns); SL_RET0(_("sh_xfer_free_all")); } /* #ifdef SH_WITH_SERVER */ #endif samhain-4.1.4/src/sh_err_syslog.c0000644000175000017500000001420112615253277013706 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include "samhain.h" #include "sh_error.h" #undef FIL__ #define FIL__ _("sh_err_syslog.c") typedef struct log_fac_struct { const char * name; int facility; } logfct; static logfct fct_tab[] = { #ifdef LOG_AUTH { N_("LOG_AUTH"), LOG_AUTH }, #endif #ifdef LOG_AUTHPRIV { N_("LOG_AUTHPRIV"), LOG_AUTHPRIV }, #endif #ifdef LOG_CRON { N_("LOG_CRON"), LOG_CRON }, #endif #ifdef LOG_DAEMON { N_("LOG_DAEMON"), LOG_DAEMON }, #endif #ifdef LOG_FTP { N_("LOG_FTP"), LOG_FTP }, #endif #ifdef LOG_KERN { N_("LOG_KERN"), LOG_KERN }, #endif #ifdef LOG_LOCAL0 { N_("LOG_LOCAL0"), LOG_LOCAL0 }, #endif #ifdef LOG_LOCAL1 { N_("LOG_LOCAL1"), LOG_LOCAL1 }, #endif #ifdef LOG_LOCAL2 { N_("LOG_LOCAL2"), LOG_LOCAL2 }, #endif #ifdef LOG_LOCAL3 { N_("LOG_LOCAL3"), LOG_LOCAL3 }, #endif #ifdef LOG_LOCAL4 { N_("LOG_LOCAL4"), LOG_LOCAL4 }, #endif #ifdef LOG_LOCAL5 { N_("LOG_LOCAL5"), LOG_LOCAL5 }, #endif #ifdef LOG_LOCAL6 { N_("LOG_LOCAL6"), LOG_LOCAL6 }, #endif #ifdef LOG_LOCAL7 { N_("LOG_LOCAL7"), LOG_LOCAL7 }, #endif #ifdef LOG_LPR { N_("LOG_LPR"), LOG_LPR }, #endif #ifdef LOG_MAIL { N_("LOG_MAIL"), LOG_MAIL }, #endif #ifdef LOG_NEWS { N_("LOG_NEWS"), LOG_NEWS }, #endif #ifdef LOG_SYSLOG { N_("LOG_SYSLOG"), LOG_SYSLOG }, #endif #ifdef LOG_USER { N_("LOG_USER"), LOG_USER }, #endif #ifdef LOG_UUCP { N_("LOG_UUCP"), LOG_UUCP }, #endif { NULL, -1 } }; #ifdef LOG_AUTHPRIV static int my_syslog_facility = LOG_AUTHPRIV; #else /*@-unrecog@*/ static int my_syslog_facility = LOG_AUTH; /*@+unrecog@*/ #endif /* set syslog facility */ int sh_log_set_facility (const char * c) { int loop = 0; SL_ENTER(_("sh_log_set_facility")); if (c == NULL) SL_RETURN(-1, _("sh_log_set_facility")); while (fct_tab[loop].name != NULL) { if (0 == strcmp ( _(fct_tab[loop].name), c)) { my_syslog_facility = fct_tab[loop].facility; SL_RETURN(0, _("sh_log_set_facility")); } ++loop; } SL_RETURN(-1, _("sh_log_set_facility")); } static int sh_stamp_priority = LOG_ERR; /* set priority for heartbeat messages */ int sh_log_set_stamp_priority (const char * c) { int retval = 0; if (0 == strcmp(c, _("LOG_DEBUG"))) { sh_stamp_priority = LOG_DEBUG; } else if (0 == strcmp(c, _("LOG_INFO"))) { sh_stamp_priority = LOG_INFO; } else if (0 == strcmp(c, _("LOG_NOTICE"))) { sh_stamp_priority = LOG_NOTICE;} else if (0 == strcmp(c, _("LOG_WARNING"))) { sh_stamp_priority = LOG_WARNING;} else if (0 == strcmp(c, _("LOG_ERR"))) { sh_stamp_priority = LOG_ERR; } else if (0 == strcmp(c, _("LOG_CRIT"))) { sh_stamp_priority = LOG_CRIT; } else if (0 == strcmp(c, _("LOG_ALERT"))) { sh_stamp_priority = LOG_ALERT; } #ifdef LOG_EMERG else if (0 == strcmp(c, _("LOG_EMERG"))) { sh_stamp_priority = LOG_EMERG; } #endif else { retval = -1; } return retval; } /* syslog error message */ int sh_log_syslog (int severity, /*@null@*/char *errmsg) { int priority; size_t len; size_t i; char store; char * p; static int init = 0; SL_ENTER(_("sh_log_syslog")); ASSERT_RET((errmsg != NULL), _("errmsg != NULL"), 0); /*@-unrecog@*/ if (severity == SH_ERR_ALL) priority = LOG_DEBUG; else if (severity == SH_ERR_INFO) priority = LOG_INFO; else if (severity == SH_ERR_NOTICE) priority = LOG_NOTICE; else if (severity == SH_ERR_WARN) priority = LOG_WARNING; else if (severity == SH_ERR_STAMP) priority = sh_stamp_priority; else if (severity == SH_ERR_ERR) priority = LOG_ERR; else if (severity == SH_ERR_SEVERE) priority = LOG_CRIT; else if (severity == SH_ERR_FATAL) priority = LOG_ALERT; else priority = LOG_DEBUG; /*@+unrecog@*/ #ifndef LOG_PID #define LOG_PID 0 #endif if (init == 0) { /*@-unrecog@*/ openlog (sh.prg_name, LOG_PID, my_syslog_facility); /*@+unrecog@*/ init = 1; } /* --- Limit the message size. --- */ len = sl_strlen(errmsg); if (len < 960) { /*@-unrecog@*/ syslog (priority, "%s", errmsg); /*@+unrecog@*/ } else { i = 960; p = errmsg; while (i < len) { store = errmsg[i]; errmsg[i] = '\0'; /*@-unrecog@*/ syslog (priority, "%s", p); /*@+unrecog@*/ errmsg[i] = store; p = &errmsg[i]; i += 960; } if (i != len) { /*@-unrecog@*/ syslog (priority, "%s", p); /*@+unrecog@*/ } } /* Solaris does not recover if a closeall() closes the * syslog file descriptor, so close it here. */ /*@-unrecog@*/ closelog(); /*@+unrecog@*/ init = 0; SL_RETURN(0, _("sh_log_syslog")); } samhain-4.1.4/src/sh_checksum.c0000664000175000017500000005026612615253277013335 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2013 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include "samhain.h" #include "sh_checksum.h" #include #undef FIL__ #define FIL__ _("sh_checksum.c") /* * sha2.c * * Version 1.0.0beta1 * * Written by Aaron D. Gifford * * Copyright 2000 Aaron D. Gifford. All rights reserved. * * 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. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``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 AUTHOR(S) OR CONTRIBUTOR(S) 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. * */ /* Modified for use in samhain by R. Wichmann */ #if WORDS_BIGENDIAN #define SHA2_BIG_ENDIAN 4321 #define SHA2_BYTE_ORDER SHA2_BIG_ENDIAN #else #define SHA2_LITTLE_ENDIAN 1234 #define SHA2_BYTE_ORDER SHA2_LITTLE_ENDIAN #endif #if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN #define REVERSE32(w,x) { \ sha2_word32 tmp = (w); \ tmp = (tmp >> 16) | (tmp << 16); \ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ } #define REVERSE64(w,x) { \ sha2_word64 tmp = (w); \ tmp = (tmp >> 32) | (tmp << 32); \ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ ((tmp & 0x0000ffff0000ffffULL) << 16); \ } #endif /* * Macro for incrementally adding the unsigned 64-bit integer n to the * unsigned 128-bit integer (represented using a two-element array of * 64-bit words): */ #define ADDINC128(w,n) { \ (w)[0] += (sha2_word64)(n); \ if ((w)[0] < (n)) { \ (w)[1]++; \ } \ } /*** THE SIX LOGICAL FUNCTIONS ****************************************/ /* * Bit shifting and rotation (used by the six SHA-XYZ logical functions: * * NOTE: The naming of R and S appears backwards here (R is a SHIFT and * S is a ROTATION) because the SHA-256/384/512 description document * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this * same "backwards" definition. */ /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ #define R(b,x) ((x) >> (b)) /* 32-bit Rotate-right (used in SHA-256): */ #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* Four of six logical functions used in SHA-256: */ #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) /*** INTERNAL FUNCTION PROTOTYPES *************************************/ /* NOTE: These should not be accessed directly from outside this * library -- they are intended for private internal visibility/use * only. */ void SHA256_Transform(SHA256_CTX*, const sha2_word32*); /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ /* Hash constant words K for SHA-256: */ static const sha2_word32 K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Initial hash value H for SHA-256: */ static const sha2_word32 sha256_initial_hash_value[8] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; /* * Constant used by SHA256/384/512_End() functions for converting the * digest to a readable hexadecimal character string: */ static const char *sha2_hex_digits = "0123456789abcdef"; /*** SHA-256: *********************************************************/ void SHA256_Init(SHA256_CTX* context) { if (context == (SHA256_CTX*)0) { return; } memcpy(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); /* bcopy(sha256_initial_hash_value, context->state, SHA256_DIGEST_LENGTH); */ memset(context->buffer, 0, SHA256_BLOCK_LENGTH); /* bzero(context->buffer, SHA256_BLOCK_LENGTH); */ context->bitcount = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-256 round macros: */ #if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ REVERSE32(*data++, W256[j]); \ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ K256[j] + W256[j]; \ (d) += T1; \ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ j++ #else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */ #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ K256[j] + (W256[j] = *data++); \ (d) += T1; \ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ j++ #endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */ #define ROUND256(a,b,c,d,e,f,g,h) \ s0 = W256[(j+1)&0x0f]; \ s0 = sigma0_256(s0); \ s1 = W256[(j+14)&0x0f]; \ s1 = sigma1_256(s1); \ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ j++ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { sha2_word32 a, b, c, d, e, f, g, h, s0, s1; sha2_word32 T1, *W256; int j; W256 = (sha2_word32*)context->buffer; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { /* Rounds 0 to 15 (unrolled): */ ROUND256_0_TO_15(a,b,c,d,e,f,g,h); ROUND256_0_TO_15(h,a,b,c,d,e,f,g); ROUND256_0_TO_15(g,h,a,b,c,d,e,f); ROUND256_0_TO_15(f,g,h,a,b,c,d,e); ROUND256_0_TO_15(e,f,g,h,a,b,c,d); ROUND256_0_TO_15(d,e,f,g,h,a,b,c); ROUND256_0_TO_15(c,d,e,f,g,h,a,b); ROUND256_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds to 64: */ do { ROUND256(a,b,c,d,e,f,g,h); ROUND256(h,a,b,c,d,e,f,g); ROUND256(g,h,a,b,c,d,e,f); ROUND256(f,g,h,a,b,c,d,e); ROUND256(e,f,g,h,a,b,c,d); ROUND256(d,e,f,g,h,a,b,c); ROUND256(c,d,e,f,g,h,a,b); ROUND256(b,c,d,e,f,g,h,a); } while (j < 64); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { sha2_word32 a, b, c, d, e, f, g, h, s0, s1; sha2_word32 T1, T2, *W256; int j; W256 = (sha2_word32*)context->buffer; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { #if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN /* Copy data while converting to host byte order */ REVERSE32(*data++,W256[j]); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; #else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */ /* Apply the SHA-256 compression function to update a..h with copy */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); #endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */ T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W256[(j+1)&0x0f]; s0 = sigma0_256(s0); s1 = W256[(j+14)&0x0f]; s1 = sigma1_256(s1); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 64); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { unsigned int freespace, usedspace; if (len == 0) { /* Calling with no data is valid - we do nothing */ return; } usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA256_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ memcpy(&context->buffer[usedspace], data, freespace); /* bcopy(data, &context->buffer[usedspace], freespace); */ context->bitcount += freespace << 3; len -= freespace; data += freespace; SHA256_Transform(context, (sha2_word32*)context->buffer); } else { /* The buffer is not yet full */ memcpy(&context->buffer[usedspace], data, len); /* bcopy(data, &context->buffer[usedspace], len); */ context->bitcount += len << 3; /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA256_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA256_Transform(context, (const sha2_word32*)data); context->bitcount += SHA256_BLOCK_LENGTH << 3; len -= SHA256_BLOCK_LENGTH; data += SHA256_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ memcpy(context->buffer, data, len); /* bcopy(data, context->buffer, len); */ context->bitcount += len << 3; } /* Clean up: */ usedspace = freespace = 0; } void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { sha2_word32 *d = (sha2_word32*)digest; unsigned int usedspace; union { sha2_word64 bitcount; sha2_byte buffer[sizeof(sha2_word64)]; } sha2_union; /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; #if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN /* Convert FROM host byte order */ REVERSE64(context->bitcount,context->bitcount); #endif if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); /* And set-up for the last transform: */ memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Set the bit count (with fix for gcc type-punning warning): */ sha2_union.bitcount = context->bitcount; memcpy (&context->buffer[SHA256_SHORT_BLOCK_LENGTH], sha2_union.buffer, sizeof(sha2_word64)); /* *(sha2_word64*) &context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; */ /* Final transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); #if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { REVERSE32(context->state[j],context->state[j]); *d++ = context->state[j]; } } #else memset(d, context->state, SHA256_DIGEST_LENGTH); /* bcopy(context->state, d, SHA256_DIGEST_LENGTH); */ #endif } /* Clean up state data: */ memset(context, 0, sizeof(SHA256_CTX)); usedspace = 0; } #include "sh_utils.h" /* If buffer is of length KEYBUF_SIZE, the digest will fit */ char *SHA256_End(SHA256_CTX* context, char buffer[]) { sha2_byte digest[SHA256_DIGEST_LENGTH]; if (buffer != (char*)0) { SHA256_Final(digest, context); sh_util_base64_enc ((unsigned char *)buffer, digest, SHA256_DIGEST_LENGTH); } else { memset(context, 0, sizeof(SHA256_CTX)); } memset(digest, 0, SHA256_DIGEST_LENGTH); return buffer; } char* SHA256_Data(const sha2_byte* data, size_t len, char digest[KEYBUF_SIZE]) { SHA256_CTX context; SHA256_Init(&context); SHA256_Update(&context, data, len); return SHA256_End(&context, digest); } char* SHA256_Base2Hex(char * b64digest, char * hexdigest) { int i; sha2_byte data[512]; sha2_byte *d; size_t len; char * buffer; len = strlen(b64digest); sh_util_base64_dec ((unsigned char*) data, (unsigned char *)b64digest, len); d = data; buffer = hexdigest; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; return hexdigest; } char * SHA256_ReplaceBaseByHex(const char * str, char * before, char after) { char keybuf[KEYBUF_SIZE]; char * s = strstr(str, before); if (s) { char * p; s += strlen(before); memcpy(keybuf, s, sizeof(keybuf)); keybuf[sizeof(keybuf)-1] = '\0'; p = strchr(keybuf, after); if (p) { char hexbuf[SHA256_DIGEST_STRING_LENGTH]; char * ret = SH_ALLOC(strlen(str) + 1 + sizeof(keybuf)); char * r = ret; *p = '\0'; SHA256_Base2Hex(keybuf, hexbuf); memcpy(ret, str, (s - str)); r += (int)(s - str); *r = '\0'; strcpy(r, hexbuf); /* flawfinder: ignore */ r += strlen(hexbuf); p = strchr(s, after); strcpy(r, p); /* flawfinder: ignore */ return ret; } } return NULL; } #ifdef SH_CUTEST #include #include "CuTest.h" void Test_sha256 (CuTest *tc) { char hexdigest[SHA256_DIGEST_STRING_LENGTH]; char b64digest[KEYBUF_SIZE]; char * b64; char * buffer; size_t len; sha2_byte data[512]; sha2_byte *d; int i; data[0] = '\0'; len = 0; b64 = SHA256_Data(data, len, b64digest); CuAssertPtrNotNull(tc, b64); len = strlen((char*)b64); sh_util_base64_dec (data, (unsigned char*)b64, len); d = data; buffer = hexdigest; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; CuAssertStrEquals(tc, hexdigest, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); memset(hexdigest, 0, sizeof(hexdigest)); buffer = SHA256_Base2Hex(b64digest, hexdigest); CuAssertPtrNotNull(tc, buffer); CuAssertStrEquals(tc, hexdigest, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); CuAssertStrEquals(tc, buffer, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); strcpy((char*)data, "The quick brown fox jumps over the lazy dog"); len = strlen((char*)data); b64 = SHA256_Data(data, len, b64digest); CuAssertPtrNotNull(tc, b64); len = strlen((char*)b64); sh_util_base64_dec (data, (unsigned char*)b64, len); d = data; buffer = hexdigest; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; CuAssertStrEquals(tc, hexdigest, "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"); strcpy((char*)data, "The quick brown fox jumps over the lazy dog."); len = strlen((char*)data); b64 = SHA256_Data(data, len, b64digest); CuAssertPtrNotNull(tc, b64); len = strlen((char*)b64); sh_util_base64_dec (data, (unsigned char*)b64, len); d = data; buffer = hexdigest; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; CuAssertStrEquals(tc, hexdigest, "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c"); } #endif samhain-4.1.4/src/sh_prelink.c0000644000175000017500000001717012615253277013172 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2004 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) #include "samhain.h" #include "sh_tiger.h" #include "sh_extern.h" #include "sh_utils.h" #include "sh_unix.h" #undef FIL__ #define FIL__ _("sh_prelink.c") static char * prelink_path = NULL; static char * prelink_hash = NULL; int sh_prelink_set_path (const char * str) { SL_ENTER(_("sh_prelink_set_path")); if (prelink_path != NULL) SH_FREE(prelink_path); if (str[0] != '/') { prelink_path = NULL; SL_RETURN((-1), _("sh_prelink_set_path")); } #ifdef SH_EVAL_SHELL prelink_path = sh_util_strdup(str); SL_RETURN(0, _("sh_prelink_set_path")); #else prelink_path = NULL; SL_RETURN((-1), _("sh_prelink_set_path")); #endif } int sh_prelink_set_hash (const char * str) { size_t len; SL_ENTER(_("sh_prelink_set_hash")); if (prelink_hash != NULL) SH_FREE(prelink_hash); len = sl_strlen (str); if (len != KEY_LEN) { prelink_hash = NULL; SL_RETURN((-1), _("sh_prelink_set_hash")); } prelink_hash = SH_ALLOC(len+1); (void) sl_strlcpy(prelink_hash, str, len+1); SL_RETURN(0, _("sh_prelink_set_hash")); } int sh_prelink_iself (SL_TICKET fd, off_t size, int alert_timeout, char * path) { long status; char magic[4]; char * tmp; /* 42 bytes is about the minimum an ELF binary might have * (with plenty of hacks to reduce the size, such as interleaving * the code with the header...) */ if (size < 42) return S_FALSE; status = sl_read_timeout (fd, magic, 4, alert_timeout, S_FALSE); (void) sl_rewind(fd); if (status == 4) { /*@-usedef@*/ if (magic[0] == (char) 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') return S_TRUE; /*@+usedef@*/ } else { tmp = sh_util_safe_name (path); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGPATH, _("Error reading file"), _("sh_prelink_iself"), tmp); SH_FREE(path); } return S_FALSE; } extern int get_the_fd (SL_TICKET ticket); static void sh_prelink_fd(sh_tas_t * task) { SL_TICKET ticket; char * tmp; char hashbuf[KEYBUF_SIZE]; if (task->com_ti != (-1)) { (void) sl_close(task->com_ti); task->com_fd = -1; task->com_ti = -1; } ticket = sl_open_read(FIL__, __LINE__, task->command, task->privileged == 0 ? SL_NOPRIV : SL_YESPRIV); if (SL_ISERROR(ticket)) { char errbuf[SH_ERRBUF_SIZE]; char errbuf2[SH_ERRBUF_SIZE]; sh_error_message(errno, errbuf2, sizeof(errbuf2)); sl_strlcpy(errbuf, sl_error_string(ticket), sizeof(errbuf)); tmp = sh_util_safe_name (task->command); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_READ, errbuf, errbuf2, tmp); SH_FREE(tmp); return; } if (*(task->checksum) == '\0' || 0 == sl_strcmp(task->checksum, sh_tiger_hash (task->command, ticket, TIGER_NOLIM, hashbuf, sizeof(hashbuf)))) { task->com_fd = get_the_fd(ticket); task->com_ti = ticket; } else { tmp = sh_util_safe_name (task->command); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_HASH, tmp); SH_FREE(tmp); (void) sl_close(ticket); } return; } /* returns static storage */ int sh_prelink_run (char * path, char * file_hash, int alert_timeout, unsigned long mask) { static int init = S_FALSE; static int args_filled = 0; static sh_tas_t task; int status = 0; char * p; SL_ENTER(_("sh_prelink_run")); /* reset if path == NULL */ if (path == NULL) { if (init == S_FALSE) { SL_RETURN (0, _("sh_prelink_run")); } sh_ext_tas_free(&task); init = S_FALSE; args_filled = 0; SL_RETURN (0, _("sh_prelink_run")); } /* initialize task structure */ if (init == S_FALSE) { char dir[SH_PATHBUF]; sh_ext_tas_init(&task); p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir)); if (p) { (void) sh_ext_tas_add_envv (&task, _("HOME"), p); } (void) sh_ext_tas_add_envv (&task, _("SHELL"), _("/bin/sh")); (void) sh_ext_tas_add_envv (&task, _("PATH"), _("/sbin:/usr/sbin:/bin:/usr/bin")); if (sh.timezone != NULL) { (void) sh_ext_tas_add_envv(&task, "TZ", sh.timezone); } if (prelink_path == NULL) { sh_ext_tas_command(&task, _("/usr/sbin/prelink")); (void) sh_ext_tas_add_argv(&task, _("/usr/sbin/prelink")); } else { sh_ext_tas_command(&task, prelink_path); (void) sh_ext_tas_add_argv(&task, prelink_path); } args_filled = sh_ext_tas_add_argv(&task, _("--verify")); if (prelink_hash != NULL) { (void) sl_strlcpy(task.checksum, prelink_hash, KEY_LEN+1); } task.rw = 'r'; task.fork_twice = S_FALSE; sh_prelink_fd(&task); init = S_TRUE; } /* rm filename arg if set; fill in filename */ if (args_filled == 3) args_filled = sh_ext_tas_rm_argv(&task); if (args_filled == 2) args_filled = sh_ext_tas_add_argv(&task, path); else { sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, args_filled, MSG_E_SUBGEN, _("Bad argument count"), _("sh_prelink_run")); SL_RETURN ((-1), _("sh_prelink_run")); } /* open pipe */ status = sh_ext_popen(&task); if (status != 0) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, _("Could not open pipe"), _("sh_prelink_run")); SL_RETURN ((-1), _("sh_prelink_run")); } if (SL_ISERROR(task.pipeTI)) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task.pipeTI, MSG_E_SUBGEN, _("No valid ticket"), _("sh_prelink_run")); SL_RETURN ((-1), _("sh_prelink_run")); } /* read from pipe */ sl_read_timeout_prep (task.pipeTI); { char hashbuf[KEYBUF_SIZE]; UINT64 length_nolim = TIGER_NOLIM; if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask); sl_strlcpy(file_hash, sh_tiger_generic_hash (path, task.pipeTI, &length_nolim, alert_timeout, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } /* close pipe and return exit status */ status = sh_ext_pclose(&task); SL_RETURN ((status), _("sh_prelink_run")); } /* defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */ #endif samhain-4.1.4/src/kern_head.h.tmp0000644000175000017500000000000012615253277013540 00000000000000samhain-4.1.4/src/CuTest.c0000644000175000017500000002075412615253277012245 00000000000000/******************* LICENSE Copyright (c) 2003 Asim Jalis This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. **********************/ #include #include #include #include #include #include #include #include "CuTest.h" /*-------------------------------------------------------------------------* * CuStr *-------------------------------------------------------------------------*/ char* CuStrAlloc(int size) { char* newStr = (char*) malloc( sizeof(char) * (size) ); return newStr; } char* CuStrCopy(const char* old) { int len = strlen(old); char* newStr = CuStrAlloc(len + 1); strcpy(newStr, old); return newStr; } /*-------------------------------------------------------------------------* * CuString *-------------------------------------------------------------------------*/ void CuStringInit(CuString* str) { str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); if (str->buffer) str->buffer[0] = '\0'; else { perror("CuStringInit"); _exit (EXIT_FAILURE); } } CuString* CuStringNew(void) { CuString* str = (CuString*) malloc(sizeof(CuString)); str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); if (str->buffer) str->buffer[0] = '\0'; else { perror("CuStringNew"); _exit (EXIT_FAILURE); } return str; } void CuStringResize(CuString* str, int newSize) { str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); str->size = newSize; } void CuStringAppend(CuString* str, const char* text) { int length; if (text == NULL) { text = "NULL"; } length = strlen(text); if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); str->length += length; strcat(str->buffer, text); } void CuStringAppendChar(CuString* str, char ch) { char text[2]; text[0] = ch; text[1] = '\0'; CuStringAppend(str, text); } void CuStringAppendFormat(CuString* str, const char* format, ...) { va_list argp; char buf[2048]; va_start(argp, format); vsnprintf(buf, sizeof(buf), format, argp); va_end(argp); CuStringAppend(str, buf); } void CuStringInsert(CuString* str, const char* text, int pos) { int length = strlen(text); if (pos > str->length) pos = str->length; if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); str->length += length; memcpy(str->buffer + pos, text, length); } /*-------------------------------------------------------------------------* * CuTest *-------------------------------------------------------------------------*/ void CuTestInit(CuTest* t, const char* name, TestFunction function) { t->name = CuStrCopy(name); t->failed = 0; t->ran = 0; t->message = NULL; t->function = function; t->jumpBuf = NULL; } CuTest* CuTestNew(const char* name, TestFunction function) { CuTest* tc = CU_ALLOC(CuTest); CuTestInit(tc, name, function); return tc; } void CuTestRun(CuTest* tc) { jmp_buf buf; tc->jumpBuf = &buf; if (setjmp(buf) == 0) { tc->ran = 1; (tc->function)(tc); } tc->jumpBuf = 0; } static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) { char buf[256]; snprintf(buf, sizeof(buf), "%s:%d: ", file, line); CuStringInsert(string, buf, 0); tc->failed = 1; tc->message = string->buffer; if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); } void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) { CuString string; CuStringInit(&string); if (message2 != NULL) { CuStringAppend(&string, message2); CuStringAppend(&string, ": "); } CuStringAppend(&string, message); CuFailInternal(tc, file, line, &string); } void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) { if (condition) return; CuFail_Line(tc, file, line, NULL, message); } void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) { CuString string; if ((expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strcmp(expected, actual) == 0)) { return; } CuStringInit(&string); if (message != NULL) { CuStringAppend(&string, message); CuStringAppend(&string, ": "); } CuStringAppend(&string, "expected <"); CuStringAppend(&string, expected); CuStringAppend(&string, "> but was <"); CuStringAppend(&string, actual); CuStringAppend(&string, ">"); CuFailInternal(tc, file, line, &string); } void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected <%d> but was <%d>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta) { char buf[STRING_MAX]; #define SH_FABS(a) (((a) < 0) ? -(a) : (a)) if (SH_FABS(expected - actual) <= delta) return; sprintf(buf, "expected <%lf> but was <%lf>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); CuFail_Line(tc, file, line, message, buf); } /*-------------------------------------------------------------------------* * CuSuite *-------------------------------------------------------------------------*/ void CuSuiteInit(CuSuite* testSuite) { testSuite->count = 0; testSuite->failCount = 0; } CuSuite* CuSuiteNew(void) { CuSuite* testSuite = CU_ALLOC(CuSuite); CuSuiteInit(testSuite); return testSuite; } void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) { assert(testSuite->count < MAX_TEST_CASES); testSuite->list[testSuite->count] = testCase; testSuite->count++; } void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) { int i; for (i = 0 ; i < testSuite2->count ; ++i) { CuTest* testCase = testSuite2->list[i]; CuSuiteAdd(testSuite, testCase); } } void CuSuiteRun(CuSuite* testSuite) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuTestRun(testCase); if (testCase->failed) { testSuite->failCount += 1; } } } void CuSuiteSummary(CuSuite* testSuite, CuString* summary) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuStringAppend(summary, testCase->failed ? "F" : "."); } CuStringAppend(summary, "\n\n"); } void CuSuiteDetails(CuSuite* testSuite, CuString* details) { int i; int failCount = 0; if (testSuite->failCount == 0) { int passCount = testSuite->count - testSuite->failCount; const char* testWord = passCount == 1 ? "test" : "tests"; CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); } else { if (testSuite->failCount == 1) CuStringAppend(details, "There was 1 failure:\n"); else CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; if (testCase->failed) { failCount++; CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); } } CuStringAppend(details, "\n!!!FAILURES!!!\n"); CuStringAppendFormat(details, "Runs: %d ", testSuite->count); CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); } } samhain-4.1.4/src/sh_database.c0000644000175000017500000014334512615253277013276 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2001 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include #ifdef WITH_DATABASE /* define this if you want to debug the Oracle database support */ /* #define DB_DEBUG */ #define SH_REAL_SET #include "samhain.h" #include "sh_cat.h" #include "sh_error.h" #include "sh_utils.h" #undef FIL__ #define FIL__ _("sh_database.c") typedef struct my_attr_ { char * attr; char * attr_o; int inHash; int val; int size; int alen; size_t off; } my_attr; typedef struct dbins_ { struct dbins_ * next; char host[64]; char time[20]; char msg[1024]; char sev[8]; char path[MAX_PATH_STORE+1]; char user[9]; char group[9]; char program[8]; char subroutine[16]; char status[12]; char hash[50]; char path_data[1024]; char hash_data[50]; char key_uid[64]; char key_uid_data[64]; char key_id[16]; char module[8]; char syscall[16]; char ip[SH_IP_BUF]; char tty[16]; char peer[64]; char fromhost[64]; char obj[1024]; char interface[64]; char ltime[64]; char dir[MAX_PATH_STORE+1]; char linked_path[MAX_PATH_STORE+1]; char service[64]; char facility[32]; char priority[32]; char syslog_msg[1024]; char mode_old[16]; char mode_new[16]; char attr_old[16]; char attr_new[16]; char device_old[16]; char device_new[16]; char owner_old[9]; char owner_new[9]; char group_old[9]; char group_new[9]; char ctime_old[20]; char ctime_new[20]; char atime_old[20]; char atime_new[20]; char mtime_old[20]; char mtime_new[20]; char chksum_old[50]; char chksum_new[50]; char link_old[MAX_PATH_STORE+1]; char link_new[MAX_PATH_STORE+1]; char acl_old[1024]; char acl_new[1024]; unsigned long ulong_data[20]; /* long size_old; long size_new; long hardlinks_old; long hardlinks_new; long inode_old; long inode_new; */ } dbins; static my_attr * attr_tab_srch = NULL; static int attr_tab_srch_siz = 0; static my_attr attr_tab[] = { { NULL, N_("sev"), 0, 1, 8, 0, offsetof(struct dbins_, sev) }, { NULL, N_("tstamp"), 0, 2, 16, 0, offsetof(struct dbins_, time) }, { NULL, N_("remote_host"), 0, 3, 64, 0, offsetof(struct dbins_, host) }, { NULL, N_("msg"), 0, 4, 1024, 0, offsetof(struct dbins_, msg) }, { NULL, N_("path"), 0, 5,MAX_PATH_STORE+1, 0, offsetof(struct dbins_, path) }, /* username -> userid; replace (long) 'userid' - below - by 'dummy' */ { NULL, N_("userid"), 0, 6, 9, 0, offsetof(struct dbins_, user) }, { NULL, N_("group"), 0, 7, 9, 0, offsetof(struct dbins_, group) }, { NULL, N_("program"), 0, 8, 8, 0, offsetof(struct dbins_, program) }, { NULL, N_("subroutine"), 0, 9, 16, 0, offsetof(struct dbins_, subroutine)}, { NULL, N_("status"), 0, 10, 12, 0, offsetof(struct dbins_, status) }, { NULL, N_("hash"), 0, 11, 50, 0, offsetof(struct dbins_, hash) }, { NULL, N_("path_data"), 0, 12, 1024, 0, offsetof(struct dbins_, path_data) }, { NULL, N_("hash_data"), 0, 13, 50, 0, offsetof(struct dbins_, hash_data) }, { NULL, N_("key_uid"), 0, 14, 64, 0, offsetof(struct dbins_, key_uid) }, { NULL, N_("key_uid_data"),0, 15, 64, 0, offsetof(struct dbins_, key_uid_data)}, { NULL, N_("key_id"), 0, 16, 16, 0, offsetof(struct dbins_, key_id) }, { NULL, N_("module"), 0, 17, 8, 0, offsetof(struct dbins_, module) }, { NULL, N_("syscall"), 0, 19, 16, 0, offsetof(struct dbins_, syscall) }, { NULL, N_("ip"), 0, 20,SH_IP_BUF, 0, offsetof(struct dbins_, ip) }, { NULL, N_("tty"), 0, 21, 16, 0, offsetof(struct dbins_, tty) }, { NULL, N_("peer"), 0, 22, 64, 0, offsetof(struct dbins_, peer) }, { NULL, N_("obj"), 0, 23, 1024, 0, offsetof(struct dbins_, obj) }, { NULL, N_("interface"), 0, 24, 64, 0, offsetof(struct dbins_, interface)}, { NULL, N_("time"), 0, 25, 64, 0, offsetof(struct dbins_, ltime) }, { NULL, N_("dir"), 0, 26, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, dir) }, { NULL, N_("linked_path"), 0, 27, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, linked_path)}, { NULL, N_("service"), 0, 29, 64, 0, offsetof(struct dbins_, service)}, { NULL, N_("facility"), 0, 30, 32, 0, offsetof(struct dbins_, facility) }, { NULL, N_("priority"), 0, 31, 32, 0, offsetof(struct dbins_, priority) }, { NULL, N_("syslog_msg"), 0, 32, 1024, 0, offsetof(struct dbins_, syslog_msg) }, { NULL, N_("mode_old"), 0, 33, 16, 0, offsetof(struct dbins_, mode_old) }, { NULL, N_("mode_new"), 0, 34, 16, 0, offsetof(struct dbins_, mode_new) }, { NULL, N_("device_old"), 0, 35, 16, 0, offsetof(struct dbins_, device_old)}, { NULL, N_("device_new"), 0, 36, 16, 0, offsetof(struct dbins_, device_new)}, { NULL, N_("owner_old"), 0, 37, 9, 0, offsetof(struct dbins_, owner_old)}, { NULL, N_("owner_new"), 0, 38, 9, 0, offsetof(struct dbins_, owner_new)}, { NULL, N_("group_old"), 0, 39, 9, 0, offsetof(struct dbins_, group_old)}, { NULL, N_("group_new"), 0, 40, 9, 0, offsetof(struct dbins_, group_new)}, { NULL, N_("ctime_old"), 0, 41, 20, 0, offsetof(struct dbins_, ctime_old)}, { NULL, N_("ctime_new"), 0, 42, 20, 0, offsetof(struct dbins_, ctime_new)}, { NULL, N_("atime_old"), 0, 43, 20, 0, offsetof(struct dbins_, atime_old)}, { NULL, N_("atime_new"), 0, 44, 20, 0, offsetof(struct dbins_, atime_new)}, { NULL, N_("mtime_old"), 0, 45, 20, 0, offsetof(struct dbins_, mtime_old)}, { NULL, N_("mtime_new"), 0, 46, 20, 0, offsetof(struct dbins_, mtime_new)}, { NULL, N_("chksum_old"), 0, 47, 50, 0, offsetof(struct dbins_, chksum_old)}, { NULL, N_("chksum_new"), 0, 48, 50, 0, offsetof(struct dbins_, chksum_new)}, { NULL, N_("link_old"), 0, 49, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, link_old)}, { NULL, N_("link_new"), 0, 50, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, link_new)}, /* These go into dbins.ulong_data[n - START_SEC_LONGS] */ { NULL, N_("size_old"), 0, 51, 0, 0, 0 }, { NULL, N_("size_new"), 0, 52, 0, 0, 0 }, { NULL, N_("hardlinks_old"),0, 53, 0, 0, 0 }, { NULL, N_("hardlinks_new"),0, 54, 0, 0, 0 }, { NULL, N_("inode_old"), 0, 55, 0, 0, 0 }, { NULL, N_("inode_new"), 0, 56, 0, 0, 0 }, { NULL, N_("imode_old"), 0, 57, 0, 0, 0 }, { NULL, N_("imode_new"), 0, 58, 0, 0, 0 }, { NULL, N_("iattr_old"), 0, 59, 0, 0, 0 }, { NULL, N_("iattr_new"), 0, 60, 0, 0, 0 }, { NULL, N_("idevice_old"), 0, 61, 0, 0, 0 }, { NULL, N_("idevice_new"), 0, 62, 0, 0, 0 }, { NULL, N_("iowner_old"), 0, 63, 0, 0, 0 }, { NULL, N_("iowner_new"), 0, 64, 0, 0, 0 }, { NULL, N_("igroup_old"), 0, 65, 0, 0, 0 }, { NULL, N_("igroup_new"), 0, 66, 0, 0, 0 }, { NULL, N_("port"), 0, 67, 0, 0, 0 }, { NULL, N_("return_code"), 0, 68, 0, 0, 0 }, { NULL, N_("checkflags_old"), 0, 69, 0, 0, 0 }, { NULL, N_("checkflags_new"), 0, 70, 0, 0, 0 }, /* END_SEC_LONGS */ { NULL, N_("host"), 0, 71, 64, 0, offsetof(struct dbins_, fromhost)}, { NULL, N_("attr_old"), 0, 72, 16, 0, offsetof(struct dbins_, attr_old)}, { NULL, N_("attr_new"), 0, 73, 16, 0, offsetof(struct dbins_, attr_new)}, { NULL, N_("acl_old"), 0, 74, 1024, 0, offsetof(struct dbins_, acl_old)}, { NULL, N_("acl_new"), 0, 75, 1024, 0, offsetof(struct dbins_, acl_new)}, { NULL, NULL, 0, 0, 0, 0, 0 } }; #define SH_SLOT_CHECKFLAGS 69 /* need special attention b/o reserved SQL words */ #define SH_SLOT_HOST 71 #define SH_SLOT_GROUP 7 /* these go into dbins.ulong_data[n-START_SEC_LONGS */ #define START_SEC_LONGS 51 #define END_SEC_LONGS 70 #if defined(HAVE_INT_32) typedef unsigned int uint32; #elif defined(HAVE_LONG_32) typedef unsigned long uint32; #elif defined(HAVE_SHORT_32) typedef unsigned short uint32; #else #error No 32 byte type found ! #endif typedef unsigned char uint8; typedef struct md5_ctx { uint32 A; uint32 B; uint32 C; uint32 D; uint32 total[2]; uint32 buflen; char buffer[128]; } md5Param; typedef unsigned char sh_byte; extern int md5Reset(register md5Param* p); extern int md5Update(md5Param* p, const sh_byte* data, int size); extern int md5Digest(md5Param* p, uint32* data); static char db_name[64] = ""; static char db_table[64] = ""; static char db_host[64] = ""; static char db_user[64] = ""; static char db_password[64] = ""; static int sh_persistent_dbconn = S_TRUE; int sh_database_use_persistent (const char * str) { return sh_util_flagval (str, &sh_persistent_dbconn); } static int insert_value (char * ptr, const char * str) { if (!ptr || !str) return -1; if (strlen(str) > 63) return -1; (void) sl_strlcpy(ptr, str, 64); return 0; } static void init_db_entry (dbins * ptr) { memset (ptr, (int) '\0', sizeof(dbins)); ptr->next = NULL; return; } int sh_database_set_database (const char * str) { return insert_value (db_name, str); } int sh_database_set_table (const char * str) { return insert_value (db_table, str); } int sh_database_set_host (const char * str) { return insert_value (db_host, str); } int sh_database_set_user (const char * str) { return insert_value (db_user, str); } int sh_database_set_password (const char * str) { return insert_value (db_password, str); } /****************************************************************** * * Oracle and unixODBC stuff, only Oracle tested untested * * Based on the code in the snort output plugin (spo_database.c). * Copyright/license statement in spo_database.c: * * Portions Copyright (C) 2000,2001,2002 Carnegie Mellon University * Copyright (C) 2001 Jed Pickel * Portions Copyright (C) 2001 Andrew R. Baker * * 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. * ******************************************************************/ #ifdef WITH_ODBC #include #include #include static SQLHENV u_handle; static SQLHDBC u_connection; static SQLHSTMT u_statement; static SQLINTEGER u_col; static SQLINTEGER u_rows; void sh_database_reset() { return; } static int sh_database_query (char * query, /*@out@*/ long * id) { static int fatal_error = 0; int result = 0; char row_query[128]; long result_call; SL_ENTER(_("sh_database_query")); *id = 0; if (fatal_error == 1) { SL_RETURN((-1), _("sh_database_query")); } /* Connect */ if (db_name[0] == '\0') sl_strlcpy(db_name, _("samhain"), 64); if (db_user[0] == '\0') sl_strlcpy(db_user, _("samhain"), 64); result_call = SQLAllocEnv(&u_handle); if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO)) { sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call, MSG_E_SUBGEN, _("Error in SQLAllocEnv when connecting to ODBC data source"), _("sh_database_query")); fatal_error = 1; SL_RETURN((-1), _("sh_database_query")); } result_call = SQLAllocConnect(u_handle, &u_connection); if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO)) { sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call, MSG_E_SUBGEN, _("Error in SQLAllocEnv when connecting to ODBC data source"), _("sh_database_query")); fatal_error = 1; SL_RETURN((-1), _("sh_database_query")); } result_call = SQLConnect(u_connection, db_name, SQL_NTS, db_user, SQL_NTS, db_password, SQL_NTS); if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO)) { sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call, MSG_E_SUBGEN, _("Error in SQLAllocEnv when connecting to ODBC data source"), _("sh_database_query")); fatal_error = 1; SL_RETURN((-1), _("sh_database_query")); } /* Insert */ result_call = SQLAllocStmt(u_connection, &u_statement); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result_call = SQLPrepare(u_statement, query, SQL_NTS); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result_call = SQLExecute(u_statement); if((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result = 1; } } } if (result == 0) { sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Error inserting into ODBC data source"), _("sh_database_query")); goto odbc_disconnect; } /* Select */ result = 0; sl_strlcpy (row_query, _("SELECT MAX(log_index) FROM "), 128); sl_strlcat (row_query, db_table, 128); result_call = SQLAllocStmt(u_connection, &u_statement); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result_call = SQLPrepare(u_statement, row_query, SQL_NTS); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result_call = SQLExecute(u_statement); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result_call = SQLRowCount(u_statement, &u_rows); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { if((u_rows) && (u_rows == 1)) { result_call = SQLFetch(u_statement); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { result_call = SQLGetData(u_statement, 1, SQL_INTEGER, &u_col, sizeof(u_col), NULL); if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO)) { *id = (long int) u_col; result = 1; } } } } } } } if (result == 0) { sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Error selecting MAX(log_index) from ODBC data source"), _("sh_database_query")); } odbc_disconnect: SQLFreeHandle(SQL_HANDLE_STMT, u_statement); SQLDisconnect(u_connection); SQLFreeHandle(SQL_HANDLE_DBC, u_connection); SQLFreeHandle(SQL_HANDLE_ENV, u_handle); SL_RETURN(((result == 0) ? -1 : 0), _("sh_database_query")); } /* #ifdef WITH_ODBC */ #endif #ifdef WITH_ORACLE #include static OCIDefine * o_define; static OCIEnv * o_environment; static OCISvcCtx * o_servicecontext; static OCIError * o_error = NULL; static OCIStmt * o_statement; static OCIBind * o_bind = (OCIBind *) 0; static text o_errormsg[512]; static sb4 o_errorcode; static int connected = 0; void sh_database_reset() { if (connected == 1) { OCILogoff(o_servicecontext, o_error); OCIHandleFree((dvoid *) o_statement, OCI_HTYPE_STMT); OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX); OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR); o_error = NULL; } connected = 0; return; } static char * sh_stripnl (char * str) { size_t len = sl_strlen(str); if (len > 0) { if (str[len-1] == '\n') str[len-1] = '\0'; } return str; } static int sh_database_query (char * query, /*@out@*/ long * id) { static int bad_init = 0; int result = 0; char row_query[128]; int retry = 0; static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE }; SL_ENTER(_("sh_database_query")); *id = 0; if (bad_init == 1) { SL_RETURN(-1, _("sh_database_query")); } else if (connected == 1) { goto oracle_connected; } /* * Connect */ #define PRINT_ORACLE_ERR(func_name) \ do { \ OCIErrorGet(o_error, 1, NULL, &o_errorcode, \ o_errormsg, sizeof(o_errormsg), \ OCI_HTYPE_ERROR); \ sh_stripnl (o_errormsg); \ sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, \ o_errormsg, _("sh_database_query")); \ sl_snprintf(row_query, 127, \ _("%s: Connection to database '%s' failed"), \ func_name, db_name); \ sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, \ row_query, _("sh_database_query")); \ bad_init = 1; \ SL_RETURN(-1, _("sh_database_query")); \ } while (1 == 0) oracle_doconnect: if (!getenv("ORACLE_HOME")) /* flawfinder: ignore */ { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("ORACLE_HOME environment variable not set"), _("sh_database_query")); } if (db_name[0] == '\0') { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("database name not set, using default 'samhain'"), _("sh_database_query")); sl_strlcpy(db_name, _("samhain"), 64); } if (db_user[0] == '\0') { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("database user not set, using default 'samhain'"), _("sh_database_query")); sl_strlcpy(db_user, _("samhain"), 64); } if (db_password[0] == '\0') { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("database password not set, cannot proceed"), _("sh_database_query")); bad_init = 1; SL_RETURN(-1, _("sh_database_query")); } #ifdef DB_DEBUG sl_snprintf(row_query, 127, _("Conncting to oracle database '%s'"), db_name); sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, row_query, _("sh_database_query")); #endif /* a) Oracle says use OCIEnvCreate instead of OCIInitialize/OCIEnvcreate * b) why two times OCIEnvInit() ??? */ if (OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL)) PRINT_ORACLE_ERR("OCIInitialize"); if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL)) PRINT_ORACLE_ERR("OCIEnvInit"); if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL)) PRINT_ORACLE_ERR("OCIEnvInit (2)"); /* allocate and initialize the error handle */ if (OCIHandleAlloc(o_environment, (dvoid **)&o_error, OCI_HTYPE_ERROR, (size_t) 0, NULL)) PRINT_ORACLE_ERR("OCIHandleAlloc"); /* logon and allocate the service context handle */ if (OCILogon(o_environment, o_error, &o_servicecontext, (OraText*) db_user, sl_strlen(db_user), (OraText*) db_password, sl_strlen(db_password), (OraText*) db_name, sl_strlen(db_name))) { connected = 0; sh_timer.flag_ok = S_FALSE; if (S_TRUE == sh_util_timeout_check(&sh_timer)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("check database is listed in tnsnames.ora"), _("sh_database_query")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("check tnsnames.ora readable"), _("sh_database_query")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("check database accessible with sqlplus"), _("sh_database_query")); sl_snprintf(row_query, 127, _("OCILogon: Connection to database '%s' failed"), db_name); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, row_query, _("sh_database_query")); goto err_out; } else { SL_RETURN(0, _("sh_database_query")); } } if (OCIHandleAlloc(o_environment, (dvoid **)&o_statement, OCI_HTYPE_STMT, 0, NULL)) PRINT_ORACLE_ERR("OCIHandleAlloc (2)"); /* Flag connection status */ connected = 1; oracle_connected: /* Get row index */ sl_strlcpy (row_query, _("SELECT log_log_index_seq.NEXTVAL FROM dual"), 128); #ifdef DB_DEBUG sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, row_query, _("sh_database_query")); #endif if (OCIStmtPrepare(o_statement, o_error, (OraText*) row_query, sl_strlen(row_query), OCI_NTV_SYNTAX, OCI_DEFAULT)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } if (OCIStmtExecute(o_servicecontext, o_statement, o_error, 0, 0, NULL, NULL, OCI_DEFAULT)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } if (OCIDefineByPos (o_statement, &o_define, o_error, 1, &result, sizeof(result), SQLT_INT, 0, 0, 0, OCI_DEFAULT)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } if (OCIStmtFetch (o_statement, o_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } #ifdef DB_DEBUG sl_snprintf(row_query, 127, _("Returned value: %d"), result); sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, row_query, _("sh_database_query")); #endif *id = result; /* do the insert */ #ifdef DB_DEBUG sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, query, _("sh_database_query")); #endif if (OCIStmtPrepare(o_statement, o_error, (OraText*) query, sl_strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } if (OCIBindByPos(o_statement, &o_bind, o_error, 1, (dvoid *) &result, (sword) sizeof(result), SQLT_INT, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } if (OCIStmtExecute(o_servicecontext, o_statement, o_error, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS)) { OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR); sh_stripnl (o_errormsg); sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, o_errormsg, _("sh_database_query")); if (retry == 0 && (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) { ++retry; sh_database_reset(); goto oracle_doconnect; } goto err_out; } #ifdef DB_DEBUG sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("No error on insert"), _("sh_database_query")); #endif if (sh_persistent_dbconn == S_FALSE) { OCILogoff(o_servicecontext, o_error); OCIHandleFree((dvoid *) o_statement, OCI_HTYPE_STMT); OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX); OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR); o_error = NULL; connected = 0; } SL_RETURN(0, _("sh_database_query")); err_out: /* * Error */ sh_database_reset(); SL_RETURN(-1, _("sh_database_query")); } /* #ifdef WITH_ORACLE */ #endif #ifdef WITH_POSTGRES /****************************************************************** * * Postgresql stuff, tested * ******************************************************************/ #if defined(HAVE_PGSQL_LIBPQ_FE_H) #include #elif defined(HAVE_POSTGRESQL_LIBPQ_FE_H) #include #else #if !defined(USE_UNO) #include #else #include #endif #endif static int connection_status = S_FALSE; void sh_database_reset() { connection_status = S_FALSE; return; } static int sh_database_query (char * query, /*@out@*/ long * id) { char conninfo[256]; char * p; static PGconn * conn = NULL; PGresult * res; unsigned int i; const char * params[1]; char id_param[32]; static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE }; SL_ENTER(_("sh_database_query")); *id = 0; p = &conninfo[0]; if (db_host[0] == '\0') sl_strlcpy(db_host, _("localhost"), 64); if (db_name[0] == '\0') sl_strlcpy(db_name, _("samhain"), 64); if (db_user[0] == '\0') sl_strlcpy(db_user, _("samhain"), 64); if (db_host[0] != '\0' && NULL != strchr(db_host, '.')) { sl_snprintf(p, 255, "hostaddr=%s ", db_host); p = &conninfo[strlen(conninfo)]; } if (db_name[0] != '\0') { sl_snprintf(p, 255 - strlen(conninfo), "dbname=%s ", db_name); p = &conninfo[strlen(conninfo)]; } if (db_user[0] != '\0') { sl_snprintf(p, 255 - strlen(conninfo), "user=%s ", db_user); p = &conninfo[strlen(conninfo)]; } if (db_password[0] != '\0') { sl_snprintf(p, 255 - strlen(conninfo), "password=%s ", db_password); } if (connection_status == S_FALSE) { if (conn) PQfinish(conn); conn = NULL; conn = PQconnectdb(conninfo); } else { if (PQstatus(conn) == CONNECTION_BAD) PQreset(conn); } if ((conn == NULL) || (PQstatus(conn) == CONNECTION_BAD)) { connection_status = S_FALSE; sh_timer.flag_ok = S_FALSE; if (S_TRUE == sh_util_timeout_check(&sh_timer)) { goto err_out; } else { if (conn) PQfinish(conn); conn = NULL; SL_RETURN(0, _("sh_database_query")); } } connection_status = S_TRUE; /* get the unique row index */ res = PQexec(conn, _("SELECT NEXTVAL('log_log_index_seq')")); if (PQresultStatus(res) != PGRES_TUPLES_OK) { PQclear(res); goto err_out; } *id = atoi (PQgetvalue(res, 0, 0)); PQclear(res); sl_snprintf(id_param, 32, "%ld", *id); params[0] = id_param; /* do the insert */ res = PQexecParams(conn, query, 1, NULL, params, NULL, NULL, 1); if (PQresultStatus(res) != PGRES_COMMAND_OK) { PQclear(res); goto err_out; } PQclear(res); if (S_FALSE == sh_persistent_dbconn) { if (conn) PQfinish(conn); conn = NULL; connection_status = S_FALSE; } SL_RETURN(0, _("sh_database_query")); err_out: if (conn) { p = PQerrorMessage(conn); for (i = 0; i < sl_strlen(p); ++i) if (p[i] == '\n') p[i] = ' '; } else { p = NULL; } sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, (p == NULL ? _("(null)") : p), _("sh_database_query")); if (conn) PQfinish(conn); conn = NULL; connection_status = S_FALSE; SL_RETURN(-1, _("sh_database_query")); } #endif #ifdef WITH_MYSQL #ifdef HAVE_MYSQL_MYSQL_H #include #else #include #endif extern int flag_err_debug; static int connection_status = S_FALSE; void sh_database_reset(void) { connection_status = S_FALSE; return; } static int sh_database_query (char * query, /*@out@*/ long * id) { int status = 0; const char * p; static MYSQL * db_conn = NULL; static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE }; SL_ENTER(_("sh_database_query")); *id = 0; if (query == NULL) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("NULL query"), _("sh_database_query")); SL_RETURN(0, _("sh_database_query")); } if (db_host[0] == '\0') (void) sl_strlcpy(db_host, _("localhost"), 64); if (db_name[0] == '\0') (void) sl_strlcpy(db_name, _("samhain"), 64); if (db_user[0] == '\0') (void) sl_strlcpy(db_user, _("samhain"), 64); if ((db_conn == NULL) || (connection_status == S_FALSE)) { if (db_conn) { mysql_close(db_conn); db_conn = NULL; } connection_status = S_FALSE; db_conn = mysql_init(NULL); if (NULL == db_conn) { p = NULL; status = 0; sh_timer.flag_ok = S_FALSE; if (S_TRUE == sh_util_timeout_check(&sh_timer)) { goto alt_out; } else { SL_RETURN(0, _("sh_database_query")); } } /* Read in defaults from /etc/my.cnf and associated files, * suggested by arjones at simultan dyndns org * see: - http://dev.mysql.com/doc/refman/5.0/en/option-files.html * for the my.cnf format, * - http://dev.mysql.com/doc/refman/5.0/en/mysql-options.html * for possible options * We don't check the return value because it's useless (failure due * to lack of access permission is not reported). */ #if !defined(__x86_64__) /* * libmysql segfaults on x86-64 if this is used */ mysql_options(db_conn, MYSQL_READ_DEFAULT_GROUP, _("samhain")); #endif status = 0; if (NULL == mysql_real_connect(db_conn, db_host[0] == '\0' ? NULL : db_host, db_user[0] == '\0' ? NULL : db_user, db_password[0] == '\0' ? NULL : db_password, db_name[0] == '\0' ? NULL : db_name, 0, NULL, 0)) { sh_timer.flag_ok = S_FALSE; if (S_TRUE == sh_util_timeout_check(&sh_timer)) { goto err_out; } else { SL_RETURN(0, _("sh_database_query")); } } connection_status = S_TRUE; } else { if (0 != mysql_ping(db_conn)) { connection_status = S_FALSE; sh_timer.flag_ok = S_FALSE; if (S_TRUE == sh_util_timeout_check(&sh_timer)) { goto err_out; } else { SL_RETURN(0, _("sh_database_query")); } } } if (0 != mysql_query(db_conn, query)) { goto err_out; } if (flag_err_debug == S_TRUE) { p = mysql_info (db_conn); if (p != NULL) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, p, _("sh_database_query")); } } *id = (long) mysql_insert_id(db_conn); if (S_FALSE == sh_persistent_dbconn) { if (db_conn) mysql_close(db_conn); db_conn = NULL; connection_status = S_FALSE; } SL_RETURN(0, _("sh_database_query")); err_out: if (db_conn) { p = mysql_error (db_conn); status = (int) mysql_errno (db_conn); } else { p = NULL; p = 0; } alt_out: *id = 0; sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, (p == NULL ? _("(null)") : p), _("sh_database_query")); if (db_conn) mysql_close(db_conn); db_conn = NULL; connection_status = S_FALSE; SL_RETURN(status, _("sh_database_query")); } #endif static char * null_or_val (char * end, char * val, int * size, int flag) { long len; if (!((end == NULL) || (val == NULL) || (size == NULL))) { if (val[0] != '\0') { if (*size > 1) { *end = ','; ++end; (*size) -= 1; if (flag == 1) { *end = '\''; ++end; (*size) -= 1; } *end = '\0'; } len = (long) strlen(val); if ((long) *size > (len+1)) { (void) sl_strlcat(end, val, (size_t) *size); end += len; (*size) -= len; if (flag == 1) { *end = '\''; ++end; (*size) -= 1; } *end = '\0'; } } } return end; } #define SH_QUERY_MAX SH_MSG_BUF /* define SH_QUERY_MAX 16383 */ static long sh_database_entry (dbins * db_entry, long id) { /* This does not need to be re-entrant */ char * query; static char columns[1024]; char * values; long the_id; int size; char * end; int c_size; char * c_end; char * p; int i; char num[64]; md5Param crc; unsigned char md5buffer[16]; char md5out[33]; int cnt; size_t len_val; size_t len_col; SL_ENTER(_("sh_database_entry")); query = SH_ALLOC(SH_QUERY_MAX+1); values = SH_ALLOC(SH_QUERY_MAX+1); (void) md5Reset(&crc); if (db_entry->host[0] == '\0') { if (sh.host.name[0] == '\0') (void) strcpy (db_entry->host, _("localhost")); /* known to fit */ else (void) sl_strlcpy (db_entry->host, sh.host.name, 64); } /*@-bufferoverflowhigh@*/ if (id >= 0) sprintf(num, "%ld", id); /* known to fit */ /*@+bufferoverflowhigh@*/ #if defined(WITH_ORACLE) /* Oracle needs some help for the time format (fix by Michael Somers) */ (void) sl_snprintf (values, SH_QUERY_MAX, _("(:1,%s,%c%s%c,to_date(%c%s%c,'YYYY-MM-DD HH24:MI:SS'),%c%s%c,%c%s%c"), id >= 0 ? num : _("NULL"), '\'', db_entry->host,'\'', '\'', db_entry->time,'\'', '\'', db_entry->sev, '\'', '\'', (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg), '\''); (void) sl_snprintf (columns, 1023, _("(log_index,log_ref,log_host,log_time,log_sev,log_msg")); #elif defined(WITH_POSTGRES) /* Prepare query for PQexecParams */ (void) sl_snprintf (values, SH_QUERY_MAX, _("($1,%s,%c%s%c,%c%s%c,%c%s%c,%c%s%c"), id >= 0 ? num : _("NULL"), '\'', db_entry->host,'\'', '\'', db_entry->time,'\'', '\'', db_entry->sev, '\'', '\'', (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg), '\''); (void) sl_snprintf (columns, 1023, _("(log_index,log_ref,log_host,log_time,log_sev,log_msg")); #else (void) sl_snprintf (values, SH_QUERY_MAX, _("(%s,%c%s%c,%c%s%c,%c%s%c,%c%s%c"), id >= 0 ? num : _("NULL"), '\'', db_entry->host,'\'', '\'', db_entry->time,'\'', '\'', db_entry->sev, '\'', '\'', (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg), '\''); (void) sl_snprintf (columns, 1023, _("(log_ref,log_host,log_time,log_sev,log_msg")); #endif /*@-type@*//* byte* versus char[..] */ if (attr_tab[0].inHash == 1) (void) md5Update(&crc, (sh_byte*) db_entry->sev, (int) strlen(db_entry->sev)); if (attr_tab[1].inHash == 1) (void) md5Update(&crc, (sh_byte*) db_entry->time, (int) strlen(db_entry->time)); if (attr_tab[2].inHash == 1) (void) md5Update(&crc, (sh_byte*) db_entry->host, (int) strlen(db_entry->host)); if (attr_tab[3].inHash == 1 && db_entry->msg[0] != '\0') (void) md5Update(&crc, (sh_byte*) db_entry->msg, (int) strlen(db_entry->sev)); /*@+type@*/ len_val = strlen(values); size = (int) (SH_QUERY_MAX - len_val); end = values + len_val; len_col = strlen(columns); c_size = 1023 - (int) len_col; /* sizeof(colums) == 1024 */ c_end = columns + len_col; i = 4; while (attr_tab[i].attr != NULL) { if (SH_SLOT_CHECKFLAGS == attr_tab[i].val) { if (db_entry->ulong_data[attr_tab[i].val-START_SEC_LONGS] == 0 && db_entry->ulong_data[attr_tab[i+1].val-START_SEC_LONGS] == 0) { i+= 2; continue; } } if (attr_tab[i].size != 0) { if (attr_tab[i].val > 40 && attr_tab[i].val < 47) { /* remove the 'T' between date and time */ p = (char *)(db_entry)+attr_tab[i].off; p = strchr(p, 'T'); if (p) *p = ' '; } p = end; end = null_or_val(end,((char *)(db_entry)+attr_tab[i].off),&size,1); if (p != end) { if ((attr_tab[i].val != SH_SLOT_HOST) && (attr_tab[i].val != SH_SLOT_GROUP)) { c_end = null_or_val (c_end, attr_tab[i].attr, &c_size,0); } else { /* * 'host' is a reserved word in SQL */ if (attr_tab[i].val == SH_SLOT_HOST) c_end = null_or_val (c_end, _("fromhost"), &c_size,0); /* * 'group' is a reserved word in SQL */ else /* if (attr_tab[i].val == SH_SLOT_GROUP) */ c_end = null_or_val (c_end, _("grp"), &c_size,0); } } /*@-type@*//* byte* versus char[..] */ if (attr_tab[i].inHash == 1 && ((char *)(db_entry)+attr_tab[i].off) != '\0') { (void)md5Update(&crc, (sh_byte*) ((char *)(db_entry)+attr_tab[i].off), (int)strlen((char *)(db_entry)+attr_tab[i].off)); } /*@+type@*/ } else if (attr_tab[i].val >= START_SEC_LONGS && attr_tab[i].val <= END_SEC_LONGS) { (void) sl_snprintf(end, (size_t)(size-1), _(",\'%lu\'"), db_entry->ulong_data[attr_tab[i].val-START_SEC_LONGS]); while (*end != '\0') { ++end; --size; } (void) sl_snprintf(c_end, (size_t)(c_size-1), _(",%s"), attr_tab[i].attr); while (*c_end != '\0') { ++c_end; --c_size; } if (attr_tab[i].inHash == 1) { /*@-type@*//* byte* versus char[..] */ (void) md5Update(&crc, (sh_byte *) db_entry->ulong_data[attr_tab[i].val-START_SEC_LONGS], sizeof(long)); /*@+type@*/ } } ++i; } (void) md5Digest(&crc, (uint32 *) md5buffer); /*@-bufferoverflowhigh -usedef@*/ for (cnt = 0; cnt < 16; ++cnt) sprintf (&md5out[cnt*2], _("%02X"), /* known to fit */ (unsigned int) md5buffer[cnt]); /*@+bufferoverflowhigh +usedef@*/ md5out[32] = '\0'; (void) sl_snprintf(end, (size_t) (size-1), _(",%c%s%c"), '\'', md5out, '\''); while (*end != '\0') { ++end; --size; } (void) sl_snprintf(c_end, (size_t) (c_size-1),_(",log_hash")); while (*c_end != '\0') { ++c_end; --c_size; } if (size > 1) { *end = ')'; ++end; *end = '\0'; } if (c_size > 1) { *c_end = ')'; ++c_end; *c_end = '\0'; } if (db_table[0] == '\0') (void) sl_strlcpy(db_table, _("log"), 64); (void) sl_snprintf (query, SH_QUERY_MAX, _("INSERT INTO %s %s VALUES %s"), db_table, columns, values); sh_database_query (query, &the_id); /*@-usedef@*//* no, 'values' is allocated here */ SH_FREE(values); /*@+usedef@*/ SH_FREE(query); SL_RETURN(the_id, _("sh_database_entry")); } static int sh_database_comp_attr (const void *m1, const void *m2) { const my_attr *mi1 = (const my_attr *) m1; const my_attr *mi2 = (const my_attr *) m2; return strcmp(mi1->attr, mi2->attr); } static void init_attr_table(void) { static int first = S_TRUE; int i, j; #ifdef SH_STEALTH int k; if (first == S_FALSE) return; i = 0; while (attr_tab[i].attr_o != NULL) { j = strlen(attr_tab[i].attr_o); attr_tab[i].attr = calloc(1, j+1); /* only once */ if (NULL == attr_tab[i].attr) return; for (k = 0; k < j; ++k) attr_tab[i].attr[k] = attr_tab[i].attr_o[k] ^ XOR_CODE; attr_tab[i].attr[j] = '\0'; attr_tab[i].alen = strlen(attr_tab[i].attr_o); ++i; } first = S_FALSE; #else if (first == S_FALSE) return; i = 0; while (attr_tab[i].attr_o != NULL) { attr_tab[i].attr = attr_tab[i].attr_o; attr_tab[i].alen = strlen(attr_tab[i].attr_o); ++i; } first = S_FALSE; #endif /* create a sorted table for binary search */ attr_tab_srch = SH_ALLOC(i * sizeof(my_attr)); for (j=0; j= 32) { if (escp == 0) { if (!((*p == '\'') || (*p == '\"') || (*p == '\\'))) /* do nothing */; else if (*p == '\\') { #ifndef WITH_MYSQL if (p[1] == '\'') { *p = '\''; } #endif escp = 1; } else retv = S_FALSE; /* (*p == '\'' || *p == '\"') */ } else /* escp == 1 */ { escp = 0; } } else /* *p > 126 || *p < 32 */ { retv = S_FALSE; } ++p; } while (*p != '\0'); } if (escp == 0) return retv; else return S_FALSE; } /* this is not a real XML parser, but it copes with the XML format of * the log messages provided by sh_error_handle() */ static char * sh_database_parse (char * message, dbins * db_entry) { static int first = S_TRUE; char * p; char * q; char * z; dbins * new; int i; size_t j; my_attr * res; my_attr key; char key_str[64]; SL_ENTER(_("sh_database_parse")); if (!message || *message == '\0') SL_RETURN (NULL, _("sh_database_parse")); if (first == S_TRUE) { init_attr_table(); first = S_FALSE; } p = strchr (message, '<'); if (!p) SL_RETURN (NULL, _("sh_database_parse")); while ((*p != '\0') && (*p != '>')) { if (p[0] == 'l' && p[1] == 'o' && p[2] == 'g' && (p[3] == ' ' || p[3] == '>')) { p = &p[4]; goto parse; } else if (p[0] == '/' && p[1] == '>') SL_RETURN (&p[2], _("sh_database_parse")); else if (p[0] == '/' && p[1] == 'l' && p[2] == 'o' && p[3] == 'g' && p[4] == '>') SL_RETURN (&p[5], _("sh_database_parse")); ++p; } SL_RETURN(NULL, _("sh_database_parse")); parse: while (*p == ' ' || *p == '>') ++p; if (*p == '\0') SL_RETURN(NULL, _("sh_database_parse")); if (*p != '<' && *p != '/') goto par2; if (p[0] == '<' && p[1] == 'l' && p[2] == 'o' && p[3] == 'g') { /* * recursive call */ new = SH_ALLOC(sizeof(dbins)); init_db_entry(new); db_entry->next = new; p = sh_database_parse (p, new); } if (p[0] == '/' && p[1] == '>') SL_RETURN (&p[1], _("sh_database_parse")); if (p[0] == '<' && p[1] == '/' && p[2] == 'l' && p[3] == 'o' && p[4] == 'g' && p[5] == '>') SL_RETURN (&p[5], _("sh_database_parse")); par2: /* non-whitespace */ for (i=0; i < 64; ++i) { if (p[i] != '=') { key_str[i] = p[i]; } else { key_str[i] = '\0'; break; } } key_str[63] = '\0'; key.attr = &key_str[0]; res = bsearch(&key, attr_tab_srch, attr_tab_srch_siz, sizeof(my_attr), sh_database_comp_attr); if (res != NULL) { j = res->alen; /* strlen(attr_tab[i].attr); */ if (p[j] == '=' && p[j+1] == '"') { q = strchr(&p[j+2], '"'); if (q) { *q = '\0'; if (S_TRUE == is_escaped(&p[j+2])) { if (res->val == 1) (void) sl_strlcpy(db_entry->sev, &p[j+2], (size_t)res->size); else if (res->val == 2) { z = strchr(&p[j+2], 'T'); if (z) *z = ' '; (void) sl_strlcpy(db_entry->time, &p[j+2], 20); } else if (res->val == 3) (void) sl_strlcpy(db_entry->host, &p[j+2], (size_t) res->size); else if (res->val == 4) (void) sl_strlcpy(db_entry->msg, &p[j+2], (size_t) res->size); else if (res->size != 0) { (void) sl_strlcpy( (((char *)(db_entry))+ res->off), &p[j+2], (size_t) res->size); } else if (res->val >= START_SEC_LONGS && res->val <= END_SEC_LONGS) { db_entry->ulong_data[res->val-START_SEC_LONGS] = strtoul(&p[j+2], (char **) NULL, 0); } *q = '"'; p = q; ++p; goto parse; } else { /* S_FALSE == is_escaped(&p[j+2]) */ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Message not properly escaped"), _("sh_database_parse")); SL_RETURN(NULL, _("sh_database_parse")); } } else /* q == NULL */ { SL_RETURN(NULL, _("sh_database_parse")); } } } /* unknown attribute, skip */ while ((p != NULL) && (*p != '\0') && (*p != ' ')) ++p; goto parse; } static int enter_wrapper = 1; int set_enter_wrapper (const char * str) { return sh_util_flagval(str, &enter_wrapper); } /* recursively enter linked list of messages into database, last first * - last is client (if this is a client message received by client) */ long sh_database_insert_rec (dbins * curr, int depth, char * host) { unsigned long id = 0; SL_ENTER(_("sh_database_insert_rec")); if (curr->next) { /* prev = curr->next; sl_strlcpy(prev->host, curr->host, 64); id = sh_database_insert_rec (curr->next, (depth + 1)); */ ++depth; id = sh_database_insert_rec (curr->next, depth, curr->host); } if (host) sl_strlcpy(curr->host, host, 64); if (id != 0) /* this is a server wrapper */ { if (enter_wrapper != 0) { id = sh_database_entry (curr, id); } } else { /* * id = -1 is the client message; log_ref will be NULL */ if (depth > 0) /* this is a client message */ id = sh_database_entry (curr, -1); else /* this is a generic server message */ id = sh_database_entry (curr, 0); } SH_FREE(curr); SL_RETURN(id, _("sh_database_insert_rec")); } int sh_database_insert (char * message) { dbins * db_entry; SL_ENTER(_("sh_database_insert")); db_entry = SH_ALLOC(sizeof(dbins)); init_db_entry(db_entry); /* recursively parse the message into a linked list */ (void) sh_database_parse (message, db_entry); /* recursively enter the linked list into the database */ (void) sh_database_insert_rec (db_entry, 0, NULL); SL_RETURN(0, _("sh_database_insert")); } #endif samhain-4.1.4/src/mkhdr.c0000644000175000017500000001155312615253277012140 00000000000000#include "config.h" #ifdef HAVE_BROKEN_INCLUDES #define _ANSI_C_SOURCE #define _POSIX_SOURCE #endif #include extern void exit(int status); extern int fclose(FILE *stream); #ifndef TRUE #define TRUE (1 == 1) #endif #ifndef FALSE #define FALSE (1 != 1) #endif struct description_int { int int_size; char int_name[20]; }; struct description_int int_descrs[] = { #ifdef LONGLONG { sizeof(unsigned long long), "unsigned long long" }, #endif { sizeof(unsigned long), "unsigned long" }, { sizeof(unsigned int), "unsigned int" }, { sizeof(unsigned short), "unsigned short" }, { sizeof(unsigned char), "unsigned char" } }; int size_count = sizeof(int_descrs) / sizeof(struct description_int); struct trnc_data { long a, b, q, r; }; struct trnc_data trunc_tbl[] = { { 13, 4, 3, 1 }, { 13, -4, -3, 1 }, { -13, 4, -3, -1 }, { -13, -4, 3, -1 }, { 15, 4, 3, 3 }, { 15, -4, -3, 3 }, { -15, 4, -3, -3 }, { -15, -4, 3, -3 } }; int size_trunc_tbl = sizeof(trunc_tbl) / sizeof(struct trnc_data); struct rand_data { unsigned long dig_size, a1, c1, a2, c2; }; struct rand_data rand_tbl[] = { { 8, 197, 11, 37, 37 }, { 16, 805, 345, 925, 767 }, { 18, 13405, 4801, 20325, 19777 }, { 32, 13405, 4801, 20325, 19777 } }; int size_rand_tbl = sizeof(rand_tbl) / sizeof(struct rand_data); int digit_bits; int div_trunc_p(void) { int i; for (i = 0; i < size_trunc_tbl; i++) { if (trunc_tbl[i].a / trunc_tbl[i].b != trunc_tbl[i].q) { printf("%ld / %ld = %ld, should have been %ld\n", trunc_tbl[i].a, trunc_tbl[i].b, trunc_tbl[i].a / trunc_tbl[i].b, trunc_tbl[i].q); printf("when division truncates towards zero.\n"); return FALSE; } if (trunc_tbl[i].a % trunc_tbl[i].b != trunc_tbl[i].r) { printf("%ld %% %ld = %ld, should have been %ld\n", trunc_tbl[i].a, trunc_tbl[i].b, trunc_tbl[i].a % trunc_tbl[i].b, trunc_tbl[i].r); printf("when division truncates towards zero.\n"); printf("Here a != q*b + r. Very strange!\n"); return FALSE; } } return TRUE; } int charsize(void) { int i = 0; unsigned char ch = 1; unsigned char oldch = 0; while (ch > oldch) { oldch = ch; ch <<= 1; i++; } return i; } void RandDefsOut(FILE *fpOut, int dig_size) { int i = 0; while ((i < size_rand_tbl) && (dig_size != (int)rand_tbl[i].dig_size)) { i++; } if (i == size_rand_tbl) { if (dig_size < (int) rand_tbl[0].dig_size) { printf("Digit size %d too small.\n", dig_size); exit(10); } while ((int) rand_tbl[--i].dig_size > dig_size) { /* Count down `i' */ } } fprintf(fpOut, "\n#define BIG_RAND_A1 %ld\n", rand_tbl[i].a1); fprintf(fpOut, "#define BIG_RAND_C1 %ld\n", rand_tbl[i].c1); fprintf(fpOut, "#define BIG_RAND_A2 %ld\n", rand_tbl[i].a2); fprintf(fpOut, "#define BIG_RAND_C2 %ld\n", rand_tbl[i].c2); } int main(void) { int i, j = 0, ints_found = FALSE, char_bits; FILE *fpOut; if (!div_trunc_p()) { printf("Can't do division on this machine!\n"); exit(10); } if ((fpOut = fopen("internal.h", "w")) == NULL) { printf("Could not create \"internal.h\".\n"); exit(10); } fprintf(fpOut, "#ifndef _BIGNUM_INTERNAL_H_\n"); fprintf(fpOut, "#define _BIGNUM_INTERNAL_H_\n\n"); char_bits = charsize(); for (i = 0; (i < size_count - 1) && !ints_found; i++) { for (j = i + 1; (j < size_count) && !ints_found; j++) { if (int_descrs[i].int_size >= 2 * int_descrs[j].int_size) { fprintf(fpOut, "#define BIGNUM_DIGIT %s\n", int_descrs[j].int_name); fprintf(fpOut, "#define BIGNUM_TWO_DIGITS %s\n\n", int_descrs[i].int_name); ints_found = TRUE; } } } if (!ints_found) { fprintf(stderr, "Strange, no integer type was two times bigger "); fprintf(stderr, "than another integer type.\n"); fprintf(stderr, "Can't create header file.\nExiting.\n"); exit(10); } if (i > 0) i--; if (j > 0) j--; digit_bits = char_bits * int_descrs[j].int_size; fprintf(fpOut, "#define BIG_CHARBITS %d\n", char_bits); fprintf(fpOut, "#define BIGNUM_DIGIT_BITS %d\n", digit_bits); fprintf(fpOut, "#define BIGNUM_TWO_DIGITS_BITS %d\n\n", char_bits * int_descrs[i].int_size); fprintf(fpOut, "struct big_struct\n{\n int sign;\n"); fprintf(fpOut, " unsigned long dgs_alloc;\n"); fprintf(fpOut, " unsigned long dgs_used;\n"); fprintf(fpOut, " BIGNUM_DIGIT *dp;\n};\n"); RandDefsOut(fpOut, char_bits * int_descrs[j].int_size); if (sizeof(long) == sizeof(int)) { fprintf(fpOut, "\n#define MEMCPY_LONG_COUNTER\n"); } #ifdef BIG_SHORT_NAMES fprintf(fpOut, "\n#define BIG_SHORT_NAMES\n"); #endif fprintf(fpOut, "\n#endif\n"); fclose(fpOut); exit(0); return 0; /* Keep gcc from complaining */ } samhain-4.1.4/src/sh_dbCreate.c0000664000175000017500000001245412615253277013241 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include "samhain.h" #include "sh_utils.h" #include "sh_hash.h" #include "sh_files.h" #include "sh_dbIO.h" #include "sh_dbIO_int.h" #include "sh_pthread.h" #include "sh_guid.h" #undef FIL__ #define FIL__ _("sh_dbCreate.c") #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) static int dbCreate_writeout() { char uuid[SH_UUID_BUF]; char * path; int retval; if (sh.outpath == NULL || sh.outpath[0] == '\0') { sh_uuid_generate_random(uuid, sizeof(uuid)); path = sh_util_strconcat(_("file."), sh.host.name, ".", uuid, NULL); } else path = sh_util_strdup(sh.outpath); retval = sh_dbIO_writeout_to_path(path); SH_FREE(path); return retval; } static void dbCreate_run_filecheck(unsigned long add_mask, char * str) { int status; int reported = 0; unsigned long check_flags = (MASK_READONLY_ | MODI_INIT | add_mask); char * dir_name = sh_util_dirname(str); char * file_name = sh_util_basename(str); status = sh_files_filecheck (SH_LEVEL_READONLY, check_flags, dir_name, file_name, &reported, 0); if (status == SH_FILE_UNKNOWN) { sh_hash_insert_null(str); } return; } static int dbCreate_filecheck(char * str) { unsigned long add_mask = 0; if (*str == '+') { add_mask = MODI_TXT; ++str; while (isspace((int)*str)) ++str; } if (*str != '/') { char * tmp = sh_util_safe_name (str); sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_SUBGPATH, _("Not an absolute path"), _("dbCreate_filecheck"), tmp); SH_FREE(tmp); return -1; } dbCreate_run_filecheck(add_mask, str); return 0; } char * rtrim(char * str) { size_t len; if (!str) return str; len = strlen(str); while (len > 0) { --len; if (str[len] == '\n' || str[len] == '\r') str[len] = '\0'; else break; } return str; } static int dbCreate_loop(FILE * fd) { int status, retval = 0; size_t linesize = MAX_PATH_STORE+2; char * line = SH_ALLOC(linesize); do { status = sh_dbIO_getline(fd, line, linesize); if (status > 0) { char * str = rtrim(line); while (isspace((int)*str)) ++str; if (*str != '#') { int fstatus = -1; size_t len = 0; char * p = sh_files_parse_input(str, &len); if (p) { fstatus = dbCreate_filecheck(p); SH_FREE(p); } if (fstatus != 0) retval = -1; } } } while (status != -1); SH_FREE(line); return retval; } static FILE * dbCreate_open (const char * path) { FILE * fd = fopen(path, "r"); if (!fd) { int error = errno; char * tmp = sh_util_safe_name (path); sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_SUBGPATH, _("Cannot open file for read"), _("dbCreate_open"), tmp); SH_FREE(tmp); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } return fd; } static void dbCreate_setup() { sh_hash_set_initialized(); sh.flag.isdaemon = S_FALSE; sh.flag.loop = S_FALSE; sh.flag.update = S_FALSE; sh.flag.checkSum = SH_CHECK_CHECK; sh.statistics.files_report = 0; ShDFLevel[SH_ERR_T_FILE] = SH_ERR_SEVERE; ShDFLevel[SH_ERR_T_RO] = SH_ERR_SEVERE; ShDFLevel[SH_ERR_T_NAME] = SH_ERR_SEVERE; sh_error_only_stderr (S_TRUE); sh_error_setprint(_("none")); return; } int sh_dbCreate (const char * path) { FILE * fd; /* Initialize application status */ dbCreate_setup(); /* Open file list */ fd = dbCreate_open(path); /* Load the database */ sh_hash_init_and_checksum(); /* Loop over file list to check files. */ dbCreate_loop(fd); /* Close file list */ fclose(fd); /* Write out database */ if (0 != dbCreate_writeout()) aud_exit(FIL__, __LINE__, EXIT_FAILURE); /* Exit on success. */ aud_exit(FIL__, __LINE__, EXIT_SUCCESS); return 0; } #endif samhain-4.1.4/src/sh_log_correlate.c0000644000175000017500000001723512615253277014351 00000000000000#include "config_xor.h" #ifdef USE_LOGFILE_MONITOR #undef FIL__ #define FIL__ _("sh_log_correlate.c") #include #include /* Debian/Ubuntu: libpcre3-dev */ #ifdef HAVE_PCRE_PCRE_H #include #else #include #endif #ifndef PCRE_NO_AUTO_CAPTURE #define PCRE_NO_AUTO_CAPTURE 0 #endif #include "samhain.h" #include "sh_pthread.h" #include "sh_utils.h" #include "sh_string.h" #include "sh_log_check.h" #include "sh_log_evalrule.h" extern int flag_err_debug; /*-------------------------------------------------------------- * * Event correlation * *--------------------------------------------------------------*/ /* For each even to be correlated, we keep a label in a list. We * then build a string from the (time-sorted) list of labels, and * match this string against a regular expression. */ /* -- The list of labels kept in memory ----------------------- */ struct sh_keep { sh_string * label; /* label of keep rule */ unsigned long delay; /* valid delay */ time_t last; /* seen at */ struct sh_keep * next; }; static struct sh_keep * keeplist = NULL; static struct sh_keep * keeplast = NULL; static unsigned long keepcount = 0; static void sh_keep_free(void * item) { struct sh_keep * keep = (struct sh_keep *) item; if (!keep) return; sh_string_destroy(&(keep->label)); SH_FREE(keep); } void sh_keep_destroy() { struct sh_keep * keep; while (keeplist) { keep = keeplist; keeplist = keep->next; sh_keep_free(keep); --keepcount; } keeplist = NULL; keeplast = NULL; keepcount = 0; } int sh_keep_add(sh_string * label, unsigned long delay, time_t last) { struct sh_keep * keep = SH_ALLOC(sizeof(struct sh_keep)); keep->label = sh_string_copy(label); keep->delay = delay; keep->last = last; keep->next = NULL; if (keeplast && keeplist) { keeplast->next = keep; keeplast = keep; } else { keeplist = keep; keeplast = keeplist; } ++keepcount; return 0; } int sh_keep_comp(const void * a, const void * b) { return ( (int)(((const struct sh_keep *)a)->last) - (int)(((const struct sh_keep *)b)->last) ); } /* -- Sort the kept labels and build a string ----------------- */ static sh_string * sh_keep_eval() { unsigned long count = 0; sh_string * res = NULL; time_t now = time(NULL); struct sh_keep * keep = keeplist; struct sh_keep * prev = keeplist; struct sh_keep * arr; if (keepcount > 0) { arr = SH_ALLOC (keepcount * sizeof(struct sh_keep)); while (count < keepcount && keep) { if ((now >= keep->last) && ((unsigned long)(now - keep->last) <= keep->delay)) { memcpy(&(arr[count]), keep, sizeof(struct sh_keep)); ++count; prev = keep; keep = keep->next; } else /* Too old or in future, delete it */ { if (keep != keeplist) { prev->next = keep->next; sh_keep_free(keep); keep = prev->next; --keepcount; } else /* list head */ { keeplist = keep->next; prev = keeplist; sh_keep_free(keep); keep = keeplist; --keepcount; } } } if (count > 0) { unsigned long i; qsort(arr, count, sizeof(struct sh_keep), sh_keep_comp); res = sh_string_copy(arr[0].label); for (i = 1; i < count; ++i) res = sh_string_add(res, arr[i].label); } SH_FREE(arr); } return res; } /* -- Match the string against correlation rules -------------- */ struct sh_mkeep { sh_string * label; /* label of match rule */ pcre * rule; /* compiled regex for rule */ time_t reported; /* last reported */ struct sh_qeval * queue; /* assigned queue */ struct sh_mkeep * next; }; struct sh_mkeep * mkeep_list = NULL; unsigned long mkeep_deadtime = 60; int sh_keep_deadtime (const char * str) { unsigned long value; char * foo; value = (size_t) strtoul(str, &foo, 0); if (*foo == '\0') { mkeep_deadtime = value; return 0; } return -1; } int sh_keep_match_add(const char * str, const char * queue, const char * pattern) { unsigned int nfields = 1; /* seconds:label */ size_t lengths[1]; char * new = sh_util_strdup(str); char ** splits = split_array_braced(new, _("CORRELATE"), &nfields, lengths); if (nfields == 1 && lengths[0] > 0) { struct sh_mkeep * mkeep = SH_ALLOC(sizeof(struct sh_mkeep)); const char * error; int erroffset; struct sh_qeval * rqueue = NULL; mkeep->rule = pcre_compile(pattern, PCRE_NO_AUTO_CAPTURE, &error, &erroffset, NULL); if (!(mkeep->rule)) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Bad regex: ")); sh_string_add_from_char(msg, pattern); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_keep_match_add")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(splits); SH_FREE(mkeep); SH_FREE(new); return -1; } if (0 != strcmp(queue, _("trash"))) { rqueue = sh_log_find_queue(queue); if (!rqueue) { pcre_free(mkeep->rule); SH_FREE(splits); SH_FREE(mkeep); SH_FREE(new); return -1; } } mkeep->queue = rqueue; mkeep->label = sh_string_new_from_lchar(splits[0], strlen(splits[0])); mkeep->reported = 0; mkeep->next = mkeep_list; mkeep_list = mkeep; } SH_FREE(new); return 0; } void sh_keep_match_del() { struct sh_mkeep * mkeep = mkeep_list; while (mkeep) { mkeep_list = mkeep->next; sh_string_destroy(&(mkeep->label)); pcre_free(mkeep->rule); mkeep = mkeep_list; } mkeep_list = NULL; } static struct sh_mkeep ** dummy_mkeep; void sh_keep_match() { if (mkeep_list) { sh_string * res = sh_keep_eval(); if (res) { struct sh_mkeep * mkeep = mkeep_list; dummy_mkeep = &mkeep; while (mkeep) { /* Use pcre_dfa_exec() to obtain number of matches. Needs ovector * array, otherwise number of matches is not returned. */ #if defined(HAVE_PCRE_DFA_EXEC) int ovector[SH_MINIBUF]; int wspace[SH_MINIBUF]; #endif #if defined(HAVE_PCRE_DFA_EXEC) int val = pcre_dfa_exec(mkeep->rule, NULL, sh_string_str(res), (int)sh_string_len(res), 0, /* start at offset 0 in the subject */ 0, ovector, SH_MINIBUF, wspace, SH_MINIBUF); #else int val = pcre_exec(mkeep->rule, NULL, sh_string_str(res), (int)sh_string_len(res), 0, /* start at offset 0 in the subject */ 0, NULL, 0); val = (val >= 0) ? 1 : val; #endif if (val >= 0) { sh_string * alias; time_t now = time(NULL); if ((mkeep->reported < now) && (mkeep_deadtime < (unsigned int)(now - mkeep->reported))) { mkeep->reported = now; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle (mkeep->queue->severity, FIL__, __LINE__, 0, MSG_LOGMON_COR, sh_string_str(mkeep->label), val); alias = mkeep->queue->alias; if (alias) { sh_error_mail (sh_string_str(alias), mkeep->queue->severity, FIL__, __LINE__, 0, MSG_LOGMON_COR, sh_string_str(mkeep->label), val); } SH_MUTEX_UNLOCK(mutex_thread_nolog); } } mkeep = mkeep->next; } sh_string_destroy(&res); } } return; } #endif samhain-4.1.4/src/sh_html.c0000644000175000017500000003220212615253277012463 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #include #ifdef SH_WITH_SERVER #include "samhain.h" #include "sh_xfer.h" #include "sh_error.h" #include "sh_unix.h" #include "sh_utils.h" #include "sh_html.h" #undef FIL__ #define FIL__ _("sh_html.c") s_stat server_status; static char * replace_stat (char * line) { st_format rep_serv_tab[] = { { 'T', S_FMT_TIME, 0, 0, NULL}, { 'S', S_FMT_TIME, 0, 0, NULL}, { 'L', S_FMT_TIME, 0, 0, NULL}, { 'O', S_FMT_ULONG, 0, 0, NULL}, { 'A', S_FMT_ULONG, 0, 0, NULL}, { 'M', S_FMT_ULONG, 0, 0, NULL}, {'\0', S_FMT_ULONG, 0, 0, NULL}, }; rep_serv_tab[0].data_ulong = (unsigned long) time(NULL); rep_serv_tab[1].data_ulong = server_status.start; rep_serv_tab[2].data_ulong = server_status.last; rep_serv_tab[3].data_ulong = server_status.conn_open; rep_serv_tab[4].data_ulong = server_status.conn_total; rep_serv_tab[5].data_ulong = server_status.conn_max; return (sh_util_formatted(line, rep_serv_tab)); } static int sh_html_head(SL_TICKET ticket) { long status = SL_ENONE; SL_TICKET fd = (-1); char line[512]; char endhead[512]; char outline[1024]; char ts1[81]; char ts2[81]; time_t now; struct tm * time_ptr; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) struct tm time_tm; #endif char * formatted; char * qstr; char * p; SL_ENTER(_("sh_html_head")); p = sh_util_strconcat(DEFAULT_DATAROOT, _("/head.html"), NULL); if (p) { fd = sl_open_read (FIL__, __LINE__, p, SL_YESPRIV); SH_FREE(p); } if (!SL_ISERROR(fd)) { while (!SL_ISERROR(status) && sh_unix_getline (fd, line, sizeof(line)) > 0) { formatted = replace_stat (line); if (formatted) { status = sl_write_line (ticket, formatted, sl_strlen(formatted)); SH_FREE(formatted); } } sl_close(fd); } else { qstr = sh_util_basename(DEFAULT_HTML_FILE); if (qstr != NULL) { sl_snprintf(endhead, 511, _(""), 34, 34, 34, qstr, 34); SH_FREE(qstr); } else { sl_snprintf(endhead, 511, _("")); } status = sl_write_line (ticket, _("Report"), sizeof("Report")-1); if (!SL_ISERROR(status)) status = sl_write_line (ticket, endhead, strlen(endhead)); if (!SL_ISERROR(status)) status = sl_write_line (ticket, _("

Samhain Server Report

"), sizeof("

Samhain Server Report

")-1); if (!SL_ISERROR(status)) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) time_ptr = localtime_r (&(server_status.start), &time_tm); #else time_ptr = localtime (&(server_status.start)); #endif if (time_ptr != NULL) strftime (ts1, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr); else sl_strlcpy(ts1, _("01-01-1970 00:00:00"), sizeof(ts1)); now = time(NULL); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) time_ptr = localtime_r (&now, &time_tm); #else time_ptr = localtime (&now); #endif if (time_ptr != NULL) strftime (ts2, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr); else sl_strlcpy(ts2, _("01-01-1970 00:00:00"), sizeof(ts2)); sl_snprintf(outline, 1023, _("

Time:
Now: %s
Start: %s

"), ts2, ts1); status = sl_write_line (ticket, outline, sl_strlen(outline)); } if (!SL_ISERROR(status)) { sl_snprintf(outline, 1023, _("

Connections (max. %d simultaneous):"\ "
Now: %d
Total: %ld

"), server_status.conn_max, server_status.conn_open, server_status.conn_total); status = sl_write_line (ticket, outline, sl_strlen(outline)); if (server_status.last > (time_t) 0) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) time_ptr = localtime_r (&(server_status.last), &time_tm); #else time_ptr = localtime (&(server_status.last)); #endif if (time_ptr != NULL) strftime (ts1, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr); else sl_strlcpy(ts1, _("01-01-1970 00:00:00"), sizeof(ts1)); sl_snprintf(outline, 1023, _("

Last connection at %s

"), ts1); status = sl_write_line (ticket, outline, sl_strlen(outline)); } } if (!SL_ISERROR(status)) status = sl_write_line (ticket, _("
"), sizeof("
")-1); } if (SL_ISERROR(status)) SL_RETURN((-1), _("sh_html_head")); SL_RETURN((0), _("sh_html_head")); } static int sh_html_foot(SL_TICKET ticket) { long status = SL_ENONE; SL_TICKET fd = (-1); char line[512]; char * p; SL_ENTER(_("sh_html_foot")); p = sh_util_strconcat(DEFAULT_DATAROOT, _("/foot.html"), NULL); if (p) { fd = sl_open_read (FIL__, __LINE__, p, SL_YESPRIV); SH_FREE(p); } if (!SL_ISERROR(fd)) { while (!SL_ISERROR(status) && sh_unix_getline (fd, line, sizeof(line)) > 0) { status = sl_write_line (ticket, line, sl_strlen(line)); } sl_close(fd); } else { status = sl_write_line (ticket, _("
"), sizeof("")-1); } if (SL_ISERROR(status)) SL_RETURN((-1), _("sh_html_foot")); SL_RETURN((0), _("sh_html_foot")); } static char * replace_tab (const char * line, char * host, char * status, char * timestamp) { st_format rep_serv_tab[] = { { 'H', S_FMT_STRING, 0, 0, NULL}, { 'S', S_FMT_STRING, 0, 0, NULL}, { 'T', S_FMT_STRING, 0, 0, NULL}, {'\0', S_FMT_ULONG, 0, 0, NULL}, }; char * p; SL_ENTER(_("replace_tab")); rep_serv_tab[0].data_str = host; rep_serv_tab[1].data_str = status; rep_serv_tab[2].data_str = timestamp; p = sh_util_formatted(line, rep_serv_tab); SL_RETURN(p, _("replace_tab")); } static char * entry_orig = NULL; static size_t entry_size = 0; static int sh_html_get_entry (void) { long retval = SL_ENONE; SL_TICKET fd = (-1); char line[512]; size_t line_size; size_t add_size = 0; char * p; SL_ENTER(_("sh_html_get_entry")); p = sh_util_strconcat(DEFAULT_DATAROOT, _("/entry.html"), NULL); entry_size = 0; if (entry_orig != NULL) { free (entry_orig); entry_orig = NULL; entry_size = 0; } if (p) { fd = sl_open_read (FIL__, __LINE__, p, SL_YESPRIV); SH_FREE(p); } if (!SL_ISERROR(fd)) { while (!SL_ISERROR(retval) && sh_unix_getline (fd, line, sizeof(line)) > 0) { line_size = sl_strlen(line); add_size = 0; if (entry_orig != NULL) { char * ptr = realloc(entry_orig, /* free() ok */ entry_size + line_size + 1); if (ptr) { entry_orig = ptr; add_size = line_size; } else { { free(entry_orig); entry_orig = NULL; } } } else { entry_orig = calloc(1, line_size + 1); /* free() ok */ if (entry_orig) { entry_orig[0] = '\0'; add_size = line_size; } } if (!entry_orig) { entry_size = 0; /* add_size = 0; *//* never read */ SL_RETURN( 0, _("sh_html_get_entry")); } sl_strlcat(&entry_orig[entry_size], line, line_size + 1); entry_size += add_size; SH_VALIDATE_EQ(entry_orig[entry_size], '\0'); } sl_close(fd); } SL_RETURN( entry_size, _("sh_html_get_entry")); } static int sh_html_entry (SL_TICKET ticket, char * host, char * status, char * timestamp, int flag) { char outline[1024]; long retval = SL_ENONE; char * formatted; SL_ENTER(_("sh_html_entry")); if (entry_size > 0 && entry_orig != NULL) { formatted = replace_tab(entry_orig, host, status, timestamp); if (formatted) { retval = sl_write_line (ticket, formatted, sl_strlen(formatted)); SH_FREE(formatted); } } else { sl_snprintf(outline, 1023, _("%s%s%s"), host, status, timestamp); retval = sl_write_line (ticket, outline, sl_strlen(outline)); } /* write a status line */ if ((flag == 1) && (!SL_ISERROR(retval))) { sl_snprintf(outline, 1023, _(""), host, status, timestamp); retval = sl_write_line (ticket, outline, sl_strlen(outline)); } if (SL_ISERROR(retval)) SL_RETURN((-1), _("sh_html_entry")); SL_RETURN((0), _("sh_html_entry")); } typedef struct _sort_arr { char msg[TIM_MAX]; char tim[TIM_MAX]; } sort_arr; static sort_arr sort_stat[CLT_MAX]; static int comp_arr (const void * ao, const void * bo) { const sort_arr * a; const sort_arr * b; if (ao == NULL && bo == NULL) return 0; else if (ao == NULL && bo != NULL) return (-1); else if (ao != NULL && bo == NULL) return (1); a = (const sort_arr *) ao; b = (const sort_arr *) bo; return ((-1) * sl_strcmp(a->tim, b->tim)); } static int sh_html_print_one (SL_TICKET ticket, client_t * top) { int status; int clt_status; unsigned int i, n; SL_ENTER(_("sh_html_print_one")); if (top == NULL) SL_RETURN((0), _("sh_html_print_one")); clt_status = top->status_now; status = sh_html_entry (ticket, top->hostname, _(clt_stat[clt_status]), top->timestamp[clt_status], 1); n = 0; if (clt_status != CLT_INACTIVE) { for (i = 1; i < CLT_MAX; ++i) { if (top->status_arr[i] != CLT_INACTIVE) { clt_status = top->status_arr[i]; sl_strlcpy(sort_stat[n].msg, _(clt_stat[clt_status]), TIM_MAX); sl_strlcpy(sort_stat[n].tim, top->timestamp[clt_status],TIM_MAX); ++n; } } } if (n > 0) { qsort(&(sort_stat[0]), n, sizeof(sort_arr), comp_arr); for (i = 1; i < n; ++i) { status = sh_html_entry (ticket, " ", sort_stat[i].msg, sort_stat[i].tim, 0); } } if (SL_ISERROR(status)) SL_RETURN((-1), _("sh_html_print_one")); SL_RETURN((0), _("sh_html_print_one")); } #include "zAVLTree.h" int sh_html_write(void * inptr) { long fd; zAVLCursor avlcursor; client_t * item; zAVLTree * top = (zAVLTree *) inptr; SL_ENTER(_("sh_html_write")); if (0 != (fd = tf_trust_check (DEFAULT_HTML_FILE, SL_YESPRIV))) { sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_TRUST, (long) sh.effective.uid, DEFAULT_HTML_FILE); SL_RETURN((-1), _("sh_html_write")); } fd = sl_open_write_trunc (FIL__, __LINE__, DEFAULT_HTML_FILE, SL_YESPRIV); if (SL_ISERROR(fd)) { sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS, (long) sh.effective.uid, DEFAULT_HTML_FILE); SL_RETURN((-1), _("sh_html_write")); } sh_html_get_entry(); sh_html_head(fd); for (item = (client_t *) zAVLFirst(&avlcursor, top); item; item = (client_t *) zAVLNext(&avlcursor)) sh_html_print_one (fd, item); sh_html_foot(fd); sl_close(fd); SL_RETURN((0), _("sh_html_write")); } int sh_html_zero() { long fd; SL_ENTER(_("sh_html_zero")); if (0 != (fd = tf_trust_check (DEFAULT_HTML_FILE, SL_YESPRIV))) { SL_RETURN((-1), _("sh_html_zero")); } fd = sl_open_write_trunc (FIL__, __LINE__, DEFAULT_HTML_FILE, SL_YESPRIV); if (SL_ISERROR(fd)) { SL_RETURN((-1), _("sh_html_zero")); } sh_html_head(fd); sh_html_foot(fd); sl_close(fd); SL_RETURN((0), _("sh_html_zero")); } /* SH_WITH_SERVER */ #endif samhain-4.1.4/src/cutest_sh_utils.c0000644000175000017500000003464012615253277014256 00000000000000 #include "config_xor.h" #include #include "CuTest.h" #include "samhain.h" #include "sh_utils.h" void Test_sl_strlcpy (CuTest *tc) { int ret; char out[] = "aaaaaa"; char in[] = "bbb"; ret = sl_strlcpy (NULL, NULL, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcpy (NULL, in, 0); CuAssertIntEquals(tc, ret, SL_ENULL); ret = sl_strlcpy (out, NULL, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcpy (out, in, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcpy (out, NULL, 7); CuAssertIntEquals(tc, ret, SL_ENONE); CuAssertStrEquals(tc, "", out); out[0] = 'a'; ret = sl_strlcpy (out, in, 4); CuAssertIntEquals(tc, ret, SL_ENONE); CuAssertStrEquals(tc, "bbb", out); CuAssertStrEquals(tc, "aa", &out[4]); return; } void Test_sl_strlcat (CuTest *tc) { int ret; char out[16] = "aaaaaa"; char in[16] = "bbb"; ret = sl_strlcat (NULL, NULL, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcat (NULL, in, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcat (out, NULL, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcat (out, in, 0); CuAssertIntEquals(tc, ret, SL_ENONE); ret = sl_strlcat (out, NULL, sizeof(out)); CuAssertIntEquals(tc, ret, SL_ENONE); CuAssertStrEquals(tc, "aaaaaa", out); ret = sl_strlcat (out, in, 7); CuAssertIntEquals(tc, ret, SL_ETRUNC); CuAssertStrEquals(tc, "aaaaaa", out); ret = sl_strlcat (out, in, 8); CuAssertIntEquals(tc, ret, SL_ETRUNC); CuAssertStrEquals(tc, "aaaaaab", out); ret = sl_strlcat (out, in, sizeof(out)); CuAssertIntEquals(tc, ret, SL_ENONE); CuAssertStrEquals(tc, "aaaaaabbbb", out); CuAssertStrEquals(tc, "bbb", in); return; } void Test_sh_util_acl_compact (CuTest *tc) { char * ret = 0; char inp1[] = "user::r--\nuser:lisa:rwx\t\t#effective: r--\ngroup::r--\ngroup:toolies:rw- #effective: r--\nmask::r--\nother::r--\n"; char inp2[] = "use\n\nuser:lisa:rwx\t\t#effective: r--\ngroup::r--\ngroup:toolies:rw- #effective: r--\nmask::r--\nother::r--\n"; char inp3[] = "user:\177\145\177\122:r--\nuser:lisa:rwx\t\t#effective: r--\ngroup::r--\ngroup:toolies:rw- #effective: r--\nmask::r--\nother::r--\n"; ret = sh_util_acl_compact (inp1, strlen(inp1)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, "u::r--,u:lisa:rwx,g::r--,g:toolies:rw-,m::r--,o::r--", ret); ret = sh_util_acl_compact (inp2, strlen(inp2)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, "use,u:lisa:rwx,g::r--,g:toolies:rw-,m::r--,o::r--", ret); ret = sh_util_acl_compact (inp3, strlen(inp3)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, "u:eR:r--,u:lisa:rwx,g::r--,g:toolies:rw-,m::r--,o::r--", ret); return; } void Test_sh_util_strdup_ok (CuTest *tc) { char * ret = 0; char inp[] = "foobar"; ret = sh_util_strdup(inp); CuAssertPtrNotNull(tc, ret); CuAssert(tc, "expected inp != ret, but inp == ret", (inp != ret)); CuAssertStrEquals(tc, "foobar", ret); return; } void Test_sh_util_strconcat_ok (CuTest *tc) { char * ret = 0; ret = sh_util_strconcat("foo", NULL); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, "foo", ret); ret = sh_util_strconcat("foo", "bar", NULL); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, "foobar", ret); ret = sh_util_strconcat("/", "foo", "/", "bar", NULL); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, "/foo/bar", ret); return; } void Test_sh_util_base64_enc_ok (CuTest *tc) { unsigned char out[64]; unsigned char ou2[64]; int ret; unsigned char inp0[64] = ""; unsigned char inp1[64] = "A"; unsigned char inp2[64] = "AB"; unsigned char inp3[64] = "ABC"; unsigned char inp4[64] = "ABCD"; ret = sh_util_base64_enc (out, inp0, strlen((char*)inp0)); CuAssertIntEquals(tc, 0, ret); CuAssertStrEquals(tc, "", (char*)out); ret = sh_util_base64_dec (ou2, out, strlen((char*)out)); CuAssertIntEquals(tc, ret, 0); CuAssertStrEquals(tc, (char*)inp0, (char*)ou2); ret = sh_util_base64_enc (out, inp1, strlen((char*)inp1)); CuAssertIntEquals(tc, ret, 4); CuAssertStrEquals(tc, "QQ??", (char*)out); ret = sh_util_base64_dec (ou2, out, strlen((char*)out)); CuAssertStrEquals(tc, (char*)inp1, (char*)ou2); CuAssertIntEquals(tc, 1, ret); ret = sh_util_base64_enc (out, inp2, strlen((char*)inp2)); CuAssertIntEquals(tc, ret, 4); CuAssertStrEquals(tc, "QUI?", (char*)out); ret = sh_util_base64_dec (ou2, out, strlen((char*)out)); CuAssertStrEquals(tc, (char*)inp2, (char*)ou2); CuAssertIntEquals(tc, 2, ret); ret = sh_util_base64_enc (out, inp3, strlen((char*)inp3)); CuAssertIntEquals(tc, ret, 4); CuAssertStrEquals(tc, "QUJD", (char*)out); ret = sh_util_base64_dec (ou2, out, strlen((char*)out)); CuAssertStrEquals(tc, (char*)inp3, (char*)ou2); CuAssertIntEquals(tc, 3, ret); ret = sh_util_base64_enc (out, inp4, strlen((char*)inp4)); CuAssertIntEquals(tc, ret, 8); CuAssertStrEquals(tc, "QUJDRA??", (char*)out); ret = sh_util_base64_dec (ou2, out, strlen((char*)out)); CuAssertStrEquals(tc, (char*)inp4, (char*)ou2); CuAssertIntEquals(tc, 4, ret); return; } void Test_sh_util_dirname_ok (CuTest *tc) { char * ret = 0; char input0[] = "/foo/bar"; char res0[] = "/foo"; char input1[] = "/foo/bar/"; char res1[] = "/foo"; char input2[] = "/foo"; char res2[] = "/"; char input3[] = "/"; char res3[] = "/"; char input4[] = "///foo//bar"; char res4[] = "///foo"; char input5[] = "//foo///bar///"; char res5[] = "//foo"; char input6[] = "///"; char res6[] = "///"; char input7[] = "//f///b///"; char res7[] = "//f"; char input8[] = "/f/b/"; char res8[] = "/f"; char input9[] = "/e/b"; char res9[] = "/e"; ret = sh_util_dirname(input0); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res0, ret); ret = sh_util_dirname(input1); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res1, ret); ret = sh_util_dirname(input2); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res2, ret); ret = sh_util_dirname(input3); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res3, ret); ret = sh_util_dirname(input4); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res4, ret); ret = sh_util_dirname(input5); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res5, ret); ret = sh_util_dirname(input6); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res6, ret); ret = sh_util_dirname(input7); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res7, ret); ret = sh_util_dirname(input8); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res8, ret); ret = sh_util_dirname(input9); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res9, ret); return; } void Test_sh_util_basename_ok (CuTest *tc) { char * ret = 0; char input0[] = "/foo/bar"; char res0[] = "bar"; char input1[] = "/foo/"; char res1[] = "foo"; char input2[] = "/foo"; char res2[] = "foo"; char input3[] = "/"; char res3[] = "/"; char input4[] = "/foo/bar/"; char res4[] = "bar"; char input5[] = "/foo///bar///"; char res5[] = "bar"; char input6[] = "//foo"; char res6[] = "foo"; ret = sh_util_basename(input0); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res0, ret); ret = sh_util_basename(input1); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res1, ret); ret = sh_util_basename(input2); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res2, ret); ret = sh_util_basename(input3); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res3, ret); ret = sh_util_basename(input4); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res4, ret); ret = sh_util_basename(input5); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res5, ret); ret = sh_util_basename(input6); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, res6, ret); return; } void Test_sh_util_utf8_ok (CuTest *tc) { int ret = 0; #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) unsigned char seq[16]; unsigned char input[16] = "foobar"; seq[0] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xd7; seq[1] = 0x90; seq[2] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xed; seq[1] = 0x9f; seq[2] = 0xbf; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xee; seq[1] = 0x80; seq[2] = 0x80; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xef; seq[1] = 0xbf; seq[2] = 0xbd; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xf4; seq[1] = 0x8f; seq[2] = 0xbf; seq[3] = 0xbf; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xf4; seq[1] = 0x90; seq[2] = 0x80; seq[3] = 0x80; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); seq[0] = 0xd7; seq[1] = 0x90; seq[2] = 0xd7; seq[3] = 0x90; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_TRUE); /* cont. char */ seq[0] = 0x80; seq[1] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xbf; seq[1] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); /* overlong */ seq[0] = 0xc0; seq[1] = 0xaf; seq[2] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xe0; seq[1] = 0x8f; seq[2] = 0xaf; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xf0; seq[1] = 0x80; seq[2] = 0x80; seq[3] = 0xaf; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); /* overlong */ seq[0] = 0xc1; seq[1] = 0xbf; seq[2] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xe0; seq[1] = 0x9f; seq[2] = 0xbf; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xf0; seq[1] = 0x8f; seq[2] = 0xbf; seq[3] = 0xbf; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); /* overlong */ seq[0] = 0xc0; seq[1] = 0x80; seq[2] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xe0; seq[1] = 0x80; seq[2] = 0x80; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xf0; seq[1] = 0x80; seq[2] = 0x80; seq[3] = 0x80; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); /* cont missing */ seq[0] = 0xd7; seq[1] = 0x20; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xee; seq[1] = 0x80; seq[2] = 0x20; seq[3] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); seq[0] = 0xf4; seq[1] = 0x8f; seq[2] = 0xbf; seq[3] = 0x20; seq[4] = 0x00; ret = sh_util_valid_utf8(seq); CuAssertIntEquals(tc, ret, S_FALSE); /* switch on utf8 checking for sh_util_obscurename() */ ret = sh_util_obscure_utf8("Y"); CuAssertIntEquals(tc, ret, 0); ret = sh_util_obscure_ok ("0x01,0x02,0x03"); CuAssertIntEquals(tc, ret, 0); ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_TRUE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = '\t'; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_FALSE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, -1); input[0] = 0x01; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_TRUE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = 0x02; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_TRUE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = 0x03; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_TRUE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = 0x04; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_FALSE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, -1); input[0] = 'f'; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_TRUE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[5] = ' '; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_FALSE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, -1); input[5] = 'r'; input[3] = ' '; ret = sh_util_valid_utf8 (input); CuAssertIntEquals(tc, ret, S_TRUE); ret = sh_util_obscurename (0, (char *)input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); #else CuAssertIntEquals(tc, ret, 0); #endif } void Test_sh_util_obscure_ok (CuTest *tc) { int ret = 0; #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) char input[16] = "foobar"; /* switch off utf8 checking for sh_util_obscurename() */ ret = sh_util_obscure_utf8("N"); CuAssertIntEquals(tc, ret, 0); ret = sh_util_obscure_ok ("0xA1,0xA2,0xA3"); CuAssertIntEquals(tc, ret, 0); ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = '\t'; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, -1); input[0] = 0xA1; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = 0xA2; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = 0xA3; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[0] = 0xA4; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, -1); input[0] = 'f'; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); input[5] = ' '; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, -1); input[5] = 'r'; input[3] = ' '; ret = sh_util_obscurename (0, input, S_FALSE /* no log message */); CuAssertIntEquals(tc, ret, 0); #else CuAssertIntEquals(tc, ret, 0); #endif } samhain-4.1.4/src/sh_hash.c0000644000175000017500000023622412615253277012454 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000, 2001, 2002 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include #ifdef MAJOR_IN_MKDEV #include #else #ifdef MAJOR_IN_SYSMACROS #include #endif #endif #ifdef HAVE_MEMORY_H #include #endif #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) #include "samhain.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_dbIO_int.h" #include "sh_dbIO.h" #include "sh_hash.h" #include "sh_error.h" #include "sh_tiger.h" #include "sh_gpg.h" #include "sh_unix.h" #include "sh_files.h" #include "sh_ignore.h" #include "sh_pthread.h" #if defined(SH_WITH_CLIENT) #include "sh_xfer.h" #endif #define SH_KEY_NULL _("000000000000000000000000000000000000000000000000") #undef FIL__ #define FIL__ _("sh_hash.c") SH_MUTEX_INIT(mutex_hash,PTHREAD_MUTEX_INITIALIZER); static char * all_items (file_type * theFile, char * fileHash, int is_new); static const char *policy[] = { N_("[]"), N_("[ReadOnly]"), N_("[LogFiles]"), N_("[GrowingLogs]"), N_("[IgnoreNone]"), N_("[IgnoreAll]"), N_("[Attributes]"), N_("[User0]"), N_("[User1]"), N_("[User2]"), N_("[User3]"), N_("[User4]"), N_("[Prelink]"), NULL }; static int report_checkflags = S_FALSE; int set_report_checkflags(const char * c) { return sh_util_flagval(c, &report_checkflags); } int get_report_checkflags() { return report_checkflags; } const char * sh_hash_getpolicy(int class) { if (class > 0 && class < SH_ERR_T_DIR) return _(policy[class]); return _("[indef]"); } /********************************** * * hash table functions * ********************************** */ #include "sh_hash.h" /************************************************************** * * create a file_type from a sh_file_t * **************************************************************/ file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash) { file_type * theFile; SL_ENTER(_("sh_hash_create_ft")); theFile = SH_ALLOC(sizeof(file_type)); sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11); theFile->mode = p->theFile.mode; #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE); theFile->attributes = p->theFile.attributes; #endif sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX); if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */) { theFile->link_path = sh_util_strdup(p->linkpath); } else { theFile->link_path = NULL; } sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1); theFile->mtime = p->theFile.mtime; theFile->ctime = p->theFile.ctime; theFile->atime = p->theFile.atime; theFile->size = p->theFile.size; sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2); theFile->group = p->theFile.group; sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2); theFile->owner = p->theFile.owner; theFile->ino = p->theFile.ino; theFile->rdev = p->theFile.rdev; theFile->dev = p->theFile.dev; theFile->hardlinks = p->theFile.hardlinks; theFile->check_flags = p->theFile.checkflags; if (p->attr_string) theFile->attr_string = sh_util_strdup(p->attr_string); else theFile->attr_string = NULL; SL_RETURN((theFile), _("sh_hash_create_ft")); } struct two_sh_file_t { sh_file_t * prev; sh_file_t * this; }; static sh_file_t * hashsearch (const char * s); static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index); /************************************************************** * * >>>> The internal database <<< * **************************************************************/ static sh_file_t * tab[TABSIZE]; sh_file_t ** get_default_data_table() { return tab; } /************************************************************** * * compute hash function * **************************************************************/ static int hashfunc(const char *s) { unsigned int n = 0; for ( ; *s; s++) n = 31 * n + *s; return n & (TABSIZE - 1); /* % TABSIZE */; } int hashreport_missing( char *fullpath, int level) { sh_file_t * p; char * tmp; char fileHash[KEY_LEN + 1]; file_type * theFile; char * str; char hashbuf[KEYBUF_SIZE]; volatile int retval; /* -------- find the entry for the file ---------------- */ SH_MUTEX_LOCK(mutex_hash); retval = 0; if (sl_strlen(fullpath) <= MAX_PATH_STORE) p = hashsearch(fullpath); else p = hashsearch( sh_tiger_hash(fullpath, TIGER_DATA, sl_strlen(fullpath), hashbuf, sizeof(hashbuf)) ); if (p == NULL) { retval = -1; goto unlock_and_return; } theFile = sh_hash_create_ft (p, fileHash); str = all_items(theFile, fileHash, 0); tmp = sh_util_safe_name(fullpath); SH_MUTEX_LOCK(mutex_thread_nolog); if (!sh_global_check_silent) sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_MISS2, tmp, str); SH_MUTEX_UNLOCK(mutex_thread_nolog); ++sh.statistics.files_report; SH_FREE(tmp); SH_FREE(str); if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(theFile); unlock_and_return: ; /* 'label at end of compound statement */ SH_MUTEX_UNLOCK(mutex_hash); /* remove here to avoid second message from hash_unvisited */ if (retval == 0) sh_hash_remove (fullpath); return retval; } /************************************************************** * * search for files not visited, and check whether they exist * **************************************************************/ static sh_file_t * delete_db_entry(sh_file_t *p) { if (p->fullpath) { SH_FREE(p->fullpath); p->fullpath = NULL; } if (p->linkpath) { SH_FREE(p->linkpath); p->linkpath = NULL; } if (p->attr_string) { SH_FREE(p->attr_string); p->attr_string = NULL; } SH_FREE(p); return NULL; } static void hash_unvisited (int j, sh_file_t *prev, sh_file_t *p, ShErrLevel level) { struct stat buf; int i; char * tmp; char * ptr; char fileHash[KEY_LEN + 1]; file_type * theFile; char * str; SL_ENTER(_("hash_unvisited")); if (p->next != NULL) hash_unvisited (j, p, p->next, level); if (p->fullpath == NULL) { SL_RET0(_("hash_unvisited")); } /* Not a fully qualified path, i.e. some info stored by some module */ if (p->fullpath[0] != '/') { SL_RET0(_("hash_unvisited")); } /* visited flag not set: not seen; * checked flag set: not seen (i.e. missing), and already checked * reported flag not set: not reported yet * allignore flag not set: not under IgnoreAll * * Files/directories under IgnoreAll are noticed as missing already * during the file check. */ if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags)) && (!SH_FFLAG_REPORTED_SET(p->fflags)) /* && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)) */) { i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf); /* if file does not exist */ if (0 != i) { ptr = sh_util_dirname (p->fullpath); if (ptr) { /* If any of the parent directories is under IgnoreAll */ if ((0 != sh_files_is_allignore(ptr)) || SH_FFLAG_ALLIGNORE_SET(p->fflags)) level = ShDFLevel[SH_LEVEL_ALLIGNORE]; SH_FREE(ptr); } /* Only report if !SH_FFLAG_CHECKED_SET */ if (!SH_FFLAG_CHECKED_SET(p->fflags)) { if (S_FALSE == sh_ignore_chk_del(p->fullpath)) { tmp = sh_util_safe_name(p->fullpath); theFile = sh_hash_create_ft (p, fileHash); str = all_items(theFile, fileHash, 0); if (!sh_global_check_silent) sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_MISS2, tmp, str); ++sh.statistics.files_report; SH_FREE(str); if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(theFile); SH_FREE(tmp); } } /* We rewrite the db on update, thus we need to keep this * if the user does not want to purge it from the db. */ if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) || (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath))) { /* Remove the old entry */ if (prev == p) tab[j] = p->next; else prev->next = p->next; delete_db_entry(p); SL_RET0(_("hash_unvisited")); } } } else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags) && (!SH_FFLAG_ALLIGNORE_SET(p->fflags))) { if (S_FALSE == sh_ignore_chk_new(p->fullpath)) { tmp = sh_util_safe_name(p->fullpath); theFile = sh_hash_create_ft (p, fileHash); str = all_items(theFile, fileHash, 0); if (!sh_global_check_silent) sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_MISS2, tmp, str); ++sh.statistics.files_report; SH_FREE(str); if (theFile->attr_string) SH_FREE(theFile->attr_string); SH_FREE(theFile); SH_FREE(tmp); } CLEAR_SH_FFLAG_REPORTED(p->fflags); } if (sh.flag.reportonce == S_FALSE) CLEAR_SH_FFLAG_REPORTED(p->fflags); CLEAR_SH_FFLAG_VISITED(p->fflags); CLEAR_SH_FFLAG_CHECKED(p->fflags); SET_SH_FFLAG_ENOENT(p->fflags); SL_RET0(_("hash_unvisited")); } /********************************************************************* * * Search for files in the database that have been deleted from disk. * *********************************************************************/ void sh_hash_unvisited (ShErrLevel level) { int i; SL_ENTER(_("sh_hash_unvisited")); SH_MUTEX_LOCK(mutex_hash); for (i = 0; i < TABSIZE; ++i) { if (tab[i] != NULL) hash_unvisited (i, tab[i], tab[i], level); } SH_MUTEX_UNLOCK(mutex_hash); SL_RET0(_("hash_unvisited")); } /********************************************************************* * * Remove a single file from the database. * *********************************************************************/ void sh_hash_remove_unconditional (const char * path) { struct two_sh_file_t entries; int index; SL_ENTER(_("sh_hash_remove_unconditional")); SH_MUTEX_LOCK(mutex_hash); if (0 == hashsearch_prev (path, &entries, &index)) { sh_file_t * p = entries.this; /* Remove the old entry */ if (entries.prev == p) tab[index] = p->next; else entries.prev->next = p->next; delete_db_entry(p); } SH_MUTEX_UNLOCK(mutex_hash); SL_RET0(_("sh_hash_remove_unconditional")); } void sh_hash_remove (const char * path) { SL_ENTER(_("sh_hash_remove")); if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) || (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path))) { sh_hash_remove_unconditional (path); } SL_RET0(_("sh_hash_remove")); } /********************************************************************* * * Search for unvisited entries in the database, custom error handler. * *********************************************************************/ void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key)) { int i; sh_file_t *p = NULL; sh_file_t *prev = NULL; sh_file_t *next = NULL; SL_ENTER(_("sh_hash_unvisited_custom")); SH_MUTEX_LOCK(mutex_hash); for (i = 0; i < TABSIZE; ++i) { if (tab[i] != NULL) { p = tab[i]; prev = p; do { next = p->next; if (p->fullpath && prefix == p->fullpath[0]) { if ((!SH_FFLAG_VISITED_SET(p->fflags)) && (!SH_FFLAG_REPORTED_SET(p->fflags))) { handler(p->fullpath); if (!SH_FFLAG_CHECKED_SET(p->fflags)) { /* delete */ if (tab[i] == p) { tab[i] = p->next; prev = tab[i]; next = prev; } else { prev->next = p->next; next = prev->next; } p = delete_db_entry(p); } } if (p) { CLEAR_SH_FFLAG_VISITED(p->fflags); CLEAR_SH_FFLAG_CHECKED(p->fflags); } } if (p) prev = p; p = next; } while (p); } } SH_MUTEX_UNLOCK(mutex_hash); SL_RET0(_("hash_unvisited_custom")); } /********************************************************************** * * delete hash array * **********************************************************************/ static void hash_kill (sh_file_t *p) { SL_ENTER(_("hash_kill")); if (p == NULL) SL_RET0(_("hash_kill")); if (p->next != NULL) hash_kill (p->next); if (p->fullpath) { SH_FREE(p->fullpath); p->fullpath = NULL; } if (p->linkpath) { SH_FREE(p->linkpath); p->linkpath = NULL; } if (p->attr_string) { SH_FREE(p->attr_string); p->attr_string = NULL; } SH_FREE(p); p = NULL; SL_RET0(_("hash_kill")); } /*********************************************************************** * * get info out of hash array * ***********************************************************************/ static sh_file_t * hashsearch (const char * s) { sh_file_t * p; SL_ENTER(_("hashsearch")); if (s) { for (p = tab[hashfunc(s)]; p; p = p->next) if ((p->fullpath != NULL) && (0 == strcmp(s, p->fullpath))) SL_RETURN( p, _("hashsearch")); } SL_RETURN( NULL, _("hashsearch")); } static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index) { sh_file_t * this; sh_file_t * prev = NULL; SL_ENTER(_("hashsearch_prev")); if (s) { *index = hashfunc(s); this = tab[*index]; prev = this; if (this) { do { if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath))) { a->prev = prev; a->this = this; SL_RETURN( 0, _("hashsearch_prev")); } prev = this; this = this->next; } while(this); } } SL_RETURN( -1, _("hashsearch")); } /*********************************************************************** * * insert into hash array * ***********************************************************************/ void hashinsert (sh_file_t * mtab[TABSIZE], sh_file_t * s) { sh_file_t * p; sh_file_t * q; int key; SL_ENTER(_("hashinsert")); key = hashfunc(s->fullpath); if (mtab[key] == NULL) { mtab[key] = s; mtab[key]->next = NULL; SL_RET0(_("hashinsert")); } else { p = mtab[key]; while (1) { if (p && p->fullpath && 0 == strcmp(s->fullpath, p->fullpath)) { q = p->next; SH_FREE(p->fullpath); if(p->linkpath) SH_FREE(p->linkpath); if(p->attr_string) SH_FREE(p->attr_string); memcpy(p, s, sizeof(sh_file_t)); p->next = q; SH_FREE(s); s = NULL; SL_RET0(_("hashinsert")); } else if (p && p->next == NULL) { p->next = s; p->next->next = NULL; SL_RET0(_("hashinsert")); } if (p) p = p->next; else /* cannot really happen, but llvm/clang does not know */ break; } } /* notreached */ } /****************************************************************** * * ------- Check functions ------- * ******************************************************************/ static int IsInit = 0; void sh_hash_set_initialized() { IsInit = 1; return; } int sh_hash_get_initialized() { return IsInit; } /****************************************************************** * * Initialize * ******************************************************************/ void sh_hash_init () { volatile int retval = 0; volatile int exitval = EXIT_SUCCESS; SL_ENTER(_("sh_hash_init")); if ( sh.flag.checkSum == SH_CHECK_INIT ) { dlog(1, FIL__, __LINE__, _("Attempt to load the baseline database during initialisation. This is an internal error, please report it to the developer.\n")); SH_ABORT; aud_exit (FIL__, __LINE__, EXIT_FAILURE); } SH_MUTEX_LOCK(mutex_hash); if (IsInit == 1) { goto unlock_and_return; } /* Initialization completed. */ retval = sh_dbIO_load_db(tab); if (0 == retval) IsInit = 1; else exitval = EXIT_FAILURE; unlock_and_return: ; /* 'label at end of compound statement */ SH_MUTEX_UNLOCK(mutex_hash); if (retval == 0) { SL_RET0(_("sh_hash_init")); } sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name); aud_exit (FIL__, __LINE__, exitval); } void sh_hash_init_and_checksum() { TPT((0, FIL__, __LINE__, _("msg=\n"))) if (sh.flag.checkSum == SH_CHECK_CHECK) { if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER"))) { char hashbuf[KEYBUF_SIZE]; (void) sl_strlcpy(sh.data.hash, sh_tiger_hash (file_path('D', 'R'), TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } /* this eventually fetches the file from server to get checksum */ sh_hash_init (); } return; } /***************************************************************** * * delete hash array * *****************************************************************/ void sh_hash_hashdelete () { int i; SL_ENTER(_("sh_hash_hashdelete")); /* need deadlock detection here if called from exit handler */ SH_MUTEX_TRYLOCK(mutex_hash); if (IsInit == 0) goto unlock_and_exit; for (i = 0; i < TABSIZE; ++i) if (tab[i] != NULL) { hash_kill (tab[i]); tab[i] = NULL; } IsInit = 0; unlock_and_exit: ; /* 'label at end of compound statement */ SH_MUTEX_TRYLOCK_UNLOCK(mutex_hash); SL_RET0(_("sh_hash_hashdelete")); } static int sh_loosedircheck = S_FALSE; int sh_hash_loosedircheck(const char * str) { return sh_util_flagval(str, &sh_loosedircheck); } /********************************************************************* * * Check whether a file is present in the database. * *********************************************************************/ static sh_file_t * sh_hash_have_it_int (const char * newname) { sh_file_t * p; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_hash_have_it_int")); if (newname == NULL) SL_RETURN( (NULL), _("sh_hash_have_it_int")); if (sl_strlen(newname) <= MAX_PATH_STORE) p = hashsearch(newname); else p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname), hashbuf, sizeof(hashbuf)) ); if (p == NULL) SL_RETURN( (NULL), _("sh_hash_have_it_int")); SL_RETURN( (p), _("sh_hash_have_it_int")); } int sh_hash_have_it (const char * newname) { sh_file_t * p; int retval; if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK(mutex_hash); retval = 0; p = sh_hash_have_it_int (newname); if (!p) retval = (-1); else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) && (p->modi_mask & MODI_CHK) != 0 && (p->modi_mask & MODI_MOD) != 0) retval = 1; SH_MUTEX_UNLOCK(mutex_hash); return retval; } int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash) { sh_file_t * p; int retval; if (IsInit != 1) sh_hash_init(); tmpFile->link_path = NULL; tmpFile->attr_string = NULL; SH_MUTEX_LOCK(mutex_hash); retval = (-1); p = sh_hash_have_it_int (newname); if (p) { sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX); if (p->linkpath) tmpFile->link_path = sh_util_strdup (p->linkpath); tmpFile->size = p->theFile.size; tmpFile->mtime = p->theFile.mtime; tmpFile->ctime = p->theFile.ctime; tmpFile->atime = p->theFile.atime; if (NULL != fileHash) sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1); tmpFile->attr_string = NULL; retval = 0; } SH_MUTEX_UNLOCK(mutex_hash); return retval; } int sh_hash_getflags (char * filename) { sh_file_t * p; int retval = 0; if ( sh.flag.checkSum != SH_CHECK_INIT ) { if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK(mutex_hash); p = sh_hash_have_it_int (filename); if (p) retval = p->fflags; else retval = -1; SH_MUTEX_UNLOCK(mutex_hash); } return retval; } int sh_hash_setflags (char * filename, int flags) { sh_file_t * p; int retval = 0; if ( sh.flag.checkSum != SH_CHECK_INIT ) { if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK(mutex_hash); p = sh_hash_have_it_int (filename); if (p) { p->fflags = flags; retval = 0; } else retval = -1; SH_MUTEX_UNLOCK(mutex_hash); } return retval; } /* needs lock to be threadsafe */ void sh_hash_set_flag (char * filename, int flag_to_set) { sh_file_t * p; if ( sh.flag.checkSum != SH_CHECK_INIT ) { if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK(mutex_hash); p = sh_hash_have_it_int (filename); if (p) { p->fflags |= flag_to_set; } SH_MUTEX_UNLOCK(mutex_hash); } return; } /* needs lock to be threadsafe */ void sh_hash_clear_flag (char * filename, int flag_to_clear) { sh_file_t * p; if ( sh.flag.checkSum != SH_CHECK_INIT ) { if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK(mutex_hash); p = sh_hash_have_it_int (filename); if (p) { p->fflags &= ~flag_to_clear; } SH_MUTEX_UNLOCK(mutex_hash); } return; } /***************************************************************** * * Set a file's status to 'visited'. This is required for * files that should be ignored, and may be present in the * database, but not on disk. * *****************************************************************/ static int sh_hash_set_visited_int (char * newname, int flag) { sh_file_t * p; char hashbuf[KEYBUF_SIZE]; int retval; SL_ENTER(_("sh_hash_set_visited_int")); if (newname == NULL) SL_RETURN((-1), _("sh_hash_set_visited_int")); if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK(mutex_hash); if (sl_strlen(newname) <= MAX_PATH_STORE) p = hashsearch(newname); else p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname), hashbuf, sizeof(hashbuf))); if (p) { if (flag == SH_FFLAG_CHECKED) { CLEAR_SH_FFLAG_REPORTED(p->fflags); CLEAR_SH_FFLAG_VISITED(p->fflags); SET_SH_FFLAG_CHECKED(p->fflags); } else { SET_SH_FFLAG_VISITED(p->fflags); CLEAR_SH_FFLAG_CHECKED(p->fflags); if (flag == SH_FFLAG_REPORTED) SET_SH_FFLAG_REPORTED(p->fflags); else CLEAR_SH_FFLAG_REPORTED(p->fflags); } retval = 0; } else retval = -1; SH_MUTEX_UNLOCK(mutex_hash); SL_RETURN((retval), _("sh_hash_set_visited_int")); } /* cause the record to be deleted without a 'missing' message */ int sh_hash_set_missing (char * newname) { int i; SL_ENTER(_("sh_hash_set_missing")); i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED); if (sh.flag.checkSum != SH_CHECK_INIT) { sh_hash_remove(newname); } SL_RETURN(i, _("sh_hash_set_missing")); } /* mark the file as visited and reported */ int sh_hash_set_visited (char * newname) { int i; SL_ENTER(_("sh_hash_set_visited")); i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED); SL_RETURN(i, _("sh_hash_set_visited")); } /* mark the file as visited and NOT reported * used to avoid deletion of file from internal database */ int sh_hash_set_visited_true (char * newname) { int i; SL_ENTER(_("sh_hash_set_visited_true")); i = sh_hash_set_visited_int(newname, 0); SL_RETURN(i, _("sh_hash_set_visited_true")); } /****************************************************************** * * Data entry for arbitrary data into database * ******************************************************************/ void sh_hash_push2db (const char * key, struct store2db * save) { int i = 0; char * p; char i2h[2]; file_type * tmpFile = SH_ALLOC(sizeof(file_type)); int size = save->size; unsigned char * str = save->str; tmpFile->attr_string = NULL; tmpFile->link_path = NULL; sl_strlcpy(tmpFile->fullpath, key, PATH_MAX); tmpFile->size = save->val0; tmpFile->mtime = save->val1; tmpFile->ctime = save->val2; tmpFile->atime = save->val3; tmpFile->mode = 0; tmpFile->owner = 0; tmpFile->group = 0; sl_strlcpy(tmpFile->c_owner, _("root"), 5); sl_strlcpy(tmpFile->c_group, _("root"), 5); tmpFile->check_flags = 0; if ((str != NULL) && (size < (PATH_MAX/2)-1)) { tmpFile->c_mode[0] = 'l'; tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w'; tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r'; tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x'; tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w'; tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0'; tmpFile->link_path = SH_ALLOC((size * 2) + 2); for (i = 0; i < size; ++i) { p = sh_util_charhex (str[i],i2h); tmpFile->link_path[2*i] = p[0]; tmpFile->link_path[2*i+1] = p[1]; tmpFile->link_path[2*i+2] = '\0'; } } else { for (i = 0; i < 10; ++i) tmpFile->c_mode[i] = '-'; tmpFile->c_mode[10] = '\0'; tmpFile->link_path = sh_util_strdup("-"); } if (sh.flag.checkSum == SH_CHECK_INIT) sh_dbIO_data_write (tmpFile, (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum); else sh_hash_pushdata_memory (tmpFile, (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum); if (tmpFile->link_path) SH_FREE(tmpFile->link_path); SH_FREE(tmpFile); return; } extern int sh_util_hextobinary (char * binary, char * hex, int bytes); char * sh_hash_db2pop (const char * key, struct store2db * save) { size_t len; char * p; int i; char * retval = NULL; char fileHash[KEY_LEN+1]; file_type * tmpFile = SH_ALLOC(sizeof(file_type)); save->size = 0; if (0 == sh_hash_get_it (key, tmpFile, fileHash)) { save->val0 = tmpFile->size; save->val1 = tmpFile->mtime; save->val2 = tmpFile->ctime; save->val3 = tmpFile->atime; sl_strlcpy(save->checksum, fileHash, KEY_LEN+1); if (tmpFile->link_path && tmpFile->link_path[0] != '-') { len = strlen(tmpFile->link_path); p = SH_ALLOC((len/2)+1); i = sh_util_hextobinary (p, tmpFile->link_path, len); if (i == 0) { save->size = (len/2); p[save->size] = '\0'; retval = p; } else { SH_FREE(p); save->size = 0; } } else { save->size = 0; } } else { save->size = -1; save->val0 = 0; save->val1 = 0; save->val2 = 0; save->val3 = 0; } if (tmpFile->link_path) SH_FREE(tmpFile->link_path); SH_FREE(tmpFile); return retval; } /****************************************************************** * * Data entry in hash table * ******************************************************************/ sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash) { sh_file_t * fp; sh_filestore_t p; size_t len; char * fullpath; char * linkpath; char * attr_string = NULL; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_hash_push_int")); fp = SH_ALLOC(sizeof(sh_file_t)); p.mark = REC_MAGIC; if (buf->attr_string) p.mark |= REC_FLAGS_ATTR; sl_strlcpy(p.c_mode, buf->c_mode, 11); sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1); sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1); sl_strlcpy(p.checksum, fileHash, KEY_LEN+1); #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_strlcpy(p.c_attributes, buf->c_attributes, 13); #endif #if defined(__linux__) || defined(HAVE_STAT_FLAGS) p.attributes = (UINT32) buf->attributes; #endif p.linkmode = (UINT32) buf->linkmode; p.hardlinks = (UINT32) buf->hardlinks; p.dev = (UINT64) buf->dev; p.rdev = (UINT64) buf->rdev; p.mode = (UINT32) buf->mode; p.ino = (UINT32) buf->ino; p.size = (UINT64) buf->size; p.mtime = (UINT64) buf->mtime; p.atime = (UINT64) buf->atime; p.ctime = (UINT64) buf->ctime; p.owner = (UINT32) buf->owner; p.group = (UINT32) buf->group; p.checkflags = (UINT32) buf->check_flags; memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) ); fp->fflags = 0; /* init fflags */ fp->modi_mask = 0L; if (buf->attr_string) attr_string = sh_util_strdup(buf->attr_string); fp->attr_string = attr_string; len = sl_strlen(buf->fullpath); if (len <= MAX_PATH_STORE) { fullpath = SH_ALLOC(len+1); sl_strlcpy(fullpath, buf->fullpath, len+1); } else { fullpath = SH_ALLOC(KEY_LEN + 1); sl_strlcpy(fullpath, sh_tiger_hash (buf->fullpath, TIGER_DATA, len, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } fp->fullpath = fullpath; if (buf->link_path) { len = sl_strlen(buf->link_path); if (len <= MAX_PATH_STORE) { linkpath = SH_ALLOC(len+1); sl_strlcpy(linkpath, buf->link_path, len+1); } else { linkpath = SH_ALLOC(KEY_LEN + 1); sl_strlcpy(linkpath, sh_tiger_hash (buf->link_path, TIGER_DATA, len, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } fp->linkpath = linkpath; } else fp->linkpath = NULL; SL_RETURN( fp, _("sh_hash_push_int")); } #ifdef HAVE_INTTYPES_H #include #else #ifdef HAVE_STDINT_H #include #endif #endif #ifndef PRIu64 #ifdef HAVE_LONG_32 #define PRIu64 "llu" #else #define PRIu64 "lu" #endif #endif char * sh_hash_size_format() { static char form_rval[81]; SL_ENTER(_("sh_hash_size_format")); #ifdef SH_USE_XML sl_snprintf(form_rval, 80, _("%s%s%s%s%s"), _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" "); #else sl_snprintf(form_rval, 80, _("%s%s%s%s%s"), _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, "); #endif SL_RETURN( form_rval, _("sh_hash_size_format")); } #ifdef SH_USE_XML static char * all_items (file_type * theFile, char * fileHash, int is_new) { char timstr1c[32]; char timstr1a[32]; char timstr1m[32]; char * tmp_lnk; char * format; char * tmp = SH_ALLOC(SH_MSG_BUF); char * msg = SH_ALLOC(SH_MSG_BUF); tmp[0] = '\0'; msg[0] = '\0'; if (report_checkflags != S_FALSE) { if (is_new) format = _("checkflags_new=\"0%lo\" "); else format = _("checkflags_old=\"0%lo\" "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->check_flags); sl_strlcat(msg, tmp, SH_MSG_BUF); } #if defined(__linux__) || defined(HAVE_STAT_FLAGS) if (is_new) format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" "); else format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_mode, theFile->c_attributes, (long) theFile->mode, (long) theFile->attributes ); #else if (is_new) format = _("mode_new=\"%s\" imode_new=\"%ld\" "); else format = _("mode_old=\"%s\" imode_old=\"%ld\" "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_mode, (long) theFile->mode ); #endif sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("hardlinks_new=\"%lu\" "); else format = _("hardlinks_old=\"%lu\" "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->hardlinks); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("idevice_new=\"%lu\" "); else format = _("idevice_old=\"%lu\" "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("inode_new=\"%lu\" "); else format = _("inode_old=\"%lu\" "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino); sl_strlcat(msg, tmp, SH_MSG_BUF); /* * also report device for prelude */ #if defined(HAVE_LIBPRELUDE) if (is_new) format = _("dev_new=\"%lu,%lu\" "); else format = _("dev_old=\"%lu,%lu\" "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) major(theFile->dev), (unsigned long) minor(theFile->dev)); sl_strlcat(msg, tmp, SH_MSG_BUF); #endif if (is_new) format = _("owner_new=\"%s\" iowner_new=\"%ld\" "); else format = _("owner_old=\"%s\" iowner_old=\"%ld\" "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_owner, (long) theFile->owner); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("group_new=\"%s\" igroup_new=\"%ld\" "); else format = _("group_old=\"%s\" igroup_old=\"%ld\" "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_group, (long) theFile->group); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(), (UINT64) 0, (UINT64) theFile->size); else sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(), (UINT64) theFile->size, (UINT64) 0); sl_strlcat(msg, tmp, SH_MSG_BUF); (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c)); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c); else sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c); sl_strlcat(msg, tmp, SH_MSG_BUF); (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a)); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a); else sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a); sl_strlcat(msg, tmp, SH_MSG_BUF); (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m)); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m); else sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash); else sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash); sl_strlcat(msg, tmp, SH_MSG_BUF); if (theFile->c_mode[0] == 'l' || (theFile->link_path != NULL && theFile->link_path[0] != '-')) { tmp_lnk = sh_util_safe_name(theFile->link_path); if (tmp_lnk) { if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk); else sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk); SH_FREE(tmp_lnk); sl_strlcat(msg, tmp, SH_MSG_BUF); } } if (theFile->attr_string) { tmp_lnk = sh_util_safe_name(theFile->attr_string); if (tmp_lnk) { if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk); else sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk); SH_FREE(tmp_lnk); sl_strlcat(msg, tmp, SH_MSG_BUF); } } SH_FREE(tmp); return (msg); } #else static char * all_items (file_type * theFile, char * fileHash, int is_new) { char timstr1c[32]; char timstr1a[32]; char timstr1m[32]; char * tmp_lnk; char * format; char * tmp = SH_ALLOC(SH_MSG_BUF); char * msg = SH_ALLOC(SH_MSG_BUF); tmp[0] = '\0'; msg[0] = '\0'; if (report_checkflags == S_TRUE) { if (is_new) format = _("checkflags_new=<0%lo> "); else format = _("checkflags_old=<0%lo> "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->check_flags); sl_strlcat(msg, tmp, SH_MSG_BUF); } #if defined(__linux__) || defined(HAVE_STAT_FLAGS) if (is_new) format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, "); else format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_mode, theFile->c_attributes, (long) theFile->mode, (long) theFile->attributes ); #else if (is_new) format = _("mode_new=<%s>, imode_new=<%ld>, "); else format = _("mode_old=<%s>, imode_old=<%ld>, "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_mode, (long) theFile->mode ); #endif sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("hardlinks_new=<%lu>, "); else format = _("hardlinks_old=<%lu>, "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->hardlinks); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("idevice_new=<%lu>, "); else format = _("idevice_old=<%lu>, "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("inode_new=<%lu>, "); else format = _("inode_old=<%lu>, "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino); sl_strlcat(msg, tmp, SH_MSG_BUF); /* * also report device for prelude */ #if defined(HAVE_LIBPRELUDE) if (is_new) format = _("dev_new=<%lu,%lu>, "); else format = _("dev_old=<%lu,%lu>, "); sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) major(theFile->dev), (unsigned long) minor(theFile->dev)); sl_strlcat(msg, tmp, SH_MSG_BUF); #endif if (is_new) format = _("owner_new=<%s>, iowner_new=<%ld>, "); else format = _("owner_old=<%s>, iowner_old=<%ld>, "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_owner, (long) theFile->owner); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) format = _("group_new=<%s>, igroup_new=<%ld>, "); else format = _("group_old=<%s>, igroup_old=<%ld>, "); sl_snprintf(tmp, SH_MSG_BUF, format, theFile->c_group, (long) theFile->group); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(), (UINT64) 0, (UINT64) theFile->size); else sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(), (UINT64) theFile->size, (UINT64) 0); sl_strlcat(msg, tmp, SH_MSG_BUF); (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c)); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c); else sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c); sl_strlcat(msg, tmp, SH_MSG_BUF); (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a)); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a); else sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a); sl_strlcat(msg, tmp, SH_MSG_BUF); (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m)); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m); else sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m); sl_strlcat(msg, tmp, SH_MSG_BUF); if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash); else sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash); sl_strlcat(msg, tmp, SH_MSG_BUF); if (theFile->c_mode[0] == 'l' || (theFile->link_path != NULL && theFile->link_path[0] != '-')) { tmp_lnk = sh_util_safe_name(theFile->link_path); if (tmp_lnk) { if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk); else sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk); SH_FREE(tmp_lnk); sl_strlcat(msg, tmp, SH_MSG_BUF); } } if (theFile->attr_string) { tmp_lnk = sh_util_safe_name(theFile->attr_string); if (tmp_lnk) { if (is_new) sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk); else sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk); SH_FREE(tmp_lnk); sl_strlcat(msg, tmp, SH_MSG_BUF); } } SH_FREE(tmp); return (msg); } #endif void sh_hash_pushdata_memory (file_type * theFile, char * fileHash) { sh_file_t * p; SL_ENTER(_("sh_hash_pushdata_memory")); p = sh_hash_push_int(theFile, fileHash); if (p) { SH_MUTEX_LOCK(mutex_hash); hashinsert (tab, p); p->modi_mask = theFile->check_flags; SH_MUTEX_UNLOCK(mutex_hash); } SL_RET0(_("sh_hash_pushdata_memory")); } int sh_hash_is_null_file(file_type * theFile) { if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 && theFile->ino == 0 && theFile->ctime == 0) { return S_TRUE; } return S_FALSE; } int sh_hash_is_null_record(sh_filestore_t * theFile) { if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 && theFile->ino == 0 && theFile->ctime == 0) { return S_TRUE; } return S_FALSE; } void sh_hash_insert_null(char * str) { file_type theFile = { 0, 0, {'\0'}, 0, 0, 0, 0, 0, #if defined(__linux__) || defined(HAVE_STAT_FLAGS) 0, {'\0'}, #endif {'\0'}, 0, {'\0'}, 0, {'\0'}, 0, 0, 0, 0, 0, 0, 0, NULL, 0, {'\0'}, 0, NULL }; /* clang compiler bails out on standard conforming init with just {0} */ char fileHash[KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; sl_strlcpy(fileHash, SH_KEY_NULL, sizeof(fileHash)); theFile.hardlinks = SH_DEADFILE; if (sl_strlen(str) < PATH_MAX) sl_strlcpy(theFile.fullpath, str, PATH_MAX); else sl_strlcpy(theFile.fullpath, sh_tiger_hash(str, TIGER_DATA, sl_strlen(str), hashbuf, sizeof(hashbuf)), PATH_MAX); sh_hash_pushdata_memory(&theFile, fileHash); return; } static int handle_notfound(int log_severity, int class, file_type * theFile, char * fileHash) { sh_file_t * p; int retval = 0; if (S_FALSE == sh_ignore_chk_new(theFile->fullpath)) { char * tmp = sh_util_safe_name(theFile->fullpath); char * str; sh_files_fixup_mask(class, &(theFile->check_flags)); str = all_items (theFile, fileHash, 1); if (!sh_global_check_silent) sh_error_handle (log_severity, FIL__, __LINE__, 0, MSG_FI_ADD2, tmp, str); ++sh.statistics.files_report; SH_FREE(str); SH_FREE(tmp); } if (sh.flag.reportonce == S_TRUE) SET_SH_FFLAG_REPORTED(theFile->file_reported); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { p = sh_hash_push_int(theFile, fileHash); if (p) { hashinsert (tab, p); p->modi_mask = theFile->check_flags; p->theFile.checkflags = p->modi_mask; } } else if (S_TRUE == sh.flag.update) { if (S_TRUE == sh_util_ask_update (theFile->fullpath)) { p = sh_hash_push_int(theFile, fileHash); if (p) { hashinsert (tab, p); p->modi_mask = theFile->check_flags; p->theFile.checkflags = p->modi_mask; } } else retval = 1; } return retval; } /***************************************************************** * * Compare a file with the database status. * *****************************************************************/ int sh_hash_compdata (int class, file_type * theFile, char * fileHash, char * policy_override, int severity_override) { char * msg; sh_file_t * p; char * tmp; char * tmp_path; char * tmp_lnk; char * tmp_lnk_old; char timstr1c[32]; char timstr2c[32]; char timstr1a[32]; char timstr2a[32]; char timstr1m[32]; char timstr2m[32]; char linkHash[KEY_LEN+1]; char * linkComp; int maxcomp; volatile int checksum_flag = 0; char change_code[16]; int i; unsigned long modi_mask; char log_policy[32]; volatile int log_severity; char hashbuf[KEYBUF_SIZE]; struct { unsigned long oldflags; unsigned long newflags; } cf_report; int retval; SL_ENTER(_("sh_hash_compdata")); if (IsInit != 1) sh_hash_init(); if (severity_override < 0) log_severity = ShDFLevel[class]; else log_severity = severity_override; if (policy_override != NULL) sl_strlcpy (log_policy, policy_override, 32); /* -------- find the entry for the file ---------------- */ SH_MUTEX_LOCK(mutex_hash); modi_mask = 0; retval = 0; if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE) p = hashsearch(theFile->fullpath); else p = hashsearch( sh_tiger_hash(theFile->fullpath, TIGER_DATA, sl_strlen(theFile->fullpath), hashbuf, sizeof(hashbuf)) ); /* --------- Not found in database. ------------ */ if (p == NULL) { retval = handle_notfound(log_severity, class, theFile, fileHash); goto unlock_and_return; } /* --------- Skip if we don't want to report changes. ------------ */ if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath)) { MODI_SET(theFile->check_flags, MODI_NOCHECK); p->modi_mask = theFile->check_flags; p->theFile.checkflags = p->modi_mask; goto unlock_and_return; } cf_report.oldflags = p->theFile.checkflags; cf_report.newflags = theFile->check_flags; p->modi_mask = theFile->check_flags; p->theFile.checkflags = p->modi_mask; /* initialize change_code */ for (i = 0; i < 15; ++i) change_code[i] = '-'; change_code[15] = '\0'; TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"), theFile->fullpath, fileHash, p->theFile.checksum)); if ( (fileHash != NULL) && (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) && (theFile->check_flags & MODI_CHK) != 0) { checksum_flag = 1; if ((theFile->check_flags & MODI_SGROW) == 0) { modi_mask |= MODI_CHK; change_code[0] = 'C'; TPT ((0, FIL__, __LINE__, _("mod="))); } else { if (0 != strncmp (&fileHash[KEY_LEN + 1], p->theFile.checksum, KEY_LEN)) { if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size, (UINT64) p->theFile.ino, p->theFile.checksum, p->theFile.checkflags)) { modi_mask |= MODI_CHK; change_code[0] = 'C'; TPT ((0, FIL__, __LINE__, _("mod="))); } else { /* logfile has been rotated */ p->theFile.size = theFile->size; p->theFile.ino = theFile->ino; sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1); } } else { p->theFile.size = theFile->size; sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1); } } } if (p->theFile.c_mode[0] == 'l') { if (!(theFile->link_path) && (theFile->check_flags & MODI_LNK) != 0) { linkComp = NULL; modi_mask |= MODI_LNK; change_code[1] = 'L'; TPT ((0, FIL__, __LINE__, _("mod="))); } else { if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE) { sl_strlcpy(linkHash, sh_tiger_hash(theFile->link_path, TIGER_DATA, sl_strlen(theFile->link_path), hashbuf, sizeof(hashbuf)), MAX_PATH_STORE+1); linkComp = linkHash; maxcomp = KEY_LEN; } else { linkComp = theFile->link_path; maxcomp = MAX_PATH_STORE; } if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 && (theFile->check_flags & MODI_LNK) != 0) { modi_mask |= MODI_LNK; change_code[1] = 'L'; TPT ((0, FIL__, __LINE__, _("mod="))); } } } if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b') { if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) || minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) && (theFile->check_flags & MODI_RDEV) != 0) { modi_mask |= MODI_RDEV; change_code[2] = 'D'; TPT ((0, FIL__, __LINE__, _("mod="))); } } /* cast to UINT32 in case ino_t is not 32bit */ if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino && (theFile->check_flags & MODI_INO) != 0) { if ((theFile->check_flags & MODI_SGROW) == 0) { modi_mask |= MODI_INO; change_code[3] = 'I'; TPT ((0, FIL__, __LINE__, _("mod="))); } else { /* growing log, checksum ok but inode changed */ if (checksum_flag == 0) { if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size, (UINT64) p->theFile.ino, p->theFile.checksum, p->theFile.checkflags)) { modi_mask |= MODI_INO; change_code[3] = 'I'; TPT ((0, FIL__, __LINE__, _("mod="))); } else { /* logfile has been rotated */ p->theFile.size = theFile->size; p->theFile.ino = theFile->ino; sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1); } } else { modi_mask |= MODI_INO; change_code[3] = 'I'; TPT ((0, FIL__, __LINE__, _("mod="))); } } } if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks && (theFile->check_flags & MODI_HLN) != 0) { modi_mask |= MODI_HLN; change_code[4] = 'H'; TPT ((0, FIL__, __LINE__, _("mod="))); } if ( ( (theFile->mode != p->theFile.mode) #if defined(USE_ACL) || defined(USE_XATTR) || ( (sh_unix_check_selinux|sh_unix_check_acl) && ( (theFile->attr_string == NULL && p->attr_string != NULL) || (theFile->attr_string != NULL && p->attr_string == NULL) || (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string)) ) ) #endif #if defined(__linux__) || defined(HAVE_STAT_FLAGS) || (theFile->attributes != p->theFile.attributes) #endif ) && (theFile->check_flags & MODI_MOD) != 0) { modi_mask |= MODI_MOD; change_code[5] = 'M'; TPT ((0, FIL__, __LINE__, _("mod="))); /* * report link path if switch link/no link */ if ((theFile->check_flags & MODI_LNK) != 0 && (theFile->c_mode[0] != p->theFile.c_mode[0]) && (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l')) { modi_mask |= MODI_LNK; change_code[1] = 'L'; TPT ((0, FIL__, __LINE__, _("mod="))); } } if ( theFile->owner != (uid_t) p->theFile.owner && (theFile->check_flags & MODI_USR) != 0) { modi_mask |= MODI_USR; change_code[6] = 'U'; TPT ((0, FIL__, __LINE__, _("mod="))); } if ( theFile->group != (gid_t) p->theFile.group && (theFile->check_flags & MODI_GRP) != 0) { modi_mask |= MODI_GRP; change_code[7] = 'G'; TPT ((0, FIL__, __LINE__, _("mod="))); } if ( theFile->mtime != (time_t) p->theFile.mtime && (theFile->check_flags & MODI_MTM) != 0) { modi_mask |= MODI_MTM; change_code[8] = 'T'; TPT ((0, FIL__, __LINE__, _("mod="))); } if ( (theFile->check_flags & MODI_ATM) != 0 && theFile->atime != (time_t) p->theFile.atime) { modi_mask |= MODI_ATM; change_code[8] = 'T'; TPT ((0, FIL__, __LINE__, _("mod="))); } /* Resetting the access time will set a new ctime. Thus, either we ignore * the access time or the ctime for NOIGNORE */ if ( theFile->ctime != (time_t) p->theFile.ctime && (theFile->check_flags & MODI_CTM) != 0) { modi_mask |= MODI_CTM; change_code[8] = 'T'; TPT ((0, FIL__, __LINE__, _("mod="))); } if ( theFile->size != (off_t) p->theFile.size && (theFile->check_flags & MODI_SIZ) != 0) { if ((theFile->check_flags & MODI_SGROW) == 0 || theFile->size < (off_t) p->theFile.size) { modi_mask |= MODI_SIZ; change_code[9] = 'S'; TPT ((0, FIL__, __LINE__, _("mod="))); } } change_code[10] = '\0'; /* --- Directories special case --- */ if (p->theFile.c_mode[0] == 'd' && 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) && sh_loosedircheck == S_TRUE) { modi_mask = 0; } /* --- Report full details. --- */ if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE) { if ((theFile->check_flags & MODI_ATM) == 0) modi_mask = MASK_READONLY_; else modi_mask = MASK_NOIGNORE_; } /* --- Report on modified files. --- */ if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags))) { tmp = SH_ALLOC(SH_MSG_BUF); msg = SH_ALLOC(SH_MSG_BUF); msg[0] = '\0'; sh_files_fixup_mask(class, &(cf_report.newflags)); if ( (report_checkflags != S_FALSE) && (cf_report.oldflags != cf_report.newflags)) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("checkflags_old=\"0%lo\" checkflags_new=\"0%lo\" "), #else _("checkflags_old=<0%lo>, checkflags_new=<0%lo>, "), #endif cf_report.oldflags, cf_report.newflags); sl_strlcat(msg, tmp, SH_MSG_BUF); } if ( ((modi_mask & MODI_MOD) != 0) #if defined(HAVE_LIBPRELUDE) || ((modi_mask & MODI_USR) != 0) || ((modi_mask & MODI_GRP) != 0) #endif ) { #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "), #else _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "), #endif p->theFile.c_mode, theFile->c_mode, p->theFile.c_attributes, theFile->c_attributes #ifdef SH_USE_XML , (long) p->theFile.mode, (long) theFile->mode, (long) p->theFile.attributes, (long) theFile->attributes #endif ); #else #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "), p->theFile.c_mode, theFile->c_mode, (long) p->theFile.mode, (long) theFile->mode); #else sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "), p->theFile.c_mode, theFile->c_mode); #endif #endif sl_strlcat(msg, tmp, SH_MSG_BUF); #if defined(USE_ACL) || defined(USE_XATTR) if (theFile->attr_string != NULL || p->attr_string != NULL) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("acl_old=\"%s\" acl_new=\"%s\" "), #else _("acl_old=<%s>, acl_new=<%s>, "), #endif (p->attr_string) ? p->attr_string : _("none"), (theFile->attr_string) ? theFile->attr_string : _("none")); sl_strlcat(msg, tmp, SH_MSG_BUF); } #endif if ((modi_mask & MODI_MOD) != 0) { /* * We postpone update if sh.flag.update == S_TRUE because * in interactive mode the user may not accept the change. */ if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11); p->theFile.mode = theFile->mode; #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16); p->theFile.attributes = theFile->attributes; #endif #if defined(USE_ACL) || defined(USE_XATTR) if (p->attr_string == NULL && theFile->attr_string != NULL) { p->attr_string = sh_util_strdup (theFile->attr_string); } else if (p->attr_string != NULL && theFile->attr_string == NULL) { SH_FREE(p->attr_string); p->attr_string = NULL; } else if (theFile->attr_string != NULL && p->attr_string != NULL) { if (0 != strcmp(theFile->attr_string, p->attr_string)) { SH_FREE(p->attr_string); p->attr_string = sh_util_strdup (theFile->attr_string); } } #endif } } } if ((modi_mask & MODI_HLN) != 0) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "), #else _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "), #endif (unsigned long) p->theFile.hardlinks, (unsigned long) theFile->hardlinks); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.hardlinks = theFile->hardlinks; } if ((modi_mask & MODI_RDEV) != 0) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "), #else _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "), #endif (unsigned long) major(p->theFile.rdev), (unsigned long) minor(p->theFile.rdev), (unsigned long) major(theFile->rdev), (unsigned long) minor(theFile->rdev) #ifdef SH_USE_XML , (unsigned long) p->theFile.rdev, (unsigned long) theFile->rdev #endif ); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.rdev = theFile->rdev; } if ((modi_mask & MODI_INO) != 0) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("inode_old=\"%lu\" inode_new=\"%lu\" "), #else _("inode_old=<%lu>, inode_new=<%lu>, "), #endif (unsigned long) p->theFile.ino, (unsigned long) theFile->ino); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { p->theFile.ino = theFile->ino; p->theFile.dev = theFile->dev; } } /* * also report device for prelude */ #if defined(HAVE_LIBPRELUDE) if ((modi_mask & MODI_INO) != 0) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "), #else _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "), #endif (unsigned long) major(p->theFile.dev), (unsigned long) minor(p->theFile.dev), (unsigned long) major(theFile->dev), (unsigned long) minor(theFile->dev) ); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.dev = theFile->dev; } #endif if ( ((modi_mask & MODI_USR) != 0) #if defined(HAVE_LIBPRELUDE) || ((modi_mask & MODI_MOD) != 0) #endif ) { #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "), #else sl_snprintf(tmp, SH_MSG_BUF, _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "), #endif p->theFile.c_owner, theFile->c_owner, (long) p->theFile.owner, (long) theFile->owner ); sl_strlcat(msg, tmp, SH_MSG_BUF); if ((modi_mask & MODI_USR) != 0) { if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2); p->theFile.owner = theFile->owner; } } } if ( ((modi_mask & MODI_GRP) != 0) #if defined(HAVE_LIBPRELUDE) || ((modi_mask & MODI_MOD) != 0) #endif ) { #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "), p->theFile.c_group, theFile->c_group, (long) p->theFile.group, (long) theFile->group); #else sl_snprintf(tmp, SH_MSG_BUF, _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "), p->theFile.c_group, theFile->c_group, (long) p->theFile.group, (long) theFile->group); #endif sl_strlcat(msg, tmp, SH_MSG_BUF); if ((modi_mask & MODI_GRP) != 0) { if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2); p->theFile.group = theFile->group; } } } if ((modi_mask & MODI_SIZ) != 0) { sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(), (UINT64) p->theFile.size, (UINT64) theFile->size); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.size = theFile->size; } if ((modi_mask & MODI_CTM) != 0) { (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c)); (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c)); #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "), timstr1c, timstr2c); #else sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "), timstr1c, timstr2c); #endif sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.ctime = theFile->ctime; } if ((modi_mask & MODI_ATM) != 0) { (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a)); (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a)); #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "), timstr1a, timstr2a); #else sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "), timstr1a, timstr2a); #endif sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.atime = theFile->atime; } if ((modi_mask & MODI_MTM) != 0) { (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m)); (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m)); #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "), timstr1m, timstr2m); #else sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "), timstr1m, timstr2m); #endif sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) p->theFile.mtime = theFile->mtime; } if ((modi_mask & MODI_CHK) != 0) { sl_snprintf(tmp, SH_MSG_BUF, #ifdef SH_USE_XML _("chksum_old=\"%s\" chksum_new=\"%s\" "), #else _("chksum_old=<%s>, chksum_new=<%s>, "), #endif p->theFile.checksum, fileHash); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1); if ((theFile->check_flags & MODI_SGROW) != 0) p->theFile.size = theFile->size; } if (theFile->c_mode[0] != 'l' && theFile->link_path && strlen(theFile->link_path) > 2) modi_mask |= MODI_LNK; } if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */) { if (theFile->link_path) tmp_lnk = sh_util_safe_name(theFile->link_path); else tmp_lnk = sh_util_strdup("-"); if (p->linkpath) tmp_lnk_old = sh_util_safe_name(p->linkpath); else tmp_lnk_old = sh_util_strdup("-"); #ifdef SH_USE_XML sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "), tmp_lnk_old, tmp_lnk); #else sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>, "), tmp_lnk_old, tmp_lnk); #endif SH_FREE(tmp_lnk); SH_FREE(tmp_lnk_old); sl_strlcat(msg, tmp, SH_MSG_BUF); if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) { if (p->linkpath != NULL) SH_FREE(p->linkpath); if (!(theFile->link_path)) p->linkpath = sh_util_strdup("-"); else p->linkpath = sh_util_strdup(theFile->link_path); } } if (MODI_AUDIT_ENABLED(theFile->check_flags)) { char result[256]; sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Fetching audit record"), _("sh_hash"), theFile->fullpath ); if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, theFile->ctime, result, sizeof(result))) { #ifdef SH_USE_XML sl_strlcat(msg, _("obj=\""), SH_MSG_BUF); #else sl_strlcat(msg, _("obj=<"), SH_MSG_BUF); #endif sl_strlcat(msg, result, SH_MSG_BUF); #ifdef SH_USE_XML sl_strlcat(msg, _("\" "), SH_MSG_BUF); #else sl_strlcat(msg, _(">"), SH_MSG_BUF); #endif } } /**************************************************** * * REPORT on file change * ****************************************************/ tmp_path = sh_util_safe_name(theFile->fullpath); if (!sh_global_check_silent) sh_error_handle(log_severity, FIL__, __LINE__, (long) modi_mask, MSG_FI_CHAN, (policy_override == NULL) ? _(policy[class]):log_policy, change_code, tmp_path, msg); ++sh.statistics.files_report; SH_FREE(tmp_path); SH_FREE(tmp); SH_FREE(msg); if (S_TRUE == sh.flag.update) { if (S_FALSE == sh_util_ask_update(theFile->fullpath)) { /* user does not want to update, thus we replace * with data from the baseline database */ sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11); theFile->mode = p->theFile.mode; #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16); theFile->attributes = p->theFile.attributes; #endif #if defined(USE_ACL) || defined(USE_XATTR) if (theFile->attr_string == NULL && p->attr_string != NULL) { theFile->attr_string = sh_util_strdup (p->attr_string); } else if (theFile->attr_string != NULL && p->attr_string == NULL) { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; } else if (theFile->attr_string != NULL && p->attr_string != NULL) { if (0 != strcmp(theFile->attr_string, p->attr_string)) { SH_FREE(theFile->attr_string); theFile->attr_string = sh_util_strdup (p->attr_string); } } #endif if (theFile->c_mode[0] == 'l') /* c_mode is already copied */ { if (theFile->link_path) SH_FREE(theFile->link_path); if (p->linkpath) theFile->link_path = sh_util_strdup(p->linkpath); else theFile->link_path = sh_util_strdup("-"); } else { if (theFile->link_path) SH_FREE(theFile->link_path); if (p->linkpath) theFile->link_path = sh_util_strdup(p->linkpath); else theFile->link_path = NULL; } sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1); theFile->mtime = p->theFile.mtime; theFile->ctime = p->theFile.ctime; theFile->atime = p->theFile.atime; theFile->size = p->theFile.size; sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2); theFile->group = p->theFile.group; sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2); theFile->owner = p->theFile.owner; theFile->ino = p->theFile.ino; theFile->rdev = p->theFile.rdev; theFile->dev = p->theFile.dev; theFile->hardlinks = p->theFile.hardlinks; SET_SH_FFLAG_VISITED(p->fflags); CLEAR_SH_FFLAG_CHECKED(p->fflags); retval = 1; goto unlock_and_return; } else /* if (sh.flag.reportonce == S_TRUE) */ { /* we replace the data in the in-memory copy of the * baseline database, because otherwise we would get * another warning if the suidcheck runs */ sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11); p->theFile.mode = theFile->mode; #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16); p->theFile.attributes = theFile->attributes; #endif #if defined(USE_ACL) || defined(USE_XATTR) if (p->attr_string == NULL && theFile->attr_string != NULL) { p->attr_string = sh_util_strdup (theFile->attr_string); } else if (p->attr_string != NULL && theFile->attr_string == NULL) { SH_FREE(p->attr_string); p->attr_string = NULL; } else if (theFile->attr_string != NULL && p->attr_string != NULL) { if (0 != strcmp(theFile->attr_string, p->attr_string)) { SH_FREE(p->attr_string); p->attr_string = sh_util_strdup (theFile->attr_string); } } #endif if (theFile->c_mode[0] == 'l' || theFile->link_path) { if (p->linkpath != NULL) SH_FREE(p->linkpath); p->linkpath = sh_util_strdup(theFile->link_path); } else { if (p->linkpath != NULL) SH_FREE(p->linkpath); p->linkpath = sh_util_strdup("-"); } sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1); p->theFile.mtime = theFile->mtime; p->theFile.ctime = theFile->ctime; p->theFile.atime = theFile->atime; p->theFile.size = theFile->size; sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2); p->theFile.group = theFile->group; sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2); p->theFile.owner = theFile->owner; p->theFile.ino = theFile->ino; p->theFile.rdev = theFile->rdev; p->theFile.dev = theFile->dev; p->theFile.hardlinks = theFile->hardlinks; } } } SET_SH_FFLAG_VISITED(p->fflags); CLEAR_SH_FFLAG_CHECKED(p->fflags); unlock_and_return: ; /* 'label at end of compound statement */ SH_MUTEX_UNLOCK(mutex_hash); SL_RETURN(retval, _("sh_hash_compdata")); } int hash_full_tree () { sh_file_t * p; int i; SL_ENTER(_("hash_full_tree")); if (IsInit != 1) SL_RETURN(0, _("hash_full_tree")); SH_MUTEX_LOCK_UNSAFE(mutex_hash); for (i = 0; i < TABSIZE; ++i) { for (p = tab[i]; p; p = p->next) CLEAR_SH_FFLAG_ALLIGNORE(p->fflags); } SH_MUTEX_UNLOCK_UNSAFE(mutex_hash); SL_RETURN (0, _("hash_full_tree")); } #if !defined(SH_CUTEST) static #endif int hash_remove_tree_test(char * s, char * fullpath, size_t len_s) { size_t len_p; char * test; len_p = strlen(fullpath); if (len_p >= len_s) { if (0 == strncmp(s, fullpath, len_s)) { if (len_p > len_s) { /* continue if not inside directory; * len_s > 1 because everything is inside '/' */ if ((len_s > 1) && (fullpath[len_s] != '/')) return S_FALSE; test = sh_files_find_mostspecific_dir(fullpath); if (test && 0 != strcmp(test, s)) { /* There is a more specific directory, continue */ return S_FALSE; } if (NULL == sh_files_findfile(fullpath)) { /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */ return S_TRUE; } } else /* len_p == len */ { /* it is 's' itself, mark and continue * unless there is a policy for the inode itself */ if (NULL == sh_files_findfile(fullpath)) { /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */ return S_TRUE; } else { return S_FALSE; } } } /* if path is in tree */ } /* if path is possibly in tree */ return S_FALSE; } int hash_remove_tree (char * s) { sh_file_t * p; size_t len_s; unsigned int i; SL_ENTER(_("hash_remove_tree")); if (!s || *s == '\0') SL_RETURN ((-1), _("hash_remove_tree")); len_s = sl_strlen(s); if (IsInit != 1) sh_hash_init(); SH_MUTEX_LOCK_UNSAFE(mutex_hash); for (i = 0; i < TABSIZE; ++i) { for (p = tab[i]; p; p = p->next) { if (p->fullpath) { /* if (0 == strncmp(s, p->fullpath, len_s)) *//* old */ if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) { SET_SH_FFLAG_ALLIGNORE(p->fflags); MODI_SET(p->theFile.checkflags, MODI_ALLIGNORE); } } /* if path is not null */ } } SH_MUTEX_UNLOCK_UNSAFE(mutex_hash); SL_RETURN ((0), _("hash_remove_tree")); } #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif static int ListFullDetail = S_FALSE; static int ListWithDelimiter = S_FALSE; static char * ListFile = NULL; int set_list_file (const char * c) { ListFile = sh_util_strdup(c); return 0; } char * get_list_file() { return ListFile; } int set_full_detail (const char * c) { (void) c; ListFullDetail = S_TRUE; return 0; } int set_list_delimited (const char * c) { (void) c; ListFullDetail = S_TRUE; ListWithDelimiter = S_TRUE; return 0; } /* Always quote the string, except if it is empty. Quote quotes by * doubling them. */ char * csv_escape(const char * str) { const char * p = str; const char * q; size_t size = 0; size_t flag_quote = 0; char * new; char * pnew; if (p) { while (*p) { if (*p == '"') ++flag_quote; ++size; ++p; } if (sl_ok_adds(size, flag_quote)) size += flag_quote; /* double each quote */ else return NULL; if (sl_ok_adds(size, 3)) size += 3; /* two quotes and terminating null */ else return NULL; new = SH_ALLOC(size); if (flag_quote != 0) { new[0] = '"'; pnew = &new[1]; q = str; while (*q) { *pnew = *q; if (*pnew == '"') { ++pnew; *pnew = '"'; } ++pnew; ++q; } *pnew = '"'; ++pnew; *pnew = '\0'; } else { if (size > 3) { new[0] = '"'; sl_strlcpy (&new[1], str, size-1); new[size-2] = '"'; new[size-1] = '\0'; } else { new[0] = '\0'; } } return new; } return NULL; } int isHexKey(char * s) { int i; for (i = 0; i < KEY_LEN; ++i) { if (*s) { if ((*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F') || (*s >= 'a' && *s <= 'f')) { ++s; continue; } } return S_FALSE; } return S_TRUE; } #include "sh_checksum.h" static char * KEYBUFtolower (char * s, char * result) { char * r = result; if (s) { for (; *s; ++s) { *r = tolower((unsigned char) *s); ++r; } *r = '\0'; } return result; } void sh_hash_list_db_entry_full_detail (sh_file_t * p) { char * tmp; char * esc; char str[81]; char hexdigest[SHA256_DIGEST_STRING_LENGTH]; char keybuffer[KEYBUF_SIZE]; if (ListWithDelimiter == S_TRUE) { printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "), (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev, p->theFile.c_mode, (int) p->theFile.mode, p->theFile.c_attributes, (int) p->theFile.attributes, (int) p->theFile.hardlinks, p->theFile.c_owner, (int) p->theFile.owner, p->theFile.c_group, (int) p->theFile.group); } else { printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "), (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev, p->theFile.c_mode, (int) p->theFile.mode, p->theFile.c_attributes, (int) p->theFile.attributes, (int) p->theFile.hardlinks, p->theFile.c_owner, (int) p->theFile.owner, p->theFile.c_group, (int) p->theFile.group); } if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0]) sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev); else sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size); printf( _(" %8s"), str); if (ListWithDelimiter == S_TRUE) putchar(','); printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str))); if (ListWithDelimiter == S_TRUE) putchar(','); printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str))); if (ListWithDelimiter == S_TRUE) putchar(','); printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str))); if (ListWithDelimiter == S_TRUE) putchar(','); if (isHexKey(p->theFile.checksum)) printf( _(" %s"), KEYBUFtolower(p->theFile.checksum, keybuffer)); else printf( _(" %s"), SHA256_Base2Hex(p->theFile.checksum, hexdigest)); if (ListWithDelimiter == S_TRUE) putchar(','); tmp = sh_util_safe_name(p->fullpath); if (ListWithDelimiter != S_TRUE) { printf( _(" %s"), tmp); } else { esc = csv_escape(tmp); printf( _(" %s,"), (esc != NULL) ? esc : _("(null)")); if (esc) SH_FREE(esc); } SH_FREE(tmp); if ('l' == p->theFile.c_mode[0]) { tmp = sh_util_safe_name(p->linkpath); if (ListWithDelimiter != S_TRUE) { printf(_(" -> %s"), tmp); } else { esc = csv_escape(tmp); printf( _(" %s,"), (esc != NULL) ? esc : _("(null)")); if (esc) SH_FREE(esc); } SH_FREE(tmp); } if (p->attr_string) { tmp = sh_util_safe_name(p->attr_string); if (ListWithDelimiter != S_TRUE) { printf(_(" %s"), tmp); } else { esc = csv_escape(tmp); printf( _(" %s"), (esc != NULL) ? esc : _("(null)")); if (esc) SH_FREE(esc); } SH_FREE(tmp); } else { if (ListWithDelimiter == S_TRUE) printf("%s",_(" no_attr")); } putchar('\n'); return; } void sh_hash_list_db_entry (sh_file_t * p) { char nowtime[128]; char thetime[128]; char * tmp; time_t now = time(NULL); time_t then = (time_t) p->theFile.mtime; struct tm * time_ptr; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R) struct tm time_tm; #endif if (ListFullDetail != S_FALSE) { sh_hash_list_db_entry_full_detail (p); return; } #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R) time_ptr = gmtime_r(&then, &time_tm); if (!time_ptr) return; strftime(thetime, 127, _("%b %d %Y"), time_ptr); time_ptr = gmtime_r(&now, &time_tm); if (!time_ptr) return; strftime(nowtime, 127, _("%b %d %Y"), time_ptr); if (0 == strncmp(&nowtime[7], &thetime[7], 4)) { time_ptr = gmtime_r(&then, &time_tm); if (!time_ptr) return; strftime(thetime, 127, _("%b %d %H:%M"), time_ptr); } #else time_ptr = gmtime(&then); if (!time_ptr) return; strftime(thetime, 127, _("%b %d %Y"), time_ptr); time_ptr = gmtime(&now); if (!time_ptr) return; strftime(nowtime, 127, _("%b %d %Y"), time_ptr); if (0 == strncmp(&nowtime[7], &thetime[7], 4)) { time_ptr = gmtime(&then); if (!time_ptr) return; strftime(thetime, 127, _("%b %d %H:%M"), time_ptr); } #endif tmp = sh_util_safe_name(p->fullpath); if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0]) printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"), p->theFile.c_mode, (int) p->theFile.hardlinks, p->theFile.c_owner, p->theFile.c_group, (int) major((dev_t)p->theFile.rdev), (int) minor((dev_t)p->theFile.rdev), thetime, tmp); else printf(_("%10s %3d %-8s %-8s %8ld %s %s"), p->theFile.c_mode, (int) p->theFile.hardlinks, p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size, thetime, tmp); SH_FREE(tmp); if ('l' == p->theFile.c_mode[0]) { tmp = sh_util_safe_name(p->linkpath); printf(_(" -> %s\n"), tmp); SH_FREE(tmp); } else printf("\n"); return; } #ifdef HAVE_LIBZ #include #endif int sh_hash_printcontent(char * linkpath) { #ifdef HAVE_LIBZ unsigned char * decoded; unsigned char * decompressed = NULL; size_t dlen; unsigned long clen; unsigned long clen_o; int res; if (linkpath && *linkpath != '-') { dlen = sh_util_base64_dec_alloc (&decoded, (unsigned char *)linkpath, strlen(linkpath)); clen = dlen * 2 + 1; do { if (decompressed) SH_FREE(decompressed); clen += dlen; clen_o = clen; decompressed = SH_ALLOC(clen); res = uncompress(decompressed, &clen, decoded, dlen); if (res == Z_MEM_ERROR) { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; } if (res == Z_DATA_ERROR) { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; } } while (res == Z_BUF_ERROR || clen == clen_o); decompressed[clen] = '\0'; fputs( (char*) decompressed, stdout); SH_FREE(decompressed); return 0; } #else (void) linkpath; #endif fprintf(stderr, "%s",_("Error: No data available\n")); return -1; } /* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */ #endif samhain-4.1.4/src/sh_tiger1.s0000644000175000017500000034073012615253277012742 00000000000000 .file "sh_tiger1.c" .text .globl tiger_compress .type tiger_compress, @function tiger_compress: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx subl $1140, %esp movl 12(%ebp), %ecx movl 12(%ebp), %esi call __i686.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_, %ebx movl 8(%ebp), %eax movl (%ecx), %edi movl 12(%ebp), %ecx movl %edi, -1088(%ebp) movl 4(%esi), %edx movl 12(%ebp), %esi movl %edx, -1092(%ebp) movl 8(%ecx), %edi movl 12(%ebp), %ecx movl %edi, -1096(%ebp) movl 12(%esi), %edx movl -1096(%ebp), %esi movl %edx, -1100(%ebp) movl 16(%ecx), %edx movl 20(%ecx), %edi movl %esi, -16(%ebp) movl %edx, -20(%ebp) movl %edi, -1104(%ebp) movl (%eax), %ecx movl %ecx, -24(%ebp) movl 4(%eax), %edi movl %edi, -28(%ebp) movl 8(%eax), %esi movl %esi, -32(%ebp) movl 12(%eax), %ecx movl %ecx, -36(%ebp) movl 16(%eax), %edi movl %edi, -40(%ebp) movl 20(%eax), %esi movl %esi, -44(%ebp) movl 24(%eax), %ecx movl %ecx, -48(%ebp) movl 28(%eax), %edi movl %edi, -52(%ebp) movl 32(%eax), %esi movl %esi, -56(%ebp) movl 36(%eax), %ecx movl %ecx, -60(%ebp) movl 40(%eax), %edi movl %edi, -64(%ebp) movl 44(%eax), %esi movl %esi, -68(%ebp) movl 48(%eax), %ecx movl %ecx, -72(%ebp) movl 52(%eax), %edi movl %edi, -76(%ebp) movl 56(%eax), %esi movl -28(%ebp), %edi movl %esi, -80(%ebp) movl 60(%eax), %ecx movl -24(%ebp), %eax movl -1104(%ebp), %esi movl %ecx, -84(%ebp) xorl %eax, %edx movl tiger_table@GOT(%ebx), %ecx movl %edx, -152(%ebp) movl %edx, %eax xorl %edi, %esi movl %esi, -156(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl %ecx, %esi movl 2048(%eax,%ecx), %edx movl (%ecx,%edi,8), %ecx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -156(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -156(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax xorl %edi, %edx movl -1088(%ebp), %edi cmpl %ecx, -1088(%ebp) setb %al subl %ecx, %edi movl %edi, -168(%ebp) movl -1092(%ebp), %ecx addl %eax, %edx subl %edx, %ecx movl -152(%ebp), %edx movl %ecx, -172(%ebp) movzbl %dh, %eax leal 0(,%eax,8), %ecx movl %edx, %eax movl 6144(%ecx,%esi), %edi shrl $24, %eax sall $3, %eax movl 6148(%ecx,%esi), %ecx movl 4096(%eax,%esi), %edx xorl %edi, %edx movl 4100(%eax,%esi), %edi movl -156(%ebp), %eax xorl %edi, %ecx movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %edx movl 2052(%eax,%esi), %edi movl -156(%ebp), %eax xorl %edi, %ecx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %edx movl 4(%esi,%eax,8), %edi movl -1096(%ebp), %esi xorl %eax, %eax xorl %edi, %ecx addl %edx, %esi cmpl %edx, %esi movl -1100(%ebp), %edx setb %al movl %esi, %edi leal (%ecx,%eax), %eax addl %edx, %eax leal 0(,%esi,4), %ecx movl %eax, %edx movl %eax, -160(%ebp) addl %ecx, %esi shrl $30, %edi movl %esi, -164(%ebp) sall $2, %edx xorl %eax, %eax orl %edi, %edx cmpl %ecx, %esi movl -80(%ebp), %edi setb %al xorl %ecx, %ecx addl %eax, %edx movl -160(%ebp), %eax xorl $-1515870811, %edi movl -24(%ebp), %esi addl %eax, %edx movl -84(%ebp), %eax cmpl %edi, -24(%ebp) movl %edx, -184(%ebp) movl -32(%ebp), %edx setb %cl xorl $-1515870811, %eax subl %edi, %esi addl %ecx, %eax movl %esi, -196(%ebp) movl -28(%ebp), %ecx movl -36(%ebp), %edi movl -172(%ebp), %esi subl %eax, %ecx movl -168(%ebp), %eax movl %ecx, -200(%ebp) movl tiger_table@GOT(%ebx), %ecx xorl %edi, %esi movl %esi, -180(%ebp) xorl %edx, %eax movzbl %al,%edi movl %eax, -176(%ebp) shrl $13, %eax andl $2040, %eax movl %ecx, %esi movl 2048(%eax,%ecx), %edx movl (%ecx,%edi,8), %ecx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -180(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -180(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax xorl %edi, %edx movl -164(%ebp), %edi cmpl %ecx, -164(%ebp) setb %al subl %ecx, %edi movl %edi, -204(%ebp) movl -176(%ebp), %ecx movl -184(%ebp), %edi addl %eax, %edx movzbl %ch, %eax subl %edx, %edi movl %edi, -208(%ebp) leal 0(,%eax,8), %edi movl %ecx, %eax shrl $24, %eax movl 6144(%edi,%esi), %ecx sall $3, %eax movl 4096(%eax,%esi), %edx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -180(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -180(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -152(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -156(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx movl %edx, -188(%ebp) leal 0(,%edi,4), %ecx addl %ecx, %edi movl %edi, -192(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -188(%ebp), %edi setb %al addl %eax, %edx movl -32(%ebp), %ecx addl %edi, %edx movl -200(%ebp), %eax movl %edx, -220(%ebp) movl -36(%ebp), %edi movl -196(%ebp), %edx xorl %eax, %edi xorl %edx, %ecx movl %edi, -240(%ebp) movl -40(%ebp), %edx movl %ecx, -232(%ebp) movl -204(%ebp), %eax movl -44(%ebp), %ecx movl -208(%ebp), %edi xorl %edx, %eax movl %eax, -212(%ebp) xorl %ecx, %edi movl %edi, -216(%ebp) movzbl %al,%edi shrl $13, %eax andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -216(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -216(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -192(%ebp), %esi xorl %edi, %edx cmpl %ecx, -192(%ebp) setb %al subl %ecx, %esi movl %esi, -244(%ebp) movl -220(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -212(%ebp), %edx movl %edi, -248(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -216(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -216(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -176(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -180(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,4), %ecx movl %edx, -224(%ebp) addl %ecx, %edi shrl $30, %eax movl %edi, -228(%ebp) sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -224(%ebp), %ecx setb %al movl -232(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -232(%ebp), %eax movl -240(%ebp), %ecx movl %edx, -260(%ebp) movl -40(%ebp), %edx addl %eax, %edx movl %edx, -236(%ebp) xorl %eax, %eax cmpl %edi, %edx movl -44(%ebp), %edi setb %al addl %ecx, %eax movl -48(%ebp), %edx addl %edi, %eax movl -52(%ebp), %ecx movl %eax, -272(%ebp) movl -248(%ebp), %edi movl -244(%ebp), %eax xorl %ecx, %edi xorl %edx, %eax movl %edi, -256(%ebp) movzbl %al,%edi movl %eax, -252(%ebp) shrl $13, %eax movl (%esi,%edi,8), %ecx andl $2040, %eax movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -256(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -256(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -228(%ebp), %esi xorl %edi, %edx cmpl %ecx, -228(%ebp) setb %al subl %ecx, %esi movl %esi, -276(%ebp) movl -260(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -252(%ebp), %edx movl %edi, -280(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -256(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -256(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -212(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -216(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,4), %ecx movl %edx, -264(%ebp) addl %ecx, %edi shrl $30, %eax movl %edi, -268(%ebp) sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi setb %al addl %eax, %edx movl -264(%ebp), %eax movl -236(%ebp), %edi addl %eax, %edx movl -232(%ebp), %eax movl %edx, -292(%ebp) movl -48(%ebp), %edx notl %eax sall $19, %eax xorl %edi, %eax cmpl %eax, -48(%ebp) setb %cl movzbl %cl, %edi subl %eax, %edx movl -232(%ebp), %ecx movl -240(%ebp), %eax movl %edx, -304(%ebp) movl -272(%ebp), %edx shrl $13, %ecx sall $19, %eax orl %ecx, %eax notl %edx xorl %eax, %edx movl -52(%ebp), %eax addl %edi, %edx movl -60(%ebp), %ecx subl %edx, %eax movl -280(%ebp), %edi movl %eax, -308(%ebp) movl -56(%ebp), %edx movl -276(%ebp), %eax xorl %ecx, %edi xorl %edx, %eax movl %eax, -284(%ebp) movl %edi, -288(%ebp) movzbl %al,%edi shrl $13, %eax andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -288(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -288(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -268(%ebp), %esi xorl %edi, %edx cmpl %ecx, -268(%ebp) movl -292(%ebp), %edi setb %al addl %eax, %edx subl %ecx, %esi subl %edx, %edi movl %esi, -312(%ebp) movl -284(%ebp), %edx movl tiger_table@GOT(%ebx), %ecx movl %edi, -316(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -288(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -288(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -252(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -256(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,4), %ecx movl %edx, -296(%ebp) addl %ecx, %edi shrl $30, %eax movl %edi, -300(%ebp) sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -296(%ebp), %edi setb %al movl -56(%ebp), %ecx addl %eax, %edx addl %edi, %edx movl %edx, -328(%ebp) movl -304(%ebp), %edx xorl %edx, %ecx movl %ecx, -340(%ebp) movl -308(%ebp), %eax movl -60(%ebp), %edi movl -64(%ebp), %edx movl -68(%ebp), %ecx xorl %eax, %edi movl %edi, -348(%ebp) movl -312(%ebp), %eax movl -316(%ebp), %edi xorl %edx, %eax xorl %ecx, %edi movl %edi, -324(%ebp) movzbl %al,%edi movl %eax, -320(%ebp) shrl $13, %eax movl (%esi,%edi,8), %ecx andl $2040, %eax movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -324(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -324(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -300(%ebp), %esi xorl %edi, %edx cmpl %ecx, -300(%ebp) movl -328(%ebp), %edi setb %al addl %eax, %edx subl %ecx, %esi subl %edx, %edi movl %esi, -352(%ebp) movl -320(%ebp), %edx movl tiger_table@GOT(%ebx), %ecx movl %edi, -356(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -324(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -324(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -284(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -288(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,4), %ecx movl %edx, -332(%ebp) addl %ecx, %edi shrl $30, %eax movl %edi, -336(%ebp) sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -332(%ebp), %ecx setb %al movl -340(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -340(%ebp), %eax movl -348(%ebp), %ecx movl %edx, -368(%ebp) movl -64(%ebp), %edx addl %eax, %edx movl %edx, -344(%ebp) xorl %eax, %eax cmpl %edi, %edx movl -68(%ebp), %edi setb %al addl %ecx, %eax movl -72(%ebp), %edx addl %edi, %eax movl -76(%ebp), %ecx movl %eax, -380(%ebp) movl -356(%ebp), %edi movl -352(%ebp), %eax xorl %ecx, %edi xorl %edx, %eax movl %edi, -364(%ebp) movzbl %al,%edi movl %eax, -360(%ebp) shrl $13, %eax movl (%esi,%edi,8), %ecx andl $2040, %eax movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -364(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -364(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -336(%ebp), %esi xorl %edi, %edx cmpl %ecx, -336(%ebp) movl -368(%ebp), %edi setb %al addl %eax, %edx subl %ecx, %esi subl %edx, %edi movl %esi, -384(%ebp) movl -360(%ebp), %edx movl tiger_table@GOT(%ebx), %ecx movl %edi, -388(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -364(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -364(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -320(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi setb %al leal 0(,%edi,4), %ecx addl %eax, %edx movl -324(%ebp), %eax movl %edi, %esi shrl $30, %esi addl %ecx, %edi addl %eax, %edx xorl %eax, %eax movl %edx, -372(%ebp) sall $2, %edx orl %esi, %edx movl %edi, -376(%ebp) cmpl %ecx, %edi movl -372(%ebp), %esi setb %al movl -344(%ebp), %ecx addl %eax, %edx addl %esi, %edx movl -340(%ebp), %eax notl %ecx movl %edx, -400(%ebp) movl -348(%ebp), %edx shrl $23, %eax movl -72(%ebp), %edi sall $9, %edx movl -380(%ebp), %esi orl %edx, %eax xorl %eax, %ecx xorl %edx, %edx cmpl %ecx, -72(%ebp) movl -348(%ebp), %eax notl %eax setb %dl subl %ecx, %edi shrl $23, %eax movl %edi, -412(%ebp) movl -76(%ebp), %ecx xorl %esi, %eax addl %edx, %eax movl -80(%ebp), %edx movl -84(%ebp), %edi subl %eax, %ecx movl -384(%ebp), %eax movl -388(%ebp), %esi movl %ecx, -416(%ebp) xorl %edx, %eax movl tiger_table@GOT(%ebx), %ecx movl %eax, -392(%ebp) xorl %edi, %esi movzbl %al,%edi movl %esi, -396(%ebp) shrl $13, %eax andl $2040, %eax movl %ecx, %esi movl 2048(%eax,%ecx), %edx movl (%ecx,%edi,8), %ecx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -396(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -396(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax xorl %edi, %edx movl -376(%ebp), %edi cmpl %ecx, -376(%ebp) setb %al addl %eax, %edx movl -400(%ebp), %eax subl %ecx, %edi movl %edi, -488(%ebp) subl %edx, %eax movl %eax, -492(%ebp) movl -392(%ebp), %ecx movzbl %ch, %edi movl %ecx, %eax sall $3, %edi shrl $24, %eax movl %edi, -88(%ebp) sall $3, %eax movl 4096(%eax,%esi), %ecx movl -88(%ebp), %edx movl %esi, %edi movl %ecx, -1116(%ebp) movl 4100(%eax,%esi), %eax xorl 6144(%edx,%esi), %ecx movl %eax, %edx movl -88(%ebp), %eax xorl 6148(%eax,%esi), %edx movl -396(%ebp), %eax movzbl %ah, %eax movl %eax, -1112(%ebp) sall $3, %eax xorl 2048(%eax,%esi), %ecx xorl 2052(%eax,%esi), %edx movl -396(%ebp), %eax shrl $24, %eax xorl (%esi,%eax,8), %ecx xorl 4(%esi,%eax,8), %edx movl -360(%ebp), %esi xorl %eax, %eax addl %ecx, %esi cmpl %ecx, %esi movl -364(%ebp), %ecx setb %al addl %eax, %edx addl %ecx, %edx movl %edx, -404(%ebp) leal 0(,%esi,4), %ecx movl %esi, %eax shrl $30, %eax addl %ecx, %esi sall $2, %edx movl %esi, -408(%ebp) orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi setb %al movl -412(%ebp), %ecx addl %eax, %edx movl -404(%ebp), %eax movl -416(%ebp), %esi addl %eax, %edx xorl %eax, %eax movl %edx, -504(%ebp) movl -80(%ebp), %edx xorl %ecx, %edx movl %edx, -420(%ebp) movl -84(%ebp), %ecx xorl %esi, %ecx movl %ecx, -428(%ebp) movl -196(%ebp), %esi addl %edx, %esi movl %esi, -424(%ebp) cmpl %edx, %esi setb %al addl %ecx, %eax addl -200(%ebp), %eax movl %eax, -432(%ebp) movl %edx, %eax notl %eax sall $19, %eax xorl %edx, %edx xorl %esi, %eax cmpl %eax, -232(%ebp) setb %dl movl %edx, -436(%ebp) movl -232(%ebp), %esi movl -436(%ebp), %edx subl %eax, %esi movl %ecx, %eax movl -420(%ebp), %ecx movl %esi, -440(%ebp) movl -432(%ebp), %esi sall $19, %eax shrl $13, %ecx orl %ecx, %eax notl %esi xorl %eax, %esi movl -240(%ebp), %ecx addl %edx, %esi movl -272(%ebp), %edx subl %esi, %ecx movl -440(%ebp), %eax movl %ecx, -444(%ebp) movl -236(%ebp), %esi xorl %ecx, %edx movl %edx, -456(%ebp) movl -304(%ebp), %edx xorl %eax, %esi movl %esi, -448(%ebp) movl -456(%ebp), %ecx xorl %eax, %eax addl %esi, %edx cmpl %esi, %edx setb %al movl %edx, -452(%ebp) addl %ecx, %eax movl -308(%ebp), %ecx addl %ecx, %eax movl %edx, %ecx notl %ecx movl %eax, -460(%ebp) movl %esi, %eax movl -456(%ebp), %esi shrl $23, %eax xorl %edx, %edx sall $9, %esi orl %esi, %eax xorl %eax, %ecx movl -340(%ebp), %esi cmpl %ecx, -340(%ebp) movl -456(%ebp), %eax setb %dl subl %ecx, %esi movl -460(%ebp), %ecx notl %eax movl %esi, -464(%ebp) shrl $23, %eax xorl %ecx, %eax movl -344(%ebp), %ecx addl %edx, %eax movl -348(%ebp), %edx xorl %esi, %ecx movl -380(%ebp), %esi subl %eax, %edx movl %edx, -468(%ebp) movl %ecx, -472(%ebp) xorl %edx, %esi movl -412(%ebp), %edx movl %esi, -480(%ebp) addl %ecx, %edx cmpl %ecx, %edx movl %edx, -476(%ebp) setb %cl movzbl %cl, %eax addl %esi, %eax movl -476(%ebp), %edx movl -416(%ebp), %esi movl -420(%ebp), %ecx xorl $-1985229329, %edx addl %esi, %eax movl %eax, -484(%ebp) xorl %eax, %eax cmpl %edx, -420(%ebp) setb %al subl %edx, %ecx movl %ecx, -524(%ebp) movl -484(%ebp), %esi movl -428(%ebp), %ecx movl -424(%ebp), %edx xorl $19088743, %esi addl %eax, %esi subl %esi, %ecx movl -432(%ebp), %eax movl -492(%ebp), %esi movl %ecx, -528(%ebp) movl -488(%ebp), %ecx xorl %eax, %esi movl %esi, -500(%ebp) xorl %edx, %ecx movl -408(%ebp), %esi movl %ecx, -496(%ebp) movl %ecx, %eax movzbl %cl,%edx movl %edx, -92(%ebp) shrl $13, %eax andl $2040, %eax movl 2048(%eax,%edi), %ecx movl %ecx, -1120(%ebp) movl 2052(%eax,%edi), %eax xorl (%edi,%edx,8), %ecx movl %eax, %edx movl -92(%ebp), %eax xorl 4(%edi,%eax,8), %edx movzbl -500(%ebp),%eax sall $3, %eax xorl 4096(%eax,%edi), %ecx xorl 4100(%eax,%edi), %edx movl -500(%ebp), %eax shrl $13, %eax andl $2040, %eax xorl 6144(%eax,%edi), %ecx xorl 6148(%eax,%edi), %edx xorl %eax, %eax cmpl %ecx, -408(%ebp) setb %al addl %eax, %edx movl -504(%ebp), %eax subl %ecx, %esi movl %esi, -532(%ebp) subl %edx, %eax movl -496(%ebp), %edx movl %eax, -536(%ebp) movzbl %dh, %esi movl %edx, %eax sall $3, %esi shrl $24, %eax sall $3, %eax movl %esi, -96(%ebp) movl 4096(%eax,%edi), %ecx movl -96(%ebp), %esi movl %ecx, -1124(%ebp) movl 4100(%eax,%edi), %eax xorl 6144(%esi,%edi), %ecx movl %eax, %edx movl -500(%ebp), %eax xorl 6148(%esi,%edi), %edx movzbl %ah, %eax movl %eax, -1112(%ebp) sall $3, %eax movl -392(%ebp), %esi xorl 2048(%eax,%edi), %ecx xorl 2052(%eax,%edi), %edx movl -500(%ebp), %eax shrl $24, %eax xorl (%edi,%eax,8), %ecx xorl 4(%edi,%eax,8), %edx addl %ecx, %esi cmpl %ecx, %esi movl %esi, -508(%ebp) setb %al movl -396(%ebp), %ecx movzbl %al, %esi addl %esi, %edx movl -508(%ebp), %eax addl %ecx, %edx movl -508(%ebp), %esi movl %edx, -512(%ebp) movl -512(%ebp), %ecx shrl $29, %eax movl -508(%ebp), %edx sall $3, %ecx sall $3, %edx orl %eax, %ecx xorl %eax, %eax cmpl -508(%ebp), %edx setb %al subl %esi, %edx movl %edx, -516(%ebp) movl -512(%ebp), %esi movl -524(%ebp), %edx addl %esi, %eax xorl $-1515870811, %edx subl %eax, %ecx movl %ecx, -520(%ebp) xorl %eax, %eax cmpl %edx, -424(%ebp) movl -424(%ebp), %ecx movl -528(%ebp), %esi setb %al subl %edx, %ecx xorl $-1515870811, %esi movl %ecx, -564(%ebp) movl -432(%ebp), %ecx addl %eax, %esi movl -440(%ebp), %edx movl -444(%ebp), %eax subl %esi, %ecx movl %ecx, -568(%ebp) movl -532(%ebp), %ecx movl -536(%ebp), %esi xorl %edx, %ecx xorl %eax, %esi movl %ecx, %eax movl %esi, -544(%ebp) movzbl %cl,%edx shrl $13, %eax movl %edx, -100(%ebp) andl $2040, %eax movl -516(%ebp), %esi movl %ecx, -540(%ebp) movl 2048(%eax,%edi), %ecx movl %ecx, -1128(%ebp) movl 2052(%eax,%edi), %eax xorl (%edi,%edx,8), %ecx movl %eax, %edx movl -100(%ebp), %eax xorl 4(%edi,%eax,8), %edx movzbl -544(%ebp),%eax sall $3, %eax xorl 4096(%eax,%edi), %ecx xorl 4100(%eax,%edi), %edx movl -544(%ebp), %eax shrl $13, %eax andl $2040, %eax xorl 6144(%eax,%edi), %ecx xorl 6148(%eax,%edi), %edx xorl %eax, %eax cmpl %ecx, -516(%ebp) setb %al subl %ecx, %esi movl %esi, -572(%ebp) addl %eax, %edx movl -520(%ebp), %eax subl %edx, %eax movl -540(%ebp), %edx movl %eax, -576(%ebp) movzbl %dh, %esi movl %edx, %eax sall $3, %esi shrl $24, %eax sall $3, %eax movl %esi, -104(%ebp) movl 4096(%eax,%edi), %ecx movl -104(%ebp), %esi movl %ecx, -1132(%ebp) movl 4100(%eax,%edi), %eax xorl 6144(%esi,%edi), %ecx movl %eax, %edx movl -544(%ebp), %eax xorl 6148(%esi,%edi), %edx movzbl %ah, %eax movl %eax, -1112(%ebp) sall $3, %eax xorl 2048(%eax,%edi), %ecx xorl 2052(%eax,%edi), %edx movl -544(%ebp), %eax shrl $24, %eax xorl (%edi,%eax,8), %ecx xorl 4(%edi,%eax,8), %edx movl -496(%ebp), %eax addl %ecx, %eax movl %eax, -548(%ebp) cmpl %ecx, %eax setb %cl movzbl %cl, %eax movl -500(%ebp), %ecx addl %eax, %edx movl -548(%ebp), %eax addl %ecx, %edx shrl $29, %eax movl %edx, -552(%ebp) movl -552(%ebp), %ecx movl -548(%ebp), %edx sall $3, %ecx sall $3, %edx orl %eax, %ecx xorl %eax, %eax cmpl -548(%ebp), %edx setb %al subl -548(%ebp), %edx movl %edx, -556(%ebp) movl -552(%ebp), %edx addl %edx, %eax subl %eax, %ecx movl -440(%ebp), %edx movl -568(%ebp), %eax movl %ecx, -560(%ebp) movl -564(%ebp), %ecx xorl %ecx, %edx movl %edx, -604(%ebp) movl -444(%ebp), %ecx xorl %eax, %ecx movl %ecx, -612(%ebp) movl -448(%ebp), %edx movl -572(%ebp), %eax movl -456(%ebp), %ecx xorl %edx, %eax movl -576(%ebp), %edx movl %eax, -580(%ebp) xorl %ecx, %edx movzbl %al,%ecx movl %edx, -584(%ebp) shrl $13, %eax andl $2040, %eax movl %ecx, -108(%ebp) movl 2048(%eax,%edi), %esi movl -108(%ebp), %edx movl 2052(%eax,%edi), %eax movl %esi, %ecx movl -556(%ebp), %esi xorl (%edi,%edx,8), %ecx movl %eax, %edx movl -108(%ebp), %eax xorl 4(%edi,%eax,8), %edx movzbl -584(%ebp),%eax sall $3, %eax xorl 4096(%eax,%edi), %ecx xorl 4100(%eax,%edi), %edx movl -584(%ebp), %eax shrl $13, %eax andl $2040, %eax xorl 6144(%eax,%edi), %ecx xorl 6148(%eax,%edi), %edx xorl %eax, %eax cmpl %ecx, -556(%ebp) setb %al addl %eax, %edx movl -560(%ebp), %eax subl %ecx, %esi movl %esi, -616(%ebp) subl %edx, %eax movl -580(%ebp), %edx movl %eax, -620(%ebp) movzbl %dh, %esi movl %edx, %eax sall $3, %esi shrl $24, %eax sall $3, %eax movl %esi, -112(%ebp) movl 4096(%eax,%edi), %ecx movl -112(%ebp), %esi movl %ecx, -1140(%ebp) movl 4100(%eax,%edi), %eax xorl 6144(%esi,%edi), %ecx movl %eax, %edx movl -584(%ebp), %eax xorl 6148(%esi,%edi), %edx movzbl %ah, %eax movl %eax, -1112(%ebp) sall $3, %eax xorl 2048(%eax,%edi), %ecx xorl 2052(%eax,%edi), %edx movl -584(%ebp), %eax shrl $24, %eax xorl (%edi,%eax,8), %ecx xorl 4(%edi,%eax,8), %edx movl -540(%ebp), %eax addl %ecx, %eax movl %eax, -588(%ebp) cmpl %ecx, %eax setb %cl movzbl %cl, %eax movl -544(%ebp), %ecx addl %eax, %edx movl -588(%ebp), %eax addl %ecx, %edx shrl $29, %eax movl %edx, -592(%ebp) movl -592(%ebp), %ecx movl -588(%ebp), %edx sall $3, %ecx sall $3, %edx orl %eax, %ecx xorl %eax, %eax cmpl -588(%ebp), %edx setb %al subl -588(%ebp), %edx movl %edx, -596(%ebp) movl -592(%ebp), %edx addl %edx, %eax subl %eax, %ecx movl -448(%ebp), %edx movl -604(%ebp), %eax movl %ecx, -600(%ebp) movl -604(%ebp), %ecx addl %eax, %edx movl %edx, -608(%ebp) xorl %eax, %eax cmpl %ecx, %edx movl -612(%ebp), %edx setb %al movl -456(%ebp), %ecx addl %edx, %eax addl %ecx, %eax movl -452(%ebp), %edx movl %eax, -644(%ebp) movl -616(%ebp), %eax movl -460(%ebp), %ecx xorl %edx, %eax movl -620(%ebp), %edx movl %eax, -624(%ebp) xorl %ecx, %edx movzbl %al,%ecx movl %edx, -628(%ebp) shrl $13, %eax andl $2040, %eax movl %ecx, -116(%ebp) movl 2048(%eax,%edi), %esi movl -116(%ebp), %edx movl 2052(%eax,%edi), %eax movl %esi, %ecx movl -596(%ebp), %esi xorl (%edi,%edx,8), %ecx movl %eax, %edx movl -116(%ebp), %eax xorl 4(%edi,%eax,8), %edx movzbl -628(%ebp),%eax sall $3, %eax xorl 4096(%eax,%edi), %ecx xorl 4100(%eax,%edi), %edx movl -628(%ebp), %eax shrl $13, %eax andl $2040, %eax xorl 6144(%eax,%edi), %ecx xorl 6148(%eax,%edi), %edx xorl %eax, %eax cmpl %ecx, -596(%ebp) setb %al subl %ecx, %esi movl %esi, -652(%ebp) addl %eax, %edx movl -600(%ebp), %eax subl %edx, %eax movl -624(%ebp), %edx movl %eax, -656(%ebp) movzbl %dh, %esi movl %edx, %eax sall $3, %esi shrl $24, %eax sall $3, %eax movl %esi, -120(%ebp) movl 4096(%eax,%edi), %ecx movl -120(%ebp), %esi movl %ecx, -1148(%ebp) movl 4100(%eax,%edi), %eax xorl 6144(%esi,%edi), %ecx movl %eax, %edx movl -628(%ebp), %eax xorl 6148(%esi,%edi), %edx movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -628(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -580(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -584(%ebp), %ecx setb %al addl %eax, %edx addl %ecx, %edx movl %edx, -632(%ebp) movl %esi, %eax movl -632(%ebp), %ecx leal 0(,%esi,8), %edx shrl $29, %eax sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -632(%ebp), %esi movl %edx, -636(%ebp) xorl %edx, %edx addl %esi, %eax subl %eax, %ecx movl -604(%ebp), %eax movl -452(%ebp), %esi movl %ecx, -640(%ebp) movl -608(%ebp), %ecx notl %eax sall $19, %eax xorl %ecx, %eax movl -604(%ebp), %ecx cmpl %eax, -452(%ebp) setb %dl subl %eax, %esi movl %esi, -680(%ebp) movl -612(%ebp), %eax shrl $13, %ecx movl %edx, -648(%ebp) movl -644(%ebp), %esi movl -648(%ebp), %edx sall $19, %eax orl %ecx, %eax notl %esi xorl %eax, %esi movl -460(%ebp), %eax addl %edx, %esi subl %esi, %eax movl %eax, -684(%ebp) movl -464(%ebp), %ecx movl -652(%ebp), %eax movl -468(%ebp), %edx movl -656(%ebp), %esi xorl %ecx, %eax movl %eax, -660(%ebp) movzbl %al,%ecx xorl %edx, %esi movl %esi, -664(%ebp) shrl $13, %eax andl $2040, %eax movl %ecx, -124(%ebp) movl %ecx, %esi movl 2048(%eax,%edi), %edx movl (%edi,%ecx,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -664(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -664(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -636(%ebp), %esi cmpl %ecx, -636(%ebp) setb %al subl %ecx, %esi movl %esi, -688(%ebp) movl -660(%ebp), %ecx addl %eax, %edx movl -640(%ebp), %eax movzbl %ch, %esi sall $3, %esi movl %esi, -128(%ebp) subl %edx, %eax movl -128(%ebp), %esi movl %eax, -692(%ebp) movl %ecx, %eax shrl $24, %eax sall $3, %eax movl 6144(%esi,%edi), %ecx movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -664(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -664(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -624(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -628(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx shrl $29, %eax movl %edx, -668(%ebp) movl -668(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl %edx, -672(%ebp) movl -668(%ebp), %esi movl -464(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl -468(%ebp), %esi movl %ecx, -676(%ebp) movl -684(%ebp), %eax movl -680(%ebp), %ecx xorl %eax, %esi xorl %ecx, %edx movl -688(%ebp), %eax movl %edx, -716(%ebp) movl -472(%ebp), %ecx movl -480(%ebp), %edx movl %esi, -724(%ebp) movl -692(%ebp), %esi xorl %ecx, %eax movl %eax, -696(%ebp) movzbl %al,%ecx shrl $13, %eax movl %ecx, -132(%ebp) xorl %edx, %esi andl $2040, %eax movl %esi, -700(%ebp) movl 2048(%eax,%edi), %edx movl %ecx, %esi movl (%edi,%ecx,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -700(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -700(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -672(%ebp), %esi cmpl %ecx, -672(%ebp) setb %al subl %ecx, %esi movl %esi, -728(%ebp) movl -696(%ebp), %ecx addl %eax, %edx movl -676(%ebp), %eax movzbl %ch, %esi subl %edx, %eax movl %eax, -732(%ebp) sall $3, %esi movl %ecx, %eax movl %esi, -136(%ebp) movl -136(%ebp), %esi shrl $24, %eax sall $3, %eax movl 4096(%eax,%edi), %edx movl 6144(%esi,%edi), %ecx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -700(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -700(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -660(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -664(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx shrl $29, %eax movl %edx, -704(%ebp) movl -704(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl %edx, -708(%ebp) movl -704(%ebp), %esi movl -472(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl -716(%ebp), %eax movl %ecx, -712(%ebp) movl -716(%ebp), %ecx movl -480(%ebp), %esi addl %eax, %edx xorl %eax, %eax cmpl %ecx, %edx movl %edx, -720(%ebp) movl -724(%ebp), %edx setb %al movl -476(%ebp), %ecx addl %edx, %eax addl %esi, %eax movl %eax, -756(%ebp) movl -728(%ebp), %eax movl -484(%ebp), %edx movl -732(%ebp), %esi xorl %ecx, %eax movzbl %al,%ecx movl %eax, -736(%ebp) xorl %edx, %esi shrl $13, %eax movl %esi, -740(%ebp) andl $2040, %eax movl %ecx, %esi movl %ecx, -140(%ebp) movl 2048(%eax,%edi), %edx movl (%edi,%ecx,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -740(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -740(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -708(%ebp), %esi cmpl %ecx, -708(%ebp) setb %al subl %ecx, %esi movl %esi, -760(%ebp) movl -736(%ebp), %ecx addl %eax, %edx movl -712(%ebp), %eax movzbl %ch, %esi sall $3, %esi movl %esi, -144(%ebp) subl %edx, %eax movl -144(%ebp), %esi movl %eax, -764(%ebp) movl %ecx, %eax shrl $24, %eax sall $3, %eax movl 6144(%esi,%edi), %ecx movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -740(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl %edi, %esi movl 2048(%eax,%edi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -740(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -696(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -700(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx movl %edx, -744(%ebp) shrl $29, %eax movl -744(%ebp), %ecx leal 0(,%edi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %edi, %edx setb %al subl %edi, %edx movl -744(%ebp), %edi movl %edx, -748(%ebp) movl -724(%ebp), %edx addl %edi, %eax subl %eax, %ecx movl -716(%ebp), %eax sall $9, %edx movl %ecx, -752(%ebp) movl -720(%ebp), %ecx shrl $23, %eax orl %edx, %eax movl -476(%ebp), %edi notl %ecx xorl %eax, %ecx xorl %eax, %eax movl -756(%ebp), %edx cmpl %ecx, -476(%ebp) setb %al subl %ecx, %edi movl %edi, -788(%ebp) movl -724(%ebp), %edi movl -484(%ebp), %ecx notl %edi shrl $23, %edi xorl %edx, %edi addl %eax, %edi movl -524(%ebp), %edx subl %edi, %ecx movl %ecx, -792(%ebp) movl -760(%ebp), %ecx xorl %edx, %ecx movl %ecx, -768(%ebp) movl -528(%ebp), %eax movl -764(%ebp), %edi xorl %eax, %edi movl %ecx, %eax shrl $13, %eax movl %edi, -772(%ebp) andl $2040, %eax movzbl %cl,%edi movl 2048(%eax,%esi), %edx movl (%esi,%edi,8), %ecx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -772(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -772(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -748(%ebp), %esi xorl %edi, %edx cmpl %ecx, -748(%ebp) movl -752(%ebp), %edi setb %al addl %eax, %edx subl %ecx, %esi subl %edx, %edi movl %esi, -860(%ebp) movl -768(%ebp), %edx movl tiger_table@GOT(%ebx), %ecx movl %edi, -864(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -772(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -772(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi movl -740(%ebp), %esi xorl %eax, %eax xorl %edi, %edx movl -736(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi setb %al leal 0(,%edi,8), %ecx addl %eax, %edx addl %esi, %edx movl %edi, %eax movl %edx, -776(%ebp) shrl $29, %eax movl -776(%ebp), %esi sall $3, %esi orl %eax, %esi xorl %eax, %eax cmpl %edi, %ecx setb %al subl %edi, %ecx movl %ecx, -780(%ebp) movl -776(%ebp), %edx movl -788(%ebp), %ecx movl -568(%ebp), %edi addl %edx, %eax movl -524(%ebp), %edx subl %eax, %esi xorl %eax, %eax xorl %ecx, %edx movl %esi, -784(%ebp) movl -528(%ebp), %ecx movl -792(%ebp), %esi movl %edx, -796(%ebp) xorl %esi, %ecx movl -564(%ebp), %esi movl %ecx, -804(%ebp) addl %edx, %esi cmpl %edx, %esi movl %esi, -800(%ebp) setb %al addl %ecx, %eax addl %edi, %eax movl %eax, -808(%ebp) movl %edx, %eax notl %eax sall $19, %eax xorl %esi, %eax movl -604(%ebp), %esi cmpl %eax, -604(%ebp) setb %dl movzbl %dl, %edi subl %eax, %esi movl %ecx, %edx movl -796(%ebp), %ecx movl %esi, -812(%ebp) movl -808(%ebp), %esi sall $19, %edx movl -612(%ebp), %eax shrl $13, %ecx orl %ecx, %edx notl %esi movl -680(%ebp), %ecx xorl %edx, %esi addl %edi, %esi movl -812(%ebp), %edi subl %esi, %eax movl %eax, -816(%ebp) movl -608(%ebp), %esi movl -684(%ebp), %edx xorl %edi, %esi movl -644(%ebp), %edi addl %esi, %ecx movl %ecx, -824(%ebp) movl %esi, -820(%ebp) xorl %eax, %edi cmpl %esi, %ecx movl %edi, -828(%ebp) setb %al movzbl %al, %ecx addl %edi, %ecx movl %esi, %eax addl %edx, %ecx movl %ecx, -832(%ebp) movl -824(%ebp), %ecx movl %edi, %esi sall $9, %esi xorl %edx, %edx shrl $23, %eax orl %esi, %eax notl %ecx xorl %eax, %ecx cmpl %ecx, -716(%ebp) movl %edi, %eax movl -716(%ebp), %esi notl %eax movl -724(%ebp), %edi setb %dl subl %ecx, %esi movl -832(%ebp), %ecx shrl $23, %eax movl %esi, -836(%ebp) xorl %ecx, %eax addl %edx, %eax subl %eax, %edi movl %edi, -840(%ebp) movl -720(%ebp), %edx movl -788(%ebp), %ecx xorl %esi, %edx movl -756(%ebp), %esi addl %edx, %ecx movl %edx, -844(%ebp) movl %ecx, -848(%ebp) xorl %edi, %esi cmpl %edx, %ecx movl %esi, -852(%ebp) setb %al movl -792(%ebp), %edx movzbl %al, %eax movl %ecx, %edi addl %esi, %eax addl %edx, %eax xorl $-1985229329, %edi movl -796(%ebp), %esi movl %eax, -856(%ebp) xorl %ecx, %ecx cmpl %edi, -796(%ebp) movl -856(%ebp), %eax movl -800(%ebp), %edx setb %cl xorl $19088743, %eax subl %edi, %esi movl %esi, -884(%ebp) addl %ecx, %eax movl -804(%ebp), %ecx movl -808(%ebp), %edi movl -864(%ebp), %esi subl %eax, %ecx movl %ecx, -888(%ebp) movl -860(%ebp), %eax movl tiger_table@GOT(%ebx), %ecx xorl %edi, %esi xorl %edx, %eax movzbl %al,%edi movl %eax, -868(%ebp) shrl $13, %eax andl $2040, %eax movl %esi, -872(%ebp) movl 2048(%eax,%ecx), %edx movl %ecx, %esi movl (%ecx,%edi,8), %ecx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -872(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -872(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax xorl %edi, %edx movl -780(%ebp), %edi cmpl %ecx, -780(%ebp) setb %al subl %ecx, %edi movl %edi, -892(%ebp) movl -868(%ebp), %ecx movl -784(%ebp), %edi addl %eax, %edx movzbl %ch, %eax subl %edx, %edi movl %edi, -896(%ebp) leal 0(,%eax,8), %edi movl %ecx, %eax shrl $24, %eax movl 6144(%edi,%esi), %ecx sall $3, %eax movl 4096(%eax,%esi), %edx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -872(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -872(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -768(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -772(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx movl %edx, -876(%ebp) leal 0(,%edi,8), %ecx addl %ecx, %edi movl %edi, -880(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -876(%ebp), %ecx setb %al addl %eax, %edx movl -812(%ebp), %eax addl %ecx, %edx movl -816(%ebp), %edi movl %edx, -908(%ebp) movl -892(%ebp), %edx movl -896(%ebp), %ecx xorl %eax, %edx movl %edx, %eax xorl %edi, %ecx movl %ecx, -904(%ebp) shrl $13, %eax movzbl %dl,%edi movl %edx, -900(%ebp) andl $2040, %eax movl 2048(%eax,%esi), %edx movl (%esi,%edi,8), %ecx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -904(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -904(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -880(%ebp), %esi xorl %edi, %edx cmpl %ecx, -880(%ebp) setb %al subl %ecx, %esi movl %esi, -920(%ebp) movl -908(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -900(%ebp), %edx movl %edi, -924(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -904(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -904(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -868(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -872(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,8), %ecx movl %edx, -912(%ebp) addl %ecx, %edi shrl $29, %eax movl %edi, -916(%ebp) sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -912(%ebp), %ecx setb %al movl -828(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -820(%ebp), %eax movl -924(%ebp), %ecx movl %edx, -936(%ebp) movl -920(%ebp), %edx xorl %edi, %ecx movl %ecx, -932(%ebp) xorl %eax, %edx movl %edx, %eax movl %edx, -928(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -932(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -932(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -916(%ebp), %esi xorl %edi, %edx cmpl %ecx, -916(%ebp) setb %al subl %ecx, %esi movl %esi, -948(%ebp) movl -936(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -928(%ebp), %edx movl %edi, -952(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -932(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -932(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -900(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -904(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,8), %ecx movl %edx, -940(%ebp) addl %ecx, %edi shrl $29, %eax movl %edi, -944(%ebp) sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -940(%ebp), %ecx setb %al movl -832(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -824(%ebp), %eax movl -952(%ebp), %ecx movl %edx, -964(%ebp) movl -948(%ebp), %edx xorl %edi, %ecx movl %ecx, -960(%ebp) xorl %eax, %edx movl %edx, %eax movl %edx, -956(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -960(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -960(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -944(%ebp), %esi xorl %edi, %edx cmpl %ecx, -944(%ebp) setb %al subl %ecx, %esi movl %esi, -976(%ebp) movl -964(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -956(%ebp), %edx movl %edi, -980(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -960(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -960(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -928(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -932(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,8), %ecx movl %edx, -968(%ebp) addl %ecx, %edi shrl $29, %eax movl %edi, -972(%ebp) sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -968(%ebp), %ecx setb %al movl -840(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -836(%ebp), %eax movl -980(%ebp), %ecx movl %edx, -992(%ebp) movl -976(%ebp), %edx xorl %edi, %ecx movl %ecx, -988(%ebp) xorl %eax, %edx movl %edx, %eax movl %edx, -984(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -988(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -988(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -972(%ebp), %esi xorl %edi, %edx cmpl %ecx, -972(%ebp) setb %al subl %ecx, %esi movl %esi, -1004(%ebp) movl -992(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -984(%ebp), %edx movl %edi, -1008(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -988(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -988(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -956(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -960(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,8), %ecx movl %edx, -996(%ebp) addl %ecx, %edi shrl $29, %eax movl %edi, -1000(%ebp) sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -996(%ebp), %ecx setb %al movl -852(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -844(%ebp), %eax movl -1008(%ebp), %ecx movl %edx, -1020(%ebp) movl -1004(%ebp), %edx xorl %edi, %ecx movl %ecx, -1016(%ebp) xorl %eax, %edx movl %edx, %eax movl %edx, -1012(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -1016(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -1016(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -1000(%ebp), %esi xorl %edi, %edx cmpl %ecx, -1000(%ebp) setb %al subl %ecx, %esi movl %esi, -1032(%ebp) movl -1020(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -1012(%ebp), %edx movl %edi, -1036(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -1016(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -1016(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax movl %esi, -148(%ebp) xorl %edi, %edx movl -984(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -988(%ebp), %ecx setb %al addl %eax, %edx addl %ecx, %edx movl %edx, -1024(%ebp) leal 0(,%edi,8), %ecx movl %edi, %eax shrl $29, %eax addl %ecx, %edi sall $3, %edx movl %edi, -1028(%ebp) orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -1024(%ebp), %ecx setb %al addl %eax, %edx movl -848(%ebp), %eax movl -856(%ebp), %edi addl %ecx, %edx movl -1036(%ebp), %ecx movl %edx, -1048(%ebp) movl -1032(%ebp), %edx xorl %edi, %ecx movl %ecx, -1044(%ebp) xorl %eax, %edx movl %edx, %eax movl %edx, -1040(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -1044(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -1044(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -1028(%ebp), %esi xorl %edi, %edx cmpl %ecx, -1028(%ebp) setb %al subl %ecx, %esi movl %esi, -1060(%ebp) movl -1048(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -1040(%ebp), %edx movl %edi, -1064(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -1044(%ebp), %eax movzbl %ah, %edi leal 0(,%edi,8), %eax movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -1044(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi xorl %eax, %eax xorl %edi, %edx movl -1012(%ebp), %edi addl %ecx, %edi cmpl %ecx, %edi movl -1016(%ebp), %ecx setb %al addl %eax, %edx movl %edi, %eax addl %ecx, %edx leal 0(,%edi,8), %ecx movl %edx, -1052(%ebp) addl %ecx, %edi shrl $29, %eax movl %edi, -1056(%ebp) sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %edi movl -1052(%ebp), %ecx setb %al movl -888(%ebp), %edi addl %eax, %edx addl %ecx, %edx movl -884(%ebp), %eax movl -1064(%ebp), %ecx movl %edx, -1076(%ebp) movl -1060(%ebp), %edx xorl %edi, %ecx movl %ecx, -1072(%ebp) xorl %eax, %edx movl %edx, %eax movl %edx, -1068(%ebp) shrl $13, %eax movzbl %dl,%edi andl $2040, %eax movl (%esi,%edi,8), %ecx movl 2048(%eax,%esi), %edx movl 2052(%eax,%esi), %eax xorl %edx, %ecx movl 4(%esi,%edi,8), %edx xorl %eax, %edx movzbl -1072(%ebp),%eax sall $3, %eax movl 4096(%eax,%esi), %edi xorl %edi, %ecx movl 4100(%eax,%esi), %edi movl -1072(%ebp), %eax xorl %edi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%esi), %edi xorl %edi, %ecx movl 6148(%eax,%esi), %edi xorl %eax, %eax movl -1056(%ebp), %esi xorl %edi, %edx cmpl %ecx, -1056(%ebp) setb %al subl %ecx, %esi movl %esi, -1080(%ebp) movl -1076(%ebp), %edi addl %eax, %edx movl tiger_table@GOT(%ebx), %ecx subl %edx, %edi movl -1068(%ebp), %edx movl %edi, -1084(%ebp) movl %edx, %eax movzbl %dh, %esi shrl $24, %eax leal 0(,%esi,8), %edi movl %ecx, %esi sall $3, %eax movl 4096(%eax,%ecx), %edx movl 6144(%edi,%ecx), %ecx movl 4100(%eax,%esi), %eax xorl %edx, %ecx movl 6148(%edi,%esi), %edx xorl %eax, %edx movl -1072(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl -148(%ebp), %esi movl 2048(%eax,%esi), %edi xorl %edi, %ecx movl 2052(%eax,%esi), %edi movl -1072(%ebp), %eax xorl %edi, %edx shrl $24, %eax movl (%esi,%eax,8), %edi xorl %edi, %ecx movl 4(%esi,%eax,8), %edi movl -1040(%ebp), %esi xorl %eax, %eax xorl %edi, %edx addl %ecx, %esi cmpl %ecx, %esi movl -1044(%ebp), %edi setb %al addl %eax, %edx leal 0(,%esi,8), %ecx addl %edx, %edi movl %esi, %eax leal 0(,%edi,8), %edx addl %ecx, %esi shrl $29, %eax orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi setb %al addl %eax, %edx leal (%edi,%edx), %ecx movl -1088(%ebp), %edi movl -1092(%ebp), %edx xorl %esi, %edi movl -16(%ebp), %esi xorl %edx, %ecx cmpl %esi, -1068(%ebp) movl %ecx, -1108(%ebp) movl -16(%ebp), %edx movl -1068(%ebp), %esi movl -1100(%ebp), %ecx setb %al subl %edx, %esi movl -1072(%ebp), %edx movzbl %al, %eax addl %ecx, %eax movl -1080(%ebp), %ecx subl %eax, %edx movl -20(%ebp), %eax addl %eax, %ecx xorl %eax, %eax cmpl -20(%ebp), %ecx setb %al addl -1104(%ebp), %eax addl -1084(%ebp), %eax movl %eax, -1152(%ebp) movl 12(%ebp), %eax movl %edi, (%eax) movl -1108(%ebp), %edi movl %esi, 8(%eax) movl %edx, 12(%eax) movl %edi, 4(%eax) movl %ecx, 16(%eax) movl -1152(%ebp), %edx movl %edx, 20(%eax) addl $1140, %esp popl %ebx popl %esi popl %edi popl %ebp ret .size tiger_compress, .-tiger_compress .globl tiger_t .type tiger_t, @function tiger_t: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx subl $1032, %esp movl 12(%ebp), %eax call __i686.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_, %ebx movl %eax, -16(%ebp) cmpl $63, %eax jbe .L8 movl tiger_table@GOT(%ebx), %edi .L6: movl 16(%ebp), %esi movl 16(%ebp), %edx movl (%esi), %ecx movl 16(%ebp), %esi movl %ecx, -948(%ebp) movl 4(%edx), %eax movl 16(%ebp), %edx movl %eax, -952(%ebp) movl 8(%esi), %ecx movl 16(%ebp), %esi movl %ecx, -956(%ebp) movl 12(%edx), %eax movl -956(%ebp), %edx movl %eax, -960(%ebp) movl 16(%esi), %eax movl 20(%esi), %ecx movl %edx, -20(%ebp) movl 8(%ebp), %esi movl 8(%ebp), %edx movl %eax, -24(%ebp) movl %ecx, -964(%ebp) movl (%esi), %ecx movl %ecx, -968(%ebp) movl 4(%edx), %esi movl 8(%ebp), %ecx movl %esi, -972(%ebp) movl 8(%ecx), %edx movl 8(%ebp), %esi movl %edx, -976(%ebp) movl 12(%esi), %ecx movl 8(%ebp), %edx movl %ecx, -980(%ebp) movl 16(%edx), %esi movl %esi, -984(%ebp) movl 8(%ebp), %ecx movl 8(%ebp), %esi movl 20(%ecx), %edx movl %edx, -988(%ebp) movl 24(%esi), %ecx movl 8(%ebp), %edx movl %ecx, -992(%ebp) movl 28(%edx), %esi movl 8(%ebp), %ecx movl %esi, -996(%ebp) movl 32(%ecx), %edx movl 8(%ebp), %esi movl %edx, -1000(%ebp) movl 36(%esi), %ecx movl 8(%ebp), %edx movl %ecx, -1004(%ebp) movl 40(%edx), %esi movl 8(%ebp), %ecx movl %esi, -1008(%ebp) movl 44(%ecx), %edx movl 8(%ebp), %esi movl %edx, -1012(%ebp) movl 48(%esi), %ecx movl 8(%ebp), %edx movl %ecx, -1016(%ebp) movl 52(%edx), %esi movl 8(%ebp), %ecx movl %esi, -1020(%ebp) movl 56(%ecx), %edx movl 8(%ebp), %esi movl %edx, -1024(%ebp) movl -968(%ebp), %edx movl 60(%esi), %ecx xorl %edx, %eax movl %ecx, -1028(%ebp) movl %eax, -28(%ebp) movl -972(%ebp), %esi movl -964(%ebp), %ecx movl -28(%ebp), %eax xorl %esi, %ecx shrl $13, %eax movzbl -28(%ebp),%esi movl %ecx, -32(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax movl (%edi,%esi,8), %ecx xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -32(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -32(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -948(%ebp), %esi cmpl %ecx, -948(%ebp) setb %al subl %ecx, %esi movl %esi, -44(%ebp) movl -952(%ebp), %ecx addl %eax, %edx subl %edx, %ecx movl -28(%ebp), %edx movl %ecx, -48(%ebp) movzbl %dh, %eax leal 0(,%eax,8), %ecx movl %edx, %eax movl 6144(%ecx,%edi), %esi shrl $24, %eax sall $3, %eax movl 6148(%ecx,%edi), %ecx movl 4096(%eax,%edi), %edx xorl %esi, %edx movl 4100(%eax,%edi), %esi movl -32(%ebp), %eax xorl %esi, %ecx movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %edx movl 2052(%eax,%edi), %esi movl -32(%ebp), %eax xorl %esi, %ecx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %edx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %ecx movl -956(%ebp), %esi addl %edx, %esi cmpl %edx, %esi movl -960(%ebp), %edx setb %al leal (%ecx,%eax), %eax addl %edx, %eax movl %eax, -36(%ebp) leal 0(,%esi,4), %ecx movl %eax, %edx movl %esi, %eax sall $2, %edx addl %ecx, %esi movl %esi, -40(%ebp) shrl $30, %eax orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi setb %al addl %eax, %edx movl -36(%ebp), %eax xorl %ecx, %ecx movl -968(%ebp), %esi addl %eax, %edx movl -1028(%ebp), %eax movl %edx, -60(%ebp) movl -1024(%ebp), %edx xorl $-1515870811, %edx cmpl %edx, -968(%ebp) setb %cl subl %edx, %esi movl %esi, -72(%ebp) movl -972(%ebp), %esi xorl $-1515870811, %eax addl %ecx, %eax movl -976(%ebp), %edx movl -980(%ebp), %ecx subl %eax, %esi movl -44(%ebp), %eax movl %esi, -76(%ebp) movl -48(%ebp), %esi xorl %edx, %eax movl %eax, -52(%ebp) xorl %ecx, %esi movl %esi, -56(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -56(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -56(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -40(%ebp), %esi cmpl %ecx, -40(%ebp) setb %al subl %ecx, %esi movl %esi, -80(%ebp) movl -52(%ebp), %ecx addl %eax, %edx movl -60(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -84(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -56(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -56(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -28(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -32(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -64(%ebp) leal 0(,%esi,4), %ecx addl %ecx, %esi movl %esi, -68(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -64(%ebp), %esi setb %al addl %eax, %edx movl -976(%ebp), %ecx addl %esi, %edx movl -76(%ebp), %eax movl %edx, -96(%ebp) movl -980(%ebp), %esi movl -72(%ebp), %edx xorl %eax, %esi xorl %edx, %ecx movl %esi, -116(%ebp) movl -984(%ebp), %edx movl %ecx, -108(%ebp) movl -80(%ebp), %eax movl -988(%ebp), %ecx movl -84(%ebp), %esi xorl %edx, %eax movl %eax, -88(%ebp) xorl %ecx, %esi movl %esi, -92(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -92(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -92(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -68(%ebp), %esi cmpl %ecx, -68(%ebp) setb %al subl %ecx, %esi movl %esi, -120(%ebp) movl -88(%ebp), %ecx addl %eax, %edx movl -96(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -124(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -92(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -92(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -52(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -56(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -100(%ebp) leal 0(,%esi,4), %ecx addl %ecx, %esi movl %esi, -104(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -100(%ebp), %ecx setb %al addl %eax, %edx movl -108(%ebp), %eax addl %ecx, %edx movl -108(%ebp), %esi movl %edx, -136(%ebp) movl -984(%ebp), %edx movl -116(%ebp), %ecx addl %eax, %edx xorl %eax, %eax cmpl %esi, %edx movl %edx, -112(%ebp) movl -988(%ebp), %esi setb %al addl %ecx, %eax movl -992(%ebp), %edx movl -996(%ebp), %ecx addl %esi, %eax movl -124(%ebp), %esi movl %eax, -148(%ebp) movl -120(%ebp), %eax xorl %ecx, %esi movl %esi, -132(%ebp) xorl %edx, %eax movzbl %al,%esi movl %eax, -128(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -132(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -132(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -104(%ebp), %esi cmpl %ecx, -104(%ebp) setb %al subl %ecx, %esi movl %esi, -152(%ebp) movl -128(%ebp), %ecx addl %eax, %edx movl -136(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -156(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -132(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -132(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -88(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -92(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -140(%ebp) leal 0(,%esi,4), %ecx addl %ecx, %esi movl %esi, -144(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi setb %al movl -112(%ebp), %esi addl %eax, %edx movl -140(%ebp), %eax addl %eax, %edx movl -108(%ebp), %eax movl %edx, -168(%ebp) movl -992(%ebp), %edx notl %eax sall $19, %eax xorl %esi, %eax cmpl %eax, -992(%ebp) setb %cl movzbl %cl, %esi subl %eax, %edx movl -108(%ebp), %ecx movl -116(%ebp), %eax movl %edx, -180(%ebp) movl -148(%ebp), %edx shrl $13, %ecx sall $19, %eax orl %ecx, %eax notl %edx xorl %eax, %edx movl -996(%ebp), %eax addl %esi, %edx movl -1004(%ebp), %ecx subl %edx, %eax movl -156(%ebp), %esi movl %eax, -184(%ebp) movl -1000(%ebp), %edx movl -152(%ebp), %eax xorl %ecx, %esi movl %esi, -164(%ebp) xorl %edx, %eax movzbl %al,%esi movl %eax, -160(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -164(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -164(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -144(%ebp), %esi cmpl %ecx, -144(%ebp) setb %al subl %ecx, %esi movl %esi, -188(%ebp) movl -168(%ebp), %esi addl %eax, %edx subl %edx, %esi movl %esi, -192(%ebp) movl -160(%ebp), %ecx movzbl %ch, %eax leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax sall $3, %eax movl 6144(%esi,%edi), %ecx movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -164(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -164(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -128(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -132(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx leal 0(,%esi,4), %ecx movl %edx, -172(%ebp) addl %ecx, %esi shrl $30, %eax movl %esi, -176(%ebp) sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -172(%ebp), %esi setb %al movl -1000(%ebp), %ecx addl %eax, %edx addl %esi, %edx movl -184(%ebp), %eax movl -1004(%ebp), %esi movl %edx, -204(%ebp) movl -180(%ebp), %edx xorl %eax, %esi movl %esi, -224(%ebp) movl -188(%ebp), %eax xorl %edx, %ecx movl %ecx, -216(%ebp) movl -1008(%ebp), %edx movl -1012(%ebp), %ecx movl -192(%ebp), %esi xorl %edx, %eax movl %eax, -196(%ebp) xorl %ecx, %esi movl %esi, -200(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -200(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -200(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -176(%ebp), %esi cmpl %ecx, -176(%ebp) setb %al subl %ecx, %esi movl %esi, -228(%ebp) movl -196(%ebp), %ecx movl -204(%ebp), %esi addl %eax, %edx movzbl %ch, %eax subl %edx, %esi movl %esi, -232(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -200(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -200(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -160(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -164(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -208(%ebp) leal 0(,%esi,4), %ecx addl %ecx, %esi movl %esi, -212(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -208(%ebp), %ecx setb %al addl %eax, %edx movl -216(%ebp), %eax addl %ecx, %edx movl -216(%ebp), %esi movl %edx, -244(%ebp) movl -1008(%ebp), %edx movl -224(%ebp), %ecx addl %eax, %edx xorl %eax, %eax cmpl %esi, %edx movl %edx, -220(%ebp) movl -1012(%ebp), %esi setb %al addl %ecx, %eax movl -1016(%ebp), %edx movl -1020(%ebp), %ecx addl %esi, %eax movl -232(%ebp), %esi movl %eax, -256(%ebp) movl -228(%ebp), %eax xorl %ecx, %esi movl %esi, -240(%ebp) xorl %edx, %eax movzbl %al,%esi movl %eax, -236(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -240(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -240(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -212(%ebp), %esi cmpl %ecx, -212(%ebp) setb %al subl %ecx, %esi movl %esi, -260(%ebp) movl -236(%ebp), %ecx movl -244(%ebp), %esi addl %eax, %edx movzbl %ch, %eax subl %edx, %esi movl %esi, -264(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -240(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -240(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -196(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -200(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -248(%ebp) leal 0(,%esi,4), %ecx addl %ecx, %esi movl %esi, -252(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -248(%ebp), %esi setb %al addl %eax, %edx movl -216(%ebp), %eax addl %esi, %edx movl -220(%ebp), %ecx movl %edx, -276(%ebp) movl -224(%ebp), %edx shrl $23, %eax notl %ecx movl -1016(%ebp), %esi sall $9, %edx orl %edx, %eax xorl %eax, %ecx xorl %edx, %edx cmpl %ecx, -1016(%ebp) movl -224(%ebp), %eax setb %dl subl %ecx, %esi movl -256(%ebp), %ecx notl %eax movl %esi, -288(%ebp) shrl $23, %eax movl -1020(%ebp), %esi xorl %ecx, %eax addl %edx, %eax movl -1028(%ebp), %ecx subl %eax, %esi movl -1024(%ebp), %edx movl -260(%ebp), %eax movl %esi, -292(%ebp) movl -264(%ebp), %esi xorl %edx, %eax movl %eax, -268(%ebp) xorl %ecx, %esi movl %esi, -272(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -272(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -272(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -252(%ebp), %esi cmpl %ecx, -252(%ebp) setb %al subl %ecx, %esi movl %esi, -360(%ebp) movl -268(%ebp), %ecx addl %eax, %edx movl -276(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -364(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -272(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -272(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -236(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -240(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -280(%ebp) leal 0(,%esi,4), %ecx addl %ecx, %esi movl %esi, -284(%ebp) shrl $30, %eax sall $2, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -280(%ebp), %ecx setb %al addl %eax, %edx movl -288(%ebp), %esi addl %ecx, %edx movl %edx, -376(%ebp) movl -1024(%ebp), %edx xorl %esi, %edx movl %edx, -296(%ebp) movl -72(%ebp), %ecx movl -292(%ebp), %eax movl -1028(%ebp), %esi addl %edx, %ecx movl %ecx, -300(%ebp) xorl %eax, %esi cmpl %edx, %ecx movl %esi, -304(%ebp) setb %al movl -76(%ebp), %ecx movzbl %al, %eax addl %esi, %eax addl %ecx, %eax movl %eax, -308(%ebp) movl -300(%ebp), %esi movl %edx, %eax notl %eax movl -108(%ebp), %edx sall $19, %eax xorl %esi, %eax cmpl %eax, -108(%ebp) setb %cl movzbl %cl, %esi subl %eax, %edx movl -296(%ebp), %ecx movl -304(%ebp), %eax movl %edx, -312(%ebp) movl -308(%ebp), %edx shrl $13, %ecx sall $19, %eax orl %ecx, %eax notl %edx xorl %eax, %edx movl -112(%ebp), %ecx addl %esi, %edx movl -116(%ebp), %esi subl %edx, %esi movl -312(%ebp), %edx movl %esi, -316(%ebp) xorl %edx, %ecx movl -148(%ebp), %edx movl %ecx, -320(%ebp) xorl %esi, %edx movl -180(%ebp), %esi movl %edx, -328(%ebp) addl %ecx, %esi cmpl %ecx, %esi movl %esi, -324(%ebp) setb %al movl -184(%ebp), %ecx movzbl %al, %eax addl %edx, %eax addl %ecx, %eax movl %eax, -332(%ebp) movl -320(%ebp), %eax sall $9, %edx movl %esi, %ecx notl %ecx movl -216(%ebp), %esi shrl $23, %eax orl %edx, %eax xorl %eax, %ecx xorl %edx, %edx cmpl %ecx, -216(%ebp) movl -328(%ebp), %eax setb %dl subl %ecx, %esi movl -332(%ebp), %ecx notl %eax movl %esi, -336(%ebp) shrl $23, %eax xorl %ecx, %eax addl %edx, %eax movl -336(%ebp), %esi movl -224(%ebp), %edx movl -220(%ebp), %ecx subl %eax, %edx xorl %esi, %ecx movl %edx, -340(%ebp) movl %ecx, -344(%ebp) movl -256(%ebp), %eax xorl %edx, %eax movl %eax, -352(%ebp) movl -288(%ebp), %edx movl -352(%ebp), %esi xorl %eax, %eax addl %ecx, %edx cmpl %ecx, %edx movl %edx, -348(%ebp) movl -292(%ebp), %ecx setb %al addl %esi, %eax xorl $-1985229329, %edx movl -296(%ebp), %esi addl %ecx, %eax xorl %ecx, %ecx cmpl %edx, -296(%ebp) movl %eax, -356(%ebp) movl -356(%ebp), %eax setb %cl subl %edx, %esi xorl $19088743, %eax addl %ecx, %eax movl %esi, -392(%ebp) movl -304(%ebp), %esi movl -300(%ebp), %edx movl -308(%ebp), %ecx subl %eax, %esi movl -360(%ebp), %eax movl %esi, -396(%ebp) movl -364(%ebp), %esi xorl %edx, %eax movl %eax, -368(%ebp) xorl %ecx, %esi movl %esi, -372(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -372(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -372(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -284(%ebp), %esi cmpl %ecx, -284(%ebp) setb %al subl %ecx, %esi movl %esi, -400(%ebp) movl -376(%ebp), %esi addl %eax, %edx subl %edx, %esi movl %esi, -404(%ebp) movl -368(%ebp), %ecx movzbl %ch, %eax leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax sall $3, %eax movl 6144(%esi,%edi), %ecx movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -372(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -372(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -268(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -272(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx shrl $29, %eax movl %edx, -380(%ebp) movl -380(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl %edx, -384(%ebp) movl -380(%ebp), %esi movl -392(%ebp), %edx addl %esi, %eax subl %eax, %ecx xorl $-1515870811, %edx movl %ecx, -388(%ebp) xorl %ecx, %ecx cmpl %edx, -300(%ebp) movl -300(%ebp), %esi movl -396(%ebp), %eax setb %cl subl %edx, %esi xorl $-1515870811, %eax movl %esi, -428(%ebp) movl -308(%ebp), %esi addl %ecx, %eax movl -312(%ebp), %edx movl -316(%ebp), %ecx subl %eax, %esi movl %esi, -432(%ebp) movl -400(%ebp), %eax movl -404(%ebp), %esi xorl %edx, %eax xorl %ecx, %esi movl %esi, -412(%ebp) movzbl %al,%esi movl %eax, -408(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -412(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -412(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -384(%ebp), %esi cmpl %ecx, -384(%ebp) setb %al subl %ecx, %esi movl %esi, -436(%ebp) movl -408(%ebp), %ecx movl -388(%ebp), %esi addl %eax, %edx movzbl %ch, %eax subl %edx, %esi movl %esi, -440(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -412(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -412(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -368(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -372(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -416(%ebp) shrl $29, %eax movl -416(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -416(%ebp), %esi movl %edx, -420(%ebp) movl -428(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl -316(%ebp), %esi movl -432(%ebp), %eax movl %ecx, -424(%ebp) movl -312(%ebp), %ecx xorl %eax, %esi movl %esi, -472(%ebp) movl -436(%ebp), %eax xorl %edx, %ecx movl %ecx, -464(%ebp) movl -320(%ebp), %edx movl -328(%ebp), %ecx movl -440(%ebp), %esi xorl %edx, %eax movl %eax, -444(%ebp) xorl %ecx, %esi movl %esi, -448(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -448(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -448(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -420(%ebp), %esi cmpl %ecx, -420(%ebp) setb %al subl %ecx, %esi movl %esi, -476(%ebp) movl -444(%ebp), %ecx movl -424(%ebp), %esi addl %eax, %edx movzbl %ch, %eax subl %edx, %esi movl %esi, -480(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -448(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -448(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -408(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -412(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -452(%ebp) shrl $29, %eax movl -452(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -452(%ebp), %esi movl %edx, -456(%ebp) movl -320(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl -464(%ebp), %eax movl -464(%ebp), %esi movl %ecx, -460(%ebp) addl %eax, %edx movl -472(%ebp), %ecx movl %edx, -468(%ebp) xorl %eax, %eax cmpl %esi, %edx movl -328(%ebp), %esi setb %al addl %ecx, %eax movl -324(%ebp), %edx addl %esi, %eax movl -332(%ebp), %ecx movl %eax, -504(%ebp) movl -480(%ebp), %esi movl -476(%ebp), %eax xorl %ecx, %esi xorl %edx, %eax movl %esi, -488(%ebp) movzbl %al,%esi movl %eax, -484(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -488(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -488(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -456(%ebp), %esi cmpl %ecx, -456(%ebp) setb %al subl %ecx, %esi movl %esi, -508(%ebp) movl -484(%ebp), %ecx movl -460(%ebp), %esi addl %eax, %edx movzbl %ch, %eax subl %edx, %esi movl %esi, -512(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -488(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -488(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -444(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -448(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -492(%ebp) shrl $29, %eax movl -492(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -468(%ebp), %esi movl %edx, -496(%ebp) movl -492(%ebp), %edx addl %edx, %eax subl %eax, %ecx movl -464(%ebp), %eax movl -324(%ebp), %edx movl %ecx, -500(%ebp) notl %eax sall $19, %eax xorl %esi, %eax cmpl %eax, -324(%ebp) setb %cl movzbl %cl, %esi subl %eax, %edx movl -464(%ebp), %ecx movl -472(%ebp), %eax movl %edx, -536(%ebp) movl -504(%ebp), %edx shrl $13, %ecx sall $19, %eax orl %ecx, %eax notl %edx xorl %eax, %edx movl -332(%ebp), %eax addl %esi, %edx movl -340(%ebp), %ecx subl %edx, %eax movl -512(%ebp), %esi movl %eax, -540(%ebp) movl -336(%ebp), %edx movl -508(%ebp), %eax xorl %ecx, %esi xorl %edx, %eax movl %eax, -516(%ebp) movl %esi, -520(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -520(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -520(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -496(%ebp), %esi cmpl %ecx, -496(%ebp) setb %al subl %ecx, %esi movl %esi, -544(%ebp) movl -516(%ebp), %ecx addl %eax, %edx movl -500(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -548(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -520(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -520(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -484(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -488(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -524(%ebp) shrl $29, %eax movl -524(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -524(%ebp), %esi movl %edx, -528(%ebp) movl -536(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl %ecx, -532(%ebp) movl -336(%ebp), %ecx xorl %edx, %ecx movl %ecx, -572(%ebp) movl -540(%ebp), %eax movl -340(%ebp), %esi movl -344(%ebp), %edx movl -352(%ebp), %ecx xorl %eax, %esi movl %esi, -580(%ebp) movl -544(%ebp), %eax movl -548(%ebp), %esi xorl %edx, %eax xorl %ecx, %esi movl %esi, -556(%ebp) movzbl %al,%esi movl %eax, -552(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -556(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -556(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -528(%ebp), %esi cmpl %ecx, -528(%ebp) setb %al subl %ecx, %esi movl %esi, -584(%ebp) movl -552(%ebp), %ecx addl %eax, %edx movl -532(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -588(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -556(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -556(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -516(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -520(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -560(%ebp) movl -560(%ebp), %ecx leal 0(,%esi,8), %edx shrl $29, %eax sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -560(%ebp), %esi movl %edx, -564(%ebp) movl -344(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl -572(%ebp), %eax movl -572(%ebp), %esi movl %ecx, -568(%ebp) addl %eax, %edx movl -580(%ebp), %ecx movl %edx, -576(%ebp) xorl %eax, %eax cmpl %esi, %edx movl -352(%ebp), %esi setb %al addl %ecx, %eax movl -348(%ebp), %edx addl %esi, %eax movl -356(%ebp), %ecx movl %eax, -612(%ebp) movl -588(%ebp), %esi movl -584(%ebp), %eax xorl %ecx, %esi xorl %edx, %eax movl %esi, -596(%ebp) movzbl %al,%esi movl %eax, -592(%ebp) shrl $13, %eax movl (%edi,%esi,8), %ecx andl $2040, %eax movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -596(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -596(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -564(%ebp), %esi cmpl %ecx, -564(%ebp) setb %al subl %ecx, %esi movl %esi, -616(%ebp) movl -592(%ebp), %ecx addl %eax, %edx movl -568(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -620(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -596(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -596(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -552(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -556(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -600(%ebp) movl -600(%ebp), %ecx leal 0(,%esi,8), %edx shrl $29, %eax sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl -600(%ebp), %esi movl %edx, -604(%ebp) movl -580(%ebp), %edx addl %esi, %eax subl %eax, %ecx movl -572(%ebp), %eax sall $9, %edx movl %ecx, -608(%ebp) movl -576(%ebp), %ecx shrl $23, %eax orl %edx, %eax xorl %edx, %edx notl %ecx xorl %eax, %ecx movl -348(%ebp), %esi movl -580(%ebp), %eax cmpl %ecx, -348(%ebp) notl %eax setb %dl subl %ecx, %esi movl -612(%ebp), %ecx shrl $23, %eax movl %esi, -644(%ebp) movl -356(%ebp), %esi xorl %ecx, %eax addl %edx, %eax movl -396(%ebp), %ecx movl -392(%ebp), %edx subl %eax, %esi movl -616(%ebp), %eax movl %esi, -648(%ebp) movl -620(%ebp), %esi xorl %edx, %eax movl %eax, -624(%ebp) xorl %ecx, %esi movl %esi, -628(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -628(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -628(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -604(%ebp), %esi cmpl %ecx, -604(%ebp) setb %al subl %ecx, %esi movl %esi, -716(%ebp) movl -608(%ebp), %esi addl %eax, %edx subl %edx, %esi movl %esi, -720(%ebp) movl -624(%ebp), %ecx movzbl %ch, %eax leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax sall $3, %eax movl 6144(%esi,%edi), %ecx movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -628(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -628(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -592(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -596(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx shrl $29, %eax movl %edx, -632(%ebp) movl -632(%ebp), %ecx leal 0(,%esi,8), %edx sall $3, %ecx orl %eax, %ecx xorl %eax, %eax cmpl %esi, %edx setb %al subl %esi, %edx movl %edx, -636(%ebp) movl -632(%ebp), %edx movl -644(%ebp), %esi addl %edx, %eax movl -392(%ebp), %edx subl %eax, %ecx movl %ecx, -640(%ebp) movl -428(%ebp), %ecx movl -648(%ebp), %eax xorl %esi, %edx movl -396(%ebp), %esi addl %edx, %ecx movl %ecx, -656(%ebp) movl %edx, -652(%ebp) xorl %eax, %esi cmpl %edx, %ecx movl %esi, -660(%ebp) setb %al movl -432(%ebp), %ecx movzbl %al, %eax addl %esi, %eax addl %ecx, %eax movl %eax, -664(%ebp) movl -656(%ebp), %esi movl %edx, %eax notl %eax movl -464(%ebp), %edx sall $19, %eax xorl %esi, %eax cmpl %eax, -464(%ebp) setb %cl movzbl %cl, %esi subl %eax, %edx movl -652(%ebp), %ecx movl -660(%ebp), %eax movl %edx, -668(%ebp) movl -664(%ebp), %edx shrl $13, %ecx sall $19, %eax orl %ecx, %eax notl %edx xorl %eax, %edx addl %esi, %edx movl -472(%ebp), %esi subl %edx, %esi movl %esi, -672(%ebp) movl -668(%ebp), %edx movl -468(%ebp), %ecx xorl %edx, %ecx movl -504(%ebp), %edx movl %ecx, -676(%ebp) xorl %esi, %edx movl -536(%ebp), %esi movl %edx, -684(%ebp) addl %ecx, %esi cmpl %ecx, %esi movl %esi, -680(%ebp) setb %al movl -540(%ebp), %ecx movzbl %al, %eax addl %edx, %eax addl %ecx, %eax movl %eax, -688(%ebp) movl -676(%ebp), %eax sall $9, %edx movl %esi, %ecx notl %ecx movl -572(%ebp), %esi shrl $23, %eax orl %edx, %eax xorl %eax, %ecx xorl %edx, %edx cmpl %ecx, -572(%ebp) movl -684(%ebp), %eax setb %dl subl %ecx, %esi movl -688(%ebp), %ecx notl %eax movl %esi, -692(%ebp) shrl $23, %eax xorl %ecx, %eax addl %edx, %eax movl -580(%ebp), %edx movl -692(%ebp), %esi movl -576(%ebp), %ecx subl %eax, %edx movl -612(%ebp), %eax movl %edx, -696(%ebp) xorl %esi, %ecx movl %ecx, -700(%ebp) xorl %edx, %eax movl -644(%ebp), %edx movl %eax, -708(%ebp) movl -708(%ebp), %esi xorl %eax, %eax addl %ecx, %edx cmpl %ecx, %edx movl -648(%ebp), %ecx movl %edx, -704(%ebp) setb %al addl %esi, %eax xorl $-1985229329, %edx addl %ecx, %eax movl -652(%ebp), %esi movl %eax, -712(%ebp) xorl %ecx, %ecx movl -712(%ebp), %eax cmpl %edx, -652(%ebp) setb %cl subl %edx, %esi movl %esi, -740(%ebp) movl -660(%ebp), %esi xorl $19088743, %eax addl %ecx, %eax movl -656(%ebp), %edx subl %eax, %esi movl %esi, -744(%ebp) movl -716(%ebp), %eax xorl %edx, %eax movl %eax, -724(%ebp) movl -664(%ebp), %ecx movl -720(%ebp), %esi xorl %ecx, %esi movl %esi, -728(%ebp) movzbl %al,%esi shrl $13, %eax andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -728(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -728(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -636(%ebp), %esi cmpl %ecx, -636(%ebp) setb %al subl %ecx, %esi movl %esi, -748(%ebp) movl -724(%ebp), %ecx addl %eax, %edx movl -640(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -752(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -728(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -728(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -624(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -628(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -732(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -736(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -732(%ebp), %esi setb %al addl %eax, %edx addl %esi, %edx movl %edx, -764(%ebp) movl -668(%ebp), %eax movl -748(%ebp), %edx movl -672(%ebp), %ecx movl -752(%ebp), %esi xorl %eax, %edx movl %edx, -756(%ebp) movl %edx, %eax xorl %ecx, %esi movl %esi, -760(%ebp) shrl $13, %eax movzbl %dl,%esi andl $2040, %eax movl (%edi,%esi,8), %ecx movl 2048(%eax,%edi), %edx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -760(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -760(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -736(%ebp), %esi cmpl %ecx, -736(%ebp) setb %al subl %ecx, %esi movl %esi, -776(%ebp) movl -756(%ebp), %ecx addl %eax, %edx movl -764(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -780(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -760(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -760(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -724(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -728(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -768(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -772(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -768(%ebp), %esi setb %al addl %eax, %edx movl -676(%ebp), %eax addl %esi, %edx movl -684(%ebp), %ecx movl %edx, -792(%ebp) movl -776(%ebp), %edx movl -780(%ebp), %esi xorl %eax, %edx movl %edx, %eax xorl %ecx, %esi movl %esi, -788(%ebp) shrl $13, %eax movzbl %dl,%esi movl %edx, -784(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl (%edi,%esi,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -788(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -788(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -772(%ebp), %esi cmpl %ecx, -772(%ebp) setb %al subl %ecx, %esi movl %esi, -804(%ebp) movl -784(%ebp), %ecx addl %eax, %edx movl -792(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -808(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -788(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -788(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -756(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -760(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -796(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -800(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -796(%ebp), %esi setb %al addl %eax, %edx movl -680(%ebp), %eax addl %esi, %edx movl -688(%ebp), %ecx movl %edx, -820(%ebp) movl -804(%ebp), %edx movl -808(%ebp), %esi xorl %eax, %edx movl %edx, %eax xorl %ecx, %esi movl %esi, -816(%ebp) shrl $13, %eax movzbl %dl,%esi movl %edx, -812(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl (%edi,%esi,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -816(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -816(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -800(%ebp), %esi cmpl %ecx, -800(%ebp) setb %al subl %ecx, %esi movl %esi, -832(%ebp) movl -812(%ebp), %ecx addl %eax, %edx movl -820(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -836(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -816(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -816(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -784(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -788(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -824(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -828(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -824(%ebp), %esi setb %al addl %eax, %edx movl -692(%ebp), %eax addl %esi, %edx movl -696(%ebp), %ecx movl %edx, -848(%ebp) movl -832(%ebp), %edx movl -836(%ebp), %esi xorl %eax, %edx movl %edx, %eax xorl %ecx, %esi movl %esi, -844(%ebp) shrl $13, %eax movzbl %dl,%esi movl %edx, -840(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl (%edi,%esi,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -844(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -844(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -828(%ebp), %esi cmpl %ecx, -828(%ebp) setb %al subl %ecx, %esi movl %esi, -860(%ebp) movl -840(%ebp), %ecx addl %eax, %edx movl -848(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -864(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -844(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -844(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -812(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -816(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -852(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -856(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -852(%ebp), %esi setb %al addl %eax, %edx movl -700(%ebp), %eax addl %esi, %edx movl -708(%ebp), %ecx movl %edx, -876(%ebp) movl -860(%ebp), %edx movl -864(%ebp), %esi xorl %eax, %edx movl %edx, %eax xorl %ecx, %esi movl %esi, -872(%ebp) shrl $13, %eax movzbl %dl,%esi movl %edx, -868(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl (%edi,%esi,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -872(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -872(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -856(%ebp), %esi cmpl %ecx, -856(%ebp) setb %al subl %ecx, %esi movl %esi, -888(%ebp) movl -868(%ebp), %ecx addl %eax, %edx movl -876(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -892(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -872(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -872(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -840(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -844(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -880(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -884(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -880(%ebp), %esi setb %al addl %eax, %edx movl -704(%ebp), %eax addl %esi, %edx movl -712(%ebp), %ecx movl %edx, -904(%ebp) movl -888(%ebp), %edx movl -892(%ebp), %esi xorl %eax, %edx movl %edx, %eax xorl %ecx, %esi movl %esi, -900(%ebp) shrl $13, %eax movzbl %dl,%esi movl %edx, -896(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl (%edi,%esi,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -900(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -900(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -884(%ebp), %esi cmpl %ecx, -884(%ebp) setb %al subl %ecx, %esi movl %esi, -916(%ebp) movl -896(%ebp), %ecx addl %eax, %edx movl -904(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -920(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -900(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -900(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -868(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -872(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -908(%ebp) leal 0(,%esi,8), %ecx addl %ecx, %esi movl %esi, -912(%ebp) shrl $29, %eax sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi movl -908(%ebp), %esi setb %al addl %eax, %edx movl -740(%ebp), %eax addl %esi, %edx movl -744(%ebp), %ecx movl %edx, -932(%ebp) movl -916(%ebp), %edx movl -920(%ebp), %esi xorl %eax, %edx movl %edx, %eax xorl %ecx, %esi movl %esi, -928(%ebp) shrl $13, %eax movzbl %dl,%esi movl %edx, -924(%ebp) andl $2040, %eax movl 2048(%eax,%edi), %edx movl (%edi,%esi,8), %ecx movl 2052(%eax,%edi), %eax xorl %edx, %ecx movl 4(%edi,%esi,8), %edx xorl %eax, %edx movzbl -928(%ebp),%eax sall $3, %eax movl 4096(%eax,%edi), %esi xorl %esi, %ecx movl 4100(%eax,%edi), %esi movl -928(%ebp), %eax xorl %esi, %edx shrl $13, %eax andl $2040, %eax movl 6144(%eax,%edi), %esi xorl %esi, %ecx movl 6148(%eax,%edi), %esi xorl %eax, %eax xorl %esi, %edx movl -912(%ebp), %esi cmpl %ecx, -912(%ebp) setb %al subl %ecx, %esi movl %esi, -940(%ebp) movl -924(%ebp), %ecx addl %eax, %edx movl -932(%ebp), %esi movzbl %ch, %eax subl %edx, %esi movl %esi, -944(%ebp) leal 0(,%eax,8), %esi movl %ecx, %eax shrl $24, %eax movl 6144(%esi,%edi), %ecx sall $3, %eax movl 4096(%eax,%edi), %edx movl 4100(%eax,%edi), %eax xorl %edx, %ecx movl 6148(%esi,%edi), %edx xorl %eax, %edx movl -928(%ebp), %eax movzbl %ah, %esi leal 0(,%esi,8), %eax movl 2048(%eax,%edi), %esi xorl %esi, %ecx movl 2052(%eax,%edi), %esi movl -928(%ebp), %eax xorl %esi, %edx shrl $24, %eax movl (%edi,%eax,8), %esi xorl %esi, %ecx movl 4(%edi,%eax,8), %esi xorl %eax, %eax xorl %esi, %edx movl -896(%ebp), %esi addl %ecx, %esi cmpl %ecx, %esi movl -900(%ebp), %ecx setb %al addl %eax, %edx movl %esi, %eax addl %ecx, %edx movl %edx, -936(%ebp) leal 0(,%esi,8), %ecx shrl $29, %eax addl %ecx, %esi sall $3, %edx orl %eax, %edx xorl %eax, %eax cmpl %ecx, %esi setb %al addl %eax, %edx movl -936(%ebp), %eax movl -20(%ebp), %ecx addl %edx, %eax movl -948(%ebp), %edx xorl %edx, %esi movl %esi, -1032(%ebp) movl -952(%ebp), %esi movl -960(%ebp), %edx xorl %esi, %eax movl -924(%ebp), %esi movl %eax, -1036(%ebp) xorl %eax, %eax cmpl %ecx, -924(%ebp) setb %al subl %ecx, %esi movl -928(%ebp), %ecx addl %edx, %eax movl -964(%ebp), %edx subl %eax, %ecx movl -24(%ebp), %eax movl %ecx, -1040(%ebp) movl -940(%ebp), %ecx addl %eax, %ecx xorl %eax, %eax cmpl -24(%ebp), %ecx setb %al addl %edx, %eax movl -944(%ebp), %edx addl %edx, %eax movl -1032(%ebp), %edx movl %eax, -1044(%ebp) movl 16(%ebp), %eax movl %edx, (%eax) movl -1036(%ebp), %edx movl %esi, 8(%eax) movl %edx, 4(%eax) movl -1040(%ebp), %esi movl %ecx, 16(%eax) movl %esi, 12(%eax) movl -1044(%ebp), %edx movl %edx, 20(%eax) subl $64, -16(%ebp) addl $64, 8(%ebp) cmpl $63, -16(%ebp) ja .L6 .L8: addl $1032, %esp popl %ebx popl %esi popl %edi popl %ebp ret .size tiger_t, .-tiger_t .globl tiger .type tiger, @function tiger: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi subl $72, %esp movl 12(%ebp), %edi movl 8(%ebp), %esi cmpl $63, %edi jbe .L33 .L42: movl %esi, (%esp) movl 16(%ebp), %eax subl $64, %edi addl $64, %esi movl %eax, 4(%esp) call tiger_compress cmpl $63, %edi ja .L132 .L33: xorl %ecx, %ecx cmpl %edi, %ecx jb .L140 .L35: movb $1, -72(%ecx,%ebp) leal 1(%ecx), %edx testb $7, %dl je .L37 .L44: movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl jne .L135 .L37: cmpl $56, %edx jbe .L23 cmpl $63, %edx jbe .L141 .L39: movl 16(%ebp), %ecx leal -72(%ebp), %edx movl %edx, (%esp) movl %ecx, 4(%esp) call tiger_compress xorl %edx, %edx .L23: cmpl $55, %edx ja .L41 movb $0, -72(%ebp,%edx) movl %edx, %eax leal 1(%edx), %ecx notl %eax andl $7, %eax cmpl $55, %ecx ja .L41 testl %eax, %eax je .L46 cmpl $1, %eax je .L143 cmpl $2, %eax je .L144 cmpl $3, %eax je .L145 cmpl $4, %eax je .L146 cmpl $5, %eax je .L147 cmpl $6, %eax je .L148 movb $0, -72(%ebp,%ecx) leal 2(%edx), %ecx .L148: movb $0, -72(%ebp,%ecx) incl %ecx .L147: movb $0, -72(%ebp,%ecx) incl %ecx .L146: movb $0, -72(%ebp,%ecx) incl %ecx .L145: movb $0, -72(%ebp,%ecx) incl %ecx .L144: movb $0, -72(%ebp,%ecx) incl %ecx .L143: movb $0, -72(%ebp,%ecx) incl %ecx cmpl $55, %ecx ja .L41 .L46: movb $0, -72(%ebp,%ecx) movb $0, -71(%ecx,%ebp) movb $0, -70(%ecx,%ebp) movb $0, -69(%ecx,%ebp) movb $0, -68(%ecx,%ebp) movb $0, -67(%ecx,%ebp) movb $0, -66(%ecx,%ebp) movb $0, -65(%ecx,%ebp) addl $8, %ecx cmpl $55, %ecx ja .L41 jmp .L46 .L141: movb $0, -72(%ebp,%edx) movl %edx, %eax leal 1(%edx), %ecx notl %eax andl $7, %eax cmpl $63, %ecx ja .L39 testl %eax, %eax je .L45 cmpl $1, %eax je .L149 cmpl $2, %eax je .L150 cmpl $3, %eax je .L151 cmpl $4, %eax je .L152 cmpl $5, %eax je .L153 cmpl $6, %eax je .L154 movb $0, -72(%ebp,%ecx) leal 2(%edx), %ecx .L154: movb $0, -72(%ebp,%ecx) incl %ecx .L153: movb $0, -72(%ebp,%ecx) incl %ecx .L152: movb $0, -72(%ebp,%ecx) incl %ecx .L151: movb $0, -72(%ebp,%ecx) incl %ecx .L150: movb $0, -72(%ebp,%ecx) incl %ecx .L149: movb $0, -72(%ebp,%ecx) incl %ecx cmpl $63, %ecx ja .L39 .L45: movb $0, -72(%ebp,%ecx) movb $0, -71(%ecx,%ebp) movb $0, -70(%ecx,%ebp) movb $0, -69(%ecx,%ebp) movb $0, -68(%ecx,%ebp) movb $0, -67(%ecx,%ebp) movb $0, -66(%ecx,%ebp) movb $0, -65(%ecx,%ebp) addl $8, %ecx cmpl $63, %ecx ja .L39 jmp .L45 .L135: movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 movb $0, -72(%ebp,%edx) incl %edx testb $7, %dl je .L37 jmp .L44 .L140: movl %ecx, %eax notl %eax addl %edi, %eax movl %eax, %edx andl $7, %edx movzbl (%esi,%ecx), %eax movb %al, -72(%ebp,%ecx) incl %ecx cmpl %edi, %ecx jae .L35 testl %edx, %edx je .L43 cmpl $1, %edx je .L155 cmpl $2, %edx je .L156 cmpl $3, %edx je .L157 cmpl $4, %edx je .L158 cmpl $5, %edx je .L159 cmpl $6, %edx je .L160 movzbl (%esi,%ecx), %edx movb %dl, -72(%ebp,%ecx) incl %ecx .L160: movzbl (%esi,%ecx), %eax movb %al, -72(%ebp,%ecx) incl %ecx .L159: movzbl (%esi,%ecx), %edx movb %dl, -72(%ebp,%ecx) incl %ecx .L158: movzbl (%esi,%ecx), %eax movb %al, -72(%ebp,%ecx) incl %ecx .L157: movzbl (%esi,%ecx), %edx movb %dl, -72(%ebp,%ecx) incl %ecx .L156: movzbl (%esi,%ecx), %eax movb %al, -72(%ebp,%ecx) incl %ecx .L155: movzbl (%esi,%ecx), %edx movb %dl, -72(%ebp,%ecx) incl %ecx cmpl %edi, %ecx jae .L35 .L43: movzbl (%esi,%ecx), %edx movb %dl, -72(%ebp,%ecx) leal 1(%ecx), %edx movzbl (%esi,%edx), %eax movb %al, -72(%ebp,%edx) leal 2(%ecx), %edx movzbl (%esi,%edx), %eax movb %al, -72(%ebp,%edx) leal 3(%ecx), %edx movzbl (%esi,%edx), %eax movb %al, -72(%ebp,%edx) leal 4(%ecx), %edx movzbl (%esi,%edx), %eax movb %al, -72(%ebp,%edx) leal 5(%ecx), %edx movzbl (%esi,%edx), %eax movb %al, -72(%ebp,%edx) leal 6(%ecx), %edx movzbl (%esi,%edx), %eax movb %al, -72(%ebp,%edx) leal 7(%ecx), %edx addl $8, %ecx movzbl (%esi,%edx), %eax cmpl %edi, %ecx movb %al, -72(%ebp,%edx) jae .L35 jmp .L43 .L132: movl %esi, (%esp) movl 16(%ebp), %ecx subl $64, %edi addl $64, %esi movl %ecx, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 movl %esi, (%esp) movl 16(%ebp), %eax subl $64, %edi addl $64, %esi movl %eax, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 movl %esi, (%esp) movl 16(%ebp), %edx subl $64, %edi addl $64, %esi movl %edx, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 movl %esi, (%esp) movl 16(%ebp), %ecx subl $64, %edi addl $64, %esi movl %ecx, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 movl %esi, (%esp) movl 16(%ebp), %eax subl $64, %edi addl $64, %esi movl %eax, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 movl %esi, (%esp) movl 16(%ebp), %edx subl $64, %edi addl $64, %esi movl %edx, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 movl %esi, (%esp) movl 16(%ebp), %ecx subl $64, %edi addl $64, %esi movl %ecx, 4(%esp) call tiger_compress cmpl $63, %edi jbe .L33 jmp .L42 .L41: movl $0, -12(%ebp) movl 12(%ebp), %eax leal -72(%ebp), %esi movl %esi, (%esp) movl 16(%ebp), %edi sall $3, %eax movl %edi, 4(%esp) movl %eax, -16(%ebp) call tiger_compress addl $72, %esp popl %esi popl %edi popl %ebp ret .size tiger, .-tiger .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits .globl __i686.get_pc_thunk.bx .hidden __i686.get_pc_thunk.bx .type __i686.get_pc_thunk.bx, @function __i686.get_pc_thunk.bx: movl (%esp), %ebx ret .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.4.0" samhain-4.1.4/src/exepack.c0000644000175000017500000001366412615253277012460 00000000000000#include "config.h" #include #include #include #include #include #include #include #include #include extern char **environ; #include "minilzo.h" /* integer data type that is _exactly_ 32 bit */ #if defined(HAVE_INT_32) #define UINT32 unsigned int #elif defined(HAVE_LONG_32) #define UINT32 unsigned long #elif defined(HAVE_SHORT_32) #define UINT32 unsigned short #endif #include "exepack.data" static UINT32 cstate[3], astate[3]; /* interval [0, 4294967296] */ static UINT32 taus_get_long (UINT32 * state) { #define TAUSWORTHE(s,a,b,c,d) ((s &c) <>b) state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12); state[1] = TAUSWORTHE (state[1], 2, 25, 4294967288UL, 4); state[2] = TAUSWORTHE (state[2], 3, 11, 4294967280UL, 17); return (state[0] ^ state[1] ^ state[2]); } void taus_set_from_state (UINT32 * state, UINT32 * state0) { state[0] = state0[0] | (UINT32) 0x03; state[1] = state0[1] | (UINT32) 0x09; state[2] = state0[2] | (UINT32) 0x17; /* 'warm up' */ taus_get_long (state); taus_get_long (state); taus_get_long (state); taus_get_long (state); taus_get_long (state); taus_get_long (state); return; } void set2 (char * pos, char c1, char c2) { pos[0] = c1; pos[1] = c2; return; } void set4 (char * pos, char c1, char c2, char c3, char c4) { pos[0] = c1; pos[1] = c2; pos[2] = c3; pos[3] = c4; return; } int main(int argc, char *argv[]) { int file; long result; unsigned long i = argc; /* dummy use of argc to fix compiler warning */ unsigned long len = 0; struct stat sbuf; struct stat fbuf; /* For compression. */ lzo_byte * inbuf; lzo_byte * outbuf; int r; lzo_uint in_len; lzo_uint out_len; char * p; char fname[128]; #if defined (__linux__) char pname[128]; #endif UINT32 pid; /* no SUID */ if (getuid() != geteuid()) { setuid(getuid()); } /* reset umask */ umask(0); astate[0] = programkey_0[0]; astate[1] = programkey_0[1]; astate[2] = programkey_0[2]; taus_set_from_state (cstate, astate); out_len = (unsigned long) programlen_compressed_0; len = (unsigned long) programlen_0; in_len = len; outbuf = program_0; /* Decode. */ for (i = 0; i < out_len; ++i) { outbuf[i] ^= (taus_get_long (cstate) & 0xff); } inbuf = (lzo_byte *) malloc (sizeof(lzo_byte) * len); /* * Step 1: initialize the LZO library */ if (lzo_init() != LZO_E_OK) { return 1; } /* * Step 2: decompress again, now going from `out' to `in' */ r = lzo1x_decompress_safe (outbuf, out_len, inbuf, &in_len, NULL); if (r == LZO_E_OK && in_len == len) { /* printf("decompressed %lu bytes back into %lu bytes\n", (long) out_len, (long) in_len); */ ; } else { /* printf("internal error - decompression failed: %d\n", r); */ return 2; } /* * Step 3: choose a filename */ nameIt: p = fname; /* --- use /tmp if the sticky bit is set --- */ #if defined(S_ISVTX) set4 (p, '/', 't', 'm', 'p'); p += 4; *p = '\0'; if ( 0 != stat(fname, &sbuf)) { if ( (sbuf.st_mode & S_ISVTX) != S_ISVTX) { p = fname; set4 (p, '/', 'u', 's', 'r'); p += 4; set4 (p, '/', 'b', 'i', 'n'); p += 4; } } #else set4 (p, '/', 'u', 's', 'r'); p += 4; set4 (p, '/', 'b', 'i', 'n'); p += 4; #endif set4 (p, '/', 't', 'm', 'p'); p += 4; cstate[0] ^= (UINT32) getpid (); cstate[1] ^= (UINT32) time (NULL); cstate[0] |= (UINT32) 0x03; cstate[1] |= (UINT32) 0x09; pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate)); for (i = 0; i < 4; ++i) { *p = 'a' + (pid % 26); pid /= 26; ++p; } pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate)); for (i = 0; i < 4; ++i) { *p = 'a' + (pid % 26); pid /= 26; ++p; } pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate)); for (i = 0; i < 3; ++i) { *p = 'a' + (pid % 26); pid /= 26; ++p; } *p = '\0'; if ( (-1) != stat(fname, &sbuf) || errno != ENOENT) { /* because cstate[2] is not initialized, the next name will * be different */ goto nameIt; } if ((file = open (fname, O_CREAT|O_EXCL|O_WRONLY, 0700)) < 0) { return (4); } result = (long) write(file, inbuf, in_len); if (result < 0 || in_len != (lzo_uint) result) { return (5); } #if defined(__linux__) if ( 0 != fstat(file, &sbuf)) { return (6); } /* Must reopen for read only. */ close(file); file = open (fname, O_RDONLY, 0); if ( 0 != fstat(file, &fbuf)) { return (7); } /* check mode, inode, owner, and device, to make sure it is the same file */ if (sbuf.st_mode != fbuf.st_mode || sbuf.st_ino != fbuf.st_ino || sbuf.st_uid != fbuf.st_uid || sbuf.st_gid != fbuf.st_gid || sbuf.st_dev != fbuf.st_dev ) { close ( file ); return ( 8 ); } p = pname; set4(p, '/', 'p', 'r', 'o'); p += 4; set2(p, 'c', '/'); p += 2; set4(p, 's', 'e', 'l', 'f'); p += 4; set4(p, '/', 'f', 'd', '/'); p += 4; sprintf(p, "%d", file); if (0 == access(pname, R_OK|X_OK)) { unlink (fname); fcntl (file, F_SETFD, FD_CLOEXEC); execve (pname, argv, environ); return (9); } #endif /* /proc not working, or not linux */ close (file); if ( (i = fork()) != 0) { wait (NULL); execve (fname, argv, environ); unlink (fname); return (10); } else if (i == 0) { if (0 == fork()) { sleep (3); unlink (fname); } return (0); } /* only reached in case of error */ unlink (fname); return (-1); } samhain-4.1.4/src/t-test1.c0000644000175000017500000003455612615253277012344 00000000000000/* * Copyright (c) 1996-1999, 2001-2004 Wolfram Gloger Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that (i) the above copyright notices and this permission notice appear in all copies of the software and related documentation, and (ii) the name of Wolfram Gloger may not be used in any advertising or publicity relating to the software. THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL WOLFRAM GLOGER BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * $Id: t-test1.c,v 1.2 2004/11/04 14:58:45 wg Exp $ * by Wolfram Gloger 1996-1999, 2001, 2004 * A multi-thread test for malloc performance, maintaining one pool of * allocated bins per thread. */ /* t-test[12] n-total = total number of threads executed (default 10) n-parallel = number of threads running in parallel (2) n-allocs = number of malloc()'s / free()'s per thread (10000) size-max = max. size requested with malloc() in bytes (10000) bins = number of bins to maintain */ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #if (defined __STDC__ && __STDC__) || defined __cplusplus # include #endif #include #include #include #include #include #include #include #include /* #if !USE_MALLOC #include #else #include "malloc.h" #endif */ #ifdef USE_SYSTEM_MALLOC extern void *memalign(size_t boundary, size_t size); /* #define memalign(a,b) malloc(b) */ #else extern void *memalign(size_t boundary, size_t size); #endif static int verbose = 1; /* dummy for the samhain safe_fatal logger */ void safe_fatal(const char * details, const char * file, int line) { (void) file; (void) line; fputs("assert failed: ", stderr); puts(details); _exit(EXIT_FAILURE); } /* lran2.h * by Wolfram Gloger 1996. * * A small, portable pseudo-random number generator. */ #ifndef _LRAN2_H #define _LRAN2_H #define LRAN2_MAX 714025l /* constants for portable */ #define IA 1366l /* random number generator */ #define IC 150889l /* (see e.g. `Numerical Recipes') */ struct lran2_st { long x, y, v[97]; }; static void lran2_init(struct lran2_st* d, long seed) { long x; int j; x = (IC - seed) % LRAN2_MAX; if(x < 0) x = -x; for(j=0; j<97; j++) { x = (IA*x + IC) % LRAN2_MAX; d->v[j] = x; } d->x = (IA*x + IC) % LRAN2_MAX; d->y = d->x; } #ifdef __GNUC__ __inline__ #endif static long lran2(struct lran2_st* d) { int j = (d->y % 97); d->y = d->v[j]; d->x = (IA*d->x + IC) % LRAN2_MAX; d->v[j] = d->x; return d->y; } #undef IA #undef IC #endif /* * $Id: t-test.h,v 1.1 2004/11/04 14:32:21 wg Exp $ * by Wolfram Gloger 1996. * Common data structures and functions for testing malloc performance. */ /* Testing level */ #ifndef TEST #define TEST 99 #endif /* For large allocation sizes, the time required by copying in realloc() can dwarf all other execution times. Avoid this with a size threshold. */ #ifndef REALLOC_MAX #define REALLOC_MAX 2000 #endif struct bin { unsigned char *ptr; unsigned long size; }; #if TEST > 0 static void mem_init(unsigned char *ptr, unsigned long size) { unsigned long i, j; if(size == 0) return; #if TEST > 3 memset(ptr, '\0', size); #endif for(i=0; i>8)) & 0xFF); } j = (unsigned long)ptr ^ (size-1); ptr[size-1] = ((j ^ (j>>8)) & 0xFF); } static int mem_check(unsigned char *ptr, unsigned long size) { unsigned long i, j; if(size == 0) return 0; for(i=0; i>8)) & 0xFF)) return 1; } j = (unsigned long)ptr ^ (size-1); if(ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 2; return 0; } static int zero_check(unsigned* ptr, unsigned long size) { unsigned char* ptr2; while(size >= sizeof(*ptr)) { if(*ptr++ != 0) return -1; size -= sizeof(*ptr); } ptr2 = (unsigned char*)ptr; while(size > 0) { if(*ptr2++ != 0) return -1; --size; } return 0; } #endif /* TEST > 0 */ /* Allocate a bin with malloc(), realloc() or memalign(). r must be a random number >= 1024. */ int n_malloc=0, n_memalign=0, n_realloc=0, n_calloc=0; static void bin_alloc(struct bin *m, unsigned long size, int r) { #if TEST > 0 if(mem_check(m->ptr, m->size)) { fprintf(stderr, "memory corrupt!\n"); exit(1); } #endif r %= 1024; /*printf("%d ", r);*/ if(r < 4) { /* memalign */ if(m->size > 0) free(m->ptr); m->ptr = (unsigned char *)memalign(sizeof(int) << r, size); ++n_memalign; } else if(r < 20) { /* calloc */ if(m->size > 0) free(m->ptr); m->ptr = (unsigned char *)calloc(size, 1); #if TEST > 0 if(zero_check((unsigned*)m->ptr, size)) { unsigned long i; for(i=0; iptr[i] != 0) break; fprintf(stderr, "calloc'ed memory non-zero (ptr=%p, i=%ld)!\n", m->ptr, i); exit(1); } #endif ++n_calloc; } else if(r < 100 && m->size < REALLOC_MAX) { /* realloc */ if(m->size == 0) m->ptr = NULL; m->ptr = realloc(m->ptr, size); ++n_realloc; } else { /* plain malloc */ if(m->size > 0) free(m->ptr); m->ptr = (unsigned char *)malloc(size); ++n_malloc; } if(!m->ptr) { fprintf(stderr, "out of memory (r=%d, size=%ld)!\n", r, (long)size); exit(1); } m->size = size; #if TEST > 0 mem_init(m->ptr, m->size); #endif } /* Free a bin. */ static void bin_free(struct bin *m) { if(m->size == 0) return; #if TEST > 0 if(mem_check(m->ptr, m->size)) { fprintf(stderr, "memory corrupt!\n"); exit(1); } #endif free(m->ptr); m->size = 0; } /* * Local variables: * tab-width: 4 * End: */ struct user_data { int bins, max; unsigned long size; long seed; }; /* * $Id: thread-st.h$ * pthread version * by Wolfram Gloger 2004 */ #include #include pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER; #ifndef USE_PTHREADS_STACKS #define USE_PTHREADS_STACKS 0 #endif #ifndef STACKSIZE #define STACKSIZE 32768 #endif struct thread_st { char *sp; /* stack pointer, can be 0 */ void (*func)(struct thread_st* st); /* must be set by user */ pthread_t id; int flags; struct user_data u; }; static void mthread_init(void) { #if !defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK) extern int dnmalloc_pthread_init(void); dnmalloc_pthread_init(); #endif if (verbose) printf("Using posix threads.\n"); pthread_cond_init(&finish_cond, NULL); pthread_mutex_init(&finish_mutex, NULL); } static void * mthread_wrapper(void *ptr) { struct thread_st *st = (struct thread_st*)ptr; /*printf("begin %p\n", st->sp);*/ st->func(st); pthread_mutex_lock(&finish_mutex); st->flags = 1; pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&finish_cond); /*printf("end %p\n", st->sp);*/ return NULL; } /* Create a thread. */ static int mthread_create(struct thread_st *st) { st->flags = 0; { pthread_attr_t* attr_p = 0; #if USE_PTHREADS_STACKS pthread_attr_t attr; pthread_attr_init (&attr); if(!st->sp) st->sp = malloc(STACKSIZE+16); if(!st->sp) return -1; if(pthread_attr_setstacksize(&attr, STACKSIZE)) fprintf(stderr, "error setting stacksize"); else pthread_attr_setstackaddr(&attr, st->sp + STACKSIZE); /*printf("create %p\n", st->sp);*/ attr_p = &attr; #endif return pthread_create(&st->id, attr_p, mthread_wrapper, st); } return 0; } /* Wait for one of several subthreads to finish. */ static void wait_for_thread(struct thread_st st[], int n_thr, int (*end_thr)(struct thread_st*)) { int i; pthread_mutex_lock(&finish_mutex); for(;;) { int term = 0; for(i=0; i 0) break; pthread_cond_wait(&finish_cond, &finish_mutex); } pthread_mutex_unlock(&finish_mutex); } /* * Local variables: * tab-width: 4 * End: */ #define N_TOTAL 10 #ifndef N_THREADS #define N_THREADS 2 #endif #ifndef N_TOTAL_PRINT #define N_TOTAL_PRINT 50 #endif #ifndef MEMORY #define MEMORY 8000000l #endif #define SIZE 10000 #define I_MAX 10000 #define ACTIONS_MAX 30 #ifndef TEST_FORK #define TEST_FORK 0 #endif #define RANDOM(d,s) (lran2(d) % (s)) struct bin_info { struct bin *m; unsigned long size, bins; }; #if TEST > 0 void bin_test(struct bin_info *p) { unsigned int b; for(b=0; bbins; b++) { if(mem_check(p->m[b].ptr, p->m[b].size)) { fprintf(stderr, "memory corrupt!\n"); abort(); } } } #endif void malloc_test(struct thread_st *st) { unsigned int b; int i, j, actions, pid = 1; struct bin_info p; struct lran2_st ld; /* data for random number generator */ lran2_init(&ld, st->u.seed); #if TEST_FORK>0 if(RANDOM(&ld, TEST_FORK) == 0) { int status; #if !USE_THR pid = fork(); #else pid = fork1(); #endif if(pid > 0) { /*printf("forked, waiting for %d...\n", pid);*/ waitpid(pid, &status, 0); printf("done with %d...\n", pid); if(!WIFEXITED(status)) { printf("child term with signal %d\n", WTERMSIG(status)); exit(1); } return; } exit(0); } #endif p.m = (struct bin *)malloc(st->u.bins*sizeof(*p.m)); p.bins = st->u.bins; p.size = st->u.size; for(b=0; bu.max;) { #if TEST > 1 bin_test(&p); #endif actions = RANDOM(&ld, ACTIONS_MAX); #if USE_MALLOC && MALLOC_DEBUG if(actions < 2) { mallinfo(); } #endif for(j=0; j 2 bin_test(&p); #endif } #if 0 /* Test illegal free()s while setting MALLOC_CHECK_ */ for(j=0; j<8; j++) { b = RANDOM(&ld, p.bins); if(p.m[b].ptr) { int offset = (RANDOM(&ld, 11) - 5)*8; char *rogue = (char*)(p.m[b].ptr) + offset; /*printf("p=%p rogue=%p\n", p.m[b].ptr, rogue);*/ free(rogue); } } #endif i += actions; } for(b=0; bid); #endif if(n_total >= n_total_max) { n_running--; } else if(st->u.seed++, mthread_create(st)) { printf("Creating thread #%d failed.\n", n_total); exit(1); } else { n_total++; if (verbose) if(n_total%N_TOTAL_PRINT == 0) printf("n_total = %8d - malloc %12d / memalign %12d / realloc %12d / calloc %12d\n", n_total, n_malloc, n_memalign, n_realloc, n_calloc); } return 0; } #if 0 /* Protect address space for allocation of n threads by LinuxThreads. */ static void protect_stack(int n) { char buf[2048*1024]; char* guard; size_t guard_size = 2*2048*1024UL*(n+2); buf[0] = '\0'; guard = (char*)(((unsigned long)buf - 4096)& ~4095UL) - guard_size; printf("Setting up stack guard at %p\n", guard); if(mmap(guard, guard_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) != guard) printf("failed!\n"); } #endif int main(int argc, char *argv[]) { int i, bins; int n_thr=N_THREADS; int i_max=I_MAX; unsigned long size=SIZE; struct thread_st *st; #if USE_MALLOC && USE_STARTER==2 ptmalloc_init(); printf("ptmalloc_init\n"); #endif if((argc > 1) && (0 == strcmp(argv[1], "-h") || 0 == strcmp(argv[1], "--help"))) { printf("%s \n\n", argv[0]); printf(" n-total = total number of threads executed (default 10)\n"); printf(" n-parallel = number of threads running in parallel (2)\n"); printf(" n-allocs = number of malloc()'s / free()'s per thread (10000)\n"); printf(" size-max = max. size requested with malloc() in bytes (10000)\n"); printf(" bins = number of bins to maintain\n"); return 0; } if(argc > 1) n_total_max = atoi(argv[1]); if(n_total_max < 1) n_thr = 1; if(argc > 2) n_thr = atoi(argv[2]); if(n_thr < 1) n_thr = 1; if(n_thr > 100) n_thr = 100; if(argc > 3) i_max = atoi(argv[3]); if(argc > 4) size = atol(argv[4]); if(size < 2) size = 2; bins = MEMORY/(size*n_thr); if(argc > 5) bins = atoi(argv[5]); if(bins < 4) bins = 4; /*protect_stack(n_thr);*/ mthread_init(); printf("total=%d threads=%d i_max=%d size=%ld bins=%d\n", n_total_max, n_thr, i_max, size, bins); st = (struct thread_st *)malloc(n_thr*sizeof(*st)); if(!st) exit(-1); #if !defined NO_THREADS && (defined __sun__ || defined sun) /* I know of no other way to achieve proper concurrency with Solaris. */ thr_setconcurrency(n_thr); #endif /* Start all n_thr threads. */ for(i=0; i0;) { wait_for_thread(st, n_thr, my_end_thread); } for(i=0; i #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_MEMORY_H #include #endif #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #include #endif #include "sh_tiger.h" #include "sh_unix.h" #include "sh_error.h" #include "sh_utils.h" #include "sh_pthread.h" #include "sh_string.h" #define PRIV_MAX 32768 #if defined(TIGER_64_BIT) #if defined(HAVE_LONG_64) typedef unsigned long int word64; #elif defined(HAVE_LONG_LONG_64) typedef unsigned long long int word64; #else #error No 64 bit type found ! #endif #endif #if defined(HAVE_INT_32) typedef unsigned int sh_word32; #define MYFORMAT (_("%08X%08X%08X%08X%08X%08X")) #define GPGFORMAT (_("%08X %08X %08X %08X %08X %08X")) #elif defined(HAVE_LONG_32) typedef unsigned long sh_word32; #define MYFORMAT (_("%08lX%08lX%08lX%08lX%08lX%08lX")) #define GPGFORMAT (_("%08lX %08lX %08lX %08lX %08lX %08lX")) #elif defined(HAVE_SHORT_32) typedef unsigned short sh_word32; #define MYFORMAT (_("%08X%08X%08X%08X%08X%08X")) #define GPGFORMAT (_("%08X %08X %08X %08X %08X %08X")) #else #error No 32 bit type found ! #endif #if defined(__GNUC__) && (__GNUC__ >= 3) #undef SH_GNUC_ALIGN8 #define SH_GNUC_ALIGN8 __attribute__((aligned(8))) #else #undef SH_GNUC_ALIGN8 #define SH_GNUC_ALIGN8 #endif typedef unsigned char sh_byte; #define SH_KEY_NULL _("000000000000000000000000000000000000000000000000") #undef FIL__ #define FIL__ _("sh_tiger0.c") #if defined(TIGER_64_BIT) void tiger_t(const word64 *str, word64 length, word64 * res); void tiger(const word64 *str, word64 length, word64 * res); #ifdef TIGER_DBG static void tiger_dbg(word64 res[3], int step, unsigned long nblocks, unsigned long ncount) { return; } #endif #else void tiger(const sh_word32 *str, sh_word32 length, sh_word32 * res); void tiger_t(const sh_word32 *str, sh_word32 length, sh_word32 * res); #ifdef TIGER_DBG static void tiger_dbg(sh_word32 res[6], int step, unsigned long nblocks, unsigned long ncount) { fprintf(stderr, _("ST %d BLK %2ld CT %2ld %08lX %08lX %08lX %08lX %08lX %08lX\n"), step, nblocks, ncount, (sh_word32)(res[1]), (sh_word32)(res[0]), (sh_word32)(res[3]), (sh_word32)(res[2]), (sh_word32)(res[5]), (sh_word32)(res[4]) ); } #endif #endif /* this is the wrapper function -- not part of the tiger reference * implementation */ /* static sh_byte buffer[PRIV_MAX + 72]; */ #if defined(TIGER_64_BIT) static word64 * sh_tiger_hash_val (const char * filename, TigerType what, UINT64 * Length, int timeout, word64 * res) #else static sh_word32 * sh_tiger_hash_val (const char * filename, TigerType what, UINT64 * Length, int timeout, sh_word32 * res) #endif { SL_TICKET fd; sh_string * content = NULL; int i, j, tt; int count = 0; int blk; char * tmp; sh_byte * bptr; sh_byte SH_GNUC_ALIGN8 bbuf[64]; UINT64 bcount = 0; sh_byte * buffer = SH_ALLOC(PRIV_MAX + 72); unsigned long pages_read; uid_t euid; unsigned long ncount = 0, nblocks = 0; unsigned long t, msb, lsb; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) /*@-nestedextern@*/ extern long IO_Limit; /*@+nestedextern@*/ #endif #if defined(TIGER_64_BIT) #define TIGER_CAST (const word64*) /* word64 res[3]; */ res[0]= (word64) 0x0123456789ABCDEFLL; res[1]= (word64) 0xFEDCBA9876543210LL; res[2]= (word64) 0xF096A5B4C3B2E187LL; #else #define TIGER_CAST (const sh_word32*) /* sh_word32 res[6]; */ res[0]= (sh_word32) 0x89ABCDEF; res[1]= (sh_word32) 0x01234567; res[2]= (sh_word32) 0x76543210; res[3]= (sh_word32) 0xFEDCBA98; res[4]= (sh_word32) 0xC3B2E187; res[5]= (sh_word32) 0xF096A5B4; #endif SL_ENTER(_("sh_tiger_hash_val")); if (what >= TIGER_FILE) { if (what > TIGER_FILE) { fd = what; content = sl_get_content(fd); TPT((0,FIL__, __LINE__, _("msg=, fd=<%ld>\n"), fd)); } else { TPT((0,FIL__, __LINE__, _("msg=, path=<%s>\n"), (filename == NULL ? _("(null)") : filename) )); fd = sl_open_read (FIL__, __LINE__, filename, SL_YESPRIV); } if (SL_ISERROR (fd)) { TPT((0, FIL__, __LINE__, _("msg=\n"), fd)); tmp = sh_util_safe_name (filename); (void) sl_get_euid(&euid); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, (int)fd, MSG_E_ACCESS, (long) euid, tmp); SH_FREE(tmp); SH_FREE(buffer); *Length = 0; SL_RETURN( NULL, _("sh_tiger_hash_val")); } #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) if (skey->mlock_failed == S_FALSE) { if ( (-1) == sh_unix_mlock(FIL__, __LINE__, (char *)buffer, (PRIV_MAX)*sizeof(sh_byte))) { SH_MUTEX_LOCK_UNSAFE(mutex_skey); skey->mlock_failed = S_TRUE; SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); } } #else if (skey->mlock_failed == S_FALSE) { SH_MUTEX_LOCK_UNSAFE(mutex_skey); skey->mlock_failed = S_TRUE; SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); } #endif #ifdef TIGER_DBG tiger_dbg (res, 0, nblocks, ncount); #endif pages_read = 0; while (1) { if (timeout > 0) count = sl_read_timeout (fd, buffer, PRIV_MAX, timeout, S_TRUE); else count = sl_read (fd, buffer, PRIV_MAX); ++pages_read; if (SL_ISERROR (count)) { int error = errno; if (sig_termfast == 1) { sh_unix_munlock((char *)buffer, (PRIV_MAX)*sizeof(sh_byte)); SH_FREE(buffer); *Length = 0; SL_RETURN( NULL, _("sh_tiger_hash_val")); } TPT((0, FIL__ , __LINE__ , _("msg=\n"), count)); tmp = sh_util_safe_name (filename); if (count == SL_TIMEOUT) { if (timeout != 7) { sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, count, MSG_E_TIMEOUT, timeout, tmp); } } else { char errbuf[SH_ERRBUF_SIZE]; char errbuf2[SH_ERRBUF_SIZE]; sl_strlcpy(errbuf, sl_error_string(count), sizeof(errbuf)); sh_error_message(error, errbuf2, sizeof(errbuf2)); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, count, MSG_E_READ, errbuf, errbuf2, tmp); } SH_FREE(tmp); memset (bbuf, 0, 64); memset (buffer, 0, PRIV_MAX); sh_unix_munlock((char *)buffer, (PRIV_MAX)*sizeof(sh_byte)); SH_FREE(buffer); *Length = 0; SL_RETURN( NULL, _("sh_tiger_hash_val")); } if (content) sh_string_cat_lchar(content, (char*)buffer, count); bcount += count; if (*Length != TIGER_NOLIM) { if (bcount > *Length) { count = count - (bcount - (*Length)); bcount = *Length; count = (count < 0) ? 0 : count; } } blk = (count / 64); /* number of 64-byte words */ /* nblocks += blk; number of 64-byte words * count cannot be negative here, see 'if (SL_ISERROR (count))' */ tt = blk*64; ncount = (unsigned long) (count - tt); nblocks += blk; /* MAY_LOCK */ sh.statistics.bytes_hashed += tt; tt = 0; for (i = 0; i < blk; ++i) { bptr = &buffer[tt]; tt += 64; tiger_t(TIGER_CAST bptr, 64, res); #ifdef TIGER_DBG tiger_dbg (res, 3, nblocks, ncount); #endif } if (blk < (PRIV_MAX / 64)) /* this must be (PRIV_MAX / 64) */ break; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) if (sig_termfast == 1) { memset (bbuf, 0, 64); memset (buffer, 0, PRIV_MAX); sh_unix_munlock((char *)buffer, (PRIV_MAX)*sizeof(sh_byte)); SH_FREE(buffer); *Length = 0; SL_RETURN( NULL, _("sh_tiger_hash_val")); } if ((IO_Limit) > 0 && (pages_read == 32)) /* check for I/O limit */ { sh_unix_io_pause (); pages_read = 0; } #endif } TPT((0, FIL__, __LINE__ , _("msg=\n"))); /* copy incomplete block */ j = 0; for (i = 0; i < 64; i += 4) { bbuf[i] = (sh_byte) '\0'; bbuf[i+1] = (sh_byte) '\0'; bbuf[i+2] = (sh_byte) '\0'; bbuf[i+3] = (sh_byte) '\0'; } for (i = (count/64) * 64; i < count; ++i) /*@-usedef@*/bbuf[j++] = buffer[i];/*@+usedef@*/ #ifdef TIGER_DBG tiger_dbg (res, 5, nblocks, ncount); #endif msb = 0; t = nblocks; if( (lsb = t << 6) < t ) msb++; msb += t >> 26; t = lsb; if( (lsb = t + ncount) < t ) msb++; t = lsb; if( (lsb = t << 3) < t ) msb++; msb += t >> 29; if( j < 56 ) { bbuf[j++] = (sh_byte) 0x01; ++ncount; while( j < 56 ) { bbuf[j++] = (sh_byte) 0; ++ncount; } } else { bbuf[j++] = (sh_byte) 0x01; while( j < 64 ) bbuf[j++] = (sh_byte) 0; tiger_t(TIGER_CAST bbuf, 64, res); /* MAY_LOCK */ sh.statistics.bytes_hashed += 64; ++nblocks; #ifdef TIGER_DBG ncount = 0; #endif sl_memset(bbuf, 0, 56 ); } #ifdef TIGER_DBG tiger_dbg (res, 6, nblocks, ncount); #endif bbuf[56] = (sh_byte) (lsb ); bbuf[57] = (sh_byte) (lsb >> 8); bbuf[58] = (sh_byte) (lsb >> 16); bbuf[59] = (sh_byte) (lsb >> 24); bbuf[60] = (sh_byte) (msb ); bbuf[61] = (sh_byte) (msb >> 8); bbuf[62] = (sh_byte) (msb >> 16); bbuf[63] = (sh_byte) (msb >> 24); tiger_t(TIGER_CAST bbuf, 64, res); sh.statistics.bytes_hashed += 64; #ifdef TIGER_DBG tiger_dbg (res, 7, nblocks, ncount); #endif sl_memset (bbuf, '\0', sizeof(bbuf)); sl_memset (buffer, '\0', sizeof(buffer)); if (what == TIGER_FILE) (void) sl_close (fd); sh_unix_munlock((char *)buffer, (PRIV_MAX)*sizeof(sh_byte)); SH_FREE(buffer); *Length = bcount; SL_RETURN( res, _("sh_tiger_hash_val")); } if (what == TIGER_DATA && filename != NULL) { tiger(TIGER_CAST filename, (sh_word32) *Length, res); sh_unix_munlock((char *)buffer, (PRIV_MAX)*sizeof(sh_byte)); SH_FREE(buffer); SL_RETURN(res, _("sh_tiger_hash_val")); } sh_unix_munlock((char *)buffer, (PRIV_MAX)*sizeof(sh_byte)); SH_FREE(buffer); *Length = 0; SL_RETURN( NULL, _("sh_tiger_hash_val")); } /* Thu Oct 18 18:53:33 CEST 2001 */ #ifdef USE_MD5 /*@-type@*/ /* md5.c - Functions to compute MD5 message digest of files or memory blocks * according to the definition of MD5 in RFC 1321 from April 1992. * Copyright (C) 1995, 1996 Free Software Foundation, Inc. * * NOTE: The canonical source of this file is maintained with the GNU C * Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. * * 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. */ /* Written by Ulrich Drepper , 1995. */ /* Hacked to work with samhain by R. Wichmann */ typedef UINT32 md5_uint32; /* Structure to save state of computation between the single steps. */ typedef struct md5_ctx { md5_uint32 A; md5_uint32 B; md5_uint32 C; md5_uint32 D; md5_uint32 total[2]; md5_uint32 buflen; char buffer[128]; } md5Param; /* * The following three functions are build up the low level used in * the functions `md5_stream' and `md5_buffer'. */ /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ static void md5_init_ctx (struct md5_ctx *ctx); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is necessary that LEN is a multiple of 64!!! */ static void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ static void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx); /* Process the remaining bytes in the buffer and put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ static void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); /* Put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ static void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); #if WORDS_BIGENDIAN static md5_uint32 swapu32(md5_uint32 n) { return ( ((n & 0xffU) << 24) | ((n & 0xff00U) << 8) | ((n & 0xff0000U) >> 8) | ((n & 0xff000000U) >> 24) ); } #define SWAP(n) swapu32(n) #else #define SWAP(n) (n) #endif /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ static void md5_init_ctx(struct md5_ctx *ctx) { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } /* Put result from CTX in first 16 bytes following RESBUF. The result must be in little endian byte order. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ static void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf) { ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A); ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B); ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C); ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D); return resbuf; } /* Process the remaining bytes in the internal buffer and the usual prolog according to the standard and write the result to RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ static void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf) { /* Take yet unprocessed bytes into account. */ md5_uint32 bytes = ctx->buflen; size_t pad; md5_uint32 temp; /* Now count remaining bytes. */ ctx->total[0] += bytes; if (ctx->total[0] < bytes) ++ctx->total[1]; pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; memcpy(&ctx->buffer[bytes], fillbuf, pad); /* Put the 64-bit file length in *bits* at the end of the buffer. */ temp = SWAP(ctx->total[0] << 3); memcpy(&(ctx->buffer[bytes + pad]), &temp, sizeof(temp)); temp = SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29)); memcpy(&(ctx->buffer[bytes + pad + 4]), &temp, sizeof(temp)); /* Process last bytes. */ md5_process_block(ctx->buffer, bytes + pad + 8, ctx); return md5_read_ctx(ctx, resbuf); } /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ void *md5_buffer(const char *buffer, size_t len, void *resblock) { struct md5_ctx ctx; /* Initialize the computation context. */ md5_init_ctx(&ctx); /* Process whole buffer but last len % 64 bytes. */ md5_process_bytes(buffer, len, &ctx); /* Put result in desired memory area. */ return md5_finish_ctx(&ctx, resblock); } static void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx) { /* When we already have some bits in our internal buffer concatenate both inputs first. */ if (ctx->buflen != 0) { size_t left_over = ctx->buflen; size_t add = 128 - left_over > len ? len : 128 - left_over; memcpy(&ctx->buffer[left_over], buffer, add); ctx->buflen += add; if (left_over + add > 64) { md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx); /* The regions in the following copy operation cannot overlap. */ memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63], (left_over + add) & 63); ctx->buflen = (left_over + add) & 63; } buffer = (const char *) buffer + add; len -= add; } /* Process available complete blocks. */ if (len > 64) { md5_process_block(buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } /* Move remaining bytes in internal buffer. */ if (len > 0) { memcpy(ctx->buffer, buffer, len); ctx->buflen = len; } } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ctx) { md5_uint32 correct_words[16]; const md5_uint32 *words = buffer; size_t nwords = len / sizeof(md5_uint32); const md5_uint32 *endp = words + nwords; md5_uint32 A = ctx->A; md5_uint32 B = ctx->B; md5_uint32 C = ctx->C; md5_uint32 D = ctx->D; /* First increment the byte count. RFC 1321 specifies the possible length of the file up to 2^64 bits. Here we only compute the number of bytes. Do a double word increment. */ ctx->total[0] += len; if (ctx->total[0] < len) ++ctx->total[1]; /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp) { md5_uint32 *cwp = correct_words; md5_uint32 A_save = A; md5_uint32 B_save = B; md5_uint32 C_save = C; md5_uint32 D_save = D; /* First round: using the given function, the context and a constant the next context is computed. Because the algorithms processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ ++words; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* It is unfortunate that C does not provide an operator for cyclic rotation. Hope the C compiler is smart enough. */ #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) /* Before we start, one word to the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 */ /* Round 1. */ OP(A, B, C, D, 7, 0xd76aa478); OP(D, A, B, C, 12, 0xe8c7b756); OP(C, D, A, B, 17, 0x242070db); OP(B, C, D, A, 22, 0xc1bdceee); OP(A, B, C, D, 7, 0xf57c0faf); OP(D, A, B, C, 12, 0x4787c62a); OP(C, D, A, B, 17, 0xa8304613); OP(B, C, D, A, 22, 0xfd469501); OP(A, B, C, D, 7, 0x698098d8); OP(D, A, B, C, 12, 0x8b44f7af); OP(C, D, A, B, 17, 0xffff5bb1); OP(B, C, D, A, 22, 0x895cd7be); OP(A, B, C, D, 7, 0x6b901122); OP(D, A, B, C, 12, 0xfd987193); OP(C, D, A, B, 17, 0xa679438e); OP(B, C, D, A, 22, 0x49b40821); /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP(FG, A, B, C, D, 1, 5, 0xf61e2562); OP(FG, D, A, B, C, 6, 9, 0xc040b340); OP(FG, C, D, A, B, 11, 14, 0x265e5a51); OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP(FG, A, B, C, D, 5, 5, 0xd62f105d); OP(FG, D, A, B, C, 10, 9, 0x02441453); OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); OP(FG, D, A, B, C, 14, 9, 0xc33707d6); OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); OP(FG, B, C, D, A, 8, 20, 0x455a14ed); OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP(FG, C, D, A, B, 7, 14, 0x676f02d9); OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP(FH, A, B, C, D, 5, 4, 0xfffa3942); OP(FH, D, A, B, C, 8, 11, 0x8771f681); OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); OP(FH, B, C, D, A, 14, 23, 0xfde5380c); OP(FH, A, B, C, D, 1, 4, 0xa4beea44); OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); OP(FH, B, C, D, A, 6, 23, 0x04881d05); OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP(FI, A, B, C, D, 0, 6, 0xf4292244); OP(FI, D, A, B, C, 7, 10, 0x432aff97); OP(FI, C, D, A, B, 14, 15, 0xab9423a7); OP(FI, B, C, D, A, 5, 21, 0xfc93a039); OP(FI, A, B, C, D, 12, 6, 0x655b59c3); OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP(FI, C, D, A, B, 10, 15, 0xffeff47d); OP(FI, B, C, D, A, 1, 21, 0x85845dd1); OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP(FI, C, D, A, B, 6, 15, 0xa3014314); OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); OP(FI, A, B, C, D, 4, 6, 0xf7537e82); OP(FI, D, A, B, C, 11, 10, 0xbd3af235); OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP(FI, B, C, D, A, 9, 21, 0xeb86d391); /* Add the starting values of the context. */ A += A_save; B += B_save; C += C_save; D += D_save; } /* Put checksum in context given as argument. */ ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } /*---------------------------------------------------------------------------- *--------end of md5.c *----------------------------------------------------------------------------*/ int md5Reset(register md5Param* p) { unsigned int i; md5_init_ctx(p); for (i = 0; i < 16; i += 8) { p->buffer[i] = 0x00; p->buffer[i+1] = 0x00; p->buffer[i+2] = 0x00; p->buffer[i+3] = 0x00; p->buffer[i+4] = 0x00; p->buffer[i+5] = 0x00; p->buffer[i+6] = 0x00; p->buffer[i+7] = 0x00; } return 0; } int md5Update(md5Param* p, const sh_byte* data, int size) { md5_process_bytes(data, size, p); return 0; } static void md5Finish(md5Param* p, void *resblock) { (void) md5_finish_ctx(p, resblock); } int md5Digest(md5Param* p, md5_uint32* data) { md5Finish(p, data); (void) md5Reset(p); return 0; } /*@+type@*/ /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ static int md5_stream(char * filename, void *resblock, UINT64 * Length, int timeout, SL_TICKET fd) { /* Important: BLOCKSIZE must be a multiple of 64. */ static const int BLOCKSIZE = 8192; struct md5_ctx ctx; char * buffer = SH_ALLOC(8264); /* BLOCKSIZE + 72 AIX compiler chokes */ size_t sum; char * tmp; uid_t euid; UINT64 bcount = 0; sh_string * content; unsigned long pages_read; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) /*@-nestedextern@*/ extern long IO_Limit; /*@+nestedextern@*/ #endif /* Initialize the computation context. */ (void) md5Reset (&ctx); if (SL_ISERROR (fd)) { TPT((0, FIL__, __LINE__, _("msg=\n"), fd)); tmp = sh_util_safe_name (filename); (void) sl_get_euid(&euid); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, fd, MSG_E_ACCESS, (long) euid, tmp); SH_FREE(tmp); *Length = 0; SH_FREE(buffer); return -1; } pages_read = 0; content = sl_get_content(fd); /* Iterate over full file contents. */ while (1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ off_t n; sum = 0; /* Read block. Take care for partial reads. */ do { n = (off_t) sl_read_timeout (fd, buffer + sum, (size_t) BLOCKSIZE - sum, timeout, S_FALSE); if (SL_ISERROR (n)) { int error = errno; if (sig_termfast == 1) { SH_FREE(buffer); return -1; } TPT((0, FIL__ , __LINE__ , _("msg=\n"), n)); tmp = sh_util_safe_name (filename); if (n == SL_TIMEOUT) { if (timeout != 7) { sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, n, MSG_E_TIMEOUT, timeout, tmp); } } else { char errbuf[SH_ERRBUF_SIZE]; char errbuf2[SH_ERRBUF_SIZE]; sl_strlcpy(errbuf, sl_error_string(n), sizeof(errbuf)); sh_error_message(error, errbuf2, sizeof(errbuf2)); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, n, MSG_E_READ, errbuf, errbuf2, tmp); } SH_FREE(tmp); *Length = 0; SH_FREE(buffer); return -1; } if (content) sh_string_cat_lchar(content, buffer, n); bcount += n; if (*Length != TIGER_NOLIM) { if (bcount > *Length) { n = n - (bcount - (*Length)); bcount = *Length; n = (n < 0) ? 0 : n; } } sum += n; } while (sum < (size_t) BLOCKSIZE && n != 0); ++pages_read; /* If end of file is reached, end the loop. */ if (n == 0) break; /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ md5_process_block(buffer, BLOCKSIZE, &ctx); sh.statistics.bytes_hashed += BLOCKSIZE; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) if ((IO_Limit) > 0 && (pages_read == 32)) /* check for I/O limit */ { sh_unix_io_pause (); pages_read = 0; } if (sig_termfast == 1) { *Length = 0; SH_FREE(buffer); return -1; } #endif } /* Add the last bytes if necessary. */ if (sum > 0) { md5_process_bytes(buffer, sum, &ctx); sh.statistics.bytes_hashed += BLOCKSIZE; } /* Construct result in desired memory. */ (void) md5Digest(&ctx, resblock); *Length = bcount; SH_FREE(buffer); return 0; } static char * sh_tiger_md5_hash (char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len) { int cnt; char outbuf[KEY_LEN+1]; unsigned char md5buffer[16]; (void) md5_stream (filename, md5buffer, Length, timeout, what); /*@-bufferoverflowhigh -usedef@*/ for (cnt = 0; cnt < 16; ++cnt) sprintf (&outbuf[cnt*2], _("%02X"), /* known to fit */ (unsigned int) md5buffer[cnt]); /*@+bufferoverflowhigh +usedef@*/ for (cnt = 32; cnt < KEY_LEN; ++cnt) outbuf[cnt] = '0'; outbuf[KEY_LEN] = '\0'; sl_strlcpy(out, outbuf, len); return out; } /* USE_MD5 */ #endif /*************************************************************** * * SHA1 * ***************************************************************/ #ifdef USE_SHA1 /*@-type@*/ typedef unsigned char sha_word8; typedef sh_word32 sha_word32; /* The SHA block size and message digest sizes, in bytes */ #define SHA_DATASIZE 64 #define SHA_DATALEN 16 #define SHA_DIGESTSIZE 20 #define SHA_DIGESTLEN 5 /* The structure for storing SHA info */ typedef struct sha_ctx { sha_word32 digest[SHA_DIGESTLEN]; /* Message digest */ sha_word32 count_l, count_h; /* 64-bit block count */ sha_word8 block[SHA_DATASIZE]; /* SHA data buffer */ int index; /* index into buffer */ } SHA_CTX; static void sha_init(struct sha_ctx *ctx); static void sha_update(struct sha_ctx *ctx, sha_word8 *buffer,sha_word32 len); static void sha_final(struct sha_ctx *ctx); static void sha_digest(struct sha_ctx *ctx, sha_word8 *s); /* The SHA f()-functions. The f1 and f3 functions can be optimized to save one boolean 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 */ /* SHA initial values */ #define h0init 0x67452301L #define h1init 0xEFCDAB89L #define h2init 0x98BADCFEL #define h3init 0x10325476L #define h4init 0xC3D2E1F0L /* 32-bit rotate left - kludged with shifts */ #define ROTL(n,X) ( ( (X) << (n) ) | ( (X) >> ( 32 - (n) ) ) ) /* 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 */ #define expand(W,i) ( W[ i & 15 ] = \ ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) /* 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( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) /* Initialize the SHA values */ static void sha_init(struct sha_ctx *ctx) { /* Set the h-vars to their initial values */ ctx->digest[ 0 ] = h0init; ctx->digest[ 1 ] = h1init; ctx->digest[ 2 ] = h2init; ctx->digest[ 3 ] = h3init; ctx->digest[ 4 ] = h4init; /* Initialize bit count */ ctx->count_l = ctx->count_h = 0; /* Initialize buffer */ ctx->index = 0; } /* 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 Note that this function destroys the data area */ static void sha_transform(struct sha_ctx *ctx, sha_word32 *data ) { register sha_word32 A, B, C, D, E; /* Local vars */ /* Set up first buffer and local data buffer */ A = ctx->digest[0]; B = ctx->digest[1]; C = ctx->digest[2]; D = ctx->digest[3]; E = ctx->digest[4]; /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ subRound( A, B, C, D, E, f1, K1, data[ 0] ); subRound( E, A, B, C, D, f1, K1, data[ 1] ); subRound( D, E, A, B, C, f1, K1, data[ 2] ); subRound( C, D, E, A, B, f1, K1, data[ 3] ); subRound( B, C, D, E, A, f1, K1, data[ 4] ); subRound( A, B, C, D, E, f1, K1, data[ 5] ); subRound( E, A, B, C, D, f1, K1, data[ 6] ); subRound( D, E, A, B, C, f1, K1, data[ 7] ); subRound( C, D, E, A, B, f1, K1, data[ 8] ); subRound( B, C, D, E, A, f1, K1, data[ 9] ); subRound( A, B, C, D, E, f1, K1, data[10] ); subRound( E, A, B, C, D, f1, K1, data[11] ); subRound( D, E, A, B, C, f1, K1, data[12] ); subRound( C, D, E, A, B, f1, K1, data[13] ); subRound( B, C, D, E, A, f1, K1, data[14] ); subRound( A, B, C, D, E, f1, K1, data[15] ); subRound( E, A, B, C, D, f1, K1, expand( data, 16 ) ); subRound( D, E, A, B, C, f1, K1, expand( data, 17 ) ); subRound( C, D, E, A, B, f1, K1, expand( data, 18 ) ); subRound( B, C, D, E, A, f1, K1, expand( data, 19 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 20 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 21 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 22 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 23 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 24 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 25 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 26 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 27 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 28 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 29 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 30 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 31 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 32 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 33 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 34 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 35 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 36 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 37 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 38 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 39 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 40 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 41 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 42 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 43 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 44 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 45 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 46 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 47 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 48 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 49 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 50 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 51 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 52 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 53 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 54 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 55 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 56 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 57 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 58 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 59 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 60 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 61 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 62 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 63 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 64 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 65 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 66 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 67 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 68 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 69 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 70 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 71 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 72 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 73 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 74 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 75 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 76 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 77 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 78 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 79 ) ); /* Build message digest */ ctx->digest[0] += A; ctx->digest[1] += B; ctx->digest[2] += C; ctx->digest[3] += D; ctx->digest[4] += E; } #if 1 #ifndef EXTRACT_UCHAR #define EXTRACT_UCHAR(p) (*(unsigned char *)(p)) #endif #define STRING2INT(s) ((((((EXTRACT_UCHAR(s) << 8) \ | EXTRACT_UCHAR(s+1)) << 8) \ | EXTRACT_UCHAR(s+2)) << 8) \ | EXTRACT_UCHAR(s+3)) #else sha_word32 STRING2INT(word8 *s) { sha_word32 r; int i; for (i = 0, r = 0; i < 4; i++, s++) r = (r << 8) | *s; return r; } #endif static void sha_block(struct sha_ctx *ctx, sha_word8 *block) { sha_word32 data[SHA_DATALEN]; int i; /* Update block count */ /*@-boolops@*/ if (!++ctx->count_l) ++ctx->count_h; /*@+boolops@*/ /* Endian independent conversion */ for (i = 0; iindex != 0) { /* Try to fill partial block */ unsigned left = SHA_DATASIZE - ctx->index; if (len < left) { memmove(ctx->block + ctx->index, buffer, len); ctx->index += len; return; /* Finished */ } else { memmove(ctx->block + ctx->index, buffer, left); sha_block(ctx, ctx->block); buffer += left; len -= left; } } while (len >= SHA_DATASIZE) { sha_block(ctx, buffer); buffer += SHA_DATASIZE; len -= SHA_DATASIZE; } /*@-predboolint@*/ if ((ctx->index = len)) /* This assignment is intended */ /*@+predboolint@*/ /* Buffer leftovers */ memmove(ctx->block, buffer, len); } /* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern 1 0* (64-bit count of bits processed, MSB-first) */ static void sha_final(struct sha_ctx *ctx) { sha_word32 data[SHA_DATALEN]; int i; int words; i = ctx->index; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ ctx->block[i++] = 0x80; /* Fill rest of word */ /*@-predboolint@*/ for( ; i & 3; i++) ctx->block[i] = 0; /*@+predboolint@*/ /* i is now a multiple of the word size 4 */ /*@-shiftimplementation@*/ words = i >> 2; /*@+shiftimplementation@*/ for (i = 0; i < words; i++) data[i] = STRING2INT(ctx->block + 4*i); if (words > (SHA_DATALEN-2)) { /* No room for length in this block. Process it and * pad with another one */ for (i = words ; i < SHA_DATALEN; i++) data[i] = 0; sha_transform(ctx, data); for (i = 0; i < (SHA_DATALEN-2); i++) data[i] = 0; } else for (i = words ; i < SHA_DATALEN - 2; i++) data[i] = 0; /* Theres 512 = 2^9 bits in one block */ /*@-shiftimplementation@*/ data[SHA_DATALEN-2] = (ctx->count_h << 9) | (ctx->count_l >> 23); data[SHA_DATALEN-1] = (ctx->count_l << 9) | (ctx->index << 3); /*@+shiftimplementation@*/ sha_transform(ctx, data); } static void sha_digest(struct sha_ctx *ctx, sha_word8 *s) { int i; for (i = 0; i < SHA_DIGESTLEN; i++) { *s++ = ctx->digest[i] >> 24; *s++ = 0xff & (ctx->digest[i] >> 16); *s++ = 0xff & (ctx->digest[i] >> 8); *s++ = 0xff & ctx->digest[i]; } } /*@+type@*/ #include "sh_checksum.h" #define SH_VAR_SHA1 0 #define SH_VAR_SHA256 1 /* Compute SHA1 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ static int SHA_stream(char * filename, void *resblock, UINT64 * Length, int timeout, SL_TICKET fd, int variant) { /* Important: BLOCKSIZE must be a multiple of 64. */ static const int BLOCKSIZE = 4096; struct sha_ctx ctx; SHA256_CTX ctx_sha2; char * buffer = SH_ALLOC(4168); /* BLOCKSIZE + 72 AIX compiler chokes */ off_t sum = 0; char * tmp; uid_t euid; UINT64 bcount = 0; sh_string * content; unsigned long pages_read; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) /*@-nestedextern@*/ extern long IO_Limit; /*@+nestedextern@*/ #endif /* Initialize the computation context. */ if (variant == SH_VAR_SHA256) (void) SHA256_Init(&ctx_sha2); else (void) sha_init(&ctx); if (SL_ISERROR (fd)) { TPT((0, FIL__, __LINE__, _("msg=\n"), fd)); tmp = sh_util_safe_name (filename); (void) sl_get_euid(&euid); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, fd, MSG_E_ACCESS, (long) euid, tmp); SH_FREE(tmp); *Length = 0; SH_FREE(buffer); return -1; } /* Iterate over full file contents. */ pages_read = 0; content = sl_get_content(fd); while (1 == 1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ off_t n; sum = 0; /* Read block. Take care for partial reads. */ do { n = (off_t) sl_read_timeout(fd, buffer + sum, (size_t) BLOCKSIZE - sum, timeout, S_FALSE); if (SL_ISERROR (n)) { int error = errno; if (sig_termfast == 1) { SH_FREE(buffer); return -1; } TPT((0, FIL__ , __LINE__ , _("msg=\n"), n)); tmp = sh_util_safe_name (filename); if (n == SL_TIMEOUT) { if (timeout != 7) { sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, n, MSG_E_TIMEOUT, timeout, tmp); } } else { char errbuf[SH_ERRBUF_SIZE]; char errbuf2[SH_ERRBUF_SIZE]; sl_strlcpy(errbuf, sl_error_string(n), sizeof(errbuf)); sh_error_message(error, errbuf2, sizeof(errbuf2)); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, n, MSG_E_READ, errbuf, errbuf2, tmp); } SH_FREE(tmp); *Length = 0; SH_FREE(buffer); return -1; } if (content) sh_string_cat_lchar(content, buffer, n); bcount += n; if (*Length != TIGER_NOLIM) { if (bcount > *Length) { n = n - (bcount - (*Length)); bcount = *Length; n = (n < 0) ? 0 : n; } } sum += n; } while (sum < (off_t)BLOCKSIZE && n != 0); ++pages_read; /* If end of file is reached, end the loop. */ if (n == 0) break; /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ if (variant == SH_VAR_SHA256) SHA256_Update(&ctx_sha2, (sha2_byte*) buffer, (size_t) BLOCKSIZE); else sha_update(&ctx, (sha_word8*) buffer, (sha_word32) BLOCKSIZE); sh.statistics.bytes_hashed += BLOCKSIZE; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) if ((IO_Limit) > 0 && (pages_read == 32)) /* check for I/O limit */ { sh_unix_io_pause (); pages_read = 0; } if (sig_termfast == 1) { *Length = 0; SH_FREE(buffer); return -1; } #endif } /* Add the last bytes if necessary. */ if (sum > 0) { if (variant == SH_VAR_SHA256) SHA256_Update(&ctx_sha2, (sha2_byte*) buffer, (size_t) sum); else sha_update(&ctx, (sha_word8*) buffer, (sha_word32) sum); sh.statistics.bytes_hashed += sum; } /* Construct result in desired memory. */ if (variant == SH_VAR_SHA256) { SHA256_End(&ctx_sha2, resblock); } else { sha_final (&ctx); sha_digest (&ctx, resblock); } *Length = bcount; SH_FREE(buffer); return 0; } static char * sh_tiger_sha1_hash (char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len) { int cnt; char outbuf[KEY_LEN+1]; unsigned char sha1buffer[20]; (void) SHA_stream (filename, sha1buffer, Length, timeout, what, SH_VAR_SHA1); /*@-bufferoverflowhigh -usedef@*/ for (cnt = 0; cnt < 20; ++cnt) sprintf (&outbuf[cnt*2], _("%02X"), /* known to fit */ (unsigned int) sha1buffer[cnt]); /*@+bufferoverflowhigh +usedef@*/ for (cnt = 40; cnt < KEY_LEN; ++cnt) outbuf[cnt] = '0'; outbuf[KEY_LEN] = '\0'; sl_strlcpy(out, outbuf, len); return out; } static char * sh_tiger_sha256_hash (char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len) { char outbuf[KEYBUF_SIZE]; (void) SHA_stream (filename, outbuf, Length, timeout, what, SH_VAR_SHA256); sl_strlcpy(out, outbuf, len); return out; } /* ifdef USE_SHA1 */ #endif static int hash_type = SH_TIGER192; int sh_tiger_get_hashtype () { return hash_type; } void sh_tiger_get_mask_hashtype(unsigned long * mask) { if (hash_type == SH_TIGER192) *mask |= MODI_TIGER192; else if (hash_type == SH_SHA1) *mask |= MODI_SHA1; else if (hash_type == SH_MD5) *mask |= MODI_MD5; else if (hash_type == SH_SHA256) *mask |= MODI_SHA256; return; } void sh_tiger_set_hashtype_mask(unsigned long mask) { unsigned long type = mask & MODI_HASHTYPE; if (type == MODI_TIGER192) hash_type = SH_TIGER192; else if (type == MODI_SHA1) hash_type = SH_SHA1; else if (type == MODI_MD5) hash_type = SH_MD5; else if (type == MODI_SHA256) hash_type = SH_SHA256; return; } int sh_tiger_hashtype (const char * c) { SL_ENTER( _("sh_tiger_hashtype")); if (!c) { SL_RETURN( -1, _("sh_tiger_hashtype")); } if (0 == strcmp(c, _("TIGER192"))) hash_type = SH_TIGER192; #ifdef USE_SHA1 else if (0 == strcmp(c, _("SHA1"))) hash_type = SH_SHA1; #endif #ifdef USE_MD5 else if (0 == strcmp(c, _("MD5"))) hash_type = SH_MD5; #endif #ifdef USE_SHA1 else if (0 == strcmp(c, _("SHA256"))) hash_type = SH_SHA256; #endif else { SL_RETURN( -1, _("sh_tiger_hashtype")); } SL_RETURN( 0, _("sh_tiger_hashtype")); } static char * sh_tiger_hash_internal (const char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len); char * sh_tiger_hash (const char * filename, TigerType what, UINT64 Length, char * out, size_t len) { UINT64 local_length = Length; char * retval = sh_tiger_hash_internal (filename, what, &local_length, 0, out,len); return retval; } char * sh_tiger_generic_hash (char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len) { #ifdef USE_SHA1 if (hash_type == SH_SHA1) return sh_tiger_sha1_hash (filename, what, Length, timeout, out, len); #endif #ifdef USE_MD5 if (hash_type == SH_MD5) return sh_tiger_md5_hash (filename, what, Length, timeout, out, len); #endif #ifdef USE_SHA1 if (hash_type == SH_SHA256) return sh_tiger_sha256_hash (filename, what, Length, timeout, out, len); #endif return sh_tiger_hash_internal (filename, what, Length, timeout, out, len); } /* * ------- end new --------- */ static char * sh_tiger_hash_internal (const char * filename, TigerType what, UINT64 * Length, int timeout, char * out, size_t len) { #if defined(TIGER_64_BIT) word64 res[3]; #else sh_word32 res[6]; #endif SL_ENTER( _("sh_tiger_hash_internal")); SH_VALIDATE_GE(len, (KEY_LEN+1)); if (NULL != sh_tiger_hash_val (filename, what, Length, timeout, res)) { #if defined(TIGER_64_BIT) sl_snprintf(out, len, MYFORMAT, (sh_word32)(res[0]>>32), (sh_word32)(res[0]), (sh_word32)(res[1]>>32), (sh_word32)(res[1]), (sh_word32)(res[2]>>32), (sh_word32)(res[2]) ); #else sl_snprintf(out, len, MYFORMAT, (sh_word32)(res[1]), (sh_word32)(res[0]), (sh_word32)(res[3]), (sh_word32)(res[2]), (sh_word32)(res[5]), (sh_word32)(res[4]) ); #endif out[len-1] = '\0'; SL_RETURN( out, _("sh_tiger_hash_internal")); } SL_RETURN( SH_KEY_NULL, _("sh_tiger_hash_internal")); } char * sh_tiger_hash_gpg (const char * filename, TigerType what, UINT64 Length) { size_t len; char * out; char outhash[48+6+1]; #if defined(TIGER_64_BIT) word64 res[3]; #else sh_word32 res[6]; #endif UINT64 local_length = Length; SL_ENTER(_("sh_tiger_hash_gpg")); if (NULL != sh_tiger_hash_val (filename, what, &local_length, 0, res)) { #if defined(TIGER_64_BIT) sl_snprintf(outhash, sizeof(outhash), GPGFORMAT, (sh_word32)(res[0]>>32), (sh_word32)(res[0]), (sh_word32)(res[1]>>32), (sh_word32)(res[1]), (sh_word32)(res[2]>>32), (sh_word32)(res[2]) ); #else sl_snprintf(outhash, sizeof(outhash), GPGFORMAT, (sh_word32)(res[1]), (sh_word32)(res[0]), (sh_word32)(res[3]), (sh_word32)(res[2]), (sh_word32)(res[5]), (sh_word32)(res[4]) ); #endif outhash[sizeof(outhash)-1] = '\0'; } else { sl_strlcpy(outhash, _("00000000 00000000 00000000 00000000 00000000 00000000"), sizeof(outhash)); } if (what == TIGER_FILE && sl_ok_adds(sl_strlen (filename), (2 + 48 + 6))) len = sl_strlen (filename) + 2 + 48 + 6; else len = 48 + 6; out = SH_ALLOC(len + 1); if (what == TIGER_FILE) { (void) sl_strlcpy (out, filename, len+1); (void) sl_strlcat (out, _(": "), len+1); (void) sl_strlcat (out, outhash, len+1); } else { (void) sl_strlcpy (out, outhash, len+1); } SL_RETURN( out, _("sh_tiger_hash_gpg")); } UINT32 * sh_tiger_hash_uint32 (char * filename, TigerType what, UINT64 Length, UINT32 * out, size_t len) { #if defined(TIGER_64_BIT) word64 res[3]; #else sh_word32 res[6]; #endif UINT64 local_length = Length; SL_ENTER(_("sh_tiger_hash_uint32")); SH_VALIDATE_GE(len, 6); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 0; if (NULL != sh_tiger_hash_val (filename, what, &local_length, 0, res)) { #if defined(TIGER_64_BIT) out[0] = (UINT32)(res[0]>>32); out[1] = (UINT32)(res[0]); out[2] = (UINT32)(res[1]>>32); out[3] = (UINT32)(res[1]); out[4] = (UINT32)(res[2]>>32); out[5] = (UINT32)(res[2]); #else out[0] = (UINT32)(res[1]); out[1] = (UINT32)(res[0]); out[2] = (UINT32)(res[3]); out[3] = (UINT32)(res[2]); out[4] = (UINT32)(res[5]); out[5] = (UINT32)(res[4]); #endif } SL_RETURN(out, _("sh_tiger_hash_uint32")); } samhain-4.1.4/src/sh_err_log.c0000644000175000017500000007760712615253277013172 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include "samhain.h" #include "sh_error.h" #include "sh_utils.h" #include "sh_tiger.h" #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #include #endif #undef FIL__ #define FIL__ _("sh_err_log.c") #undef FIX_XML #define FIX_XML 1 #define MYSIGLEN (2*KEY_LEN + 32) typedef struct _sh_log_buf { char signature[KEY_LEN+1]; char timestamp[KEY_LEN+1]; #ifdef SH_USE_XML char sig[MYSIGLEN]; #endif char * msg; } sh_sh_log_buf; extern struct _errFlags errFlags; #define CHK_KEY 0 #define CHK_FIL 1 #define CHK_NON 2 static int get_key_from_file(char * path, char * keyid, char * key) { SL_TICKET fd; char * buf; char * bufc; if (path[strlen(path)-1] == '\n') path[strlen(path)-1] = '\0'; /* open the file, then check it */ if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, path, SL_NOPRIV))) { fprintf(stderr, _("Could not open file <%s>\n"), path); _exit (EXIT_FAILURE); } buf = SH_ALLOC( (size_t)(SH_BUFSIZE+1)); bufc = SH_ALLOC( (size_t)(SH_MAXBUF+1)); while (1 == 1) { buf[0] = '\0'; bufc[0] = '\0'; /* find start of next key */ while (0 != sl_strncmp(buf, _("-----BEGIN LOGKEY-----"), sizeof("-----BEGIN LOGKEY-----")-1)) { (void) sh_unix_getline (fd, buf, SH_BUFSIZE); if (buf[0] == '\0') { /* End of file reached, return. */ (void) fflush(stdout); (void) sl_close(fd); return -1; } } /* read key */ (void) sh_unix_getline (fd, buf, SH_BUFSIZE); if (0 == sl_strncmp(keyid, &buf[KEY_LEN], strlen(keyid))) { (void) sl_strlcpy(key, buf, KEY_LEN+1); (void) sl_close(fd); return 0; } } /*@notreached@*/ } static int just_list = S_FALSE; int sh_error_logverify_mod (const char * s) { just_list = S_TRUE; if (s) /* compiler warning (unused var) fix */ return 0; else return 0; } int sh_error_logverify (const char * s) { SL_TICKET fd; int len; int status; int count = 0; int start = -1; char * buf; char * bufc; #ifdef SH_USE_XML char * ptr; int fixed_xml = S_TRUE; char c_start; #endif char signature[64]; char key[KEY_LEN+2]; char path[KEY_LEN+1]; char timestamp[64]; char c_cont; int chk_mode = CHK_KEY; char hashbuf[KEYBUF_SIZE]; sh_error_logoff(); if (s == NULL || sl_strlen(s) >= PATH_MAX) { fprintf(stderr, _("FAIL: msg=\"Invalid input\", path=\"%s\"\n"), s); _exit (EXIT_FAILURE); } /* Open the file, then check it. */ if (0 != sl_is_suid()) { fprintf(stderr, _("Cannot open file %s in suid mode\n"), s); _exit (EXIT_FAILURE); } if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, s, SL_NOPRIV)) ) { fprintf(stderr, _("FAIL: msg=\"File not accessible\", error=\"%ld\", path=\"%s\"\n"), fd, s); _exit (EXIT_FAILURE); } /* Find space value. */ c_cont = ' '; #ifdef SH_STEALTH c_cont ^= XOR_CODE; #endif #ifdef SH_USE_XML c_start = '<'; #ifdef SH_STEALTH c_start ^= XOR_CODE; #endif #endif buf = (char *) SH_ALLOC( 2*SH_MSG_BUF+1 ); bufc = (char *) SH_ALLOC( 2*SH_MSG_BUF+1 ); while (1 == 1) { /* get the log message */ if (sh_unix_getline (fd, buf, (2*SH_MSG_BUF)) < 0) break; len = (int) sl_strlen(buf); #ifdef SH_USE_XML #ifdef SH_STEALTH if (0 == sl_strncmp (buf, N_(""), 7)) #else if (0 == sl_strncmp (buf, _(""), 7)) #endif #else #ifdef SH_STEALTH if (0 == sl_strncmp (buf, N_("[SOF]"), 5)) #else if (0 == sl_strncmp (buf, _("[SOF]"), 5)) #endif #endif { if (just_list == S_TRUE) { #ifdef SH_STEALTH sh_do_decode (buf, sl_strlen(buf)); #endif fprintf (stdout, _("%s\n"), buf); } /* Found start of audit trail, read first line. */ start = 1; do { if ( sh_unix_getline (fd, buf, (2*SH_MSG_BUF)) < 0) break; } while (buf[0] == '\0' || buf[0] == '\n'); len = (int) sl_strlen(buf); if (just_list == S_TRUE) { #ifdef SH_STEALTH if (buf[0] != '\n') sh_do_decode (buf, sl_strlen(buf)); #endif fprintf (stdout, _("%s\n"), buf); start = 0; } ++count; } else if (buf[0] == '\n' #ifdef SH_USE_XML || #ifdef SH_STEALTH 0 == sl_strncmp(buf, N_(""), 7) #else 0 == sl_strncmp(buf, _(""), 7) #endif #endif ) { if (just_list == S_TRUE) { #ifdef SH_STEALTH if (buf[0] != '\n') sh_do_decode (buf, sl_strlen(buf)); #endif fprintf (stdout, _("%s\n"), buf); } /* A newline. */ ++count; continue; } else if (start == 0) { /* We are inside an audit trail. */ ++count; if (just_list == S_TRUE) { #ifdef SH_STEALTH sh_do_decode (buf, sl_strlen(buf)); #endif fprintf (stdout, _("%s\n"), buf); continue; } } else { /* No start-of-file found yet. */ continue; } if (just_list == S_TRUE) continue; /* Check for a continuation line. */ while (1 == 1) { do { if ( sh_unix_getline (fd, bufc, (2*SH_MSG_BUF)) < 0) break; } while (bufc[0] == '\0' || bufc[0] == '\n'); ++count; if (bufc[0] == c_cont) { /* A continuation line. Add the newline. */ (void) sl_strlcat(buf, "\n", 2*SH_MSG_BUF+1); ++len; (void) sl_strlcat(buf, bufc, 2*SH_MSG_BUF+1); len += (int) sl_strlen(bufc); } else { /* No continuation line. Use it as signature. * A48014C05604EF7C9472330E85453E704024943E556163C2 */ #ifdef SH_USE_XML #ifdef SH_STEALTH if (bufc[0] == c_start) /* FIX XML */ #else if (bufc[0] == c_start) #endif { (void) sl_strlcpy(signature, &bufc[5], KEY_LEN+1); fixed_xml = S_TRUE; } else { (void) sl_strlcpy(signature, &bufc[4], KEY_LEN+1); fixed_xml = S_FALSE; } if (sl_strlen(bufc) > (KEY_LEN+18)) { #ifdef SH_STEALTH if (bufc[0] == c_start) /* FIX XML */ #else if (bufc[0] == c_start) #endif (void) sl_strlcpy(timestamp, &bufc[KEY_LEN+5], 64); else (void) sl_strlcpy(timestamp, &bufc[KEY_LEN+4], 64); #ifdef SH_STEALTH ptr = strchr(timestamp, c_start); #else ptr = strchr(timestamp, c_start); #endif if (ptr) *ptr = '\0'; } break; #else sl_strlcpy(signature, bufc, KEY_LEN+1); if (sl_strlen(bufc) > KEY_LEN) sl_strlcpy(timestamp, &bufc[KEY_LEN], 64); break; #endif } } /* Get starting key from command line. */ if (start == 1) { /* Get the timestamp. */ #ifdef SH_STEALTH sh_do_decode (timestamp, sl_strlen(timestamp)); #endif key[0] = '\0'; findKey: if (chk_mode != CHK_FIL) { /* Ask for the key. */ chk_mode = CHK_KEY; fprintf(stdout, _("\nNew audit trail (%s), enter key|keyfile: "), /*@-usedef@*/timestamp/*@+usedef@*/); key[0] = '\0'; while (strlen(key) < KEY_LEN ) { if (key[0] != '\n' && key[0] != '\0') fprintf(stdout, "%s",_("New audit trail, enter key: ")); else if (key[0] == '\n') { (void) sl_strlcpy(key, sh_tiger_hash(NULL, TIGER_DATA, 0, hashbuf, sizeof(hashbuf)), KEY_LEN+1); chk_mode = CHK_NON; break; } (void) fflush(stdout); key[0] = '\0'; if (NULL != fgets(key, sizeof(key), stdin)) { if (key[0] != '\n') { if (key[strlen(key) - 1] == '\n') key[strlen(key) - 1] = '\0'; } if (key[0] == '/') { chk_mode = CHK_FIL; (void) sl_strlcpy(path, key, KEY_LEN+1); break; } } } } /* we now have either a key (chk_mode == CHK_NON|CHK_KEY) * or a file (chk_mode == CHK_FIL) */ if (chk_mode == CHK_FIL) { fprintf(stdout, _("\nAudit trail (%s), searching file %s\n"), /*@-usedef@*/timestamp, path/*@+usedef@*/); if (-1 == get_key_from_file(path, timestamp, key)) { chk_mode = CHK_KEY; fprintf(stdout, "%s",_("Key not found in file\n")); goto findKey; } } sh_util_encode(key, buf, 1, 'B'); start = 0; } else { /* Iterate the key. */ (void) sl_strlcpy (key, sh_tiger_hash (key, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } (void) sl_strlcat ( buf, key, 2*SH_MSG_BUF + 1); #ifdef SH_STEALTH sh_do_decode (signature, sl_strlen(signature)); #endif status = sl_strncmp (signature, sh_tiger_hash (buf, TIGER_DATA, (unsigned long) sl_strlen(buf), hashbuf, sizeof(hashbuf)), KEY_LEN); buf[len] = '\0'; /* do not print out the key */ #ifdef SH_STEALTH sh_do_decode (buf, sl_strlen(buf)); #endif if (status != 0) { #ifdef SH_USE_XML if (chk_mode == CHK_NON) { if (fixed_xml == S_FALSE) fprintf (stdout, _("XFAIL: line=%05d %s/log>\n"), count-1, buf); else fprintf (stdout, _("XFAIL: line=%05d %s\n"), count-1, buf); } else { if (fixed_xml == S_FALSE) fprintf (stdout, _("FAIL: line=%05d %s/log>\n"), count-1, buf); else fprintf (stdout, _("FAIL: line=%05d %s\n"), count-1, buf); } #else if (chk_mode == CHK_NON) fprintf (stdout, _("XFAIL: line=%5d %s\n"), count-1, buf); else fprintf (stdout, _("FAIL: line=%5d %s\n"), count-1, buf); #endif } else { #ifdef SH_USE_XML if (fixed_xml == S_FALSE) fprintf (stdout, _("PASS: line=%05d %s/log>\n"), count-1, buf); else fprintf (stdout, _("PASS: line=%05d %s\n"), count-1, buf); #else fprintf (stdout, _("PASS: line=%5d %s\n"), count-1, buf); #endif } } /* Cleanup and exit. */ (void) sl_close (fd); SH_FREE (buf); SH_FREE (bufc); (void) fflush (stdout); _exit (EXIT_SUCCESS); /* Make compilers happy. */ /*@notreached@*/ return 0; } /******************************************************************** * * Runtime code * ********************************************************************/ static int sh_log_open (char * inet_peer, char * logfile, int * service_failure, SL_TICKET * fildesc) { SL_TICKET fd = -1; long int status; char * tmp = NULL; uid_t uid; size_t len; char * lockfile = NULL; SL_ENTER(_("sh_log_open")); /* open/create the file, then check it */ if ( 0 != (status = tf_trust_check (logfile, SL_YESPRIV)) && (*service_failure) == 0) { tmp = sh_util_safe_name (logfile); sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST, (long) sh.effective.uid, tmp); } if (status == 0) { fd = sl_open_write (FIL__, __LINE__, logfile, SL_YESPRIV); if (SL_ISERROR(fd)) { tmp = sh_util_safe_name (logfile); (void) sl_get_euid(&uid); if ((*service_failure) == 0) sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_E_ACCESS, (long) uid, tmp); status = -1; } } if (status == 0 && inet_peer == NULL ) { status = sh_unix_write_lock_file(logfile); if (status < 0) { tmp = sh_util_safe_name (logfile); len = sl_strlen(tmp); if (sl_ok_adds (6, len)) len += 6; lockfile = SH_ALLOC(len); (void) sl_strlcpy(lockfile, tmp, len); (void) sl_strlcat(lockfile, _(".lock"), len); (void) sl_get_euid(&uid); if ((*service_failure) == 0) sh_error_handle ((-1), FIL__, __LINE__, status, MSG_LOCKED, (long) uid, tmp, lockfile); status = -1; SH_FREE(lockfile); (void) sl_close(fd); } } if (status == 0) { status = sl_forward(fd); if (SL_ISERROR(status)) { tmp = sh_util_safe_name (logfile); (void) sl_get_euid(&uid); if ((*service_failure) == 0) sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_ACCESS, (long) uid, tmp); status = -1; (void) sl_close(fd); } } if (status < 0) { if ((*service_failure) == 0) { sh_error_handle ((-1), FIL__, __LINE__, status, MSG_SRV_FAIL, _("logfile"), tmp); (*service_failure) = 1; } if (tmp) SH_FREE(tmp); SL_RETURN(-1, _("sh_log_open")); } *fildesc = fd; *service_failure = 0; SL_RETURN(0, _("sh_log_open")); } typedef struct lfstc { char * logfile; int service_failure; int log_start; char sigkey_old[KEY_LEN+1]; char sigkey_new[KEY_LEN+1]; char crypto[KEY_LEN+1]; struct lfstc * next; } open_logfile; static open_logfile * logfile_list = NULL; static int flag_sep_log = S_FALSE; #ifdef SH_WITH_SERVER int set_flag_sep_log (const char * str) { return sh_util_flagval(str, &flag_sep_log); } #endif /* * --- Log error message to log file. --- */ int sh_log_file (/*@null@*/char *errmsg, /*@null@*/char * inet_peer) { int store1; int store2; int store3; int store4; int store5; int store6; int store7; int store8; SL_TICKET fd = -1; size_t status; struct _sh_log_buf log_msg; char logfile[SH_PATHBUF+SH_MINIBUF+2]; open_logfile * current = logfile_list; open_logfile * next = NULL; char * sigkey_new; char * sigkey_old; char * crypto; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_log_file")); if (errFlags.HaveLog == BAD) /* paranoia */ SL_RETURN((-1), _("sh_log_file")); #ifdef SH_USE_XML if (NULL == errmsg) { while (current != NULL) { /* don't write second EOF mark */ if (current->log_start != S_TRUE && sh.flag.islocked == GOOD) { /* Don't use inet_peer == NULL, userwise a lock file will * be created. */ (void) sh_log_open ("\0", current->logfile, &(current->service_failure), &fd); #ifdef SH_STEALTH (void) sl_write_line (fd, N_(""), 7); (void) sl_write (fd, "\n", 1); (void) sl_sync(fd); #else (void) sl_write_line (fd, _("\n"), 8); (void) sl_sync(fd); #endif (void) sl_close(fd); /* sh_unix_rm_lock_file (current->logfile); */ } next = current->next; SH_FREE(current->logfile); SH_FREE(current); current = next; } logfile_list = NULL; SL_RETURN( 0, _("sh_log_file")); } #else if (NULL == errmsg) { while (current != NULL) { /* sh_unix_rm_lock_file (current->logfile); */ next = current->next; SH_FREE(current->logfile); SH_FREE(current); current = next; } logfile_list = NULL; SL_RETURN( 0, _("sh_log_file")); } #endif (void) sl_strlcpy (logfile, sh.srvlog.name, sizeof(logfile)); if (inet_peer != NULL && flag_sep_log == S_TRUE) { (void) sl_strlcat (logfile, ".", sizeof(logfile)); (void) sl_strlcat (logfile, inet_peer, sizeof(logfile)); } if (sh.flag.log_start == S_TRUE) { while (current != NULL) { current->log_start = S_TRUE; current = current->next; } sh.flag.log_start = S_FALSE; current = logfile_list; } while (current != NULL) { if (strcmp(logfile, current->logfile) == 0) break; current = current->next; } if (current == NULL) { current = SH_ALLOC(sizeof(open_logfile)); current->logfile = SH_ALLOC(strlen(logfile) + 1); (void) sl_strlcpy(current->logfile, logfile, strlen(logfile) + 1); current->service_failure = 0; current->log_start = S_TRUE; memset(current->sigkey_old, (int)'\0', KEY_LEN+1); memset(current->sigkey_new, (int)'\0', KEY_LEN+1); memset(current->crypto, (int)'\0', KEY_LEN+1); current->next = logfile_list; logfile_list = current; } if (0 != sh_log_open (inet_peer, current->logfile, &(current->service_failure), &fd)) { SL_RETURN ((-1), _("sh_log_file")); } /* --- Allocate storage and mlock it. --- */ status = sl_strlen (errmsg); if (!sl_ok_adds(status, (2*KEY_LEN)) || !sl_ok_adds((2*KEY_LEN + status),32)) { sl_close(fd); SL_RETURN ((-1), _("sh_log_file")); } log_msg.msg = (char *) SH_ALLOC ((size_t) (2*KEY_LEN + status + 32)); #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) if (skey->mlock_failed == S_FALSE) { if ( (-1) == sh_unix_mlock( FIL__, __LINE__, log_msg.msg, (size_t)(2*KEY_LEN + status + 32) ) ) { skey->mlock_failed = S_TRUE; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK); #endif } } #else if (skey->mlock_failed == S_FALSE) { skey->mlock_failed = S_TRUE; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK); #endif } #endif /* --- Write the start marker. --- */ if (current->log_start == S_TRUE) { #ifdef SH_USE_XML #ifdef SH_STEALTH (void) sl_write (fd, "\n", 1); (void) sl_write_line (fd, N_(""), 7); (void) sl_sync(fd); #else (void) sl_write_line (fd, _("\n"), 8); (void) sl_sync(fd); #endif #else #ifdef SH_STEALTH (void) sl_write (fd, "\n", 1); (void) sl_write_line (fd, N_("[SOF]"), 5); (void) sl_sync(fd); #else (void) sl_write_line (fd, _("\n[SOF]"), 6); (void) sl_sync(fd); #endif #endif } /* reserve KEY_LEN chars at end for key */ (void) sl_strlcpy (log_msg.msg, errmsg, (size_t) status+1 ); #ifdef SH_USE_XML /* cut the trailing "/>" */ if (log_msg.msg[status-2] == '/') { #ifdef FIX_XML log_msg.msg[status-2] = ' '; /* ' ' FIX XML */ log_msg.msg[status-1] = '>'; /* '>' FIX XML */ #else log_msg.msg[status-2] = '>'; /* ' ' FIX XML */ log_msg.msg[status-1] = '<'; /* '>' FIX XML */ #endif log_msg.msg[status] = '\0'; } else if (status >= 6 && log_msg.msg[status-5] == '/' && log_msg.msg[status-6] == '<') { #ifdef FIX_XML log_msg.msg[status-6] = '\0'; status -= 6; #else log_msg.msg[status-5] = '\0'; status -= 5; #endif } #endif #ifdef SH_STEALTH sh_do_encode (log_msg.msg, status); #endif if (flag_sep_log == S_TRUE && inet_peer != NULL) { sigkey_old = current->sigkey_old; sigkey_new = current->sigkey_new; crypto = current->crypto; } else { sigkey_old = skey->sigkey_old; sigkey_new = skey->sigkey_new; crypto = skey->crypt; /* flawfinder: ignore */ } /* write the signature */ if (current->log_start == S_TRUE) { if (sh.real.user[0] == '\0') (void) sh_unix_getUser(); /* Initialize the key. */ (void) sh_util_keyinit(sigkey_old, KEY_LEN+1); /* Hash the key to make sure it has the correct format. */ (void) sl_strlcpy(sigkey_new, sh_tiger_hash (sigkey_old, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); /* Copy it to 'crypt' for encryption. */ (void) sl_strlcpy(crypto, sigkey_new, KEY_LEN+1); /* Use message and compiled-in key to encrypt. */ BREAKEXIT(sh_util_encode); sh_util_encode(crypto, log_msg.msg, 0, 'B'); /* Send out the key. */ (void) sh_unix_time(0, log_msg.timestamp, KEY_LEN+1); store1 = errFlags.loglevel; store2 = errFlags.sysloglevel; store3 = errFlags.printlevel; store4 = errFlags.exportlevel; store5 = errFlags.maillevel; store6 = errFlags.externallevel; store7 = errFlags.databaselevel; store8 = errFlags.preludelevel; /* mail the key */ errFlags.loglevel = SH_ERR_NOT; errFlags.sysloglevel = SH_ERR_NOT; errFlags.printlevel = SH_ERR_NOT; errFlags.exportlevel = SH_ERR_NOT; errFlags.externallevel = SH_ERR_NOT; errFlags.databaselevel = SH_ERR_NOT; errFlags.preludelevel = SH_ERR_NOT; sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_KEY_MAIL, sh.prg_name, crypto, crypto, log_msg.timestamp); /* send to other allowed channels */ errFlags.maillevel = SH_ERR_NOT; /* errFlags.printlevel = store3; */ errFlags.exportlevel = store4; errFlags.externallevel = store6; errFlags.databaselevel = store7; errFlags.preludelevel = store8; sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_KEY, sh.prg_name, crypto); /* Cleanup. */ errFlags.loglevel = store1; errFlags.sysloglevel = store2; errFlags.printlevel = store3; errFlags.exportlevel = store4; errFlags.maillevel = store5; errFlags.externallevel = store6; errFlags.databaselevel = store7; memset (crypto, (int) '\0', KEY_LEN); sh.flag.log_start = S_FALSE; current->log_start = S_FALSE; } else { log_msg.timestamp[0] = '\0'; (void) sl_strlcpy (sigkey_new, sh_tiger_hash (sigkey_old, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } /* --- Sign the message with the signature key. --- */ sh_tiger_hash (log_msg.msg, TIGER_DATA, (unsigned long)(status + KEY_LEN), (char *) hashbuf, (size_t) sizeof(hashbuf)); (void) sl_strlcat (log_msg.msg, sigkey_new, (size_t)(status + KEY_LEN + 2)); (void) sl_strlcpy (log_msg.signature, sh_tiger_hash (log_msg.msg, (TigerType) TIGER_DATA, (unsigned long)(status + KEY_LEN), hashbuf, sizeof(hashbuf)), KEY_LEN+1); (void) sl_strlcpy (sigkey_old, sigkey_new, KEY_LEN+1); /*@-usedef@*/ #ifdef SH_USE_XML if (log_msg.timestamp[0] != '\0') sl_snprintf(log_msg.sig, sizeof(log_msg.sig), #ifdef FIX_XML _("\n%s%s\n"), /* FIX XML */ #else _("\nsig>%s%s\n"), /* FIX XML */ #endif log_msg.signature, log_msg.timestamp); else sl_snprintf(log_msg.sig, sizeof(log_msg.sig), #ifdef FIX_XML _("\n%s\n"), /* FIX XML */ #else _("\nsig>%s\n"), /* FIX XML */ #endif log_msg.signature); /*@+usedef@*/ #ifdef SH_STEALTH /* don't encode the line breaks (0 + last char) */ sh_do_encode (&log_msg.sig[1], (sl_strlen(log_msg.sig)-2) ); #endif #else #ifdef SH_STEALTH sh_do_encode (log_msg.signature, KEY_LEN); sh_do_encode (log_msg.timestamp, sl_strlen(log_msg.timestamp)); #endif #endif #ifdef SH_USE_XML log_msg.msg[status] = '\0'; (void) sl_strlcat (log_msg.msg, log_msg.sig, (size_t)(status + 2*KEY_LEN + 32)); #ifdef SH_STEALTH if (NULL != sl_strstr(log_msg.msg, N_("EXIT")) && NULL == sl_strstr(log_msg.msg, N_("remote_host"))) { (void) sl_strlcat (log_msg.msg, N_(""), (size_t)(status + 2*KEY_LEN + 32)); #else if (NULL != sl_strstr(log_msg.msg, _("msg=\"EXIT\"")) && NULL == sl_strstr(log_msg.msg, _("remote_host"))) { (void) sl_strlcat (log_msg.msg, _(""), (size_t)(status + 2*KEY_LEN + 32)); #endif (void) sl_strlcat (log_msg.msg, _("\n"), (size_t)(status + 2*KEY_LEN + 32)); current->log_start = S_TRUE; } #else log_msg.msg[status] = '\0'; (void) sl_strlcat (log_msg.msg, "\n", (size_t)(status + KEY_LEN + 2)); (void) sl_strlcat (log_msg.msg, log_msg.signature, (size_t)(status + KEY_LEN + 2)); if (log_msg.timestamp[0] != '\0') (void) sl_strlcat (log_msg.msg, log_msg.timestamp, (size_t)(status + 2*KEY_LEN + 2)); (void) sl_strlcat (log_msg.msg, "\n", (size_t)(status + 2*KEY_LEN + 3)); #endif /* --- Write out the record. --- */ (void) sl_write (fd, log_msg.msg, (long) strlen(log_msg.msg)); (void) sl_sync (fd); (void) sl_close (fd); /* --- Clean up and free record. --- */ memset (log_msg.msg, (int)'\0', (size_t)(status + 2*KEY_LEN + 32)); memset (log_msg.signature, (int)'\0', KEY_LEN); (void) sh_unix_munlock (log_msg.msg, (size_t)(status + 2*KEY_LEN + 32)); SH_FREE(log_msg.msg); SL_RETURN (0, _("sh_log_file")); } /* >>>>>>>>>>>>>>>>>>>>>>>>>>>> efile <<<<<<<<<<<<<<<<<< */ static char * gEfile = NULL; static int gFail = 0; static long gGid = 0; int sh_efile_group(const char * str) { int fail; long gid = sh_group_to_gid(str, &fail); if (fail < 0) { return -1; } gGid = gid; return 0; } int sh_efile_path(const char * str) { if (!str || !strcmp(str, _("none"))) { if (gEfile) SH_FREE(gEfile); gEfile = NULL; } else if (str[0] != '/') { return -1; } else { if (gEfile) SH_FREE(gEfile); gEfile = sh_util_strdup(str); } gFail = 0; return 0; } /* write lock for filename */ static int sh_efile_lock (char * filename, int flag) { extern int get_the_fd (SL_TICKET ticket); size_t len; int res = -1; char myPid[64]; SL_TICKET fd; char * lockfile; int status; sprintf (myPid, "%ld\n", (long) sh.pid); /* known to fit */ if (filename == NULL) return res; len = sl_strlen(filename); if (sl_ok_adds(len, 6)) len += 6; lockfile = SH_ALLOC(len); sl_strlcpy(lockfile, filename, len); sl_strlcat(lockfile, _(".lock"), len); if ( 0 != (status = tf_trust_check (lockfile, SL_YESPRIV)) && gFail == 0) { char * tmp = sh_util_safe_name (lockfile); sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST, (long) sh.effective.uid, tmp); ++gFail; SH_FREE(tmp); } if (status == 0) { if (flag == 0) { /* --- Delete the lock file. --- */ res = retry_aud_unlink (FIL__, __LINE__, lockfile); } else { unsigned int count = 0; /* fails if file exists */ do { fd = sl_open_safe_rdwr (FIL__, __LINE__, lockfile, SL_YESPRIV); if (SL_ISERROR(fd)) { retry_msleep(0, 100); ++count; } } while (SL_ISERROR(fd) && count < 3); if (!SL_ISERROR(fd)) { int filed; res = sl_write (fd, myPid, sl_strlen(myPid)); filed = get_the_fd(fd); fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); sl_close (fd); } else { static int nFail = 0; if (nFail == 0) { char errmsg[1024]; char * tmp = sh_util_safe_name (lockfile); sl_snprintf(errmsg, sizeof(errmsg), _("Error creating lockfile %s"), tmp); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, errmsg, _("sh_efile_lock")); ++nFail; SH_FREE(tmp); } } } } SH_FREE(lockfile); return res; } static size_t gSave[6] = { 0 }; static void sh_efile_clear() { int i; for (i = 0; i < 6; ++i) gSave[i] = 0; return; } static void sh_efile_load(size_t * tmp) { int i; if (S_TRUE == sl_ok_adds (gSave[0], sh.statistics.bytes_hashed)) gSave[0] += sh.statistics.bytes_hashed; if (S_TRUE == sl_ok_adds (gSave[1], sh.statistics.dirs_checked)) gSave[1] += sh.statistics.dirs_checked; if (S_TRUE == sl_ok_adds (gSave[2], sh.statistics.files_checked)) gSave[2] += sh.statistics.files_checked; if (S_TRUE == sl_ok_adds (gSave[3], sh.statistics.files_report)) gSave[3] += sh.statistics.files_report; if (S_TRUE == sl_ok_adds (gSave[4], sh.statistics.files_error)) gSave[4] += sh.statistics.files_error; if (S_TRUE == sl_ok_adds (gSave[5], sh.statistics.files_nodir)) gSave[5] += sh.statistics.files_nodir; for (i = 0; i < 6; ++i) tmp[i] = gSave[i]; return; } void sh_efile_report() { extern int get_the_fd (SL_TICKET ticket); SL_TICKET fd; char *efile; int status = -1; if (gEfile) { size_t tmp[6]; sh_efile_load(tmp); efile = sh_util_strdup(gEfile); if (sh_efile_lock (efile, 1) < 0) goto end; if ( 0 != (status = tf_trust_check (efile, SL_YESPRIV)) && gFail == 0) { char * tmp = sh_util_safe_name (efile); sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST, (long) sh.effective.uid, tmp); ++gFail; SH_FREE(tmp); } if (status == 0) { fd = sl_open_write (FIL__, __LINE__, efile, SL_YESPRIV); if (!SL_ISERROR(fd)) { char report[511]; char tstamp[TIM_MAX]; time_t now = time(NULL); int filed = get_the_fd(fd); (void) sh_unix_time (now, tstamp, sizeof(tstamp)); #ifdef HAVE_LONG_LONG sl_snprintf(report, sizeof(report), _("%s %lld %ld %ld %ld %ld %ld %ld\n"), tstamp, (long long) now, (long) tmp[0], (long) tmp[1], (long) tmp[2], (long) tmp[3], (long) tmp[4], (long) tmp[5]); #else sl_snprintf(report, sizeof(report), _("%s %ld %ld %ld %ld %ld %ld %ld\n"), tstamp, (long) now, (long) tmp[0], (long) tmp[1], (long) tmp[2], (long) tmp[3], (long) tmp[4], (long) tmp[5]); #endif status = sl_forward(fd); if (!SL_ISERROR(status)) status = sl_write (fd, report, strlen(report)); (void) sl_sync(fd); /* make group writeable, such that nagios can truncate */ fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); status = fchown (filed, -1, gGid); if (status < 0) { int errnum = errno; static int nFail = 0; if (nFail == 0) { char errmsg[1024]; char buf[256]; char * tmp = sh_util_safe_name (efile); sl_snprintf(errmsg, sizeof(errmsg), _("Error changing group of %s to %ld: %s"), tmp, gGid, sh_error_message (errnum, buf, sizeof(buf))); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_E_SUBGEN, errmsg, _("sh_efile_report")); ++nFail; SH_FREE(tmp); } } (void) sl_close(fd); } else { status = -1; } } (void) sh_efile_lock (efile, 0); end: SH_FREE(efile); if (!SL_ISERROR(status)) { sh_efile_clear(); } } return; } samhain-4.1.4/src/sh_log_parse_apache.c0000644000175000017500000002622412615253277015002 00000000000000/************************************** ** ** PARSER RULES ** ** (a) must set record->host ** (eventually to dummy value) ** ** (b) must set record->prefix ** (itoa(status)) ** ** **************************************/ /* for strptime */ #define _XOPEN_SOURCE 500 #include "config_xor.h" #include #include #include #include #include #ifdef USE_LOGFILE_MONITOR #undef FIL__ #define FIL__ _("sh_log_parse_apache.c") /* Debian/Ubuntu: libpcre3-dev */ #ifdef HAVE_PCRE_PCRE_H #include #else #include #endif #include "samhain.h" #include "sh_pthread.h" #include "sh_log_check.h" #include "sh_utils.h" #include "sh_string.h" extern int flag_err_debug; struct sh_fileinfo_apache { pcre * line_regex; int * line_ovector; /* captured substrings */ int line_ovecnum; /* how many captured */ int pos_host; int pos_status; int pos_time; char * format_time; }; static const char lf_error0[] = N_("%error"); static const char lf_common0[] = N_("%h %l %u %t \"%r\" %>s %b"); static const char lf_combined0[] = N_("%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""); /* This variable is not used anywhere. It only exist * to assign &new to them, which keeps gcc from * putting it into a register, and avoids the 'clobbered * by longjmp' warning. And no, 'volatile' proved insufficient. */ void * sh_dummy_65_new = NULL; void * sh_dummy_66_fti = NULL; void * sh_dummy_67_ftr = NULL; void * sh_eval_fileinfo_apache(char * str) { struct sh_fileinfo_apache * result = NULL; unsigned int i, quotes; unsigned int nfields = 64; size_t lengths[64]; char * new = NULL; char ** splits; char * token; sh_string * re_string; char * p; volatile int p_host = -1; volatile int p_status = -1; volatile int p_time = -1; char * f_time = NULL; const char * error; int erroffset; /* Take the address to keep gcc from putting them into registers. * Avoids the 'clobbered by longjmp' warning. */ sh_dummy_65_new = (void*) &new; sh_dummy_66_fti = (void*) &f_time; sh_dummy_67_ftr = (void*) &result; if (0 == strncmp("common", str, 6)) { new = sh_util_strdup(_(lf_common0)); } else if (0 == strncmp("combined", str, 8)) { new = sh_util_strdup(_(lf_combined0)); } else if (0 == strncmp("error", str, 8)) { new = sh_util_strdup(_(lf_error0)); } else { new = sh_util_strdup(str); } if (flag_err_debug == S_TRUE) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, new, _("eval_fileinfo")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } splits = split_array_ws(new, &nfields, lengths); if (nfields < 1) { SH_FREE(splits); SH_FREE(new); return NULL; } /* Build the regex string re_string */ re_string = sh_string_new(0); sh_string_add_from_char(re_string, "^"); for (i = 0; i < nfields; ++i) { if (i > 0) sh_string_add_from_char(re_string, " "); if (splits[i][0] != '"') quotes = 0; else quotes = 1; if (quotes && lengths[i] > 1 && splits[i][lengths[i]-1] == '"') { splits[i][lengths[i]-1] = '\0'; /* cut trailing quote */ token = &(splits[i][1]); } else { token = splits[i]; } if(quotes) { if(strcmp(token, "%r") == 0 || strstr(token, _("{Referer}")) != NULL || strstr(token, _("{User-Agent}")) != NULL || strstr(token, _("{X-Forwarded-For}")) != NULL ) { /* p = "\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\""; sh_string_add_from_char(re_string, p); */ sh_string_add_from_char(re_string, "\"([^"); sh_string_add_from_char(re_string, "\"\\\\"); sh_string_add_from_char(re_string, "]*"); sh_string_add_from_char(re_string, "(?:"); sh_string_add_from_char(re_string, "\\\\."); sh_string_add_from_char(re_string, "[^\""); sh_string_add_from_char(re_string, "\\\\]*"); sh_string_add_from_char(re_string, ")*)\""); } else { sh_string_add_from_char(re_string, "("); sh_string_add_from_char(re_string, "\\S+"); sh_string_add_from_char(re_string, ")"); } } else if (token[0] == 'R' && token[1] == 'E' && token[2] == '{' && token[strlen(token)-1] == '}') { char * lb = strchr(token, '{'); char * rb = strrchr(token, '}'); if (lb && rb) { ++lb; *rb = '\0'; sh_string_add_from_char(re_string, lb); } } else if (token[0] == '%' && token[strlen(token)-1] == 't') { char * lb = strchr(token, '{'); char * rb = strchr(token, '}'); sh_string_add_from_char(re_string, "\\["); sh_string_add_from_char(re_string, "([^"); sh_string_add_from_char(re_string, "(\\]"); sh_string_add_from_char(re_string, "]+)"); sh_string_add_from_char(re_string, "\\]"); p_time = i+1; if (lb && rb) { ++lb; *rb = '\0'; f_time = sh_util_strdup(lb); } else { f_time = sh_util_strdup(_("%d/%b/%Y:%T")); } } else if (token[0] == '%' && token[1] == 'e' && 0 == strcmp(token, _("%error"))) { sh_string_add_from_char(re_string, "\\["); sh_string_add_from_char(re_string, "([^"); sh_string_add_from_char(re_string, "]"); sh_string_add_from_char(re_string, "]+)"); sh_string_add_from_char(re_string, "\\]"); p_time = i+1; f_time = sh_util_strdup(_("%a %b %d %T %Y")); ++i; sh_string_add_from_char(re_string, " "); sh_string_add_from_char(re_string, "\\["); sh_string_add_from_char(re_string, "([^"); sh_string_add_from_char(re_string, "]"); sh_string_add_from_char(re_string, "]+)"); sh_string_add_from_char(re_string, "\\]"); p_status = i+1; sh_string_add_from_char(re_string, " "); p = "(.+)"; sh_string_add_from_char(re_string, p); nfields = 3; break; } else { sh_string_add_from_char(re_string, "("); sh_string_add_from_char(re_string, "\\S+"); sh_string_add_from_char(re_string, ")"); if (token[0] == '%' && token[strlen(token)-1] == 's') p_status = i+1; else if (token[0] == '%' && token[strlen(token)-1] == 'v') p_host = i+1; } } sh_string_add_from_char(re_string, "$"); if (flag_err_debug == S_TRUE) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(re_string), _("eval_fileinfo")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } result = SH_ALLOC(sizeof(struct sh_fileinfo_apache)); result->line_regex = pcre_compile(sh_string_str(re_string), 0, &error, &erroffset, NULL); if (!(result->line_regex)) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Bad regex: ")); sh_string_add_from_char(msg, sh_string_str(re_string)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("eval_fileinfo")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(result); SH_FREE(splits); SH_FREE(new); sh_string_destroy(&msg); sh_string_destroy(&re_string); return NULL; } sh_string_destroy(&re_string); result->line_ovector = SH_ALLOC(sizeof(int) * (nfields+1) * 3); result->line_ovecnum = nfields; result->pos_host = p_host; result->pos_status = p_status; result->pos_time = p_time; result->format_time = f_time; SH_FREE(splits); SH_FREE(new); return (void*)result; } struct sh_logrecord * sh_parse_apache (sh_string * logline, void * fileinfo) { static struct tm old_tm; static time_t old_time; char tstr[128]; char sstr[128]; const char * hstr; int res; const char **hstr_addr = (const char **) &hstr; struct sh_fileinfo_apache * info = (struct sh_fileinfo_apache *) fileinfo; if (sh_string_len(logline) > 0 && flag_err_debug == S_TRUE) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(logline), _("sh_parse_apache")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } if (logline == NULL || info == NULL) { return NULL; } res = pcre_exec(info->line_regex, NULL, sh_string_str(logline), (int)sh_string_len(logline), 0, 0, info->line_ovector, (3*(1+info->line_ovecnum))); if (res == (1+info->line_ovecnum)) { struct sh_logrecord * record; time_t timestamp = 0; if (info->pos_time > 0) { res = pcre_copy_substring(sh_string_str(logline), info->line_ovector, res, info->pos_time, tstr, sizeof(tstr)); if (res <= 0) goto corrupt; } else { res = 0; timestamp = 0; info->format_time = sh_util_strdup(_("%d/%b/%Y:%T")); sl_strlcpy(tstr, _("01/Jan/1970:00:00:00"), sizeof(tstr)); } if (res > 0) { struct tm btime; char * ptr = NULL; memset(&btime, '\0', sizeof(struct tm)); btime.tm_isdst = -1; /* example: 01/Jun/2008:07:55:28 +0200 */ ptr = /*@i@*/strptime(tstr, info->format_time, &btime); if (ptr) { timestamp = conv_timestamp(&btime, &old_tm, &old_time); } else goto corrupt; } if (info->pos_status > 0) { res = pcre_copy_substring(sh_string_str(logline), info->line_ovector, res, info->pos_status, sstr, sizeof(sstr)); if (res <= 0) goto corrupt; } else { sl_strlcpy(sstr, _("000"), sizeof(sstr)); } if (info->pos_host > 0) { res = pcre_get_substring(sh_string_str(logline), info->line_ovector, res, info->pos_host, hstr_addr); if (res <= 0) goto corrupt; } else { hstr = NULL; } record = SH_ALLOC(sizeof(struct sh_logrecord)); record->timestamp = timestamp; record->timestr = sh_string_new_from_lchar(tstr, strlen(tstr)); if (hstr) record->host = sh_string_new_from_lchar(hstr, strlen(hstr)); else record->host = sh_string_new_from_lchar(sh.host.name, strlen(sh.host.name)); record->message = sh_string_new_from_lchar(sh_string_str(logline), sh_string_len(logline)); record->pid = PID_INVALID; pcre_free_substring(hstr); return record; } else { char msg[128]; sl_snprintf(msg, sizeof(msg), _("Incorrect number of captured subexpressions: %d vs %d"), res, info->line_ovecnum); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, msg, _("sh_parse_apache")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } /* Corrupted logline */ corrupt: { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Corrupt logline: ")); sh_string_add_from_char(msg, sh_string_str(logline)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_parse_apache")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); } return NULL; } /* USE_LOGFILE_MONITOR */ #endif samhain-4.1.4/src/encode.c0000644000175000017500000001061112615253277012262 00000000000000 /* #include "config.h" */ #include #include int main(int argv, char * argc[]) { int xor_base = -1; FILE * inf; FILE * ouf; char a, b; int i, j; char outfile[1024]; int inbracket = 0, quoted = 0; unsigned long count; /* char command[1024]; */ if ( argv < 3) { fprintf(stderr,"\nUsage: encode "\ "\n\n"); fprintf(stderr," This program will:\n"); fprintf(stderr," - take as input a source code file ,\n"); fprintf(stderr," - search for literal strings inclosed by _(), "\ "like '_(string)',\n"); fprintf(stderr," - replace _(string) by "\ "_(string XOR ),\n"); fprintf(stderr, " - and output the result to './x_'.\n\n"); fprintf(stderr," _() is supposed to be defined as a macro in "\ "the code, that\n"); fprintf(stderr," will allow the program to decode the xor'ed string "\ "at runtime.\n"); fprintf(stderr," The effect is that the compiled executable does "\ "not contain literal\n"); fprintf(stderr," strings that may trivially be found with the Unix "\ "'strings' command,\n"); fprintf(stderr," and thus reveal the nature of "\ "the program.\n"); return -1; } --argv; ++argc; xor_base = atoi(argc[0]); if (xor_base < 0 || (xor_base > 0 && xor_base < 128) || xor_base > 255) { fprintf(stderr, "\nERROR: encode: XOR_VAL=%d is out of "\ "range (0, 128..255)\n", xor_base); fprintf(stderr, "** please follow these steps to fix the problem:\n\n"); fprintf(stderr, " make clean\n"); fprintf(stderr, " ./configure [more options] "\ "--with-stealth=XOR_VAL (range 0, 128..255)\n"); fprintf(stderr, " make\n\n"); return -1; } /* fprintf(stderr, " %d\n", xor_base); */ --argv; ++argc; /* fprintf(stderr, "File: %d\n", argv); */ while (argv > 0) { inf = fopen(argc[0], "r"); if (inf == NULL) { fprintf(stderr, "Error opening %s\n", argc[0]); return -1; } /* outfile name */ i = 0; j = 0; while (argc[0][i] != '\0') { if (argc[0][i] == '/') j = i+1; ++i; } i = 0; outfile[0] = 'x'; outfile[1] = '_'; outfile[2] = '\0'; while (argc[0][j+i] != '\0') { outfile[i+2] = argc[0][j+i]; ++i; } outfile[i+2] = '\0'; ouf = fopen(outfile, "w"); if (ouf == NULL) { fprintf(stderr, "Error opening %s\n", outfile); return -1; } /* fprintf(stderr, "File: %s\n", argc[0]); */ count = 0; while (fread(&a, 1, 1, inf) != 0) { count++; if (a == '"' && quoted == 0) { quoted = 1; fwrite(&a, 1, 1, ouf); continue; } if (a == '"' && quoted == 1) { quoted = 0; fwrite(&a, 1, 1, ouf); continue; } if (a == '\n' && quoted == 1) { quoted = 0; fwrite(&a, 1, 1, ouf); continue; } /* macro start ? */ if (a == '_' && inbracket == 0 && quoted == 0) { fwrite(&a, 1, 1, ouf); b = '\0'; fread(&b, 1, 1, inf); count++; fwrite(&b, 1, 1, ouf); if (b == '(') inbracket = 1; continue; } /* macro end */ if (a == ')' && quoted == 0 && inbracket == 1) { inbracket = 0; /* fprintf(stdout, "\n"); */ fwrite(&a, 1, 1, ouf); continue; } /* in a bracket */ if (inbracket == 1 && quoted == 1) { /* fprintf(stdout, "%c", a); */ if (a == '\\') { fread(&b, 1, 1, inf); /* escape sequences */ if (b == 't' || b == 'n' || b == 'r' || b == '"') { fwrite(&a, 1, 1, ouf); fwrite(&b, 1, 1, ouf); } else { a ^= (char) xor_base; b ^= (char) xor_base; } } else { a ^= (char) xor_base; fwrite(&a, 1, 1, ouf); } continue; } fwrite(&a, 1, 1, ouf); } /* fprintf(stderr, "Bytes read: %ld\n", count); */ /* sprintf(command, "mv tempfile %s", argc[0]); */ /* system(command); */ fclose(ouf); fclose(inf); --argv; ++argc; } return 0; } samhain-4.1.4/src/sh_tiger2.c0000644000175000017500000012236112615253277012721 00000000000000/* Tiger: A Fast New Hash Function * * Ross Anderson and Eli Biham * * From the homepage (http://www.cs.technion.ac.il/~biham/Reports/Tiger/): * * Tiger has no usage restrictions nor patents. It can be used freely, * with the reference implementation, with other implementations or with * a modification to the reference implementation (as long as it still * implements Tiger). We only ask you to let us know about your * implementation and to cite the origin of Tiger and of the reference * implementation. * * * The authors' home pages can be found both in * http://www.cs.technion.ac.il/~biham/ and in * http://www.cl.cam.ac.uk/users/rja14/. * The authors' email addresses are biham@cs.technion.ac.il * and rja14@cl.cam.ac.uk. */ #include "config_xor.h" #if !defined(TIGER_64_BIT) /* #if !defined(HAVE_LONG_64) && !defined(HAVE_LONG_LONG_64) */ /* sboxes32.c: Tiger S boxes for 32-bit-only compilers */ #if defined(HAVE_INT_32) typedef unsigned int sh_word32; #elif defined(HAVE_LONG_32) typedef unsigned long sh_word32; #elif defined(HAVE_SHORT_32) typedef unsigned short sh_word32; #else #error No 32 bit type found ! #endif sh_word32 tiger_table[4*256][2] = { { 0xF7E90C5E, 0x02AAB17C /* 0 */}, { 0xE243A8EC, 0xAC424B03 /* 1 */}, { 0x0DD5FCD3, 0x72CD5BE3 /* 2 */}, { 0xF6F97F3A, 0x6D019B93 /* 3 */}, { 0xD21F9193, 0xCD9978FF /* 4 */}, { 0x708029E2, 0x7573A1C9 /* 5 */}, { 0x922A83C3, 0xB164326B /* 6 */}, { 0x04915870, 0x46883EEE /* 7 */}, { 0x7103ECE6, 0xEAACE305 /* 8 */}, { 0x08A3535C, 0xC54169B8 /* 9 */}, { 0x8DDEC47C, 0x4CE75491 /* 10 */}, { 0xDC0DF40C, 0x0AA2F4DF /* 11 */}, { 0xA74DBEFA, 0x10B76F18 /* 12 */}, { 0x5AD1AB6A, 0xC6CCB623 /* 13 */}, { 0x572FE2FF, 0x13726121 /* 14 */}, { 0x199D921E, 0x1A488C6F /* 15 */}, { 0xDA0007CA, 0x4BC9F9F4 /* 16 */}, { 0xE85241C7, 0x26F5E6F6 /* 17 */}, { 0xEA5947B6, 0x859079DB /* 18 */}, { 0xC99E8C92, 0x4F1885C5 /* 19 */}, { 0xA96F864B, 0xD78E761E /* 20 */}, { 0x52B5C17D, 0x8E36428C /* 21 */}, { 0x373063C1, 0x69CF6827 /* 22 */}, { 0x9BB4C56E, 0xB607C93D /* 23 */}, { 0x0E76B5EA, 0x7D820E76 /* 24 */}, { 0xF07FDC42, 0x645C9CC6 /* 25 */}, { 0x243342E0, 0xBF38A078 /* 26 */}, { 0x9D2E7D04, 0x5F6B343C /* 27 */}, { 0x600B0EC6, 0xF2C28AEB /* 28 */}, { 0x7254BCAC, 0x6C0ED85F /* 29 */}, { 0xA4DB4FE5, 0x71592281 /* 30 */}, { 0xCE0FED9F, 0x1967FA69 /* 31 */}, { 0xB96545DB, 0xFD5293F8 /* 32 */}, { 0xF2A7600B, 0xC879E9D7 /* 33 */}, { 0x0193194E, 0x86024892 /* 34 */}, { 0x2D9CC0B3, 0xA4F9533B /* 35 */}, { 0x15957613, 0x9053836C /* 36 */}, { 0xFC357BF1, 0xDB6DCF8A /* 37 */}, { 0x7A370F57, 0x18BEEA7A /* 38 */}, { 0x50B99066, 0x037117CA /* 39 */}, { 0x74424A35, 0x6AB30A97 /* 40 */}, { 0xE325249B, 0xF4E92F02 /* 41 */}, { 0x061CCAE1, 0x7739DB07 /* 42 */}, { 0xECA42A05, 0xD8F3B49C /* 43 */}, { 0x51382F73, 0xBD56BE3F /* 44 */}, { 0x43B0BB28, 0x45FAED58 /* 45 */}, { 0x11BF1F83, 0x1C813D5C /* 46 */}, { 0xD75FA169, 0x8AF0E4B6 /* 47 */}, { 0x87AD9999, 0x33EE18A4 /* 48 */}, { 0xB1C94410, 0x3C26E8EA /* 49 */}, { 0xC0A822F9, 0xB510102B /* 50 */}, { 0x0CE6123B, 0x141EEF31 /* 51 */}, { 0x59DDB154, 0xFC65B900 /* 52 */}, { 0xC5E0E607, 0xE0158640 /* 53 */}, { 0x26C3A3CF, 0x884E0798 /* 54 */}, { 0x23C535FD, 0x930D0D95 /* 55 */}, { 0x4E9A2B00, 0x35638D75 /* 56 */}, { 0x40469DD5, 0x4085FCCF /* 57 */}, { 0x8BE23A4C, 0xC4B17AD2 /* 58 */}, { 0x6A3E6A2E, 0xCAB2F0FC /* 59 */}, { 0x6B943FCD, 0x2860971A /* 60 */}, { 0x12E30446, 0x3DDE6EE2 /* 61 */}, { 0xE01765AE, 0x6222F32A /* 62 */}, { 0x478308FE, 0x5D550BB5 /* 63 */}, { 0xA0EDA22A, 0xA9EFA98D /* 64 */}, { 0x86C40DA7, 0xC351A716 /* 65 */}, { 0x9C867C84, 0x1105586D /* 66 */}, { 0xFDA22853, 0xDCFFEE85 /* 67 */}, { 0x2C5EEF76, 0xCCFBD026 /* 68 */}, { 0x8990D201, 0xBAF294CB /* 69 */}, { 0x2AFAD975, 0xE69464F5 /* 70 */}, { 0xDF133E14, 0x94B013AF /* 71 */}, { 0x2823C958, 0x06A7D1A3 /* 72 */}, { 0x30F61119, 0x6F95FE51 /* 73 */}, { 0x462C06C0, 0xD92AB34E /* 74 */}, { 0x887C71D2, 0xED7BDE33 /* 75 */}, { 0x6518393E, 0x79746D6E /* 76 */}, { 0x5D713329, 0x5BA41938 /* 77 */}, { 0x48A97564, 0x7C1BA6B9 /* 78 */}, { 0x7BFDAC67, 0x31987C19 /* 79 */}, { 0x4B053D02, 0xDE6C23C4 /* 80 */}, { 0xD002D64D, 0x581C49FE /* 81 */}, { 0x38261571, 0xDD474D63 /* 82 */}, { 0xE473D062, 0xAA4546C3 /* 83 */}, { 0x9455F860, 0x928FCE34 /* 84 */}, { 0xCAAB94D9, 0x48161BBA /* 85 */}, { 0x770E6F68, 0x63912430 /* 86 */}, { 0x02C6641C, 0x6EC8A5E6 /* 87 */}, { 0x337DDD2B, 0x87282515 /* 88 */}, { 0x034B701B, 0x2CDA6B42 /* 89 */}, { 0x81CB096D, 0xB03D37C1 /* 90 */}, { 0x66C71C6F, 0xE1084382 /* 91 */}, { 0xEB51B255, 0x2B3180C7 /* 92 */}, { 0x96C08BBC, 0xDF92B82F /* 93 */}, { 0xA632F3BA, 0x5C68C8C0 /* 94 */}, { 0x1C3D0556, 0x5504CC86 /* 95 */}, { 0x5FB26B8F, 0xABBFA4E5 /* 96 */}, { 0xB3BACEB4, 0x41848B0A /* 97 */}, { 0xAA445D32, 0xB334A273 /* 98 */}, { 0xA85AD881, 0xBCA696F0 /* 99 */}, { 0xB528D56C, 0x24F6EC65 /* 100 */}, { 0x90F4524A, 0x0CE1512E /* 101 */}, { 0x5506D35A, 0x4E9DD79D /* 102 */}, { 0xC6CE9779, 0x258905FA /* 103 */}, { 0x3E109B33, 0x2019295B /* 104 */}, { 0x73A054CC, 0xF8A9478B /* 105 */}, { 0x34417EB0, 0x2924F2F9 /* 106 */}, { 0x536D1BC4, 0x3993357D /* 107 */}, { 0x1DB6FF8B, 0x38A81AC2 /* 108 */}, { 0x7D6016BF, 0x47C4FBF1 /* 109 */}, { 0x7667E3F5, 0x1E0FAADD /* 110 */}, { 0x938BEB96, 0x7ABCFF62 /* 111 */}, { 0x8FC179C9, 0xA78DAD94 /* 112 */}, { 0x2911E50D, 0x8F1F98B7 /* 113 */}, { 0x27121A91, 0x61E48EAE /* 114 */}, { 0x31859808, 0x4D62F7AD /* 115 */}, { 0xEF5CEAEB, 0xECEBA345 /* 116 */}, { 0xBC9684CE, 0xF5CEB25E /* 117 */}, { 0xB7F76221, 0xF633E20C /* 118 */}, { 0xAB8293E4, 0xA32CDF06 /* 119 */}, { 0xA5EE2CA4, 0x985A202C /* 120 */}, { 0xCC8A8FB1, 0xCF0B8447 /* 121 */}, { 0x979859A3, 0x9F765244 /* 122 */}, { 0xA1240017, 0xA8D516B1 /* 123 */}, { 0xBB5DC726, 0x0BD7BA3E /* 124 */}, { 0xB86ADB39, 0xE54BCA55 /* 125 */}, { 0x6C478063, 0x1D7A3AFD /* 126 */}, { 0xE7669EDD, 0x519EC608 /* 127 */}, { 0xD149AA23, 0x0E5715A2 /* 128 */}, { 0x848FF194, 0x177D4571 /* 129 */}, { 0x41014C22, 0xEEB55F32 /* 130 */}, { 0x3A6E2EC2, 0x0F5E5CA1 /* 131 */}, { 0x75F5C361, 0x8029927B /* 132 */}, { 0xC3D6E436, 0xAD139FAB /* 133 */}, { 0x4CCF402F, 0x0D5DF1A9 /* 134 */}, { 0xBEA5DFC8, 0x3E8BD948 /* 135 */}, { 0xBD3FF77E, 0xA5A0D357 /* 136 */}, { 0x1F74F645, 0xA2D12E25 /* 137 */}, { 0x5E81A082, 0x66FD9E52 /* 138 */}, { 0x7F687A49, 0x2E0C90CE /* 139 */}, { 0xBA973BC5, 0xC2E8BCBE /* 140 */}, { 0xE509745F, 0x000001BC /* 141 */}, { 0xE6DAB3D6, 0x423777BB /* 142 */}, { 0xAEF06EB5, 0xD1661C7E /* 143 */}, { 0x4DAACFD8, 0xA1781F35 /* 144 */}, { 0x2B16AFFC, 0x2D11284A /* 145 */}, { 0xFA891D1F, 0xF1FC4F67 /* 146 */}, { 0xCB920ADA, 0x73ECC25D /* 147 */}, { 0xC2A12651, 0xAE610C22 /* 148 */}, { 0xD356B78A, 0x96E0A810 /* 149 */}, { 0x2FE7870F, 0x5A9A381F /* 150 */}, { 0xE94E5530, 0xD5AD62ED /* 151 */}, { 0x368D1427, 0xD225E5E8 /* 152 */}, { 0xC7AF4631, 0x65977B70 /* 153 */}, { 0xDE39D74F, 0x99F889B2 /* 154 */}, { 0x54E1D143, 0x233F30BF /* 155 */}, { 0xD9A63C97, 0x9A9675D3 /* 156 */}, { 0xF334F9A8, 0x5470554F /* 157 */}, { 0x4A4F5688, 0x166ACB74 /* 158 */}, { 0xB2E4AEAD, 0x70C74CAA /* 159 */}, { 0x6F294D12, 0xF0D09164 /* 160 */}, { 0x684031D1, 0x57B82A89 /* 161 */}, { 0x61BE0B6B, 0xEFD95A5A /* 162 */}, { 0x69F2F29A, 0x2FBD12E9 /* 163 */}, { 0xFEFF9FE8, 0x9BD37013 /* 164 */}, { 0xD6085A06, 0x3F9B0404 /* 165 */}, { 0x166CFE15, 0x4940C1F3 /* 166 */}, { 0xCDF3DEFB, 0x09542C4D /* 167 */}, { 0x85CD5CE3, 0xB4C52183 /* 168 */}, { 0x4462A641, 0xC935B7DC /* 169 */}, { 0x8ED3B63F, 0x3417F8A6 /* 170 */}, { 0x5B215B40, 0xB8095929 /* 171 */}, { 0x3B8C8572, 0xF99CDAEF /* 172 */}, { 0xF8FCB95D, 0x018C0614 /* 173 */}, { 0x1A3ACDF3, 0x1B14ACCD /* 174 */}, { 0x00BB732D, 0x84D471F2 /* 175 */}, { 0x95E8DA16, 0xC1A3110E /* 176 */}, { 0xBF1A82B8, 0x430A7220 /* 177 */}, { 0x39DF210E, 0xB77E090D /* 178 */}, { 0x3CD05E9D, 0x5EF4BD9F /* 179 */}, { 0x7E57A444, 0x9D4FF6DA /* 180 */}, { 0x83D4A5F8, 0xDA1D60E1 /* 181 */}, { 0x17998E47, 0xB287C384 /* 182 */}, { 0x1BB31886, 0xFE3EDC12 /* 183 */}, { 0x980CCBEF, 0xC7FE3CCC /* 184 */}, { 0x189BFD03, 0xE46FB590 /* 185 */}, { 0x9A4C57DC, 0x3732FD46 /* 186 */}, { 0x7CF1AD65, 0x7EF700A0 /* 187 */}, { 0xA31D8859, 0x59C64468 /* 188 */}, { 0xD45B61F6, 0x762FB0B4 /* 189 */}, { 0x99047718, 0x155BAED0 /* 190 */}, { 0x3D50BAA6, 0x68755E4C /* 191 */}, { 0x22D8B4DF, 0xE9214E7F /* 192 */}, { 0x2EAC95F4, 0x2ADDBF53 /* 193 */}, { 0xB4BD0109, 0x32AE3909 /* 194 */}, { 0xB08E3450, 0x834DF537 /* 195 */}, { 0x4220728D, 0xFA209DA8 /* 196 */}, { 0x9EFE23F7, 0x9E691D9B /* 197 */}, { 0xC4AE8D7F, 0x0446D288 /* 198 */}, { 0xE169785B, 0x7B4CC524 /* 199 */}, { 0x35CA1385, 0x21D87F01 /* 200 */}, { 0x137B8AA5, 0xCEBB400F /* 201 */}, { 0x580796BE, 0x272E2B66 /* 202 */}, { 0x25C2B0DE, 0x36122641 /* 203 */}, { 0xAD1EFBB2, 0x057702BD /* 204 */}, { 0xACF84BE9, 0xD4BABB8E /* 205 */}, { 0x641BC67B, 0x91583139 /* 206 */}, { 0x8036E024, 0x8BDC2DE0 /* 207 */}, { 0xF49F68ED, 0x603C8156 /* 208 */}, { 0xDBEF5111, 0xF7D236F7 /* 209 */}, { 0x8AD21E80, 0x9727C459 /* 210 */}, { 0x670A5FD7, 0xA08A0896 /* 211 */}, { 0x09EBA9CB, 0xCB4A8F43 /* 212 */}, { 0x0F7036A1, 0x81AF564B /* 213 */}, { 0x78199ABD, 0xC0B99AA7 /* 214 */}, { 0x3FC8E952, 0x959F1EC8 /* 215 */}, { 0x794A81B9, 0x8C505077 /* 216 */}, { 0x056338F0, 0x3ACAAF8F /* 217 */}, { 0x627A6778, 0x07B43F50 /* 218 */}, { 0xF5ECCC77, 0x4A44AB49 /* 219 */}, { 0xB679EE98, 0x3BC3D6E4 /* 220 */}, { 0xCF14108C, 0x9CC0D4D1 /* 221 */}, { 0x206BC8A0, 0x4406C00B /* 222 */}, { 0xC8D72D89, 0x82A18854 /* 223 */}, { 0x5C3C432C, 0x67E366B3 /* 224 */}, { 0x102B37F2, 0xB923DD61 /* 225 */}, { 0xD884271D, 0x56AB2779 /* 226 */}, { 0xFF1525AF, 0xBE83E1B0 /* 227 */}, { 0x217E49A9, 0xFB7C65D4 /* 228 */}, { 0x6D48E7D4, 0x6BDBE0E7 /* 229 */}, { 0x45D9179E, 0x08DF8287 /* 230 */}, { 0xDD53BD34, 0x22EA6A9A /* 231 */}, { 0x5622200A, 0xE36E141C /* 232 */}, { 0x8CB750EE, 0x7F805D1B /* 233 */}, { 0x9F58E837, 0xAFE5C7A5 /* 234 */}, { 0x4FB1C23C, 0xE27F996A /* 235 */}, { 0x0775F0D0, 0xD3867DFB /* 236 */}, { 0x6E88891A, 0xD0E673DE /* 237 */}, { 0xAFB86C25, 0x123AEB9E /* 238 */}, { 0xC145B895, 0x30F1D5D5 /* 239 */}, { 0xEE7269E7, 0xBB434A2D /* 240 */}, { 0xF931FA38, 0x78CB67EC /* 241 */}, { 0x323BBF9C, 0xF33B0372 /* 242 */}, { 0xFB279C74, 0x52D66336 /* 243 */}, { 0x0AFB4EAA, 0x505F33AC /* 244 */}, { 0xA2CCE187, 0xE8A5CD99 /* 245 */}, { 0x1E2D30BB, 0x53497480 /* 246 */}, { 0xD5876D90, 0x8D2D5711 /* 247 */}, { 0x91BC038E, 0x1F1A4128 /* 248 */}, { 0x82E56648, 0xD6E2E71D /* 249 */}, { 0x497732B7, 0x74036C3A /* 250 */}, { 0x6361F5AB, 0x89B67ED9 /* 251 */}, { 0xF1EA02A2, 0xFFED95D8 /* 252 */}, { 0x1464D43D, 0xE72B3BD6 /* 253 */}, { 0x0BDC4820, 0xA6300F17 /* 254 */}, { 0xED78A77A, 0xEBC18760 /* 255 */}, { 0x05A12138, 0xE6A6BE5A /* 256 */}, { 0xB4F87C98, 0xB5A122A5 /* 257 */}, { 0x140B6990, 0x563C6089 /* 258 */}, { 0x391F5DD5, 0x4C46CB2E /* 259 */}, { 0xC9B79434, 0xD932ADDB /* 260 */}, { 0x2015AFF5, 0x08EA70E4 /* 261 */}, { 0x3E478CF1, 0xD765A667 /* 262 */}, { 0xAB278D99, 0xC4FB757E /* 263 */}, { 0x2D6E0692, 0xDF11C686 /* 264 */}, { 0x0D7F3B16, 0xDDEB84F1 /* 265 */}, { 0xA665EA04, 0x6F2EF604 /* 266 */}, { 0xF0E0DFB3, 0x4A8E0F0F /* 267 */}, { 0x3DBCBA51, 0xA5EDEEF8 /* 268 */}, { 0x0EA4371E, 0xFC4F0A2A /* 269 */}, { 0x5CB38429, 0xE83E1DA8 /* 270 */}, { 0xBA1B1CE2, 0xDC8FF882 /* 271 */}, { 0x8353E80D, 0xCD45505E /* 272 */}, { 0xD4DB0717, 0x18D19A00 /* 273 */}, { 0xA5F38101, 0x34A0CFED /* 274 */}, { 0x8887CAF2, 0x0BE77E51 /* 275 */}, { 0xB3C45136, 0x1E341438 /* 276 */}, { 0x9089CCF9, 0xE05797F4 /* 277 */}, { 0xF2591D14, 0xFFD23F9D /* 278 */}, { 0x8595C5CD, 0x543DDA22 /* 279 */}, { 0x99052A33, 0x661F81FD /* 280 */}, { 0xDB0F7B76, 0x8736E641 /* 281 */}, { 0x418E5307, 0x15227725 /* 282 */}, { 0x162EB2FA, 0xE25F7F46 /* 283 */}, { 0x6C13D9FE, 0x48A8B212 /* 284 */}, { 0x92E76EEA, 0xAFDC5417 /* 285 */}, { 0xC6D1898F, 0x03D912BF /* 286 */}, { 0x1B83F51B, 0x31B1AAFA /* 287 */}, { 0xE42AB7D9, 0xF1AC2796 /* 288 */}, { 0xFCD2EBAC, 0x40A3A7D7 /* 289 */}, { 0x0AFBBCC5, 0x1056136D /* 290 */}, { 0x9A6D0C85, 0x7889E1DD /* 291 */}, { 0x2A7974AA, 0xD3352578 /* 292 */}, { 0x078AC09B, 0xA7E25D09 /* 293 */}, { 0xEAC6EDD0, 0xBD4138B3 /* 294 */}, { 0x71EB9E70, 0x920ABFBE /* 295 */}, { 0x4FC2625C, 0xA2A5D0F5 /* 296 */}, { 0x0B1290A3, 0xC054E36B /* 297 */}, { 0x62FE932B, 0xF6DD59FF /* 298 */}, { 0x11A8AC7D, 0x35373545 /* 299 */}, { 0x72FADCD4, 0xCA845E91 /* 300 */}, { 0x329D20DC, 0x84F82B60 /* 301 */}, { 0xCD672F18, 0x79C62CE1 /* 302 */}, { 0xD124642C, 0x8B09A2AD /* 303 */}, { 0x19D9E726, 0xD0C1E96A /* 304 */}, { 0x4BA9500C, 0x5A786A9B /* 305 */}, { 0x634C43F3, 0x0E020336 /* 306 */}, { 0xEB66D822, 0xC17B474A /* 307 */}, { 0xEC9BAAC2, 0x6A731AE3 /* 308 */}, { 0xE0840258, 0x8226667A /* 309 */}, { 0x91CAECA5, 0x67D45676 /* 310 */}, { 0x4875ADB5, 0x1D94155C /* 311 */}, { 0x5B813FDF, 0x6D00FD98 /* 312 */}, { 0xB774CD06, 0x51286EFC /* 313 */}, { 0x1FA744AF, 0x5E883447 /* 314 */}, { 0xE761AE2E, 0xF72CA0AE /* 315 */}, { 0xAEE8E09A, 0xBE40E4CD /* 316 */}, { 0x5118F665, 0xE9970BBB /* 317 */}, { 0x33DF1964, 0x726E4BEB /* 318 */}, { 0x29199762, 0x703B0007 /* 319 */}, { 0xF5EF30A7, 0x4631D816 /* 320 */}, { 0x1504A6BE, 0xB880B5B5 /* 321 */}, { 0x7ED84B6C, 0x641793C3 /* 322 */}, { 0xF6E97D96, 0x7B21ED77 /* 323 */}, { 0x2EF96B73, 0x77630631 /* 324 */}, { 0xE86FF3F4, 0xAE528948 /* 325 */}, { 0x86A3F8F8, 0x53DBD7F2 /* 326 */}, { 0x4CFC1063, 0x16CADCE7 /* 327 */}, { 0xFA52C6DD, 0x005C19BD /* 328 */}, { 0x64D46AD3, 0x68868F5D /* 329 */}, { 0xCF1E186A, 0x3A9D512C /* 330 */}, { 0x385660AE, 0x367E62C2 /* 331 */}, { 0x77DCB1D7, 0xE359E7EA /* 332 */}, { 0x749ABE6E, 0x526C0773 /* 333 */}, { 0xD09F734B, 0x735AE5F9 /* 334 */}, { 0x8A558BA8, 0x493FC7CC /* 335 */}, { 0x3041AB45, 0xB0B9C153 /* 336 */}, { 0x470A59BD, 0x321958BA /* 337 */}, { 0x5F46C393, 0x852DB00B /* 338 */}, { 0xD336B0E5, 0x91209B2B /* 339 */}, { 0x659EF19F, 0x6E604F7D /* 340 */}, { 0x782CCB24, 0xB99A8AE2 /* 341 */}, { 0xC814C4C7, 0xCCF52AB6 /* 342 */}, { 0xBE11727B, 0x4727D9AF /* 343 */}, { 0x0121B34D, 0x7E950D0C /* 344 */}, { 0x70AD471F, 0x756F4356 /* 345 */}, { 0x615A6849, 0xF5ADD442 /* 346 */}, { 0x80B9957A, 0x4E87E099 /* 347 */}, { 0x50AEE355, 0x2ACFA1DF /* 348 */}, { 0xFD2FD556, 0xD898263A /* 349 */}, { 0xD80C8FD6, 0xC8F4924D /* 350 */}, { 0x754A173A, 0xCF99CA3D /* 351 */}, { 0xAF91BF3C, 0xFE477BAC /* 352 */}, { 0xD690C12D, 0xED5371F6 /* 353 */}, { 0x5E687094, 0x831A5C28 /* 354 */}, { 0x3708A0A4, 0xC5D3C90A /* 355 */}, { 0x17D06580, 0x0F7F9037 /* 356 */}, { 0xB8FDF27F, 0x19F9BB13 /* 357 */}, { 0x4D502843, 0xB1BD6F1B /* 358 */}, { 0x8FFF4012, 0x1C761BA3 /* 359 */}, { 0xE2E21F3B, 0x0D1530C4 /* 360 */}, { 0xA7372C8A, 0x8943CE69 /* 361 */}, { 0xFEB5CE66, 0xE5184E11 /* 362 */}, { 0xBD736621, 0x618BDB80 /* 363 */}, { 0x8B574D0B, 0x7D29BAD6 /* 364 */}, { 0x25E6FE5B, 0x81BB613E /* 365 */}, { 0xBC07913F, 0x071C9C10 /* 366 */}, { 0x09AC2D97, 0xC7BEEB79 /* 367 */}, { 0x3BC5D757, 0xC3E58D35 /* 368 */}, { 0xF38F61E8, 0xEB017892 /* 369 */}, { 0x9B1CC21A, 0xD4EFFB9C /* 370 */}, { 0xF494F7AB, 0x99727D26 /* 371 */}, { 0x956B3E03, 0xA3E063A2 /* 372 */}, { 0x4AA09C30, 0x9D4A8B9A /* 373 */}, { 0x00090FB4, 0x3F6AB7D5 /* 374 */}, { 0x57268AC0, 0x9CC0F2A0 /* 375 */}, { 0xEDBF42D1, 0x3DEE9D2D /* 376 */}, { 0x7960A972, 0x330F49C8 /* 377 */}, { 0x87421B41, 0xC6B27202 /* 378 */}, { 0x7C00369C, 0x0AC59EC0 /* 379 */}, { 0xCB353425, 0xEF4EAC49 /* 380 */}, { 0xEF0129D8, 0xF450244E /* 381 */}, { 0xCAF4DEB6, 0x8ACC46E5 /* 382 */}, { 0x989263F7, 0x2FFEAB63 /* 383 */}, { 0x5D7A4578, 0x8F7CB9FE /* 384 */}, { 0x4E634635, 0x5BD8F764 /* 385 */}, { 0xBF2DC900, 0x427A7315 /* 386 */}, { 0x2125261C, 0x17D0C4AA /* 387 */}, { 0x93518E50, 0x3992486C /* 388 */}, { 0xA2D7D4C3, 0xB4CBFEE0 /* 389 */}, { 0x2C5DDD8D, 0x7C75D620 /* 390 */}, { 0xE35B6C61, 0xDBC295D8 /* 391 */}, { 0x02032B19, 0x60B369D3 /* 392 */}, { 0xDCE44132, 0xCE42685F /* 393 */}, { 0xDDF65610, 0x06F3DDB9 /* 394 */}, { 0xB5E148F0, 0x8EA4D21D /* 395 */}, { 0x2FCD496F, 0x20B0FCE6 /* 396 */}, { 0x58B0EE31, 0x2C1B9123 /* 397 */}, { 0x18F5A308, 0xB28317B8 /* 398 */}, { 0x9CA6D2CF, 0xA89C1E18 /* 399 */}, { 0x6AAADBC8, 0x0C6B1857 /* 400 */}, { 0x1299FAE3, 0xB65DEAA9 /* 401 */}, { 0x7F1027E7, 0xFB2B794B /* 402 */}, { 0x443B5BEB, 0x04E4317F /* 403 */}, { 0x5939D0A6, 0x4B852D32 /* 404 */}, { 0xFB207FFC, 0xD5AE6BEE /* 405 */}, { 0x81C7D374, 0x309682B2 /* 406 */}, { 0x94C3B475, 0xBAE309A1 /* 407 */}, { 0x13B49F05, 0x8CC3F97B /* 408 */}, { 0xF8293967, 0x98A9422F /* 409 */}, { 0x1076FF7C, 0x244B16B0 /* 410 */}, { 0x663D67EE, 0xF8BF571C /* 411 */}, { 0xEEE30DA1, 0x1F0D6758 /* 412 */}, { 0x7ADEB9B7, 0xC9B611D9 /* 413 */}, { 0x7B6C57A2, 0xB7AFD588 /* 414 */}, { 0x6B984FE1, 0x6290AE84 /* 415 */}, { 0xACC1A5FD, 0x94DF4CDE /* 416 */}, { 0xC5483AFF, 0x058A5BD1 /* 417 */}, { 0x42BA3C37, 0x63166CC1 /* 418 */}, { 0xB2F76F40, 0x8DB8526E /* 419 */}, { 0x6F0D6D4E, 0xE1088003 /* 420 */}, { 0x971D311D, 0x9E0523C9 /* 421 */}, { 0xCC7CD691, 0x45EC2824 /* 422 */}, { 0xE62382C9, 0x575B8359 /* 423 */}, { 0xC4889995, 0xFA9E400D /* 424 */}, { 0x45721568, 0xD1823ECB /* 425 */}, { 0x8206082F, 0xDAFD983B /* 426 */}, { 0x2386A8CB, 0xAA7D2908 /* 427 */}, { 0x03B87588, 0x269FCD44 /* 428 */}, { 0x28BDD1E0, 0x1B91F5F7 /* 429 */}, { 0x040201F6, 0xE4669F39 /* 430 */}, { 0x8CF04ADE, 0x7A1D7C21 /* 431 */}, { 0xD79CE5CE, 0x65623C29 /* 432 */}, { 0x96C00BB1, 0x23684490 /* 433 */}, { 0x9DA503BA, 0xAB9BF187 /* 434 */}, { 0xA458058E, 0xBC23ECB1 /* 435 */}, { 0xBB401ECC, 0x9A58DF01 /* 436 */}, { 0xA85F143D, 0xA070E868 /* 437 */}, { 0x7DF2239E, 0x4FF18830 /* 438 */}, { 0x1A641183, 0x14D565B4 /* 439 */}, { 0x52701602, 0xEE133374 /* 440 */}, { 0x3F285E09, 0x950E3DCF /* 441 */}, { 0xB9C80953, 0x59930254 /* 442 */}, { 0x8930DA6D, 0x3BF29940 /* 443 */}, { 0x53691387, 0xA955943F /* 444 */}, { 0xA9CB8784, 0xA15EDECA /* 445 */}, { 0x352BE9A0, 0x29142127 /* 446 */}, { 0xFF4E7AFB, 0x76F0371F /* 447 */}, { 0x274F2228, 0x0239F450 /* 448 */}, { 0x1D5E868B, 0xBB073AF0 /* 449 */}, { 0xC10E96C1, 0xBFC80571 /* 450 */}, { 0x68222E23, 0xD2670885 /* 451 */}, { 0x8E80B5B0, 0x9671A3D4 /* 452 */}, { 0xE193BB81, 0x55B5D38A /* 453 */}, { 0xA18B04B8, 0x693AE2D0 /* 454 */}, { 0xADD5335F, 0x5C48B4EC /* 455 */}, { 0x4916A1CA, 0xFD743B19 /* 456 */}, { 0x34BE98C4, 0x25770181 /* 457 */}, { 0x3C54A4AD, 0xE77987E8 /* 458 */}, { 0xDA33E1B9, 0x28E11014 /* 459 */}, { 0x226AA213, 0x270CC59E /* 460 */}, { 0x6D1A5F60, 0x71495F75 /* 461 */}, { 0x60AFEF77, 0x9BE853FB /* 462 */}, { 0xF7443DBF, 0xADC786A7 /* 463 */}, { 0x73B29A82, 0x09044561 /* 464 */}, { 0xC232BD5E, 0x58BC7A66 /* 465 */}, { 0x673AC8B2, 0xF306558C /* 466 */}, { 0xB6C9772A, 0x41F639C6 /* 467 */}, { 0x9FDA35DA, 0x216DEFE9 /* 468 */}, { 0x1C7BE615, 0x11640CC7 /* 469 */}, { 0x565C5527, 0x93C43694 /* 470 */}, { 0x46777839, 0xEA038E62 /* 471 */}, { 0x5A3E2469, 0xF9ABF3CE /* 472 */}, { 0x0FD312D2, 0x741E768D /* 473 */}, { 0xCED652C6, 0x0144B883 /* 474 */}, { 0xA33F8552, 0xC20B5A5B /* 475 */}, { 0xC3435A9D, 0x1AE69633 /* 476 */}, { 0x088CFDEC, 0x97A28CA4 /* 477 */}, { 0x1E96F420, 0x8824A43C /* 478 */}, { 0x6EEEA746, 0x37612FA6 /* 479 */}, { 0xF9CF0E5A, 0x6B4CB165 /* 480 */}, { 0xA0ABFB4A, 0x43AA1C06 /* 481 */}, { 0xF162796B, 0x7F4DC26F /* 482 */}, { 0x54ED9B0F, 0x6CBACC8E /* 483 */}, { 0xD2BB253E, 0xA6B7FFEF /* 484 */}, { 0xB0A29D4F, 0x2E25BC95 /* 485 */}, { 0xDEF1388C, 0x86D6A58B /* 486 */}, { 0x76B6F054, 0xDED74AC5 /* 487 */}, { 0x2B45805D, 0x8030BDBC /* 488 */}, { 0xE94D9289, 0x3C81AF70 /* 489 */}, { 0x9E3100DB, 0x3EFF6DDA /* 490 */}, { 0xDFCC8847, 0xB38DC39F /* 491 */}, { 0x8D17B87E, 0x12388552 /* 492 */}, { 0x40B1B642, 0xF2DA0ED2 /* 493 */}, { 0xD54BF9A9, 0x44CEFADC /* 494 */}, { 0x433C7EE6, 0x1312200E /* 495 */}, { 0x3A78C748, 0x9FFCC84F /* 496 */}, { 0x248576BB, 0xF0CD1F72 /* 497 */}, { 0x3638CFE4, 0xEC697405 /* 498 */}, { 0x0CEC4E4C, 0x2BA7B67C /* 499 */}, { 0xE5CE32ED, 0xAC2F4DF3 /* 500 */}, { 0x26EA4C11, 0xCB33D143 /* 501 */}, { 0xC77E58BC, 0xA4E9044C /* 502 */}, { 0xD934FCEF, 0x5F513293 /* 503 */}, { 0x06E55444, 0x5DC96455 /* 504 */}, { 0x317DE40A, 0x50DE418F /* 505 */}, { 0x69DDE259, 0x388CB31A /* 506 */}, { 0x55820A86, 0x2DB4A834 /* 507 */}, { 0x84711AE9, 0x9010A91E /* 508 */}, { 0xB1498371, 0x4DF7F0B7 /* 509 */}, { 0xC0977179, 0xD62A2EAB /* 510 */}, { 0xAA8D5C0E, 0x22FAC097 /* 511 */}, { 0xF1DAF39B, 0xF49FCC2F /* 512 */}, { 0x6FF29281, 0x487FD5C6 /* 513 */}, { 0xFCDCA83F, 0xE8A30667 /* 514 */}, { 0xD2FCCE63, 0x2C9B4BE3 /* 515 */}, { 0x93FBBBC2, 0xDA3FF74B /* 516 */}, { 0xFE70BA66, 0x2FA165D2 /* 517 */}, { 0x970E93D4, 0xA103E279 /* 518 */}, { 0xB0E45E71, 0xBECDEC77 /* 519 */}, { 0x3985E497, 0xCFB41E72 /* 520 */}, { 0x5EF75017, 0xB70AAA02 /* 521 */}, { 0x3840B8E0, 0xD42309F0 /* 522 */}, { 0x35898579, 0x8EFC1AD0 /* 523 */}, { 0xE2B2ABC5, 0x96C6920B /* 524 */}, { 0x375A9172, 0x66AF4163 /* 525 */}, { 0xCA7127FB, 0x2174ABDC /* 526 */}, { 0x4A72FF41, 0xB33CCEA6 /* 527 */}, { 0x083066A5, 0xF04A4933 /* 528 */}, { 0xD7289AF5, 0x8D970ACD /* 529 */}, { 0x31C8C25E, 0x8F96E8E0 /* 530 */}, { 0x76875D47, 0xF3FEC022 /* 531 */}, { 0x056190DD, 0xEC7BF310 /* 532 */}, { 0xBB0F1491, 0xF5ADB0AE /* 533 */}, { 0x0FD58892, 0x9B50F885 /* 534 */}, { 0x58B74DE8, 0x49754883 /* 535 */}, { 0x91531C61, 0xA3354FF6 /* 536 */}, { 0x81D2C6EE, 0x0702BBE4 /* 537 */}, { 0x7DEDED98, 0x89FB2405 /* 538 */}, { 0x8596E902, 0xAC307513 /* 539 */}, { 0x172772ED, 0x1D2D3580 /* 540 */}, { 0x8E6BC30D, 0xEB738FC2 /* 541 */}, { 0x63044326, 0x5854EF8F /* 542 */}, { 0x5ADD3BBE, 0x9E5C5232 /* 543 */}, { 0x325C4623, 0x90AA53CF /* 544 */}, { 0x349DD067, 0xC1D24D51 /* 545 */}, { 0xA69EA624, 0x2051CFEE /* 546 */}, { 0x862E7E4F, 0x13220F0A /* 547 */}, { 0x04E04864, 0xCE393994 /* 548 */}, { 0x7086FCB7, 0xD9C42CA4 /* 549 */}, { 0x8A03E7CC, 0x685AD223 /* 550 */}, { 0xAB2FF1DB, 0x066484B2 /* 551 */}, { 0xEFBF79EC, 0xFE9D5D70 /* 552 */}, { 0x9C481854, 0x5B13B9DD /* 553 */}, { 0xED1509AD, 0x15F0D475 /* 554 */}, { 0x0EC79851, 0x0BEBCD06 /* 555 */}, { 0x183AB7F8, 0xD58C6791 /* 556 */}, { 0x52F3EEE4, 0xD1187C50 /* 557 */}, { 0xE54E82FF, 0xC95D1192 /* 558 */}, { 0xB9AC6CA2, 0x86EEA14C /* 559 */}, { 0x53677D5D, 0x3485BEB1 /* 560 */}, { 0x1F8C492A, 0xDD191D78 /* 561 */}, { 0xA784EBF9, 0xF60866BA /* 562 */}, { 0xA2D08C74, 0x518F643B /* 563 */}, { 0xE1087C22, 0x8852E956 /* 564 */}, { 0xC410AE8D, 0xA768CB8D /* 565 */}, { 0xBFEC8E1A, 0x38047726 /* 566 */}, { 0xCD3B45AA, 0xA67738B4 /* 567 */}, { 0xEC0DDE19, 0xAD16691C /* 568 */}, { 0x80462E07, 0xC6D43193 /* 569 */}, { 0x0BA61938, 0xC5A5876D /* 570 */}, { 0xA58FD840, 0x16B9FA1F /* 571 */}, { 0x3CA74F18, 0x188AB117 /* 572 */}, { 0xC99C021F, 0xABDA2F98 /* 573 */}, { 0x134AE816, 0x3E0580AB /* 574 */}, { 0x73645ABB, 0x5F3B05B7 /* 575 */}, { 0x5575F2F6, 0x2501A2BE /* 576 */}, { 0x4E7E8BA9, 0x1B2F7400 /* 577 */}, { 0x71E8D953, 0x1CD75803 /* 578 */}, { 0x62764E30, 0x7F6ED895 /* 579 */}, { 0x596F003D, 0xB15926FF /* 580 */}, { 0xA8C5D6B9, 0x9F65293D /* 581 */}, { 0xD690F84C, 0x6ECEF04D /* 582 */}, { 0xFF33AF88, 0x4782275F /* 583 */}, { 0x3F820801, 0xE4143308 /* 584 */}, { 0x9A1AF9B5, 0xFD0DFE40 /* 585 */}, { 0x2CDB396B, 0x4325A334 /* 586 */}, { 0xB301B252, 0x8AE77E62 /* 587 */}, { 0x6655615A, 0xC36F9E9F /* 588 */}, { 0x92D32C09, 0x85455A2D /* 589 */}, { 0x49477485, 0xF2C7DEA9 /* 590 */}, { 0x33A39EBA, 0x63CFB4C1 /* 591 */}, { 0x6EBC5462, 0x83B040CC /* 592 */}, { 0xFDB326B0, 0x3B9454C8 /* 593 */}, { 0x87FFD78C, 0x56F56A9E /* 594 */}, { 0x99F42BC6, 0x2DC2940D /* 595 */}, { 0x6B096E2D, 0x98F7DF09 /* 596 */}, { 0x3AD852BF, 0x19A6E01E /* 597 */}, { 0xDBD4B40B, 0x42A99CCB /* 598 */}, { 0x45E9C559, 0xA59998AF /* 599 */}, { 0x07D93186, 0x366295E8 /* 600 */}, { 0xFAA1F773, 0x6B48181B /* 601 */}, { 0x157A0A1D, 0x1FEC57E2 /* 602 */}, { 0xF6201AD5, 0x4667446A /* 603 */}, { 0xCFB0F075, 0xE615EBCA /* 604 */}, { 0x68290778, 0xB8F31F4F /* 605 */}, { 0xCE22D11E, 0x22713ED6 /* 606 */}, { 0x2EC3C93B, 0x3057C1A7 /* 607 */}, { 0x7C3F1F2F, 0xCB46ACC3 /* 608 */}, { 0x02AAF50E, 0xDBB893FD /* 609 */}, { 0x600B9FCF, 0x331FD92E /* 610 */}, { 0x48EA3AD6, 0xA498F961 /* 611 */}, { 0x8B6A83EA, 0xA8D8426E /* 612 */}, { 0xB7735CDC, 0xA089B274 /* 613 */}, { 0x1E524A11, 0x87F6B373 /* 614 */}, { 0xCBC96749, 0x118808E5 /* 615 */}, { 0xB19BD394, 0x9906E4C7 /* 616 */}, { 0x9B24A20C, 0xAFED7F7E /* 617 */}, { 0xEB3644A7, 0x6509EADE /* 618 */}, { 0xE8EF0EDE, 0x6C1EF1D3 /* 619 */}, { 0xE9798FB4, 0xB9C97D43 /* 620 */}, { 0x740C28A3, 0xA2F2D784 /* 621 */}, { 0x6197566F, 0x7B849647 /* 622 */}, { 0xB65F069D, 0x7A5BE3E6 /* 623 */}, { 0x78BE6F10, 0xF96330ED /* 624 */}, { 0x7A076A15, 0xEEE60DE7 /* 625 */}, { 0xA08B9BD0, 0x2B4BEE4A /* 626 */}, { 0xC7B8894E, 0x6A56A63E /* 627 */}, { 0xBA34FEF4, 0x02121359 /* 628 */}, { 0x283703FC, 0x4CBF99F8 /* 629 */}, { 0x0CAF30C8, 0x39807135 /* 630 */}, { 0xF017687A, 0xD0A77A89 /* 631 */}, { 0x9E423569, 0xF1C1A9EB /* 632 */}, { 0x2DEE8199, 0x8C797628 /* 633 */}, { 0xDD1F7ABD, 0x5D1737A5 /* 634 */}, { 0x09A9FA80, 0x4F53433C /* 635 */}, { 0xDF7CA1D9, 0xFA8B0C53 /* 636 */}, { 0x886CCB77, 0x3FD9DCBC /* 637 */}, { 0xA91B4720, 0xC040917C /* 638 */}, { 0xF9D1DCDF, 0x7DD00142 /* 639 */}, { 0x4F387B58, 0x8476FC1D /* 640 */}, { 0xF3316503, 0x23F8E7C5 /* 641 */}, { 0xE7E37339, 0x032A2244 /* 642 */}, { 0x50F5A74B, 0x5C87A5D7 /* 643 */}, { 0x3698992E, 0x082B4CC4 /* 644 */}, { 0xB858F63C, 0xDF917BEC /* 645 */}, { 0x5BF86DDA, 0x3270B8FC /* 646 */}, { 0x29B5DD76, 0x10AE72BB /* 647 */}, { 0x7700362B, 0x576AC94E /* 648 */}, { 0xC61EFB8F, 0x1AD112DA /* 649 */}, { 0xC5FAA427, 0x691BC30E /* 650 */}, { 0xCC327143, 0xFF246311 /* 651 */}, { 0x30E53206, 0x3142368E /* 652 */}, { 0xE02CA396, 0x71380E31 /* 653 */}, { 0x0AAD76F1, 0x958D5C96 /* 654 */}, { 0xC16DA536, 0xF8D6F430 /* 655 */}, { 0x1BE7E1D2, 0xC8FFD13F /* 656 */}, { 0x004DDBE1, 0x7578AE66 /* 657 */}, { 0x067BE646, 0x05833F01 /* 658 */}, { 0x3BFE586D, 0xBB34B5AD /* 659 */}, { 0xA12B97F0, 0x095F34C9 /* 660 */}, { 0x25D60CA8, 0x247AB645 /* 661 */}, { 0x017477D1, 0xDCDBC6F3 /* 662 */}, { 0xDECAD24D, 0x4A2E14D4 /* 663 */}, { 0xBE0A1EEB, 0xBDB5E6D9 /* 664 */}, { 0x794301AB, 0x2A7E70F7 /* 665 */}, { 0x270540FD, 0xDEF42D8A /* 666 */}, { 0xA34C22C1, 0x01078EC0 /* 667 */}, { 0xF4C16387, 0xE5DE511A /* 668 */}, { 0xBD9A330A, 0x7EBB3A52 /* 669 */}, { 0xAA7D6435, 0x77697857 /* 670 */}, { 0x03AE4C32, 0x004E8316 /* 671 */}, { 0xAD78E312, 0xE7A21020 /* 672 */}, { 0x6AB420F2, 0x9D41A70C /* 673 */}, { 0xEA1141E6, 0x28E06C18 /* 674 */}, { 0x984F6B28, 0xD2B28CBD /* 675 */}, { 0x446E9D83, 0x26B75F6C /* 676 */}, { 0x4D418D7F, 0xBA47568C /* 677 */}, { 0xE6183D8E, 0xD80BADBF /* 678 */}, { 0x5F166044, 0x0E206D7F /* 679 */}, { 0x11CBCA3E, 0xE258A439 /* 680 */}, { 0xB21DC0BC, 0x723A1746 /* 681 */}, { 0xF5D7CDD3, 0xC7CAA854 /* 682 */}, { 0x3D261D9C, 0x7CAC3288 /* 683 */}, { 0x23BA942C, 0x7690C264 /* 684 */}, { 0x478042B8, 0x17E55524 /* 685 */}, { 0x56A2389F, 0xE0BE4776 /* 686 */}, { 0x67AB2DA0, 0x4D289B5E /* 687 */}, { 0x8FBBFD31, 0x44862B9C /* 688 */}, { 0x9D141365, 0xB47CC804 /* 689 */}, { 0x2B91C793, 0x822C1B36 /* 690 */}, { 0xFB13DFD8, 0x4EB14655 /* 691 */}, { 0x14E2A97B, 0x1ECBBA07 /* 692 */}, { 0x5CDE5F14, 0x6143459D /* 693 */}, { 0xD5F0AC89, 0x53A8FBF1 /* 694 */}, { 0x1C5E5B00, 0x97EA04D8 /* 695 */}, { 0xD4FDB3F3, 0x622181A8 /* 696 */}, { 0x572A1208, 0xE9BCD341 /* 697 */}, { 0x43CCE58A, 0x14112586 /* 698 */}, { 0xA4C6E0A4, 0x9144C5FE /* 699 */}, { 0x65CF620F, 0x0D33D065 /* 700 */}, { 0x9F219CA1, 0x54A48D48 /* 701 */}, { 0x6D63C821, 0xC43E5EAC /* 702 */}, { 0x72770DAF, 0xA9728B3A /* 703 */}, { 0x20DF87EF, 0xD7934E7B /* 704 */}, { 0x1A3E86E5, 0xE35503B6 /* 705 */}, { 0xC819D504, 0xCAE321FB /* 706 */}, { 0xAC60BFA6, 0x129A50B3 /* 707 */}, { 0x7E9FB6C3, 0xCD5E68EA /* 708 */}, { 0x9483B1C7, 0xB01C9019 /* 709 */}, { 0xC295376C, 0x3DE93CD5 /* 710 */}, { 0x2AB9AD13, 0xAED52EDF /* 711 */}, { 0xC0A07884, 0x2E60F512 /* 712 */}, { 0xE36210C9, 0xBC3D86A3 /* 713 */}, { 0x163951CE, 0x35269D9B /* 714 */}, { 0xD0CDB5FA, 0x0C7D6E2A /* 715 */}, { 0xD87F5733, 0x59E86297 /* 716 */}, { 0x898DB0E7, 0x298EF221 /* 717 */}, { 0xD1A5AA7E, 0x55000029 /* 718 */}, { 0xB5061B45, 0x8BC08AE1 /* 719 */}, { 0x6C92703A, 0xC2C31C2B /* 720 */}, { 0xAF25EF42, 0x94CC596B /* 721 */}, { 0x22540456, 0x0A1D73DB /* 722 */}, { 0xD9C4179A, 0x04B6A0F9 /* 723 */}, { 0xAE3D3C60, 0xEFFDAFA2 /* 724 */}, { 0xB49496C4, 0xF7C8075B /* 725 */}, { 0x1D1CD4E3, 0x9CC5C714 /* 726 */}, { 0x218E5534, 0x78BD1638 /* 727 */}, { 0xF850246A, 0xB2F11568 /* 728 */}, { 0x9502BC29, 0xEDFABCFA /* 729 */}, { 0xDA23051B, 0x796CE5F2 /* 730 */}, { 0xDC93537C, 0xAAE128B0 /* 731 */}, { 0xEE4B29AE, 0x3A493DA0 /* 732 */}, { 0x416895D7, 0xB5DF6B2C /* 733 */}, { 0x122D7F37, 0xFCABBD25 /* 734 */}, { 0x105DC4B1, 0x70810B58 /* 735 */}, { 0xF7882A90, 0xE10FDD37 /* 736 */}, { 0x518A3F5C, 0x524DCAB5 /* 737 */}, { 0x8451255B, 0x3C9E8587 /* 738 */}, { 0x19BD34E2, 0x40298281 /* 739 */}, { 0x5D3CECCB, 0x74A05B6F /* 740 */}, { 0x42E13ECA, 0xB6100215 /* 741 */}, { 0x2F59E2AC, 0x0FF979D1 /* 742 */}, { 0xE4F9CC50, 0x6037DA27 /* 743 */}, { 0x0DF1847D, 0x5E92975A /* 744 */}, { 0xD3E623FE, 0xD66DE190 /* 745 */}, { 0x7B568048, 0x5032D6B8 /* 746 */}, { 0x8235216E, 0x9A36B7CE /* 747 */}, { 0x24F64B4A, 0x80272A7A /* 748 */}, { 0x8C6916F7, 0x93EFED8B /* 749 */}, { 0x4CCE1555, 0x37DDBFF4 /* 750 */}, { 0x4B99BD25, 0x4B95DB5D /* 751 */}, { 0x69812FC0, 0x92D3FDA1 /* 752 */}, { 0x90660BB6, 0xFB1A4A9A /* 753 */}, { 0x46A4B9B2, 0x730C1969 /* 754 */}, { 0x7F49DA68, 0x81E289AA /* 755 */}, { 0x83B1A05F, 0x64669A0F /* 756 */}, { 0x9644F48B, 0x27B3FF7D /* 757 */}, { 0x8DB675B3, 0xCC6B615C /* 758 */}, { 0xBCEBBE95, 0x674F20B9 /* 759 */}, { 0x75655982, 0x6F312382 /* 760 */}, { 0x3E45CF05, 0x5AE48871 /* 761 */}, { 0x54C21157, 0xBF619F99 /* 762 */}, { 0x40A8EAE9, 0xEABAC460 /* 763 */}, { 0xF2C0C1CD, 0x454C6FE9 /* 764 */}, { 0x6412691C, 0x419CF649 /* 765 */}, { 0x265B0F70, 0xD3DC3BEF /* 766 */}, { 0xC3578A9E, 0x6D0E60F5 /* 767 */}, { 0x26323C55, 0x5B0E6085 /* 768 */}, { 0xFA1B59F5, 0x1A46C1A9 /* 769 */}, { 0x7C4C8FFA, 0xA9E245A1 /* 770 */}, { 0xDB2955D7, 0x65CA5159 /* 771 */}, { 0xCE35AFC2, 0x05DB0A76 /* 772 */}, { 0xA9113D45, 0x81EAC77E /* 773 */}, { 0xB6AC0A0D, 0x528EF88A /* 774 */}, { 0x597BE3FF, 0xA09EA253 /* 775 */}, { 0xAC48CD56, 0x430DDFB3 /* 776 */}, { 0xF45CE46F, 0xC4B3A67A /* 777 */}, { 0xFBE2D05E, 0x4ECECFD8 /* 778 */}, { 0xB39935F0, 0x3EF56F10 /* 779 */}, { 0x9CD619C6, 0x0B22D682 /* 780 */}, { 0x74DF2069, 0x17FD460A /* 781 */}, { 0x8510ED40, 0x6CF8CC8E /* 782 */}, { 0x3A6ECAA7, 0xD6C824BF /* 783 */}, { 0x1A817049, 0x61243D58 /* 784 */}, { 0xBBC163A2, 0x048BACB6 /* 785 */}, { 0x7D44CC32, 0xD9A38AC2 /* 786 */}, { 0xAAF410AB, 0x7FDDFF5B /* 787 */}, { 0xA804824B, 0xAD6D495A /* 788 */}, { 0x2D8C9F94, 0xE1A6A74F /* 789 */}, { 0x35DEE8E3, 0xD4F78512 /* 790 */}, { 0x6540D893, 0xFD4B7F88 /* 791 */}, { 0x2AA4BFDA, 0x247C2004 /* 792 */}, { 0x17D1327C, 0x096EA1C5 /* 793 */}, { 0x361A6685, 0xD56966B4 /* 794 */}, { 0x1221057D, 0x277DA5C3 /* 795 */}, { 0xA43ACFF7, 0x94D59893 /* 796 */}, { 0xCDC02281, 0x64F0C51C /* 797 */}, { 0xFF6189DB, 0x3D33BCC4 /* 798 */}, { 0x4CE66AF1, 0xE005CB18 /* 799 */}, { 0x1DB99BEA, 0xFF5CCD1D /* 800 */}, { 0xFE42980F, 0xB0B854A7 /* 801 */}, { 0x718D4B9F, 0x7BD46A6A /* 802 */}, { 0x22A5FD8C, 0xD10FA8CC /* 803 */}, { 0x2BE4BD31, 0xD3148495 /* 804 */}, { 0xCB243847, 0xC7FA975F /* 805 */}, { 0x5846C407, 0x4886ED1E /* 806 */}, { 0x1EB70B04, 0x28CDDB79 /* 807 */}, { 0xF573417F, 0xC2B00BE2 /* 808 */}, { 0x2180F877, 0x5C959045 /* 809 */}, { 0xF370EB00, 0x7A6BDDFF /* 810 */}, { 0xD6D9D6A4, 0xCE509E38 /* 811 */}, { 0x647FA702, 0xEBEB0F00 /* 812 */}, { 0x76606F06, 0x1DCC06CF /* 813 */}, { 0xA286FF0A, 0xE4D9F28B /* 814 */}, { 0xC918C262, 0xD85A305D /* 815 */}, { 0x32225F54, 0x475B1D87 /* 816 */}, { 0x68CCB5FE, 0x2D4FB516 /* 817 */}, { 0xD72BBA20, 0xA679B9D9 /* 818 */}, { 0x912D43A5, 0x53841C0D /* 819 */}, { 0xBF12A4E8, 0x3B7EAA48 /* 820 */}, { 0xF22F1DDF, 0x781E0E47 /* 821 */}, { 0x0AB50973, 0xEFF20CE6 /* 822 */}, { 0x9DFFB742, 0x20D261D1 /* 823 */}, { 0x062A2E39, 0x16A12B03 /* 824 */}, { 0x39650495, 0x1960EB22 /* 825 */}, { 0xD50EB8B8, 0x251C16FE /* 826 */}, { 0xF826016E, 0x9AC0C330 /* 827 */}, { 0x953E7671, 0xED152665 /* 828 */}, { 0xA6369570, 0x02D63194 /* 829 */}, { 0x94B1C987, 0x5074F083 /* 830 */}, { 0x90B25CE1, 0x70BA598C /* 831 */}, { 0x0B9742F6, 0x794A1581 /* 832 */}, { 0xFCAF8C6C, 0x0D5925E9 /* 833 */}, { 0xD868744E, 0x3067716C /* 834 */}, { 0xE8D7731B, 0x910AB077 /* 835 */}, { 0x5AC42F61, 0x6A61BBDB /* 836 */}, { 0xF0851567, 0x93513EFB /* 837 */}, { 0x9E83E9D5, 0xF494724B /* 838 */}, { 0x5C09648D, 0xE887E198 /* 839 */}, { 0x75370CFD, 0x34B1D3C6 /* 840 */}, { 0xBC0D255D, 0xDC35E433 /* 841 */}, { 0x34131BE0, 0xD0AAB842 /* 842 */}, { 0xB48B7EAF, 0x08042A50 /* 843 */}, { 0x44A3AB35, 0x9997C4EE /* 844 */}, { 0x201799D0, 0x829A7B49 /* 845 */}, { 0xB7C54441, 0x263B8307 /* 846 */}, { 0xFD6A6CA6, 0x752F95F4 /* 847 */}, { 0x2C08C6E5, 0x92721740 /* 848 */}, { 0xA795D9EE, 0x2A8AB754 /* 849 */}, { 0x2F72943D, 0xA442F755 /* 850 */}, { 0x19781208, 0x2C31334E /* 851 */}, { 0xEAEE6291, 0x4FA98D7C /* 852 */}, { 0x665DB309, 0x55C3862F /* 853 */}, { 0x5D53B1F3, 0xBD061017 /* 854 */}, { 0x40413F27, 0x46FE6CB8 /* 855 */}, { 0xDF0CFA59, 0x3FE03792 /* 856 */}, { 0x2EB85E8F, 0xCFE70037 /* 857 */}, { 0xADBCE118, 0xA7BE29E7 /* 858 */}, { 0xDE8431DD, 0xE544EE5C /* 859 */}, { 0x41F1873E, 0x8A781B1B /* 860 */}, { 0xA0D2F0E7, 0xA5C94C78 /* 861 */}, { 0x77B60728, 0x39412E28 /* 862 */}, { 0xAFC9A62C, 0xA1265EF3 /* 863 */}, { 0x6A2506C5, 0xBCC2770C /* 864 */}, { 0xDCE1CE12, 0x3AB66DD5 /* 865 */}, { 0x4A675B37, 0xE65499D0 /* 866 */}, { 0x81BFD216, 0x7D8F5234 /* 867 */}, { 0xEC15F389, 0x0F6F64FC /* 868 */}, { 0x8B5B13C8, 0x74EFBE61 /* 869 */}, { 0x14273E1D, 0xACDC82B7 /* 870 */}, { 0x03199D17, 0xDD40BFE0 /* 871 */}, { 0xE7E061F8, 0x37E99257 /* 872 */}, { 0x04775AAA, 0xFA526269 /* 873 */}, { 0x463D56F9, 0x8BBBF63A /* 874 */}, { 0x43A26E64, 0xF0013F15 /* 875 */}, { 0x879EC898, 0xA8307E9F /* 876 */}, { 0x150177CC, 0xCC4C27A4 /* 877 */}, { 0xCA1D3348, 0x1B432F2C /* 878 */}, { 0x9F6FA013, 0xDE1D1F8F /* 879 */}, { 0x47A7DDD6, 0x606602A0 /* 880 */}, { 0xCC1CB2C7, 0xD237AB64 /* 881 */}, { 0x25FCD1D3, 0x9B938E72 /* 882 */}, { 0x8E0FF476, 0xEC4E0370 /* 883 */}, { 0x3D03C12D, 0xFEB2FBDA /* 884 */}, { 0xEE43889A, 0xAE0BCED2 /* 885 */}, { 0xEBFB4F43, 0x22CB8923 /* 886 */}, { 0x3CF7396D, 0x69360D01 /* 887 */}, { 0xD2D4E022, 0x855E3602 /* 888 */}, { 0xD01F784C, 0x073805BA /* 889 */}, { 0x3852F546, 0x33E17A13 /* 890 */}, { 0x8AC7B638, 0xDF487405 /* 891 */}, { 0x678AA14A, 0xBA92B29C /* 892 */}, { 0x6CFAADCD, 0x0CE89FC7 /* 893 */}, { 0x08339E34, 0x5F9D4E09 /* 894 */}, { 0x1F5923B9, 0xF1AFE929 /* 895 */}, { 0x0F4A265F, 0x6E3480F6 /* 896 */}, { 0xB29B841C, 0xEEBF3A2A /* 897 */}, { 0x8F91B4AD, 0xE21938A8 /* 898 */}, { 0x45C6D3C3, 0x57DFEFF8 /* 899 */}, { 0xF62CAAF2, 0x2F006B0B /* 900 */}, { 0x6F75EE78, 0x62F479EF /* 901 */}, { 0x1C8916A9, 0x11A55AD4 /* 902 */}, { 0x84FED453, 0xF229D290 /* 903 */}, { 0x16B000E6, 0x42F1C27B /* 904 */}, { 0x9823C074, 0x2B1F7674 /* 905 */}, { 0xC2745360, 0x4B76ECA3 /* 906 */}, { 0xB91691BD, 0x8C98F463 /* 907 */}, { 0xF1ADE66A, 0x14BCC93C /* 908 */}, { 0x6D458397, 0x8885213E /* 909 */}, { 0x274D4711, 0x8E177DF0 /* 910 */}, { 0x503F2951, 0xB49B73B5 /* 911 */}, { 0xC3F96B6B, 0x10168168 /* 912 */}, { 0x63CAB0AE, 0x0E3D963B /* 913 */}, { 0x55A1DB14, 0x8DFC4B56 /* 914 */}, { 0x6E14DE5C, 0xF789F135 /* 915 */}, { 0x4E51DAC1, 0x683E68AF /* 916 */}, { 0x8D4B0FD9, 0xC9A84F9D /* 917 */}, { 0x52A0F9D1, 0x3691E03F /* 918 */}, { 0xE1878E80, 0x5ED86E46 /* 919 */}, { 0x99D07150, 0x3C711A0E /* 920 */}, { 0x0C4E9310, 0x5A0865B2 /* 921 */}, { 0xE4F0682E, 0x56FBFC1F /* 922 */}, { 0x105EDF9B, 0xEA8D5DE3 /* 923 */}, { 0x2379187A, 0x71ABFDB1 /* 924 */}, { 0xBEE77B9C, 0x2EB99DE1 /* 925 */}, { 0x33CF4523, 0x21ECC0EA /* 926 */}, { 0x1805C7A1, 0x59A4D752 /* 927 */}, { 0x56AE7C72, 0x3896F5EB /* 928 */}, { 0xB18F75DC, 0xAA638F3D /* 929 */}, { 0xABE9808E, 0x9F39358D /* 930 */}, { 0xC00B72AC, 0xB7DEFA91 /* 931 */}, { 0x62492D92, 0x6B5541FD /* 932 */}, { 0xF92E4D5B, 0x6DC6DEE8 /* 933 */}, { 0xC4BEEA7E, 0x353F57AB /* 934 */}, { 0xDA5690CE, 0x735769D6 /* 935 */}, { 0x42391484, 0x0A234AA6 /* 936 */}, { 0x28F80D9D, 0xF6F95080 /* 937 */}, { 0x7AB3F215, 0xB8E319A2 /* 938 */}, { 0x51341A4D, 0x31AD9C11 /* 939 */}, { 0x7BEF5805, 0x773C22A5 /* 940 */}, { 0x07968633, 0x45C7561A /* 941 */}, { 0x249DBE36, 0xF913DA9E /* 942 */}, { 0x78A64C68, 0xDA652D9B /* 943 */}, { 0x3BC334EF, 0x4C27A97F /* 944 */}, { 0xE66B17F4, 0x76621220 /* 945 */}, { 0x9ACD7D0B, 0x96774389 /* 946 */}, { 0xE0ED6782, 0xF3EE5BCA /* 947 */}, { 0x00C879FC, 0x409F7536 /* 948 */}, { 0xB5926DB6, 0x06D09A39 /* 949 */}, { 0x317AC588, 0x6F83AEB0 /* 950 */}, { 0x86381F21, 0x01E6CA4A /* 951 */}, { 0xD19F3025, 0x66FF3462 /* 952 */}, { 0xDDFD3BFB, 0x72207C24 /* 953 */}, { 0xE2ECE2EB, 0x4AF6B6D3 /* 954 */}, { 0xC7EA08DE, 0x9C994DBE /* 955 */}, { 0xB09A8BC4, 0x49ACE597 /* 956 */}, { 0xCF0797BA, 0xB38C4766 /* 957 */}, { 0xC57C2A75, 0x131B9373 /* 958 */}, { 0x61931E58, 0xB1822CCE /* 959 */}, { 0x09BA1C0C, 0x9D7555B9 /* 960 */}, { 0x937D11D2, 0x127FAFDD /* 961 */}, { 0xC66D92E4, 0x29DA3BAD /* 962 */}, { 0x54C2ECBC, 0xA2C1D571 /* 963 */}, { 0x82F6FE24, 0x58C5134D /* 964 */}, { 0x5B62274F, 0x1C3AE351 /* 965 */}, { 0x01CB8126, 0xE907C82E /* 966 */}, { 0x13E37FCB, 0xF8ED0919 /* 967 */}, { 0xC80046C9, 0x3249D8F9 /* 968 */}, { 0xE388FB63, 0x80CF9BED /* 969 */}, { 0x116CF19E, 0x1881539A /* 970 */}, { 0x6BD52457, 0x5103F3F7 /* 971 */}, { 0xAE47F7A8, 0x15B7E6F5 /* 972 */}, { 0xD47E9CCF, 0xDBD7C6DE /* 973 */}, { 0x0228BB1A, 0x44E55C41 /* 974 */}, { 0x5EDB4E99, 0xB647D425 /* 975 */}, { 0xB8AAFC30, 0x5D11882B /* 976 */}, { 0x29D3212A, 0xF5098BBB /* 977 */}, { 0xE90296B3, 0x8FB5EA14 /* 978 */}, { 0x57DD025A, 0x677B9421 /* 979 */}, { 0xA390ACB5, 0xFB58E7C0 /* 980 */}, { 0x83BD4A01, 0x89D3674C /* 981 */}, { 0x4BF3B93B, 0x9E2DA4DF /* 982 */}, { 0x8CAB4829, 0xFCC41E32 /* 983 */}, { 0xBA582C52, 0x03F38C96 /* 984 */}, { 0x7FD85DB2, 0xCAD1BDBD /* 985 */}, { 0x6082AE83, 0xBBB442C1 /* 986 */}, { 0xA5DA9AB0, 0xB95FE86B /* 987 */}, { 0x3771A93F, 0xB22E0467 /* 988 */}, { 0x493152D8, 0x845358C9 /* 989 */}, { 0x97B4541E, 0xBE2A4886 /* 990 */}, { 0xD38E6966, 0x95A2DC2D /* 991 */}, { 0x923C852B, 0xC02C11AC /* 992 */}, { 0x0DF2A87B, 0x2388B199 /* 993 */}, { 0x1B4F37BE, 0x7C8008FA /* 994 */}, { 0x4D54E503, 0x1F70D0C8 /* 995 */}, { 0x7ECE57D4, 0x5490ADEC /* 996 */}, { 0xD9063A3A, 0x002B3C27 /* 997 */}, { 0x8030A2BF, 0x7EAEA384 /* 998 */}, { 0xED2003C0, 0xC602326D /* 999 */}, { 0x69A94086, 0x83A7287D /* 1000 */}, { 0x30F57A8A, 0xC57A5FCB /* 1001 */}, { 0x79EBE779, 0xB56844E4 /* 1002 */}, { 0x05DCBCE9, 0xA373B40F /* 1003 */}, { 0x88570EE2, 0xD71A786E /* 1004 */}, { 0xBDE8F6A0, 0x879CBACD /* 1005 */}, { 0xC164A32F, 0x976AD1BC /* 1006 */}, { 0x9666D78B, 0xAB21E25E /* 1007 */}, { 0xE5E5C33C, 0x901063AA /* 1008 */}, { 0x48698D90, 0x9818B344 /* 1009 */}, { 0x3E1E8ABB, 0xE36487AE /* 1010 */}, { 0x893BDCB4, 0xAFBDF931 /* 1011 */}, { 0x5FBBD519, 0x6345A0DC /* 1012 */}, { 0x9B9465CA, 0x8628FE26 /* 1013 */}, { 0x3F9C51EC, 0x1E5D0160 /* 1014 */}, { 0xA15049B7, 0x4DE44006 /* 1015 */}, { 0xF776CBB1, 0xBF6C70E5 /* 1016 */}, { 0xEF552BED, 0x411218F2 /* 1017 */}, { 0x705A36A3, 0xCB0C0708 /* 1018 */}, { 0x4F986044, 0xE74D1475 /* 1019 */}, { 0x0EA8280E, 0xCD56D943 /* 1020 */}, { 0x535F5065, 0xC12591D7 /* 1021 */}, { 0x720AEF96, 0xC83223F1 /* 1022 */}, { 0x7363A51F, 0xC3A0396F /* 1023 */} }; #else void dummy_2 (int a) { (void) a; return; } #endif samhain-4.1.4/src/sh_utils.c0000644000175000017500000015457512703402717012672 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #include "samhain.h" #include "sh_error.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_tiger.h" #include "sh_entropy.h" #include "sh_pthread.h" #undef FIL__ #define FIL__ _("sh_utils.c") UINT32 ErrFlag[2]; int sh_util_flagval(const char * c, int * fval) { SL_ENTER(_("sh_util_flagval")); if (c == NULL) SL_RETURN( (-1), _("sh_util_flagval")); if ( c[0] == '1' || c[0] == 'y' || c[0] == 'Y' || c[0] == 't' || c[0] == 'T') { *fval = S_TRUE; SL_RETURN( (0), _("sh_util_flagval")); } if ( c[0] == '0' || c[0] == 'n' || c[0] == 'N' || c[0] == 'f' || c[0] == 'F') { *fval = S_FALSE; SL_RETURN( (0), _("sh_util_flagval")); } SL_RETURN( (-1), _("sh_util_flagval")); } int sh_util_timeout_check (SH_TIMEOUT * sh_timer) { UINT64 now = (UINT64) time(NULL); UINT64 dif; if (sh_timer->flag_ok == S_FALSE) { /* first time */ if (sh_timer->time_last == 0) { sh_timer->time_last = now; return S_TRUE; } /* later on */ dif = now - sh_timer->time_last; if (dif < sh_timer->time_dist) { return S_FALSE; } sh_timer->time_last = now; return S_TRUE; } sh_timer->time_last = now; return S_FALSE; } static int sh_ask_update = S_FALSE; int sh_util_set_interactive(const char * str) { (void) str; sh_ask_update = S_TRUE; sh_unix_setnodeamon(NULL); return 0; } static char * sh_update_file = NULL; int sh_util_update_file (const char * str) { if (str) { if (0 == access(str, R_OK)) /* flawfinder: ignore */ { if (NULL != sh_update_file) SH_FREE(sh_update_file); sh_update_file = sh_util_strdup(str); sh_ask_update = S_TRUE; sh_unix_setnodeamon(NULL); return 0; } else { char ebuf[SH_ERRBUF_SIZE]; int errnum = errno; sh_error_message(errnum, ebuf, sizeof(ebuf)); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("sh_util_update_file") ); return -1; } } return -1; } #if !defined(STDIN_FILENO) #define STDIN_FILENO 0 #endif #if !defined(STDERR_FILENO) #define STDERR_FILENO 0 #endif /* Returns S_FALSE if no update desired */ int sh_util_update_checkfile(const char * path) { FILE * fd = fopen(sh_update_file, "r"); char * line; if (!fd) { uid_t euid; int errnum = errno; sl_get_euid(&euid); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_NOACCESS, (long) euid, sh_update_file); aud_exit (FIL__, __LINE__, EXIT_FAILURE); return S_FALSE; } line = SH_ALLOC(8192); while (NULL != fgets(line, 8192, fd)) { char * nl = strrchr(line, '\n'); if (nl) { *nl = '\0'; /* Check for MS Windows line terminator */ if (nl > line) --nl; if (*nl == '\r') *nl = '\0'; } if (0 == sl_strcmp(line, path)) { SH_FREE(line); fclose(fd); return S_TRUE; } } SH_FREE(line); fclose(fd); return S_FALSE; } /* Returns S_FALSE if no update desired */ int sh_util_ask_update(const char * path) { int inchar, c; int i = S_TRUE; char * tmp = NULL; SL_ENTER(_("sh_util_ask_update")); if (sh_ask_update != S_TRUE) { SL_RETURN(i, _("sh_util_ask_update")); } if (sh_update_file) { i = sh_util_update_checkfile(path); SL_RETURN(i, _("sh_util_ask_update")); } #ifdef HAVE_TTYNAME if (!ttyname(STDIN_FILENO)) { if (NULL != ttyname(STDERR_FILENO)) { /* cppcheck-suppress leakReturnValNotUsed */ if (NULL == freopen(ttyname(STDERR_FILENO), "r", stdin)) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Cannot continue: stdin is not a terminal"), _("sh_util_ask_update")); exit(EXIT_FAILURE); } } else { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Cannot continue: stdin is not a terminal"), _("sh_util_ask_update")); exit(EXIT_FAILURE); } } #endif if (sh_ask_update == S_TRUE) { tmp = sh_util_safe_name (path); fprintf (stderr, _("Update %s [Y/n] ? "), tmp); SH_FREE(tmp); while (1 == 1) { c = fgetc(stdin); inchar = c; /*@+charintliteral@*/ while (c != '\n' && c != EOF) c = fgetc(stdin); /* fprintf(stderr, "CHAR (1): %c\n", inchar); */ if (inchar == 'Y' || inchar == 'y' || inchar == '\n') { break; } else if (inchar == 'n' || inchar == 'N') { i = S_FALSE; break; } else { fprintf(stderr, "%s", _("Please answer y(es) or n(o)\n")); } /*@-charintliteral@*/ } } SL_RETURN(i, _("sh_util_ask_update")); } int sh_util_hidesetup(const char * c) { int i; SL_ENTER(_("sh_util_hidesetup")); i = sh_util_flagval(c, &(sh.flag.hidefile)); SL_RETURN(i, _("sh_util_hidesetup")); } char * sh_util_acl_compact(char * buf, ssize_t len) { unsigned char * p = (unsigned char *) buf; int state = 0; ssize_t rem = 0; char * out; SH_VALIDATE_NE(buf, NULL); SH_VALIDATE_GE(len, 0); out = SH_ALLOC(len + 1); while (*p != '\0') { /* -- not at start or after newline */ if (state == 1) { if (*p == '\n' || *p == ' ' || *p == '\t' || *p == '#') { while (*p != '\n') { ++p; if (*p == '\0') { goto exit_it; } } out[rem] = ','; ++rem; /* <-- ensures (rem > 0) is true */ while (p[1] == '\n') ++p; /* scan over consecutive newlines */ state = 0; if (p[1] == '\0') { out[rem-1] = '\0'; /* rem > 0 because of 4 lines above */ break; } } else { if (*p <= 0x7F && isgraph((int) *p)) { out[rem] = (char) *p; ++rem; } } } /* -- at start or after newline */ else /* if (state == 0) */ { if (0 == strncmp((char *) p, "user", 4)) { out[rem] = 'u'; ++rem; p += 3; } else if (0 == strncmp((char *) p, "group", 5)) { out[rem] = 'g'; ++rem; p += 4; } else if (0 == strncmp((char *) p, "mask", 4)) { out[rem] = 'm'; ++rem; p += 3; } else if (0 == strncmp((char *) p, "other", 5)) { out[rem] = 'o'; p += 4; ++rem; } else if (*p == '\0') { if (rem > 0) { out[rem-1] = '\0'; } break; } else { if (*p <= 0x7F && isprint((int) *p)) { out[rem] = (char) *p; ++rem; } } state = 1; } ++p; } exit_it: out[rem] = '\0'; return out; } char * sh_util_strdup_l (const char * str, size_t len) { char * p = NULL; SL_ENTER(_("sh_util_strdup_l")); SH_VALIDATE_NE(str, NULL); SH_VALIDATE_NE(len, 0); if (str && sl_ok_adds (len, 1)) { p = SH_ALLOC (len + 1); (void) memcpy (p, str, len+1); } else { safe_fatal(_("integer overflow in sh_util_strdup_l"), FIL__, __LINE__); } SL_RETURN( p, _("sh_util_strdup_l")); } char * sh_util_strdup (const char * str) { char * p = NULL; size_t len; SL_ENTER(_("sh_util_strdup")); SH_VALIDATE_NE(str, NULL); if (str) { len = sl_strlen(str); p = SH_ALLOC (len + 1); (void) memcpy (p, str, len+1); } SL_RETURN( p, _("sh_util_strdup")); } char * sh_util_strdup_track (const char * str, char * file, int line) { char * p = NULL; size_t len; SL_ENTER(_("sh_util_strdup_track")); SH_VALIDATE_NE(str, NULL); if (str) { len = sl_strlen(str); p = SH_OALLOC (len + 1, file, line); (void) memcpy (p, str, len+1); } SL_RETURN( p, _("sh_util_strdup_track")); } /* by the eircom.net computer incident * response team */ char * sh_util_strsep (char **str, const char *delim) { char *ret, *c; const char *d; SL_ENTER(_("sh_util_strsep")); ret = *str; SH_VALIDATE_NE(ret, NULL); if (*str) { for (c = *str; *c != '\0'; c++) { for (d = delim; *d != '\0'; d++) { if (*c == *d) { *c = '\0'; *str = c + 1; SL_RETURN(ret, _("sh_util_strsep")); } } } } /* If we get to here, there's no delimiters in the string */ *str = NULL; SL_RETURN(ret, _("sh_util_strsep")); } /* returned string must be free'd by caller. */ char * sh_util_formatted (const char * formatt, st_format * ftab) { struct tm * time_ptr; size_t size; size_t isiz; char * fmt = NULL; char * p; char * q; char * outstr; int i; int j; time_t inpp; char * clist[16] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int nn = 0; SL_ENTER(_("sh_util_formatted")); if (formatt == NULL || ftab == NULL || *formatt == '\0') SL_RETURN(NULL, _("sh_util_formatted")); /* -- save the format (we overwrite it !!) -- */ size = sl_strlen(formatt); if (!sl_ok_adds(size, 1)) SL_RETURN(NULL, _("sh_util_formatted")); ++size; fmt = SH_ALLOC(size); (void) sl_strlcpy(fmt, formatt, size); p = fmt; j = 0; while (ftab[j].fchar != '\0') { if (ftab[j].type != S_FMT_STRING) ftab[j].data_str = NULL; ++j; } while (p != NULL && *p != '\0' && NULL != (q = strchr(p, '%'))) { ++q; /* fprintf(stderr, "p == %s q == %s\n", p, q); */ /* -- end of string is a '%' -- */ if (*q == '\0') { --q; *q = '\0'; break; } i = 0; j = 0; /* -- search the format char in input table -- * put (nn < 16) here -> all remaining %foo will be * converted to %% */ while (ftab[j].fchar != '\0' && nn < 16) { if (ftab[j].fchar == *q) { /* -- Convert it to a string format (%s). -- */ *q = 's' ; i = 1; switch(ftab[j].type) { case S_FMT_STRING: { isiz = sl_strlen(ftab[j].data_str); if (isiz > 0 && sl_ok_adds(size, isiz)) { size += isiz; clist[nn] = ftab[j].data_str; ++nn; } else *q = '%'; goto endsrch; } break; case S_FMT_ULONG: { ftab[j].data_str = (char *) SH_ALLOC(64); /*@-bufferoverflowhigh@*/ sprintf (ftab[j].data_str, "%lu", /* known to fit */ ftab[j].data_ulong); /*@+bufferoverflowhigh@*/ isiz = sl_strlen(ftab[j].data_str); if (isiz > 0 && sl_ok_adds(size, isiz)) { size += isiz; clist[nn] = ftab[j].data_str; ++nn; } else *q = '%'; goto endsrch; } break; case S_FMT_LONG: { ftab[j].data_str = (char *) SH_ALLOC(64); /*@-bufferoverflowhigh@*/ sprintf (ftab[j].data_str, "%ld", /* known to fit */ ftab[j].data_long); /*@+bufferoverflowhigh@*/ isiz = sl_strlen(ftab[j].data_str); if (isiz > 0 && sl_ok_adds(size, isiz)) { size += isiz; clist[nn] = ftab[j].data_str; ++nn; } else *q = '%'; goto endsrch; } break; case S_FMT_TIME: { ftab[j].data_str = (char *) SH_ALLOC(64); inpp = (time_t)ftab[j].data_ulong; if (inpp != 0) { time_ptr = localtime (&(inpp)); if (time_ptr != NULL) (void) strftime(ftab[j].data_str, 64, _("%d-%m-%Y %H:%M:%S"), time_ptr); else (void) sl_strlcpy(ftab[j].data_str, _("00-00-0000 00:00:00"), 64); } else { (void) sl_strlcpy(ftab[j].data_str, _("(None)"), 64); } isiz = sl_strlen(ftab[j].data_str); if (isiz > 0 && sl_ok_adds(size, isiz)) { size += isiz; clist[nn] = ftab[j].data_str; ++nn; } else *q = '%'; goto endsrch; } break; default: /* do nothing */; } } ++j; } endsrch: p = q; /* -- not found -- */ if (i == 0) { *q = '%'; ++p; } } /* -- Format string evaluated. clist[] List of strings size Total size of format string + clist[] strings -- */ /* -- closing '\0' -- */ if (sl_ok_adds(size, 1)) size++; outstr = (char *) SH_ALLOC(size); /* -- print it -- */ (void) sl_snprintf( outstr, size, fmt, clist[0], clist[1], clist[2], clist[3], clist[4], clist[5], clist[6], clist[7], clist[8], clist[9], clist[10], clist[11], clist[12], clist[13], clist[14], clist[15]); outstr[size-1] = '\0'; /* -- cleanup -- */ j = 0; while (ftab[j].fchar != '\0') { if (ftab[j].type != S_FMT_STRING && ftab[j].data_str != NULL) SH_FREE(ftab[j].data_str); ++j; } SH_FREE(fmt); SL_RETURN(outstr, _("sh_util_formatted")); } /* read a hexchar, return int value (0-15) * can't inline (AIX) */ int sh_util_hexchar( const char c ) { /*@+charint@*/ if ( c >= '0' && c <= '9' ) return c - '0'; else if ( c >= 'a' && c <= 'f' ) return c - 'a' + 10; else if ( c >= 'A' && c <= 'F' ) return c - 'A' + 10; else return -1; /*@-charint@*/ } char * sh_util_charhex( unsigned char i , char * i2h) { int j, k; j = i / 16; k = i - (j*16); if (j < 10) i2h[0] = '0'+j; else i2h[0] = 'A'+(j-10); if (k < 10) i2h[1] = '0'+k; else i2h[1] = 'A'+(k-10); return i2h; } /* read a hexadecimal key, convert to binary */ int sh_util_hextobinary (char * binary, const char * hex, int bytes) { int i = 0, j, k, l = 0; char c; #define SH_HEXCHAR(x, y) \ c = (x); \ if ( c >= '0' && c <= '9' ) \ y = c - '0'; \ else if ( c >= 'a' && c <= 'f' ) \ y = c - 'a' + 10; \ else if ( c >= 'A' && c <= 'F' ) \ y = c - 'A' + 10; \ else \ SL_RETURN((-1), _("sh_util_hextobinary")) SL_ENTER(_("sh_util_hextobinary")); if (bytes < 2) SL_RETURN((-1), _("sh_util_hextobinary")); while (i < (bytes-1)) { SH_HEXCHAR(hex[i], k); SH_HEXCHAR(hex[i+1], j); binary[l] = (char)(k * 16 + j); ++l; i+= 2; } SL_RETURN((0), _("sh_util_hextobinary")); } static void copy_four (unsigned char * dest, UINT32 in) { UINT32 i, j; int count; SL_ENTER(_("copy_four")); for (count = 0; count < 4; ++count) { i = in / 256; j = in - (i*256); dest[count] = (unsigned char) j; in = i; } SL_RET0(_("copy_four")); } /* compute HMAC-TIGER */ static char * sh_util_hmac_tiger (char * hexkey, char * text, size_t textlen, char * res, size_t len) { static char opad[KEY_BLOCK] = { (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C }; static char ipad[KEY_BLOCK] = { (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36 }; static char zap[KEY_BLOCK] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00 }; char K[KEY_BLOCK]; char outer[KEY_BLOCK]; char * inner; UINT32 * h1; UINT32 * h2; UINT32 cc[KEY_LEN/4]; UINT32 kbuf[KEY_BYT/sizeof(UINT32)]; char hashbuf[KEYBUF_SIZE]; int result; size_t i; SL_ENTER(_("sh_util_hmac_tiger")); ASSERT((KEY_BLOCK <= (KEY_LEN/2)), _("KEY_BLOCK <= (KEY_LEN/2)")); memcpy (K, zap, KEY_BLOCK); result = sh_util_hextobinary (K, hexkey, KEY_LEN); ASSERT((result >= 0), _("result >= 0")); if ((result >= 0) && sl_ok_adds(textlen, KEY_BLOCK)) { inner = (char *) SH_ALLOC (textlen + KEY_BLOCK); for (i = 0; i < KEY_BLOCK; ++i) { outer[i] = K[i] ^ opad[i]; inner[i] = K[i] ^ ipad[i]; } for (i = KEY_BLOCK; i < (KEY_BLOCK+textlen); ++i) { inner[i] = text[i - KEY_BLOCK]; } } else { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("integer overflow"), _("sh_util_hmac_tiger")); (void) sh_tiger_hash (NULL, TIGER_DATA, 0, hashbuf, sizeof(hashbuf)); sl_strlcpy(res, hashbuf, len); SL_RETURN(res, _("sh_util_hmac_tiger")); } /* now compute the hash */ h1 = sh_tiger_hash_uint32 ( outer, TIGER_DATA, KEY_BLOCK, kbuf, KEY_BYT/sizeof(UINT32)); for (i = 0; i < (KEY_LEN/8); ++i) copy_four ( (unsigned char *) &(cc[i]), h1[i]); h2 = sh_tiger_hash_uint32 ( inner, TIGER_DATA, (unsigned long) KEY_BLOCK+textlen, kbuf, KEY_BYT/sizeof(UINT32)); for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i) copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]); SH_FREE(inner); (void) sh_tiger_hash ((char *) &cc[0], TIGER_DATA, (unsigned long) (KEY_LEN/4 * sizeof(UINT32)), hashbuf, sizeof(hashbuf)); sl_strlcpy(res, hashbuf, len); SL_RETURN(res, _("sh_util_hmac_tiger")); } static char * sh_util_hash_tiger ( char * hexkey, char * text, size_t textlen, char * res, size_t len) { char h2[2*KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_util_hash_tiger")); (void) sl_strlcpy(h2, hexkey, KEY_LEN+1); (void) sl_strlcat(h2, sh_tiger_hash(text, TIGER_DATA, (unsigned long) textlen, hashbuf, sizeof(hashbuf)), 2*KEY_LEN+1 ); (void) sh_tiger_hash(h2, TIGER_DATA, 2*KEY_LEN, hashbuf, sizeof(hashbuf)); sl_strlcpy(res, hashbuf, len); SL_RETURN(res, _("sh_util_hash_tiger")); } /* --- compute signature on data --- */ #define TYPE_HMAC 0 #define TYPE_HASH 1 static int sigtype = TYPE_HMAC; int sh_util_sigtype (const char * c) { SL_ENTER(_("sh_util_sigtype")); if (c == NULL) SL_RETURN( -1, _("sh_util_sigtype")); if (0 == strcmp(_("HMAC-TIGER"), c)) sigtype = TYPE_HMAC; else if (0 == strcmp(_("HASH-TIGER"), c)) sigtype = TYPE_HASH; else SL_RETURN( -1, _("sh_util_sigtype")); SL_RETURN( 0, _("sh_util_sigtype")); } char * sh_util_siggen (char * hexkey, char * text, size_t textlen, char * res, size_t len) { char * p; SL_ENTER(_("sh_util_siggen")); if (sigtype == TYPE_HMAC) p = sh_util_hmac_tiger (hexkey, text, textlen, res, len); else p = sh_util_hash_tiger (hexkey, text, textlen, res, len); SL_RETURN(p, _("sh_util_siggen")); } /* a simple compressor */ size_t sh_util_compress (char * dest, char * src, size_t dest_size) { char * add; char * get; size_t count = 0; size_t dest_end; SL_ENTER(_("sh_util_compress")); if (dest_size == 0) SL_RETURN((0), _("sh_util_compress")); if ((dest == NULL) || (src == NULL)) SL_RETURN((0), _("sh_util_compress")); dest_end = sl_strlen(dest); if (dest_end > dest_size) SL_RETURN((0), _("sh_util_compress")); add = &dest[dest_end]; get = src; while (count < (dest_size-dest_end)) { if (isalnum((int) *get)) { *add = *get; ++add; ++count; } ++get; if (*get == '\0' && (count < (dest_size-dest_end))) /* end of src reached */ { *add = *get; /* copy the '\0' */ break; /* and stop copying */ } } dest[dest_size-1] = '\0'; /* paranoia */ SL_RETURN((count), _("sh_util_compress")); /* no of chars copied */ } /* copy the four least significant bytes */ void sh_util_cpylong (char * dest, const char * src, int len ) { int i, j; union { long l; char c[sizeof(long)]; } u; #ifdef WORDS_BIGENDIAN unsigned char swap; unsigned char * ii = (unsigned char *) dest; #endif SL_ENTER(_("sh_util_cpylong")); u.l = 1; /* MSB is first */ if (sizeof(long)>4 &&/*@+charint@*/(u.c[sizeof(long)-1] == 1)/*@-charint@*/) { j = (int) (sizeof(long)-4); for (i = 0; i < j; ++i) ++src; } i = 0; while (i < 4) { *dest = (*src); ++dest; ++src; if (i == (len-1)) break; ++i; } #ifdef WORDS_BIGENDIAN swap = ii[0]; ii[0] = ii[3]; ii[3] = swap; swap = ii[1]; ii[1] = ii[2]; ii[2] = swap; #endif SL_RET0(_("sh_util_cpylong")); } /* This is a maximally equidistributed combined Tausworthe * generator. The sequence is, * * x_n = (s1_n ^ s2_n ^ s3_n) * * s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19)) * s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25)) * s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11)) * * computed modulo 2^32. In the three formulas above '^' means * exclusive-or (C-notation), not exponentiation. Note that the * algorithm relies on the properties of 32-bit unsigned integers (it * is formally defined on bit-vectors of length 32). * * Stolen from GSL (GNU scientific library) and modified somewhat. * I am using UINT32, which is guaranteed to be 32 bits. Also made * sure that the initialization vector is valid. */ /* interval [0, 4294967295] */ static UINT32 taus_get_long (void *vstate) { UINT32 * state = (UINT32 *) vstate; /* if (skey->rngI == BAD) (void)taus_seed(); */ #define TAUSWORTHE(s,a,b,c,d) ((s &c) <>b) /*@+ignorequals@*/ state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12); state[1] = TAUSWORTHE (state[1], 2, 25, 4294967288UL, 4); state[2] = TAUSWORTHE (state[2], 3, 11, 4294967280UL, 17); /*@-ignorequals@*/ return (state[0] ^ state[1] ^ state[2]); } /* Hide the internal state of the PRNG by using its output as * input for a one-way hash function. */ UINT32 taus_get () { #define TAUS_SAMPLE 12 UINT32 taus_svec[TAUS_SAMPLE]; UINT32 retval; UINT32 * res; UINT32 * res_vec = &(skey->res_vec[0]); static int res_num = 0; register int i; UINT32 kbuf[KEY_BYT/sizeof(UINT32)]; SH_MUTEX_LOCK_UNSAFE(mutex_skey); if (res_num > 0) { retval = res_vec[res_num]; res_num = (res_num == 5) ? 0 : (res_num + 1); SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); /* alternative path */ return retval; } SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); (void)taus_seed(); SH_MUTEX_LOCK_UNSAFE(mutex_skey); for (i = 0; i < (TAUS_SAMPLE/3); ++i) { taus_svec[i*3] = taus_get_long (&(skey->rng0[0])); taus_svec[i*3+1] = taus_get_long (&(skey->rng1[0])); taus_svec[i*3+2] = taus_get_long (&(skey->rng2[0])); } SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); res = sh_tiger_hash_uint32 ( (char *) &taus_svec[0], TIGER_DATA, (unsigned long)(TAUS_SAMPLE * sizeof(UINT32)), kbuf, KEY_BYT/sizeof(UINT32)); SH_MUTEX_LOCK_UNSAFE(mutex_skey); for (i = 1; i < 6; ++i) { res_vec[i] = res[i]; } retval = res[0]; res_num = 1; SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); memset(taus_svec, '\0', TAUS_SAMPLE * sizeof(UINT32)); return retval; } /* interval [0,1) */ double taus_get_double (void *vstate) { return taus_get_long (vstate) / (4294967296.0 + 1.0) ; } #define LCG(n) ((69069 * n) & 0xffffffffUL) /* TAKE CARE: state[0], state[1], state[2] must be > 2,8,16, respectively */ static void taus_set_from_ulong (void *vstate, unsigned long int s) { UINT32 *state = (UINT32 *) vstate; if (s == 0) s = 1; /* default seed is 1 */ state[0] = (UINT32)(LCG (s) | (UINT32) 0x03); state[1] = (UINT32)(LCG (state[0]) | (UINT32) 0x09); state[2] = (UINT32)(LCG (state[1]) | (UINT32) 0x17); /* 'warm up' */ (void) taus_get_long (state); (void) taus_get_long (state); (void) taus_get_long (state); (void) taus_get_long (state); (void) taus_get_long (state); (void) taus_get_long (state); return; } static void taus_set_from_state (void *vstate, void *init_state) { UINT32 *state = (UINT32 *) vstate; UINT32 *state0 = (UINT32 *) init_state; state[0] = state0[0] | (UINT32) 0x03; state[1] = state0[1] | (UINT32) 0x09; state[2] = state0[2] | (UINT32) 0x17; return; } int taus_seed () { char bufx[9 * sizeof(UINT32) + 1]; int status; static unsigned long seed_time = 0; static unsigned long seed_counter = 3000; unsigned long gtime; SL_ENTER(_("taus_seed")); if (skey->rngI == GOOD) { ++seed_counter; if ( ((sh_unix_longtime () - seed_time) < 1800) && ( seed_counter < 3000)) SL_RETURN( (0), _("taus_seed")); } seed_time = sh_unix_longtime (); seed_counter = 0; status = sh_entropy (24, bufx); if (!SL_ISERROR(status)) { SH_MUTEX_LOCK_UNSAFE(mutex_skey); memcpy (&skey->rng0[0], &bufx[0], 2*sizeof(UINT32)); memcpy (&skey->rng1[0], &bufx[2*sizeof(UINT32)], 2*sizeof(UINT32)); memcpy (&skey->rng2[0], &bufx[4*sizeof(UINT32)], 2*sizeof(UINT32)); memset (bufx, 0, 9 * sizeof(UINT32) + 1); skey->rng0[2] = 0; skey->rng1[2] = 0; skey->rng2[2] = 0; taus_set_from_state( &(skey->rng0[0]), &(skey->rng0[0])); taus_set_from_state( &(skey->rng1[0]), &(skey->rng1[0])); taus_set_from_state( &(skey->rng2[0]), &(skey->rng2[0])); skey->rngI = GOOD; SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); SL_RETURN( (0), _("taus_seed")); } sh_error_handle ((-1), FIL__, __LINE__, status, MSG_ES_ENT, _("sh_entropy")); /* emergency backup - unsafe ! */ #ifdef HAVE_GETTIMEOFDAY gtime = sh_unix_notime(); #else gtime = seed_time; #endif SH_MUTEX_LOCK_UNSAFE(mutex_skey); taus_set_from_ulong ( &(skey->rng0[0]), LCG (gtime) ); taus_set_from_ulong ( &(skey->rng1[0]), LCG (skey->rng0[0]) ); taus_set_from_ulong ( &(skey->rng2[0]), LCG (skey->rng1[0]) ); skey->rngI = BAD; SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); SL_RETURN( (-1), _("taus_seed")); } /*@+charint@*/ static unsigned char new_key[] = { 0xA7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xA7 }; /*@-charint@*/ static void copy_four (unsigned char * dest, UINT32 in); int sh_util_set_newkey (const char * new_in) { size_t i, j = 0; size_t len; SL_TICKET fp; SL_TICKET fout; char * key; char * path = NULL; char * outpath = NULL; unsigned char * image = NULL; long s = 0; long ilen = 0; long ii, k = 0; UINT32 * h1; char * new = NULL; if (0 != sl_is_suid()) { fprintf(stderr, "%s", _("ERROR: insufficient privilege\n")); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; /* braindead MAC OSX compiler needs this */ } if (new_in == NULL || new_in[0] == '\0') { fprintf(stderr, "%s", _("ERROR: no key given\n Argument must be 'key@path'\n")); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; } if (NULL == (new = calloc(1,strlen(new_in) + 1))) goto bail_mem; sl_strncpy(new, new_in, strlen(new_in) + 1); key = new; len = strlen(new); for (i = 1; i < (len-2); ++i) { if (new[i] == '@' && new[i+1] == '/') { j = i+1; new[i] = '\0'; break; } } if (j == 0) { fprintf(stderr, "%s", _("ERROR: no path to executable given\n Argument must be 'key@path'\n")); free(new); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; } else path = &new[j]; len = strlen(path) + 1 + 4; /*@-usedef@*/ if (NULL == (outpath = calloc(1,len))) goto bail_mem; /*@-usedef@*/ sl_snprintf (outpath, len, _("%s.out"), path); fp = sl_open_read(FIL__, __LINE__, path, SL_NOPRIV); if (SL_ISERROR(fp)) { fprintf(stderr, _("ERROR: cannot open %s for read (errnum = %ld)\n"), path, fp); free(new); free (outpath); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; } fout = sl_open_write(FIL__, __LINE__, outpath, SL_NOPRIV); if (SL_ISERROR(fout)) { fprintf(stderr, _("ERROR: cannot open %s (errnum = %ld)\n"), outpath, fout); free(new); free (outpath); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; } image = calloc(1,4096); if (!image) goto bail_mem; while (0 < (ii = sl_read (fp, &image[s], 4096))) { unsigned char * ptr; ilen += ii; s += 4096; ptr = realloc (image, (size_t) (4096 + s)); if (ptr) image = ptr; else { free(image); image = NULL; } if (!image) goto bail_mem; } printf(_("%ld bytes read\n"), ilen); for (k = 0; k < (ilen - 8); ++k) { if (image[k] == new_key[0] && image[k+1] == new_key[1] && image[k+2] == new_key[2] && image[k+3] == new_key[3] && image[k+4] == new_key[4] && image[k+5] == new_key[5] && image[k+6] == new_key[6] && image[k+7] == new_key[7]) { UINT32 kbuf[KEY_BYT/sizeof(UINT32)]; printf("%s", _("old key found\n")); h1 = sh_tiger_hash_uint32 (key, TIGER_DATA, (unsigned long)strlen(key), kbuf, KEY_BYT/sizeof(UINT32)); copy_four( (unsigned char *) &(image[k]), h1[0]); copy_four( (unsigned char *) &(image[k+4]), h1[1]); (void) sl_write (fout, image, ilen); (void) sl_close (fout); printf(_("new file %s written\n"), outpath); free(new); free (outpath); free(image); _exit (EXIT_SUCCESS); /*@notreached@*/ return 0; } } fprintf(stderr, "%s", _("ERROR: old key not found\n")); free(new); free (outpath); free(image); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; bail_mem: fprintf(stderr, "%s", _("ERROR: out of memory\n")); if (new) free(new); if (outpath) free (outpath); if (image) free (image); _exit (EXIT_FAILURE); /*@notreached@*/ return -1; } /* A simple en-/decoder, based on Vernam cipher. We use the * message as salt to hide the key by obtaining a different one-time * pad each time. * Should be safe against a listener on the network, but not against someone * with read access to the binary. */ void sh_util_encode (char * data, char * salt, int mode, char fill) { static char cc1[17] = N_("0123456789ABCDEF"); char cc[17] = "\0"; register int i, j, j1 = 0, j2 = 0, j3; char * dez; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_util_encode")); /* init */ (void) sl_strlcpy( cc, _(cc1), sizeof(cc)); /* max 128 bits keyspace */ memset (skey->vernam, (int)fill, KEY_LEN+1); dez = (char *) &(skey->ErrFlag[0]); sh_util_cpylong (skey->vernam, dez, 4); dez = (char *) &(skey->ErrFlag[1]); sh_util_cpylong (&skey->vernam[4], dez, 4); skey->vernam[KEY_LEN] = '\0'; (void) sl_strlcpy(skey->vernam, sh_tiger_hash(skey->vernam, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); (void) sl_strlcpy(skey->vernam, sh_util_hmac_tiger (skey->vernam, salt, strlen(salt), hashbuf, sizeof(hashbuf)), KEY_LEN+1); (void) sl_strlcpy(skey->vernam, sh_util_hmac_tiger (skey->vernam, (char*) new_key, 8, hashbuf, sizeof(hashbuf)), KEY_LEN+1); /* The following routine adds/subtracts data[j] and vernam[j] mod 16. */ j = 0; while (j < KEY_LEN) { for (i = 0; i < 16; ++i) { if (cc[i] == data[j]) j1 = i; if (cc[i] == skey->vernam[j]) j2 = i; } if (mode == 0) { j3 = j1 + j2; if (j3 > 15) j3 -= 16; data[j] = cc[j3]; } else { j3 = j1 - j2; if (j3 < 0) j3 += 16; data[j] = cc[j3]; } ++j; } SL_RET0(_("sh_util_encode")); } /* server mode */ int sh_util_setserver (const char * dummy) { SL_ENTER(_("sh_util_setserver")); (void) dummy; sh.flag.isserver = GOOD; SL_RETURN((0),_("sh_util_setserver")); } int sh_util_setlooptime (const char * str) { int i = atoi (str); SL_ENTER(_("sh_util_setlooptime")); if (i >= 0 && i < INT_MAX) { sh.looptime = i; SL_RETURN((0),_("sh_util_setlooptime")); } else { sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("loop time"), str); SL_RETURN((-1),_("sh_util_setlooptime")); } } #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) int sh_util_setchecksum (const char * str) { static int reject = 0; SL_ENTER(_("sh_util_setchecksum")); if (reject == 1) SL_RETURN((0), _("sh_util_setchecksum")); reject = 1; if (sl_strncmp (str, _("init"), sizeof("init")-1) == 0) { sh.flag.checkSum = SH_CHECK_INIT; } else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0) { if (S_TRUE == file_is_remote()) { sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("checksum testing"), str); SL_RETURN((-1), _("sh_util_setchecksum")); } else { sh.flag.checkSum = SH_CHECK_CHECK; sh.flag.update = S_TRUE; } } else if (sl_strncmp (str, _("check"), sizeof("check")-1) == 0) { sh.flag.checkSum = SH_CHECK_CHECK; } /* else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0) { sh.flag.checkSum = SH_CHECK_INIT; sh.flag.update = S_TRUE; } */ else if (sl_strncmp (str, _("none"), sizeof("none")-1) == 0) { sh.flag.checkSum = SH_CHECK_NONE; } else { sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("checksum testing"), str); SL_RETURN((-1), _("sh_util_setchecksum")); } SL_RETURN((0), _("sh_util_setchecksum")); } #endif /*@+charint@*/ unsigned char TcpFlag[8][PW_LEN+1] = { #if (POS_TF == 1) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 2) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 3) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 4) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 5) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 6) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 7) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 }, #if (POS_TF == 8) { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 }, #endif }; /*@-charint@*/ /* initialize a key to a random value * rev 0.8 */ int sh_util_keyinit (char * buf, long size) { UINT32 bufy[6]; int i; int status = 0; char * p; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_util_keyinit")); ASSERT((size <= KEY_LEN+1), _("size <= KEY_LEN+1")) if (size > KEY_LEN+1) size = KEY_LEN+1; /* seed / re-seed the PRNG if required */ status = taus_seed (); if (status == -1) sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_ES_KEY1, _("taus_seed")); for (i = 0; i < 6; ++i) bufy[i] = taus_get(); p = sh_tiger_hash ((char *) bufy, TIGER_DATA, (unsigned long)(6*sizeof(UINT32)), hashbuf, sizeof(hashbuf)); i = sl_strlcpy(buf, p, (size_t)size); memset (bufy, 0, 6*sizeof(UINT32)); if ((status == 0) && (!SL_ISERROR(i)) ) SL_RETURN((0),_("sh_util_keyinit")); if (SL_ISERROR(i)) sh_error_handle ((-1), FIL__, __LINE__, i, MSG_ES_KEY2, _("sl_strlcpy")); SL_RETURN((-1),_("sh_util_keyinit")); } #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) static unsigned char sh_obscure_index[256]; static int sh_obscure_no_check = S_FALSE; int sh_util_valid_utf8 (const unsigned char * str) { const int sh_val_utf8_1 = 1; const int sh_val_utf8_2 = 2; const int sh_val_utf8_3 = 3; const int sh_val_utf8_4 = 4; size_t len = strlen((const char *)str); size_t l = 0; int typ = 0; unsigned char c = '\0'; unsigned char c2[2] = { 0x00, 0x00 }; unsigned char c3[3] = { 0x00, 0x00, 0x00 }; #define SH_VAL_UTF8_1 ((c != '\0') && ((c & 0x80) == 0x00)) #define SH_VAL_UTF8_2 ((c != '\0') && ((c & 0xE0) == 0xC0)) /* 110x xxxx */ #define SH_VAL_UTF8_3 ((c != '\0') && ((c & 0xF0) == 0xE0)) /* 1110 xxxx */ #define SH_VAL_UTF8_4 ((c != '\0') && ((c & 0xF8) == 0xF0)) /* 1111 0xxx */ #define SH_VAL_UTF8_N ((c != '\0') && ((c & 0xC0) == 0x80)) /* 10xx xxxx */ #define SH_VAL_BAD ((c == '"') || (c == '\t') || (c == '\b') || \ (c == '\f') || (c == '\n') || \ (c == '\r') || (c == '\v') || iscntrl((int) c) || \ (c != ' ' && !isgraph ((int) c))) while(l < len) { c = str[l]; if (SH_VAL_UTF8_1) { if (!(SH_VAL_BAD && (sh_obscure_index[c] != 1))) { typ = sh_val_utf8_1; ++l; continue; } else { return S_FALSE; } } else if (SH_VAL_UTF8_2) { typ = sh_val_utf8_2; c2[0] = c; if ((c & 0x3e) != 0x00) /* !(overlong 2-byte seq.) */ { ++l; if (l != len) { c = str[l]; if(SH_VAL_UTF8_N) { c2[1] = c; ++l; continue; } else { return S_FALSE; } } else { return S_FALSE; } } else { return S_FALSE; /* overlong 2-byte seq. */ } } else if (SH_VAL_UTF8_3) { typ = sh_val_utf8_3; c3[0] = c; ++l; if (l == len) return S_FALSE; c = str[l]; if(!SH_VAL_UTF8_N) return S_FALSE; if (((str[l-1] & 0x1F) == 0x00) && ((c & 0x60) == 0x00)) return S_FALSE; /* overlong 3-byte seq. */ c3[1] = c; ++l; if (l == len) return S_FALSE; c = str[l]; if(!SH_VAL_UTF8_N) return S_FALSE; c3[2] = c; ++l; continue; } else if (SH_VAL_UTF8_4) { typ = sh_val_utf8_4; ++l; if (l == len) return S_FALSE; c = str[l]; if(!SH_VAL_UTF8_N) return S_FALSE; if (((str[l-1] & 0x0F) == 0x00) && ((c & 0x70) == 0x00)) return S_FALSE; /* overlong 4-byte seq. */ ++l; if (l == len) return S_FALSE; c = str[l]; if(!SH_VAL_UTF8_N) return S_FALSE; ++l; if (l == len) return S_FALSE; c = str[l]; if(!SH_VAL_UTF8_N) return S_FALSE; ++l; continue; } return S_FALSE; } /* last character is invisible (space or else) */ if (typ == sh_val_utf8_1) { if (c != ' ') return S_TRUE; else return S_FALSE; } else if (typ == sh_val_utf8_2) { if (c2[0] == 0xC2 && c2[1] == 0xA0) /* nbsp */ return S_FALSE; else return S_TRUE; } else if (typ == sh_val_utf8_3) { if (c3[0] == 0xE2) { if (c3[1] == 0x80 && c3[2] >= 0x80 && c3[2] <= 0x8F) return S_FALSE; /* various spaces, left-to-right, right-to-left */ else if (c3[1] == 0x80 && (c3[2] == 0xA8 || c3[2] == 0xA9 || c3[2] == 0xAD || c3[2] == 0xAF)) return S_FALSE; /* line sep, para sep, zw word joiner, nnbsp */ else if (c3[1] == 0x81 && (c3[2] == 0xA0 || c3[2] == 0xA1 || c3[2] == 0x9F)) return S_FALSE; /* word joiner, function app, math space */ else return S_TRUE; } else if (c3[0] == 0xE3 && c3[1] == 0x80 && c3[2] == 0x80) { return S_FALSE; /* ideographic space */ } else if (c3[0] == 0xEF && c3[1] == 0xBB && c3[2] == 0xBF) { return S_FALSE; /* zwnbsp */ } else { return S_TRUE; } } else { return S_TRUE; } } int sh_util_obscure_ok (const char * str) { unsigned long i; char * endptr = NULL; SL_ENTER(_("sh_util_obscure_ok")); if (0 == sl_strncmp("all", str, 3)) { for (i = 0; i < 255; ++i) { sh_obscure_index[i] = (unsigned char)1; } sh_obscure_no_check = S_TRUE; SL_RETURN(0, _("sh_util_obscure_ok")); } sh_obscure_no_check = S_FALSE; for (i = 0; i < 255; ++i) { sh_obscure_index[i] = (unsigned char)0; } i = strtoul (str, &endptr, 0); if (i > 255) { SL_RETURN(-1, _("sh_util_obscure_ok")); } sh_obscure_index[i] = (unsigned char)1; if (*endptr == ',') ++endptr; while (*endptr != '\0') { i = strtoul (endptr, &endptr, 0); if (i > 255) { SL_RETURN(-1, _("sh_util_obscure_ok")); } sh_obscure_index[i] = (unsigned char)1; if (*endptr == ',') ++endptr; } SL_RETURN(0, _("sh_util_obscure_ok")); } static int sh_obscure_check_utf8 = S_FALSE; int sh_util_obscure_utf8 (const char * c) { int i; SL_ENTER(_("sh_util_obscure_utf8")); i = sh_util_flagval(c, &(sh_obscure_check_utf8)); if (sh_obscure_check_utf8 == S_TRUE) sh_obscure_no_check = S_FALSE; SL_RETURN(i, _("sh_util_obscure_utf8")); } int sh_util_obscurename (ShErrLevel level, const char * name_orig, int flag) { const unsigned char * name = (const unsigned char *) name_orig; char * safe; unsigned int i; size_t len = 0; SL_ENTER(_("sh_util_obscurename")); ASSERT_RET((name != NULL), _("name != NULL"), (0)) if (sh_obscure_no_check == S_FALSE) { if (sh_obscure_check_utf8 != S_TRUE) { /* -- Check name. -- */ while (*name != '\0') { if ( (*name) > 0x7F || (*name) == '"' || (*name) == '\t' || (*name) == '\b' || (*name) == '\f' || (*name) == '\n' || (*name) == '\r' || (*name) == '\v' || iscntrl((int) *name) || ((*name) != ' ' && !isgraph ((int) *name)) ) { i = (unsigned char) *name; if (sh_obscure_index[i] != (unsigned char)1) { goto err; } } name++; ++len; } /* Check for blank at end of name */ if ((len > 0) && (name_orig[len-1] == ' ')) { goto err; } } else { if (S_FALSE == sh_util_valid_utf8(name)) { goto err; } SL_RETURN((0),_("sh_util_obscurename")); } } SL_RETURN((0),_("sh_util_obscurename")); err: if (flag == S_TRUE) { safe = sh_util_safe_name (name_orig); sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC, safe); SH_FREE(safe); } SL_RETURN((-1),_("sh_util_obscurename")); } #endif /* returns freshly allocated memory, return value should be free'd */ char * sh_util_dirname(const char * fullpath) { char * retval; size_t len; char * tmp; SL_ENTER(_("sh_util_dirname")); ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL)) ASSERT_RET ((*fullpath == '/'), _("*fullpath == '/'"), (NULL)) retval = sh_util_strdup(fullpath); tmp = retval; while (*tmp == '/') ++tmp; /* (1) only leading slashes -- return exact copy */ if (*tmp == '\0') { SL_RETURN(retval, _("sh_util_dirname")); } /* (2) there are non-slash characters, so delete trailing slashes */ len = sl_strlen (retval); /* retval[len] is terminating '\0' */ while (len > 1 && retval[len-1] == '/') /* delete trailing slash */ { retval[len-1] = '\0'; --len; } /* (3) now delete all non-slash characters up to the preceding slash */ while (len > 1 && retval[len-1] != '/') { retval[len-1] = '\0'; --len; } /* (4a) only leading slashes left, so return this */ if (&(retval[len]) == tmp) { SL_RETURN(retval, _("sh_util_dirname")); } /* (4b) strip trailing slash(es) of parent directory */ while (len > 1 && retval[len-1] == '/') { retval[len-1] = '\0'; --len; } SL_RETURN(retval, _("sh_util_dirname")); } /* returns freshly allocated memory, return value should be free'd */ char * sh_util_basename(const char * fullpath) { char * retval = NULL; const char * tmp; char * tmp2; char * c; size_t len; SL_ENTER(_("sh_util_basename")); ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL)) tmp = fullpath; while (*tmp == '/') ++tmp; if (*tmp == '\0') { retval = sh_util_strdup(fullpath); } else { tmp2 = sh_util_strdup(tmp); len = sl_strlen (tmp2); while (len > 1 && tmp2[len-1] == '/') { tmp2[len-1] = '\0'; --len; } if (tmp2) /* for llvm/clang analyzer */ { c = strrchr(tmp2, '/'); if (c) { retval = sh_util_strdup(++c); SH_FREE(tmp2); } else { retval = tmp2; } } } SL_RETURN(retval, _("sh_util_basename")); } #define SH_ESCAPE_SPACE 1 #define SH_DONT_ESCAPE_SPACE 0 char * sh_util_safe_name_int (const char * name, int escape_space); char * sh_util_safe_name (const char * name) { return sh_util_safe_name_int (name, SH_ESCAPE_SPACE); } char * sh_util_safe_name_keepspace (const char * name) { return sh_util_safe_name_int (name, SH_DONT_ESCAPE_SPACE); } /* returns freshly allocated memory, return value should be free'd */ char * sh_util_safe_name_int (const char * name, int escape_space) { register int i = 0; const char * p; char * retval; char oct[32]; char format[16]; size_t len; SL_ENTER(_("sh_util_safe_name")); if (name == NULL) { /* return an allocated array */ retval = SH_ALLOC(7); (void) sl_strlcpy(retval, _("(null)"), 7); SL_RETURN(retval, _("sh_util_safe_name")); } /* ASSERT_RET ((name != NULL), _("name != NULL"), _("NULL")) */ len = sl_strlen(name); p = name; #ifdef SH_USE_XML if (sl_ok_muls (6, len) && sl_ok_adds ((6*len), 2)) { retval = SH_ALLOC(6 * len + 2); } else { /* return an allocated array */ retval = SH_ALLOC(11); (void) sl_strlcpy(retval, _("(overflow)"), 11); SL_RETURN(retval, _("sh_util_safe_name")); } #else if (sl_ok_muls (4, len) && sl_ok_adds ((4*len), 2)) { retval = SH_ALLOC(4 * len + 2); } else { /* return an allocated array */ retval = SH_ALLOC(11); (void) sl_strlcpy(retval, _("(overflow)"), 11); SL_RETURN(retval, _("sh_util_safe_name")); } #endif (void) sl_strncpy(format, _("%c%03o"), 16); while (*p != '\0') { /* Most frequent cases first */ if ( ((*p) >= 'a' && (*p) <= 'z') || ((*p) == '/') || ((*p) == '.') || ((*p) >= '0' && (*p) <= '9') || ((*p) >= 'A' && (*p) <= 'Z')) { retval[i] = *p; } else if ( (*p) == '\\') { /* backslash */ retval[i] = '\\'; ++i; retval[i] = '\\'; } else if ( (*p) == '\n') { /* newline */ retval[i] = '\\'; ++i; retval[i] = 'n'; } else if ( (*p) == '\b') { /* backspace */ retval[i] = '\\'; ++i; retval[i] = 'b'; } else if ( (*p) == '\r') { /* carriage return */ retval[i] = '\\'; ++i; retval[i] = 'r'; } else if ( (*p) == '\t') { /* horizontal tab */ retval[i] = '\\'; ++i; retval[i] = 't'; } else if ( (*p) == '\v') { /* vertical tab */ retval[i] = '\\'; ++i; retval[i] = 'v'; } else if ( (*p) == '\f') { /* form-feed */ retval[i] = '\\'; ++i; retval[i] = 'f'; #ifdef WITH_DATABASE } else if ( (*p) == '\'') { /* single quote */ retval[i] = '\\'; ++i; retval[i] = '\''; #endif } else if ( (*p) == ' ') { /* space */ if (escape_space) { retval[i] = '\\'; ++i; retval[i] = ' '; } else { retval[i] = *p; } #ifdef SH_USE_XML } else if ( (*p) == '"') { /* double quote */ retval[i] = '&'; ++i; retval[i] = 'q'; ++i; retval[i] = 'u'; ++i; retval[i] = 'o'; ++i; retval[i] = 't'; ++i; retval[i] = ';'; } else if ( (*p) == '&') { /* ampersand */ retval[i] = '&'; ++i; retval[i] = 'a'; ++i; retval[i] = 'm'; ++i; retval[i] = 'p'; ++i; retval[i] = ';'; } else if ( (*p) == '<') { /* left angle */ retval[i] = '&'; ++i; retval[i] = 'l'; ++i; retval[i] = 't'; ++i; retval[i] = ';'; } else if ( (*p) == '>') { /* right angle */ retval[i] = '&'; ++i; retval[i] = 'g'; ++i; retval[i] = 't'; ++i; retval[i] = ';'; #else } else if ( (*p) == '"') { /* double quote */ retval[i] = '\\'; ++i; retval[i] = '\"'; #endif } else if (!isgraph ((int) *p)) { /* not printable */ /*@-bufferoverflowhigh -formatconst@*/ /* flawfinder: ignore */ sprintf(oct, format, '\\', /* known to fit */ (unsigned char) *p); /*@+bufferoverflowhigh +formatconst@*/ retval[i] = oct[0]; ++i; retval[i] = oct[1]; ++i; retval[i] = oct[2]; ++i; retval[i] = oct[3]; } else { retval[i] = *p; } ++p; ++i; } retval[i] = '\0'; SL_RETURN(retval, _("sh_util_safe_name")); } int sh_util_isnum (const char *str) { const char *p = str; SL_ENTER(_("sh_util_isnum")); ASSERT_RET ((str != NULL), _("str != NULL"), (-1)) while (p) { if (!isdigit((int) *p) ) SL_RETURN((-1), _("sh_util_isnum")); ++p; } SL_RETURN((0), _("sh_util_isnum")); } char * sh_util_strconcat (const char * arg1, ...) { size_t length, l2; char * s; char * strnew; va_list vl; SL_ENTER(_("sh_util_strconcat")); ASSERT_RET ((arg1 != NULL), _("arg1 != NULL"), (NULL)) length = sl_strlen (arg1) + 1; va_start (vl, arg1); s = va_arg (vl, char * ); while (s != NULL) { l2 = sl_strlen (s); if (sl_ok_adds(length, l2)) length += l2; else SL_RETURN(NULL, _("sh_util_strconcat")); s = va_arg (vl, char * ); } va_end (vl); if (sl_ok_adds(length, 2)) strnew = SH_ALLOC( length + 2 ); else SL_RETURN(NULL, _("sh_util_strconcat")); strnew[0] = '\0'; (void) sl_strlcpy (strnew, arg1, length + 2); va_start (vl, arg1); s = va_arg (vl, char * ); while (s) { (void) sl_strlcat (strnew, s, length + 2); s = va_arg (vl, char * ); } va_end (vl); SL_RETURN(strnew, _("sh_util_strconcat")); } static const char bto64_0[] = N_("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()"); static char bto64[65] = { '\0' }; size_t sh_util_base64_enc (unsigned char * out, const unsigned char * instr, size_t lin) { int ll; unsigned char a, b, c; size_t len = 0; size_t j = 0; start: if (bto64[0] != '\0') { if (instr /* && *instr *//* need to handle binary data */) { if (lin == 0) lin = strlen((const char *)instr); if (lin > 0) { do { ll = 0; if (len < lin) { a = *instr; ++instr; ++len; ++ll; } else { a = 0; } if (len < lin) { b = *instr; ++instr; ++len; ++ll; } else { b = 0; } if (len < lin) { c = *instr; ++instr; ++len; ++ll; } else { c = 0; } *out = bto64[ a >> 2 ]; ++j; ++out; *out = bto64[ ((a & 0x03) << 4) | ((b & 0xf0) >> 4) ]; ++j; ++out; *out = (unsigned char) (ll > 1 ? bto64[ ((b & 0x0f) << 2) | ((c & 0xc0) >> 6) ] : '?'); ++j; ++out; *out = (unsigned char) (ll > 2 ? bto64[ c & 0x3f ] : '?'); ++j; ++out; } while (len < lin); } } *out = '\0'; return j; } memcpy(bto64, _(bto64_0), 65); goto start; } size_t sh_util_base64_enc_alloc (char **out, const char *in, size_t inlen) { size_t outlen = SH_B64_SIZ(inlen); if (inlen > outlen) /* overflow */ { *out = NULL; return 0; } *out = SH_ALLOC(outlen); return sh_util_base64_enc((unsigned char *)*out, (const unsigned char *)in, inlen); } size_t sh_util_base64_dec (unsigned char *out, const unsigned char *in, size_t lin) { size_t i; unsigned char c; unsigned char b; size_t lout = 0; unsigned int w = 0; if (out && in) { if (lin == 0) lin = strlen((const char *)in); for (i = 0; i < lin; i++) { c = *in; ++in; b = 0; if ((c >= 'A') && (c <= 'Z')) { b = (c - 'A'); } else if ((c >= 'a') && (c <= 'z')) { b = (c - 'a' + 26); } else if ((c >= '0') && (c <= '9')) { b = (c - '0' + 52); } else if (c == '(' || c == '+') { b = 62; } else if (c == ')' || c == '/') { b = 63; } else if (c == '?' || c == '=') { /* last byte was written to, but will now get * truncated */ if (lout > 0) --lout; break; } if (w == 0) { *out = (b << 2) & 0xfc; ++lout; } else if (w == 1) { *out |= (b >> 4) & 0x03; ++out; *out = (b << 4) & 0xf0; ++lout; } else if (w == 2) { *out |= (b >> 2) & 0x0f; ++out; *out = (b << 6) & 0xc0; ++lout; } else if (w == 3) { *out |= b & 0x3f; ++out; } ++w; if (w == 4) { w = 0; } } *out = '\0'; } return lout; } size_t sh_util_base64_dec_alloc (unsigned char **out, const unsigned char *in, size_t lin) { size_t lout = 3 * (lin / 4) + 2; *out = SH_ALLOC(lout); return sh_util_base64_dec (*out, in, lin); } #ifdef HAVE_REGEX_H #include int sh_util_regcmp (char * regex_str, char * in_str) { #if defined(REG_ESPACE) int status = REG_ESPACE; #else int status = -1; #endif regex_t preg; char * errbuf; SL_ENTER(_("sh_util_regcmp")); status = regcomp(&preg, regex_str, REG_NOSUB|REG_EXTENDED); if (status == 0) { if ((status = regexec(&preg, in_str, 0, NULL, 0)) == 0) { regfree (&preg); SL_RETURN((0), _("sh_util_regcmp")); } } if (status != 0 && status != REG_NOMATCH) { errbuf = SH_ALLOC(BUFSIZ); (void) regerror(status, &preg, errbuf, BUFSIZ); errbuf[BUFSIZ-1] = '\0'; sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX, errbuf, regex_str); SH_FREE(errbuf); } regfree (&preg); SL_RETURN((-1), _("sh_util_regcmp")); } #endif samhain-4.1.4/src/sh_xfer_client.c0000644000175000017500000011763212615253277014034 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000, 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include /* Must be early on FreeBSD */ #include /* must be .le. than (1020 * 64) * (see sh_tools.c -- put_header) * * also: must be (N * 16), otherwise * binary files cannot be transferred encrypted * * 65280 = (1020*64) * #define TRANS_BYTES 8000 V0.8 */ #ifdef SH_ENCRYPT #define TRANS_BYTES 65120 #else #define TRANS_BYTES 65280 #endif /* timeout for session key */ #define TIMEOUT_KEY 7200 /* max time between connection attempts */ #define TIMEOUT_CON 2048 /* #undef SRP_DEBUG */ /* #define SRP_DEBUG */ #ifdef HAVE_MEMORY_H #include #endif #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_UNISTD_H #include #include #include #include #include #include #include #include #include #include #endif #ifndef FD_SET #define NFDBITS 32 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #endif /* !FD_SET */ #ifndef FD_SETSIZE #define FD_SETSIZE 32 #endif #ifndef FD_ZERO #define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p))) #endif #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) #include #endif #include #include #include #include #ifndef S_SPLINT_S #include #endif #include "sh_ipvx.h" #include "samhain.h" #include "sh_tiger.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_xfer.h" #include "sh_srp.h" #include "sh_fifo.h" #include "sh_tools.h" #include "sh_entropy.h" #include "sh_html.h" #include "sh_nmail.h" #include "sh_socket.h" #define SH_NEED_GETHOSTBYXXX #include "sh_static.h" #ifdef SH_ENCRYPT #include "rijndael-api-fst.h" char * sh_tools_makePack (unsigned char * header, int flag, char * payload, unsigned long payload_size, keyInstance * keyInstE); char * sh_tools_revertPack (unsigned char * header, int flag, char * message, keyInstance * keyInstE, unsigned long message_size); #endif /* define this if you want to debug the client/server communication */ /* #define SH_DBG_PROT 1 */ #ifdef SH_DBG_PROT #define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d)) #else #define SH_SHOWPROT(c,d) #endif /* the port client will be connecting to */ #ifndef SH_DEFAULT_PORT #define SH_DEFAULT_PORT 49777 #endif #ifndef SH_SELECT_REPEAT #define SH_SELECT_REPEAT 60 #endif #ifndef SH_HEADER_SIZE #define SH_HEADER_SIZE 7 #endif #ifndef SH_CHALLENGE_SIZE #define SH_CHALLENGE_SIZE 9 #endif #undef FIL__ #define FIL__ _("sh_xfer_client.c") extern int flag_err_debug; extern int flag_err_info; #ifndef SH_STANDALONE #if defined(WITH_TRACE) || defined(WITH_TPT) char * hu_trans(const char * ihu) { static char ohu[17]; sprintf(ohu, _("%c%03o"), '\\', /* known to fit */ (unsigned char) ihu[0]); sprintf(&(ohu[4]), _("%c%03o"), '\\', /* known to fit */ (unsigned char) ihu[1]); sprintf(&(ohu[8]), _("%c%03o"), '\\', /* known to fit */ (unsigned char) ihu[2]); sprintf(&(ohu[12]), _("%c%03o"), '\\', /* known to fit */ (unsigned char) ihu[3]); ohu[16] = '\0'; return ohu; } #endif /* #ifndef SH_STANDALONE */ #endif #if !defined(USE_SRP_PROTOCOL) void sh_passwd (char * salt, char * password, char * nounce, char *hash) { char *combi; size_t len; unsigned char * tmp = NULL; char hashbuf[KEYBUF_SIZE]; if (password == NULL) { tmp = (unsigned char *) &(skey->pw[0]); memcpy(skey->vernam, tmp, PW_LEN); sl_strlcpy (skey->vernam, sh_tiger_hash(skey->vernam, TIGER_DATA, PW_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } else if (sl_strlen(password) < PW_LEN) { fprintf(stderr, _("Password has less than %d chars !\n"), PW_LEN); _exit(EXIT_FAILURE); } else { sl_strlcpy (skey->vernam, password, KEY_LEN+1); } len = sl_strlen(salt) + 1; if (sl_ok_adds(len, sl_strlen(skey->vernam))) len += sl_strlen(skey->vernam); if (nounce != NULL && sl_ok_adds(len, sl_strlen(nounce))) len += sl_strlen(nounce); /* H(s,P) */ combi = SH_ALLOC(len); (void) sl_strlcpy (combi, salt, len); (void) sl_strlcat (combi, skey->vernam, len); if (nounce != NULL) (void) sl_strlcat (combi, nounce, len); (void) sl_strlcpy (hash, sh_tiger_hash(combi, TIGER_DATA, (unsigned long) sl_strlen(combi), hashbuf, sizeof(hashbuf)), KEY_LEN+1); SH_FREE (combi); hash[KEY_LEN] = '\0'; return; } #endif #if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) /* Server addresses in use */ static int count_dev_server = 0; void reset_count_dev_server(void) { count_dev_server = 0; return; } int sh_xfer_set_logserver (const char * address) { SL_ENTER(_("sh_xfer_set_logserver")); if (address != NULL && count_dev_server < 2 && sl_strlen(address) < SH_PATHBUF && sl_strlen(address) > 0) { if (count_dev_server == 0) (void) sl_strlcpy (sh.srvexport.name, address, SH_PATHBUF); else (void) sl_strlcpy (sh.srvexport.alt, address, SH_PATHBUF); ++count_dev_server; SL_RETURN (0, _("sh_xfer_set_logserver")); } SL_RETURN (-1, _("sh_xfer_set_logserver")); } static int xfer_send_intern (int mysocket, const int protocol, char * micro, char * msgbuf, unsigned long length, int docrypt) { unsigned long numbytes, countbytes; int flag_err = 0; unsigned char head[SH_HEADER_SIZE]; char * outbuf; #ifdef SH_ENCRYPT char * msg2buf = NULL; #else (void) docrypt; #endif SL_ENTER(_("xfer_send_intern")); #ifdef SH_ENCRYPT if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0)) { put_header (head, protocol, &length, micro); msg2buf = sh_tools_makePack (head, 0, msgbuf, length, &(skey->keyInstE)); length = (unsigned long) (256 * (unsigned int)head[1] + (unsigned int)head[2]); outbuf = msg2buf; } else { outbuf = msgbuf; put_header (head, protocol, &length, micro); } #else outbuf = msgbuf; put_header (head, protocol, &length, micro); #endif SH_SHOWPROT(head,'>'); numbytes = SH_HEADER_SIZE; countbytes = write_port (mysocket, (char *)head, numbytes, &flag_err, 300); if (countbytes == numbytes && outbuf != NULL) { numbytes = length; countbytes = write_port (mysocket, outbuf, numbytes, &flag_err, 300); } #ifdef SH_ENCRYPT if (msg2buf != NULL) SH_FREE(msg2buf); #endif if (countbytes == numbytes) SL_RETURN( 0, _("xfer_send_intern")); else SL_RETURN( flag_err, _("xfer_send_intern")); } static int xfer_send (int mysocket, const int protocol, char * micro, char * msgbuf, unsigned long length) { int i; SL_ENTER(_("xfer_send")); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); i = xfer_send_intern (mysocket, protocol, micro, msgbuf, length, S_FALSE); SL_RETURN(i, _("xfer_send")); } static int xfer_send_crypt (int mysocket, const int protocol, char * micro, char * msgbuf, unsigned long length) { int i; SL_ENTER(_("xfer_send_crypt")); #ifdef SH_ENCRYPT TPT(( 0, FIL__, __LINE__, _("msg=\n"))); #else TPT(( 0, FIL__, __LINE__, _("msg=\n"))); #endif i = xfer_send_intern (mysocket, protocol, micro, msgbuf, length, S_TRUE); SL_RETURN(i, _("xfer_send_crypt")); } /* receive answer, add a trailing NULL to terminate string * decrypt answer */ static long xfer_receive_intern (int mysocket, const int protocol, char * micro, char * msgbuf, unsigned long length, int docrypt) { unsigned long numbytes, countbytes; int flag_err = -1; unsigned char head[SH_HEADER_SIZE]; #ifndef SH_ENCRYPT (void) docrypt; #endif SL_ENTER(_("xfer_receive_intern")); #ifdef SH_ENCRYPT /* make sure length is not multiple of B_SIZ, see below */ ASSERT_RET((length % B_SIZ != 0), _("length % 16 != 0"), flag_err); #endif if (micro != NULL) micro[4] = '\0'; if (msgbuf != NULL) msgbuf[0] = '\0'; numbytes = SH_HEADER_SIZE; countbytes = read_port (mysocket, (char *)head, numbytes, &flag_err, 300); if (countbytes != numbytes) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN(flag_err, _("xfer_receive_intern")); } else if (msgbuf == NULL) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("msgbuf is NULL"), _("xfer_receive_intern")); SL_RETURN((-1), _("xfer_receive_intern")); } else if (head[0] != protocol && (head[0] & SH_PROTO_SRP) == 0) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISMATCH); SL_RETURN((-1), _("xfer_receive_intern")); } else { get_header (head, &numbytes, micro); SH_SHOWPROT(head, '<'); if (numbytes > 0) { numbytes = (numbytes > length ? length : numbytes); countbytes = read_port (mysocket, msgbuf, numbytes, &flag_err, 300); if (countbytes < length) msgbuf[countbytes] = '\0'; else msgbuf[length-1] = '\0'; if (flag_err != 0) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN((-1), _("xfer_receive_intern")); } } } #ifdef SH_ENCRYPT if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0)) { unsigned long head_length; char * tmp = SH_ALLOC((size_t)length); memcpy(tmp, msgbuf, (size_t)length); tmp = sh_tools_revertPack (head, 0, tmp, &(skey->keyInstD), countbytes); head_length = (unsigned long) (256 * (unsigned int)head[1] + (unsigned int)head[2]); /* * revertPack returns header with length <= (original_length-16), so * the following msgbuf[length] = '\0' is always safe. * Nevertheless, check for proper length. */ if (head_length <= (length-1)) length = head_length; else --length; memcpy(msgbuf, tmp, (size_t)length); msgbuf[length] = '\0'; SH_FREE(tmp); if (countbytes == numbytes) countbytes = length; /* to avoid error on return, see below */ numbytes = length; } #endif if (countbytes == numbytes) SL_RETURN(((long)numbytes), _("xfer_receive_intern")); else { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN(flag_err, _("xfer_receive_intern")); } } static long xfer_receive (int mysocket, const int protocol, char * micro, char * msgbuf, unsigned long length) { long i; SL_ENTER(_("xfer_receive")); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); i = xfer_receive_intern (mysocket, protocol, micro, msgbuf, length, S_FALSE); SL_RETURN(i, _("xfer_receive")); } static long xfer_receive_crypt (int mysocket, const int protocol, char * micro, char * msgbuf, unsigned long length) { long i; SL_ENTER(_("xfer_receive_crypt")); #ifdef SH_ENCRYPT TPT(( 0, FIL__, __LINE__, _("msg=\n"))); #else TPT(( 0, FIL__, __LINE__, _("msg=\n"))); #endif i = xfer_receive_intern (mysocket, protocol, micro, msgbuf, length, S_TRUE); SL_RETURN(i, _("xfer_receive_crypt")); } /************************************************** * * * C L I E N T * * ***************************************************/ #include static SH_FIFO * fifo = NULL; static long xfer_try_report (char * errmsg); unsigned int ServerPort = SH_DEFAULT_PORT; int sh_xfer_server_port (const char * str) { unsigned long l; char * endptr; SL_ENTER(_("sh_xfer_server_port")); l = strtoul (str, &endptr, 0); if (l > 65535 || endptr == str) { SL_RETURN (-1, _("sh_xfer_server_port")); } ServerPort = (unsigned int) l; SL_RETURN (0, _("sh_xfer_server_port")); } long sh_xfer_report (char * errmsg) { static int have_server = S_TRUE; long status; char * popmsg; static int nofail = S_TRUE; SL_ENTER(_("sh_xfer_report")); /* --- No log server available. --- */ if (have_server == S_TRUE && sh.srvexport.name[0] == '\0') { have_server = S_FALSE; sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NONAME); SL_RETURN (-1, _("sh_xfer_report")); } else if (have_server == BAD) { SL_RETURN (-1, _("sh_xfer_report")); } /* --- Allocate fifo. --- */ if (fifo == NULL) { fifo = SH_ALLOC(sizeof(SH_FIFO)); fifo_init(fifo); } /* --- Check for messages on the queue, and send them first. --- */ while (NULL != (popmsg = pop_list(fifo)) ) { status = xfer_try_report (popmsg); if (status != 0) { (void) push_tail_list (fifo, popmsg, 0, NULL); SH_FREE(popmsg); if (SH_FIFO_MAX == push_list (fifo, errmsg, 0,NULL)) SL_RETURN (-2, _("sh_xfer_report")); SL_RETURN (-1, _("sh_xfer_report")); } SH_FREE(popmsg); } /* --- Now send the error message. --- */ status = xfer_try_report (errmsg); if (status != 0) { if (nofail == S_TRUE) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL, _("log server"), sh.srvexport.name); nofail = S_FALSE; if (SH_FIFO_MAX == push_list (fifo, errmsg, 0, NULL)) SL_RETURN (-2, _("sh_xfer_report")); SL_RETURN (-1, _("sh_xfer_report")); } nofail = S_TRUE; SL_RETURN (0, _("sh_xfer_report")); } static long xfer_try_report_int (char * errmsg, const int what); static long xfer_try_report (char * errmsg) { long i; SL_ENTER(_("xfer_try_report")); i = xfer_try_report_int (errmsg, SH_PROTO_MSG); SL_RETURN(i, _("xfer_try_report")); } long sh_xfer_request_file (const char * file) { long i; char tmp_file[64]; SL_ENTER(_("sh_xfer_request_file")); sl_strlcpy(tmp_file, file, sizeof(tmp_file)); i = xfer_try_report_int (tmp_file, SH_PROTO_BIG); SL_RETURN(i, _("sh_xfer_request_file")); } static unsigned long sh_throttle_delay = 0; int sh_xfer_set_throttle_delay (const char * c) { long val; SL_ENTER(_("sh_xfer_set_throttle_delay")); val = strtol (c, (char **)NULL, 10); if (val < 0) SL_RETURN( (-1), _("sh_xfer_set_throttle_delay")); val = (val > 1000) ? 1000 : val; sh_throttle_delay = (unsigned long) val; SL_RETURN( (0), _("sh_xfer_set_throttle_delay")); } static time_t xfer_timeout_val = 1; static int xfer_conn_state(int initialized, int conn_state) { static time_t time_now = 1200; static time_t time_last = 0; if (initialized == S_FALSE || conn_state == S_FALSE) { xfer_timeout_val = ((xfer_timeout_val > TIMEOUT_CON) ? TIMEOUT_CON : xfer_timeout_val); /* --- Retry bad attempt only after some time. --- */ time_now = time (NULL); if ((time_now - time_last) < xfer_timeout_val) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); return -1; } TPT(( 0, FIL__, __LINE__, _("msg=\n"))); } time_last = time (NULL); return 0; } static int xfer_connect(int * conn_state) { char error_msg[256]; char error_call[SH_MINIBUF] = { 0 }; int error_num = 0; int sockfd = connect_port_2 (sh.srvexport.name, sh.srvexport.alt, ServerPort, error_call, &error_num, error_msg, 256); if (sockfd < 3) { *conn_state = S_FALSE; xfer_timeout_val *= 2; sh_error_handle ((-1), FIL__, __LINE__, error_num, MSG_E_NET, error_msg, error_call, _("export"), sh.srvexport.name); return -1; } *conn_state = S_TRUE; return sockfd; } int xfer_greet_server(int sockfd, char * answer) { int flag_err; char head_u[5]; int theProto = SH_PROTO_SRP; TPT(( 0, FIL__, __LINE__, _("msg=\n"))); sl_strlcpy (answer, sh.host.name, 512); flag_err = xfer_send (sockfd, theProto, _("SALT"), answer, (unsigned long)sl_strlen(answer)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), flag_err)); /* get nonce from server */ if (flag_err == 0) { flag_err = xfer_receive (sockfd, (char)theProto, head_u, answer, 511); flag_err = (flag_err < 0) ? flag_err : 0; TPT(( 0, FIL__, __LINE__, _("msg=\n"), flag_err)); } if ( 0 != check_request (head_u, _("INIT")) ) { TPT(( 0, FIL__, __LINE__, _("msg=\n"), head_u[0], head_u[1], head_u[2], head_u[3])); flag_err = -1; } return flag_err; } #if !defined(USE_SRP_PROTOCOL) static int xfer_auth(int is_reinit, int * initialized, int sockfd, char * answer) { /************************************************** * * --- challenge/response authentication --- * **************************************************/ int flag_err = 0; int theProto = 0; char nounce[KEY_LEN+1]; char temp[2*KEY_LEN+1]; char nonce_u[KEY_LEN+1]; UINT32 ticks; char head_u[5]; char foo_M1[KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; #ifdef SH_ENCRYPT int err_num; char expbuf[SH_ERRBUF_SIZE]; #endif SL_REQUIRE((sockfd > 2), _("sockfd > 2")); if (is_reinit == S_FALSE) flag_err = xfer_greet_server(sockfd, answer); else sh_tools_probe_reset(); /* entry point for jump from message forward if session key must * be re-initialized */ if ( flag_err == 0 && sl_strlen(answer) > KEY_LEN ) (void) sl_strlcpy(nounce, &answer[KEY_LEN], KEY_LEN+1); else flag_err = (-1); TPT(( 0, FIL__, __LINE__, _("msg=\n"), flag_err)); /* verify random nonce v from server H(v, P)v */ sh_passwd (nounce, NULL, NULL, temp); if ( 0 != sl_strncmp(temp, answer, KEY_LEN)) flag_err = (-1); TPT(( 0, FIL__, __LINE__, _("msg=\n"), flag_err)); /* --- Create own nonce. --- */ ticks = (UINT32) taus_get (); (void) sl_strlcpy(nonce_u, sh_tiger_hash((char *) &ticks, TIGER_DATA, (unsigned long)sizeof(UINT32), hashbuf, sizeof(hashbuf)), KEY_LEN+1); /* --- Form the message H(H(u,v),P)u --- */ (void) sl_strlcpy(temp, nonce_u, 2*KEY_LEN+1); (void) sl_strlcat(temp, nounce, 2*KEY_LEN+1); (void) sl_strlcpy(temp, sh_tiger_hash(temp, TIGER_DATA, (unsigned long)sl_strlen(temp), hashbuf, sizeof(hashbuf)), KEY_LEN+1); sh_passwd (temp, NULL, NULL, foo_M1); (void) sl_strlcpy(temp, foo_M1, 2*KEY_LEN+1); (void) sl_strlcat(temp, nonce_u, 2*KEY_LEN+1); /* --- Send it to server. --- */ if (flag_err == 0) { flag_err = xfer_send (sockfd, (theProto|SH_PROTO_SRP), _("PASS"), temp, (unsigned long)sl_strlen(temp)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), flag_err)); } if (flag_err == 0) { flag_err = xfer_receive (sockfd, (theProto|SH_PROTO_SRP), head_u, answer, 511); sh_passwd (nounce, NULL, nonce_u, foo_M1); (void) sl_strlcpy (skey->session, foo_M1, KEY_LEN+1); #ifdef SH_ENCRYPT err_num = rijndael_makeKey(&(skey->keyInstE), (BYTE)DIR_ENCRYPT, 192, skey->session); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("xfer_try_report_int: makeKey")); err_num = rijndael_makeKey(&(skey->keyInstD), (BYTE)DIR_DECRYPT, 192, skey->session); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("xfer_try_report_int: make_key")); #endif *initialized = S_TRUE; } if (*initialized == S_FALSE) { xfer_timeout_val *= 2; sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH); memset(answer, 0, 512); MUNLOCK(answer, 512); SH_FREE(answer); return -1; } else { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH); } return 0; } #else static void noise() { UINT32 n = taus_get(); retry_msleep(0, (n & 0x0000007F)); return; } static int xfer_auth(int is_reinit, int * initialized, int sockfd, char * answer) { /* This is the SRP authenticated key exchange protocol. * Produces a session key skey->session. */ int flag_err = 0; int theProto = 0; char head_u[5]; char u_real[SH_CHALLENGE_SIZE]; char * foo_A; char * foo_Sc; char * M; char foo_M1[KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; #ifdef SH_ENCRYPT int err_num; char expbuf[SH_ERRBUF_SIZE]; #endif SL_REQUIRE((sockfd > 2), _("sockfd > 2")); if (is_reinit == S_FALSE) flag_err = xfer_greet_server(sockfd, answer); else sh_tools_probe_reset(); /* Entry point for jump from message forward if session key must * be re-initialized. */ TPT(( 0, FIL__, __LINE__, _("msg=\n"))); if ( flag_err == 0 ) { if (0 != sh_srp_init()) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EBGN); else { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); sh_srp_x (answer, NULL); /* x password */ sh_srp_make_a (); /* a random number */ foo_A = sh_srp_A(); /* g^a */ TPT(( 0, FIL__, __LINE__, _("msg=\n"), foo_A)); if (foo_A == NULL) flag_err = (-1); noise(); if (flag_err == 0) flag_err = xfer_send (sockfd, (theProto|SH_PROTO_SRP), _("PC01"), foo_A, sl_strlen(foo_A)+1); if (flag_err == 0) { flag_err = xfer_receive (sockfd, (theProto|SH_PROTO_SRP), head_u, answer, 511); flag_err = (flag_err < 0) ? flag_err : 0; TPT(( 0, FIL__, __LINE__, _("msg=\n"), answer)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), head_u[0], head_u[1], head_u[2], head_u[3])); } /* u nounce */ /* B answer */ /* S = (B-g^x)^(a+ux) */ if (flag_err == 0) { noise(); if (0 != sh_srp_check_zero (answer)) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EZERO); else { sl_strlcpy(u_real, sh_tiger_hash(head_u, TIGER_DATA, 4, hashbuf, sizeof(hashbuf)), SH_CHALLENGE_SIZE); foo_Sc = sh_srp_S_c (u_real, answer); TPT(( 0, FIL__, __LINE__, _("msg=\n"), u_real)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), foo_Sc)); /* --- Now send H(A,B,H(Sc)) and check. --- */ if (foo_Sc != NULL && 0 == sh_srp_check_zero (foo_Sc)) { sh_srp_M(foo_A, answer, sh_tiger_hash(foo_Sc, TIGER_DATA, sl_strlen(foo_Sc), hashbuf, sizeof(hashbuf)), foo_M1, KEY_LEN+1); TPT(( 0, FIL__, __LINE__, _("msg=\n"), foo_M1)); flag_err = xfer_send(sockfd, (theProto|SH_PROTO_SRP), _("PC02"), foo_M1, KEY_LEN+1); } else flag_err = (-1); if (flag_err == 0) { flag_err = xfer_receive(sockfd, (theProto|SH_PROTO_SRP), head_u, answer, 511); flag_err = (flag_err < 0) ? flag_err : 0; TPT(( 0, FIL__, __LINE__, _("msg=\n"), answer)); } if (flag_err == 0 && 0 == check_request (head_u, _("PARP")) ) { /* ------ verify M2 = H(A, M1, K) -------- */ char M_buf[KEY_LEN+1]; M = sh_srp_M (foo_A, foo_M1, sh_tiger_hash(foo_Sc, TIGER_DATA, sl_strlen(foo_Sc), hashbuf, sizeof(hashbuf)), M_buf, sizeof(M_buf) ); if (M != NULL && 0 == sl_strncmp (answer, M, KEY_LEN+1)) { sl_strlcpy (skey->session, sh_tiger_hash(foo_Sc, TIGER_DATA, sl_strlen(foo_Sc), hashbuf, sizeof(hashbuf)), KEY_LEN+1); TPT(( 0, FIL__, __LINE__, _("msg=\n"), skey->session)); #ifdef SH_ENCRYPT err_num = rijndael_makeKey(&(skey->keyInstE), DIR_ENCRYPT, 192, skey->session); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("xfer_try_report_int: makeKey")); err_num = rijndael_makeKey(&(skey->keyInstD), DIR_DECRYPT, 192, skey->session); if (err_num < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errorExplain(err_num, expbuf, sizeof(expbuf)), _("xfer_try_report_int: makeKey")); #endif *initialized = S_TRUE; noise(); } } if (foo_Sc != NULL) SH_FREE(foo_Sc); } } if (foo_A != NULL) SH_FREE(foo_A); sh_srp_exit(); } } if (*initialized == S_FALSE) { xfer_timeout_val *= 2; sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH); memset(answer, '\0', 512); MUNLOCK(answer, 512); SH_FREE(answer); return -1; } else { if (flag_err_info == S_TRUE) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH); } return 0; } #endif int xfer_check_server_cmd(char * answer, char * buffer) { int flag_err; size_t pos; char sigbuf[KEYBUF_SIZE]; /* --- SERVER CMD --- */ if (answer[KEY_LEN] != '\0' && sl_strlen(answer) > (2*KEY_LEN)) { pos = sl_strlen(answer) - (2*KEY_LEN); /* * buffer is >= 256 * answer has <= 255 bytes */ (void) sl_strlcpy(buffer, &answer[KEY_LEN], pos+1); flag_err = sl_strncmp(&answer[KEY_LEN+pos], sh_util_siggen(skey->session, buffer, pos, sigbuf, sizeof(sigbuf)), KEY_LEN); TPT((0, FIL__, __LINE__, _("CONF RECV <%d> <%s>\n"), flag_err, &answer[KEY_LEN])); if (flag_err != 0) { sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_NOCONF); } #ifdef SH_WITH_CLIENT else { sh_socket_server_cmd(buffer); } #endif flag_err = 0; } else { TPT((0, FIL__, __LINE__, _("CONF RECV <0> <[null]>\n"))); } /* --- SERVER CMD END --- */ return 0; } int xfer_send_message(char * errmsg, int sockfd, char * answer) { char hash[KEY_LEN+1]; size_t len; char * buffer; char nsrv[KEY_LEN+1]; char sigbuf[KEYBUF_SIZE]; char head_u[5]; int flag_err; SL_REQUIRE((sockfd > 2), _("sockfd > 2")); /* --- Save the challenge. --- */ (void) sl_strlcpy(nsrv, answer, KEY_LEN + 1); /* --- Hash(msg,challenge,sessionkey). --- */ len = sl_strlen(errmsg) + sl_strlen(answer) + KEY_LEN + 1; len = (size_t)((len < 256) ? 256 : len); buffer = SH_ALLOC(len); MLOCK(buffer, len); (void) sl_strlcpy(buffer, errmsg, len); (void) sl_strlcat(buffer, answer, len); (void) sl_strlcpy(hash, sh_util_siggen (skey->session, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)), KEY_LEN+1); TPT((0, FIL__, __LINE__, _("msg=\n"), sh_util_siggen(skey->session, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)))); (void) sl_strlcpy(buffer, errmsg, len); (void) sl_strlcat(buffer, hash, len); flag_err = xfer_send_crypt (sockfd, #ifdef SH_ENCRYPT (char)(SH_PROTO_MSG|SH_PROTO_ENC), #else (char)(SH_PROTO_MSG), #endif _("MESG"), buffer, (unsigned long)(sl_strlen(buffer)+1)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), answer, flag_err)); /* --- Get confirmation. --- */ if (flag_err == 0) { flag_err = (int) xfer_receive_crypt (sockfd, #ifdef SH_ENCRYPT (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_END), #else (char)(SH_PROTO_MSG|SH_PROTO_END), #endif head_u, answer, 255); TPT(( 0, FIL__, __LINE__, _("msg=\n"), answer, hu_trans(head_u), flag_err)); flag_err = (flag_err < 0) ? flag_err : 0; } /* --- Check confirmation. --- */ if (flag_err == 0) { /* CLIENT CONF RECV * * first KEY_LEN bytes must be * sig(skey->session (errmsg nsrv)) * */ (void) sl_strlcpy(buffer, errmsg, len); (void) sl_strlcat(buffer, nsrv, len); flag_err = sl_strncmp(answer, sh_util_siggen(skey->session, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)), KEY_LEN); TPT((0, FIL__, __LINE__, _("msg=\n"), sh_util_siggen(skey->session, buffer, sl_strlen(buffer), sigbuf, sizeof(sigbuf)))); if (flag_err != 0) { #ifdef ENOMSG flag_err = ENOMSG; #else flag_err = EIO; #endif sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_NOCONF); } else { #ifdef SH_ENCRYPT flag_err = xfer_check_server_cmd(answer, buffer); #endif if (flag_err_debug == S_TRUE) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CONF); } } memset(buffer, 0, len); MUNLOCK(buffer, len); SH_FREE(buffer); if (flag_err != 0) return -1; return 0; } static SL_TICKET xfer_get_file(int sockfd, char * answer, char * nclt, char * foo_M1, const int theProto) { /* --- Open a temporary file. --- */ int flag_err = 0; SL_TICKET sfd; SL_REQUIRE((sockfd > 2), _("sockfd > 2")); if ( (sfd = open_tmp ()) < 0) { flag_err = (-1); sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_EFIL); } else { /* --- Read from socket into tmp file. --- */ int transfercount = 0; char head_u[5]; do { flag_err = (int) xfer_receive_crypt (sockfd, #ifdef SH_ENCRYPT (char)(SH_PROTO_BIG|SH_PROTO_ENC), #else (char)(SH_PROTO_BIG), #endif head_u, answer, TRANS_BYTES + 255); TPT(( 0, FIL__, __LINE__, _("msg=\n"), flag_err, hu_trans(head_u))); if (flag_err > 0 && 0 == check_request_nerr(head_u, _("FILE"))) { if (0 == hash_check (foo_M1, answer, flag_err)) { (void) sl_write(sfd, &answer[KEY_LEN], flag_err-KEY_LEN); ++transfercount; /* Delay for throughput throttling */ if (sh_throttle_delay > 0) retry_msleep(sh_throttle_delay/1000, sh_throttle_delay % 1000); flag_err = xfer_send_crypt (sockfd, theProto, _("RECV"), nclt, (unsigned long)sl_strlen(nclt)); } else { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); break; } } else { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); break; } } while (transfercount < 32000); /* 64 Mbyte */ if (0 == check_request_nerr(head_u, _("EEOT")) && 0 < flag_err && 0 == hash_check (foo_M1, answer, (int)sl_strlen(answer))) { flag_err = xfer_send_crypt (sockfd, theProto, _("EOTE"), nclt, (unsigned int) sl_strlen(nclt)); (void) rewind_tmp (sfd); (void) sl_sync(sfd); if (flag_err_info == S_TRUE) sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_FOK); } else { (void) sl_close (sfd); sfd = (-1); } } return sfd; } static long xfer_try_report_int (char * errmsg, const int what) { static int initialized = S_FALSE; static int conn_state = S_TRUE; int sockfd; int flag_err = 0; char * answer; int theProto = 0; UINT32 ticks; char head_u[5]; char * buffer; char nsrv[KEY_LEN+1]; char nclt[KEY_LEN+1]; char foo_M1[KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; char sigbuf[KEYBUF_SIZE]; SL_ENTER(_("xfer_try_report_int")); /* --- No message to transmit. --- */ if (errmsg == NULL && initialized == S_TRUE) SL_RETURN( 0, _("xfer_try_report_int")); /* --- Connection in bad state. --- */ if (xfer_conn_state(initialized, conn_state) < 0) SL_RETURN( (-1), _("xfer_try_report_int")); /* --- Try to connect to log server. --- */ sockfd = xfer_connect(&conn_state); if (sockfd < 0) SL_RETURN( (-1), _("xfer_try_report_int")); /************************* * * initialization * */ flag_err = 0; answer = SH_ALLOC(512); MLOCK(answer, 512); if (initialized == S_FALSE) { if (xfer_auth(S_FALSE, &initialized, sockfd, answer) < 0) SL_RETURN( (-1), _("xfer_try_report_int")); } retry_send: /* no message, just session key negotiated */ if (errmsg == NULL) { xfer_timeout_val = 1; memset(answer, 0, 512); MUNLOCK(answer, 512); SH_FREE(answer); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN( (0), _("xfer_try_report_int")); } else if (what == SH_PROTO_BIG) { MUNLOCK(answer, 512); SH_FREE (answer); answer = SH_ALLOC(TRANS_BYTES + 256); MLOCK(answer, TRANS_BYTES + 256); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); } sl_strlcpy (answer, sh_util_siggen(skey->session, sh.host.name, sl_strlen(sh.host.name), sigbuf, sizeof(sigbuf)), KEY_LEN+1); TPT((0, FIL__, __LINE__, _("msg=\n"), sh.host.name)); TPT((0, FIL__, __LINE__, _("msg=\n"), skey->session)); TPT((0, FIL__, __LINE__, _("msg=\n"), answer)); sl_strlcat (answer, sh.host.name, 512); TPT((0, FIL__, __LINE__, _("msg=\n"), answer)); /*********************************************** * * send the message * */ if (what == SH_PROTO_MSG) theProto = SH_PROTO_MSG; else if (what == SH_PROTO_BIG) theProto = SH_PROTO_BIG; /* --- Say HELO --- */ flag_err = xfer_send (sockfd, theProto, _("HELO"), answer, sl_strlen(answer)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), answer, flag_err)); if (flag_err == 0) { /* --- Get NSRV. --- */ flag_err = (int) xfer_receive (sockfd, theProto, head_u, answer, 255); TPT(( 0, FIL__, __LINE__, _("msg=\n"), answer, hu_trans(head_u), flag_err)); flag_err = (flag_err < 0) ? flag_err : 0; } if (what == SH_PROTO_MSG) { if (flag_err == 0) { /* --- Re-negotiate key. --- */ if (0 == check_request_nerr(head_u, _("INIT"))) { flag_err = 0; initialized = S_FALSE; if (xfer_auth(S_TRUE, &initialized, sockfd, answer) == 0) goto retry_send; } else if (0 == check_request(head_u, _("TALK"))) { flag_err = xfer_send_message(errmsg, sockfd, answer); } else { /* --- Unexpected reply from server. --- */ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_UNEXP); flag_err = (-1); } } } else if (what == SH_PROTO_BIG) { if (flag_err == 0) { /* --- Re-negotiate key. --- */ if (0 == check_request_nerr(head_u, _("INIT"))) { flag_err = 0; initialized = BAD; if (xfer_auth(S_TRUE, &initialized, sockfd, answer) == 0) goto retry_send; } else if (0 == check_request(head_u, _("NSRV"))) { size_t buffersize; #ifdef SH_ENCRYPT /* --- Set encryption flag. --- */ theProto = (SH_PROTO_BIG|SH_PROTO_ENC); #endif (void) sl_strlcpy(nsrv, answer, KEY_LEN+1); /* --- Generate a nonce. --- */ ticks = (UINT32) taus_get (); (void) sl_strlcpy(nclt, sh_tiger_hash((char *) &ticks, TIGER_DATA, (unsigned long)sizeof(UINT32), hashbuf, sizeof(hashbuf)), KEY_LEN+1); /* --- Compute H(nsrv, nclt, skey). --- */ buffer = sh_util_strconcat (nsrv, nclt, skey->session, NULL); (void)sl_strlcpy(foo_M1, sh_tiger_hash(buffer, TIGER_DATA, (unsigned long)sl_strlen(buffer), hashbuf, sizeof(hashbuf)), KEY_LEN+1); memset (buffer, 0, sl_strlen(buffer)); SH_FREE(buffer); /* --- Send (nclt, msg) --- */ if (S_TRUE == sl_ok_adds(strlen(errmsg), strlen(nclt)+2+KEY_LEN)) { buffersize = strlen(nclt)+strlen(errmsg)+2; #if !defined(SH_ENCRYPT) buffersize += KEY_LEN; #endif buffer = SH_ALLOC(buffersize); sl_strlcpy(buffer, nclt, buffersize); sl_strlcat(buffer, errmsg, buffersize); #if !defined(SH_ENCRYPT) if (4 == sl_strlen(errmsg)) { /* backward compatibility */ buffersize = sl_strlen(buffer); buffer[buffersize] = theProto; /* nctl//DATA//theProto */ buffer[buffersize+1] = '\0'; } sh_tools_hash_add(foo_M1, buffer, buffersize+1); #endif flag_err = xfer_send_crypt (sockfd, (char) theProto, _("NCLT"), buffer, (unsigned long) sl_strlen(buffer)); TPT(( 0, FIL__, __LINE__, _("msg=\n"), buffer, flag_err)); SH_FREE (buffer); } else { flag_err = -1; } } } if (flag_err == 0) { /* --- Receive the file. --- */ SL_TICKET sfd = xfer_get_file(sockfd, answer, nclt, foo_M1, theProto); if (!SL_ISERROR(sfd)) { (void) sl_close_fd (FIL__, __LINE__, sockfd); memset(answer, 0, TRANS_BYTES + 256); MUNLOCK(answer, TRANS_BYTES + 256); SH_FREE(answer); xfer_timeout_val = 1; SL_RETURN( (sfd), _("xfer_try_report_int")); } } (void) sl_close_fd (FIL__, __LINE__, sockfd); memset(answer, 0, TRANS_BYTES + 256); MUNLOCK(answer, TRANS_BYTES + 256); SH_FREE(answer); xfer_timeout_val *= 2; SL_RETURN( (-1), _("xfer_try_report_int")); } (void) sl_close_fd (FIL__, __LINE__, sockfd); memset(answer, 0, 512); MUNLOCK(answer, 512); SH_FREE(answer); #ifndef EIO #define EIO 5 #endif #ifdef SH_ERROR_H if (flag_err != 0) { char errbuf[SH_ERRBUF_SIZE]; conn_state = S_FALSE; xfer_timeout_val *= 2; if (flag_err < 0 || NULL == sh_error_message(flag_err, errbuf, sizeof(errbuf))) flag_err = EIO; sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_ECONN, sh_error_message(flag_err, errbuf, sizeof(errbuf))); SL_RETURN( (-1), _("xfer_try_report_int")); } #endif xfer_timeout_val = 1; SL_RETURN( (0), _("xfer_try_report_int")); } /* #ifdef SH_WITH_CLIENT */ #endif samhain-4.1.4/src/sh_socket.c0000644000175000017500000010362112615253277013013 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2003,2005 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" /* define if you want debug info * #define SH_DEBUG_SOCKET */ #if defined(SH_WITH_SERVER) && defined(__linux__) #define _GNU_SOURCE #endif #include #include #include #include #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #include "samhain.h" #include "sh_socket.h" #include "sh_error.h" #include "sh_unix.h" #include "sh_calls.h" #include "sh_guid.h" #include "sh_fifo.h" #include "sh_utils.h" #undef FIL__ #define FIL__ _("sh_socket.c") #if defined (SH_WITH_CLIENT) #include typedef struct delta_tofetch { char uuid[SH_UUID_BUF]; time_t last_time; unsigned int count; } SH_DELTA_DB; static SH_DELTA_DB * parse_entry(SH_DELTA_DB * db, const char * str) { long last_time; unsigned int count; char buf[SH_UUID_BUF]; int res = sscanf(str, _("%u:%ld:%36s"), &count, &last_time, buf); if (res == 3) { db->count = count; db->last_time = (time_t) last_time; sl_strlcpy(db->uuid, buf, SH_UUID_BUF); return db; } return NULL; } static char * unparse_entry(const SH_DELTA_DB * db, char * str, size_t len) { int nbytes = sl_snprintf(str, len, _("%u:%ld:%s"), db->count, (long) db->last_time, db->uuid); if (nbytes < 0 || nbytes >= (int) len) return NULL; return str; } static SH_FIFO xfifo = SH_FIFO_INITIALIZER; int sh_socket_store_uuid(const char * cmd) { char * p = sh_util_strdup(cmd); char * q = strchr(cmd, ':'); char entry[SH_BUFSIZE]; SH_DELTA_DB db; if (!q) { SH_FREE(p); return -1; } ++q; if (0 != sh_uuid_check(q)) { SH_FREE(p); return -1; } db.count = 0; db.last_time = (time_t) 0; sl_strlcpy(db.uuid, q, SH_UUID_BUF); SH_FREE(p); if (NULL != unparse_entry(&db, entry, sizeof(entry))) { sh_fifo_push(&xfifo, entry); return 0; } return -1; } static unsigned int try_interval = 60; static unsigned int try_max = 2; int set_delta_retry_interval(const char * str) { long val = strtol (str, (char **)NULL, 10); if (val < 0 || val > INT_MAX) return -1; try_interval = (unsigned int) val; return 0; } int set_delta_retry_count(const char * str) { long val = strtol (str, (char **)NULL, 10); if (val < 0 || val > INT_MAX) return -1; try_max = (unsigned int) val; return 0; } char * sh_socket_get_uuid(int * errflag, unsigned int * count, time_t * last) { char * entry = sh_fifo_pop(&xfifo); char * uuid = NULL; if (entry) { SH_DELTA_DB db; time_t now; if (NULL == parse_entry(&db, entry)) { SH_FREE(entry); sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Bad entry in fifo"), _("sh_socket_get_uuid")); *errflag = -1; return NULL; } now = time(NULL); if ( (db.count > 0) && ((unsigned long)(now - db.last_time) < try_interval) ) { sh_fifo_push_tail(&xfifo, entry); SH_FREE(entry); *errflag = -1; return NULL; } SH_FREE(entry); uuid = sh_util_strdup(db.uuid); *count = db.count; *last = db.last_time; } *errflag = 0; return uuid; } int sh_socket_return_uuid (const char * uuid, unsigned int count, time_t last) { (void) last; if (count < try_max) { char entry[SH_BUFSIZE]; SH_DELTA_DB db; time_t now = time(NULL); db.count = count + 1; db.last_time = now; sl_strlcpy(db.uuid, uuid, SH_UUID_BUF); if (NULL != unparse_entry(&db, entry, sizeof(entry))) return sh_fifo_push_tail(&xfifo, entry); /* >0 for success */ } return -1; } void sh_socket_server_cmd(const char * srvcmd) { SL_ENTER(_("sh_tools_server_cmd")); if ((srvcmd == NULL) || (srvcmd[0] == '\0') || (sl_strlen(srvcmd) < 4)) { SL_RET0(_("sh_socket_server_cmd")); } if (0 == strncmp(srvcmd, _("STOP"), 4)) { TPT((0, FIL__, __LINE__, _("msg=\n"))); #ifdef SIGQUIT raise(SIGQUIT); #else sig_terminate = 1; ++sig_raised; #endif } else if (0 == strncmp(srvcmd, _("RELOAD"), 6)) { TPT((0, FIL__, __LINE__, _("msg=\n"))); #ifdef SIGHUP raise(SIGHUP); #else sig_config_read_again = 1; ++sig_raised; #endif } else if (0 == strncmp(srvcmd, _("DELTA:"), 6)) { TPT((0, FIL__, __LINE__, _("msg=\n"))); if (sh_socket_store_uuid(srvcmd) == 0) { ++sh_load_delta_flag; ++sig_raised; } } else if (0 == strncmp(srvcmd, _("SCAN"), 4)) { TPT((0, FIL__, __LINE__, _("msg=\n"))); if (sh.flag.isdaemon == S_TRUE) { #ifdef SIGTTOU raise(SIGTTOU); #else sig_force_check = 1; ++sig_raised; #endif } else { sig_force_check = 1; ++sig_raised; } } /* Unknown command */ else { sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, srvcmd, _("sh_socket_server_cmd")); } SL_RET0(_("sh_socket_server_cmd")); } #endif /* #if defined (SH_WITH_CLIENT) */ #if defined(SH_WITH_SERVER) #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_UIO_H #include #endif #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) #if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED) #include #include #endif #endif int pf_unix_fd = -1; static char * sh_sockname = NULL; static char sh_sockpass_real[SOCKPASS_MAX+1]; struct socket_cmd { char cmd[SH_MAXMSGLEN]; char clt[SH_MAXMSGLEN]; char cti[81]; struct socket_cmd * next; }; #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif #if !defined(AF_FILE) #define AF_FILE AF_UNIX #endif static struct socket_cmd * cmdlist = NULL; static struct socket_cmd * runlist = NULL; static int sh_socket_flaguse = S_FALSE; static int sh_socket_flaguid = 0; #include "sh_utils.h" /* The reload list stores information about * reloads confirmed by clients (startup and/or * runtime cinfiguration reloaded). */ struct reload_cmd { char clt[SH_MAXMSGLEN]; time_t cti; struct reload_cmd * next; }; static struct reload_cmd * reloadlist = NULL; void sh_socket_add2reload (const char * clt) { struct reload_cmd * new = reloadlist; while (new) { if (0 == sl_strcmp(new->clt, clt)) { #ifdef SH_DEBUG_SOCKET fprintf(stderr, "add2reload: time reset for %s\n", clt); #endif sl_strlcpy (new->clt, clt, SH_MAXMSGLEN); new->cti = time(NULL); return; } new = new->next; } new = SH_ALLOC(sizeof(struct reload_cmd)); #ifdef SH_DEBUG_SOCKET fprintf(stderr, "add2reload: time set for %s\n", clt); #endif sl_strlcpy (new->clt, clt, SH_MAXMSGLEN); new->cti = time(NULL); new->next = reloadlist; reloadlist = new; return; } #include "zAVLTree.h" #include "sh_html.h" #include "sh_tools.h" static void sh_socket_add2list (struct socket_cmd * in); static void sh_socket_probe4reload (void) { struct reload_cmd * new; struct socket_cmd cmd; zAVLCursor avlcursor; client_t * item; extern zAVLTree * all_clients; char * file; unsigned long dummy; struct stat buf; for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item; item = (client_t *) zAVLNext(&avlcursor)) { if (item->status_now != CLT_INACTIVE) { int flag = 0; file = get_client_conf_file (item->hostname, &dummy); if (0 == stat (file, &buf)) { new = reloadlist; while (new) { if (0 == sl_strcmp(new->clt, item->hostname)) { flag = 1; /* Client is in list already */ if (buf.st_mtime > new->cti) { /* reload */ sl_strlcpy(cmd.cmd, _("RELOAD"), SH_MAXMSGLEN); sl_strlcpy(cmd.clt, item->hostname, SH_MAXMSGLEN); sh_socket_add2list (&cmd); } break; } new = new->next; } if (flag == 0) { /* client is active, but start message has been missed; reload */ sl_strlcpy(cmd.cmd, _("RELOAD"), SH_MAXMSGLEN); sl_strlcpy(cmd.clt, item->hostname, SH_MAXMSGLEN); sh_socket_add2list (&cmd); /* Add the client to the reload list and set * time to 0, since we don't know the startup time. */ sh_socket_add2reload (item->hostname); new = reloadlist; while (new) { if (0 == sl_strcmp(new->clt, item->hostname)) { new->cti = 0; break; } new = new->next; } } } /* if stat(file).. */ } /* if !CLT_INACTIVE */ } /* loop over clients */ return; } char * sh_get_sockpass (void) { size_t j = 0; while (skey->sh_sockpass[2*j] != '\0' && j < sizeof(sh_sockpass_real)) { sh_sockpass_real[j] = skey->sh_sockpass[2*j]; ++j; } sh_sockpass_real[j] = '\0'; return sh_sockpass_real; } void sh_set_sockpass (void) { int j; for (j = 0; j < 15; ++j) { sh_sockpass_real[j] = '\0'; } } int sh_socket_use (const char * c) { return sh_util_flagval(c, &sh_socket_flaguse); } int sh_socket_remove () { int retval = 0; #ifdef S_ISSOCK struct stat sbuf; #endif SL_ENTER(_("sh_socket_remove")); if (NULL == sh_sockname) { SL_RETURN((retval),_("sh_socket_remove")); } if (0 != tf_trust_check (DEFAULT_PIDDIR, SL_YESPRIV)) { SL_RETURN((-1),_("sh_socket_remove")); } if ( (retry_lstat(FIL__, __LINE__, sh_sockname, &sbuf) == 0) && (sbuf.st_uid == getuid())) { #ifdef S_ISSOCK if (S_ISSOCK (sbuf.st_mode)) { retval = retry_aud_unlink (FIL__, __LINE__, sh_sockname); } #else retval = retry_aud_unlink (FIL__, __LINE__, sh_sockname); #endif } SL_RETURN((retval),_("sh_socket_remove")); } #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)) #define NEED_PASSWORD_AUTH #endif int sh_socket_uid (const char * c) { uid_t val = (uid_t) strtol (c, (char **)NULL, 10); sh_socket_flaguid = val; #if defined(NEED_PASSWORD_AUTH) sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, errno, MSG_E_SUBGEN, _("Config option SetSocketAllowUID not supported, use SetSocketPassword"), _("sh_socket_uid")); #endif return 0; } int sh_socket_password (const char * c) { #if defined(NEED_PASSWORD_AUTH) int j, i; #define LCG(n) ((69069 * n) & 0xffffffffUL) i = sl_strlen(c); if (i > SOCKPASS_MAX) { return -1; } for (j = 0; j < (2*SOCKPASS_MAX+1); ++j) { skey->sh_sockpass[j] = '\0'; } for (j = 0; j < i; ++j) { skey->sh_sockpass[2*j] = c[j]; skey->sh_sockpass[(2*j)+1] = (LCG(c[j]) % 256); } return 0; #else sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, errno, MSG_E_SUBGEN, _("Config option SetSocketPassword not supported, use SetSocketAllowUID"), _("sh_socket_password")); (void) c; return 0; #endif } int sh_socket_open_int () { struct sockaddr_un name; size_t size; int flags; #if defined(SO_PASSCRED) socklen_t optval = 1; #endif struct stat buf; char errbuf[SH_ERRBUF_SIZE]; SL_ENTER(_("sh_socket_open_int")); if (sh_socket_flaguse == S_FALSE) { SL_RETURN(0, _("sh_socket_open_int")); } if (sh_sockname == NULL) { size = sl_strlen(DEFAULT_PIDDIR) + 1 + sl_strlen(SH_INSTALL_NAME) + 6; sh_sockname = SH_ALLOC(size); /* compile-time constant */ sl_strlcpy(sh_sockname, DEFAULT_PIDDIR, size); sl_strlcat(sh_sockname, "/", size); sl_strlcat(sh_sockname, SH_INSTALL_NAME, size); sl_strlcat(sh_sockname, _(".sock"), size); } if (0 != sh_unix_check_piddir (sh_sockname)) { SH_FREE(sh_sockname); SL_RETURN((-1),_("sh_socket_open_int")); } pf_unix_fd = socket (PF_UNIX, SOCK_STREAM, 0); if ((pf_unix_fd) < 0) { sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_open_int: socket")); SL_RETURN( (-1), _("sh_socket_open_int")); } if (sizeof(name.sun_path) < (1 + sl_strlen(sh_sockname))) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("PID dir path too long"), _("sh_socket_open_int")); SL_RETURN( (-1), _("sh_socket_open_int")); } name.sun_family = AF_FILE; sl_strlcpy (name.sun_path, sh_sockname, sizeof(name.sun_path)); size = (offsetof (struct sockaddr_un, sun_path) + strlen (name.sun_path) + 1); flags = retry_lstat (FIL__, __LINE__, sh_sockname, &buf); if (flags == 0) { sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, -1, MSG_E_SUBGEN, _("Socket exists, trying to unlink it"), _("sh_socket_open_int")); if (sh_socket_remove() < 0) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("Unlink of socket failed, maybe path not trusted"), _("sh_socket_open_int")); SL_RETURN( (-1), _("sh_socket_open_int")); } } if (bind ((pf_unix_fd), (struct sockaddr *) &name, size) < 0) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_open_int: bind")); SL_RETURN( (-1), _("sh_socket_open_int")); } #ifdef SO_PASSCRED if (0 != setsockopt(pf_unix_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval))) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_open_int: setsockopt")); SL_RETURN( (-1), _("sh_socket_open_int")); } #endif flags = fcntl((pf_unix_fd), F_GETFL); if (flags < 0) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_open_int: fcntl1")); SL_RETURN( (-1), _("sh_socket_open_int")); } flags = fcntl((pf_unix_fd), F_SETFL, flags|O_NONBLOCK); if (flags < 0) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_open_int: fcntl2")); SL_RETURN( (-1), _("sh_socket_open_int")); } if (0 != listen(pf_unix_fd, 5)) { sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1; sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_open_int: listen")); SL_RETURN( (-1), _("sh_socket_open_int")); } SL_RETURN( (0), _("sh_socket_open_int")); } /* * Parts of the socket authentication code is copied from PostgreSQL: * * PostgreSQL Database Management System * (formerly known as Postgres, then as Postgres95) * * Portions Copyright (c) 1996-2001, The PostgreSQL Global Development Group * * Portions Copyright (c) 1994, The Regents of the University of California * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without a written agreement * is hereby granted, provided that the above copyright notice and this * paragraph and the following two paragraphs appear in all copies. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ static int receive_message(int talkfd, struct msghdr * msg, size_t message_size) { unsigned int retry = 0; int nbytes; char * message = msg->msg_iov->iov_base; char errbuf[SH_ERRBUF_SIZE]; do { nbytes = recvmsg (talkfd, msg, 0); if ((nbytes < 0) && (errno != EAGAIN)) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: recvmsg")); sl_close_fd(FIL__, __LINE__, talkfd); return -1; } else if (nbytes < 0) { ++retry; retry_msleep(0, 10); } } while ((nbytes < 0) && (retry < 3)); /* msg.msg_iov.iov_base, filled by recvmsg */ message[message_size-1] = '\0'; if (nbytes < 0) { if (errno == EAGAIN) { /* no data */ sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: recvfrom")); sl_close_fd(FIL__, __LINE__, talkfd); return 0; } sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: recvfrom")); sl_close_fd(FIL__, __LINE__, talkfd); return -1; } return 0; } #if defined(HAVE_GETPEEREID) static int get_peer_uid(int talkfd) { uid_t peer_uid; gid_t peer_gid; char errbuf[SH_ERRBUF_SIZE]; if (0 != getpeereid(talkfd, &peer_uid, &peer_gid)) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: getpeereid")); sl_close_fd(FIL__, __LINE__, talkfd); return -1; } return peer_uid; } #elif defined(SO_PEERCRED) static int get_peer_uid(int talkfd) { char errbuf[SH_ERRBUF_SIZE]; struct ucred cr; #ifdef HAVE_SOCKLEN_T socklen_t cl = sizeof(cr); #else int cl = sizeof(cr); #endif if (0 != getsockopt(talkfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: getsockopt")); sl_close_fd(FIL__, __LINE__, talkfd); return -1; } return cr.uid; } #endif #if defined(NEED_PASSWORD_AUTH) char * check_password(char * message, int * client_uid, int talkfd) { char * cmd = NULL; char * eopw = NULL; char * goodpassword = NULL; goodpassword = sh_get_sockpass(); eopw = strchr(message, '@'); if (eopw) *eopw = '\0'; /* * message is null-terminated and >> goodpassword */ if (0 == strcmp(goodpassword, message) && strlen(goodpassword) < (sizeof(message)/2)) { *client_uid = sh_socket_flaguid; cmd = &message[strlen(goodpassword)+1]; sh_set_sockpass(); } else { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Bad password"), _("sh_socket_read")); sh_set_sockpass(); sl_close_fd(FIL__, __LINE__, talkfd); return NULL; } return cmd; } #endif static int list_all (int talkfd, char * cmd); static int process_message(int talkfd, char * cmd, struct socket_cmd * srvcmd); static int sh_socket_read (struct socket_cmd * srvcmd) { char message[SH_MAXMSG]; struct sockaddr_un name; ACCEPT_TYPE_ARG3 size = sizeof(name); int talkfd; char * cmd = NULL; int client_uid = -1; char errbuf[SH_ERRBUF_SIZE]; struct msghdr msg; struct iovec iov; int status; if (pf_unix_fd < 0) return 0; iov.iov_base = (char *) &message; iov.iov_len = sizeof(message); memset (&msg, 0, sizeof (msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; /* the socket is non-blocking * 'name' is the address of the sender socket */ do { talkfd = accept(pf_unix_fd, (struct sockaddr *) &name, &size); } while (talkfd < 0 && errno == EINTR); if ((talkfd < 0) && (errno == EAGAIN)) { return 0; } else if (talkfd < 0) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: accept")); return -1; } if (receive_message(talkfd, &msg, sizeof(message)) < 0) return -1; /* Authenticate request by peer uid or password. */ #if defined(HAVE_GETPEEREID) client_uid = get_peer_uid(talkfd); cmd = message; #elif defined(SO_PEERCRED) client_uid = get_peer_uid(talkfd); cmd = message; #elif defined(NEED_PASSWORD_AUTH) cmd = check_password(message, &client_uid, talkfd); #else sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, _("Socket credentials not supported on this OS"), _("sh_socket_read")); sl_close_fd(FIL__, __LINE__, talkfd); return -1; #endif if (client_uid != sh_socket_flaguid) { sh_error_handle((-1), FIL__, __LINE__, client_uid, MSG_E_SUBGEN, _("client does not have required uid"), _("sh_socket_read: getsockopt")); sl_close_fd(FIL__, __LINE__, talkfd); return -1; } status = process_message(talkfd, cmd, srvcmd); sl_close_fd(FIL__, __LINE__, talkfd); return status; } static int check_valid_command(const char * str) { unsigned int i = 0; char * commands[] = { N_("DELTA"), N_("RELOAD"), N_("STOP"), N_("SCAN"), N_("CANCEL"), N_("LISTALL"), N_("LIST"), N_("PROBE"), NULL }; while (commands[i]) { if (0 == strcmp(_(commands[i]), str)) { return 0; } ++i; } return -1; } static int send_reply (int fd, char * msg) { int nbytes = send (fd, msg, strlen(msg) + 1, 0); if (nbytes < 0) { char errbuf[SH_ERRBUF_SIZE]; sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("send_reply")); return -1; } return nbytes; } static int process_message(int talkfd, char * cmd, struct socket_cmd * srvcmd) { int nbytes; char error_type[SH_ERRBUF_SIZE] = { '\0' }; char * clt = (cmd) ? strchr(cmd, ':') : NULL; if (clt && 0 == strncmp(cmd, _("DELTA:"), 6)) { /* DELTA:uuid:hostname */ char * uuid = clt; *uuid = '\0'; ++uuid; clt = strchr(uuid, ':'); if (clt) { *clt = '\0'; ++clt; } if (sh_uuid_check(uuid) < 0) { sl_strlcpy(error_type, _("!E:uuid-format:"), sizeof(error_type)); sl_strlcat(error_type, uuid, sizeof(error_type)); clt = NULL; } --uuid; *uuid = ':'; } else if (clt && *clt == ':') { *clt = '\0'; ++clt; if (check_valid_command(cmd) < 0) { sl_strlcpy(error_type, _("!E:cmd-invalid:"), sizeof(error_type)); sl_strlcat(error_type, cmd, sizeof(error_type)); clt = NULL; } } if (clt != NULL) { if (sl_strlen(cmd) >= SH_MAXMSGLEN) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, _("Bad message format: command too long"), _("sh_socket_read")); sl_strlcpy(error_type, _("!E:cmd-toolong"), sizeof(error_type)); send_reply(talkfd, error_type); return -1; } else if (sl_strlen(clt) >= SH_MAXMSGLEN) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, _("Bad message format: hostname too long"), _("sh_socket_read")); sl_strlcpy(error_type, _("!E:hostname-toolong"), sizeof(error_type)); send_reply(talkfd, error_type); return -1; } if (0 == strncmp(cmd, _("LIST"), 4)) return list_all(talkfd, cmd); else if (0 == strncmp(cmd, _("PROBE"), 4)) { sh_socket_probe4reload(); sl_strlcpy(cmd, _("LIST"), 5); return list_all(talkfd, cmd); } sl_strlcpy (srvcmd->cmd, cmd, SH_MAXMSGLEN); sl_strlcpy (srvcmd->clt, clt, SH_MAXMSGLEN); --clt; *clt = ':'; } else { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, _("Bad message format"), _("sh_socket_read")); if (error_type[0] == '\0') sl_strlcpy(error_type, _("!E:message-format"), sizeof(error_type)); send_reply(talkfd, error_type); return -1; } /* Bounce the message back to the sender. */ nbytes = send_reply(talkfd, cmd); return nbytes; } static int list_all (int talkfd, char * cmd) { int nbytes; struct socket_cmd * list_cmd; char message[SH_MAXMSG]; char errbuf[SH_ERRBUF_SIZE]; if (0 == strncmp(cmd, _("LISTALL"), 7)) { list_cmd = runlist; while (list_cmd) { sl_snprintf(message, sizeof(message), _("SENT %42s %32s %s"), list_cmd->cmd, list_cmd->clt, list_cmd->cti); nbytes = send (talkfd, message, sl_strlen(message) + 1, 0); if (nbytes < 0) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: sendto")); return -1; } list_cmd = list_cmd->next; } } list_cmd = cmdlist; while (list_cmd) { sl_snprintf(message, sizeof(message), _(">>>> %42s %32s %s"), list_cmd->cmd, list_cmd->clt, list_cmd->cti); nbytes = send (talkfd, message, sl_strlen(message) + 1, 0); if (nbytes < 0) { sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message (errno, errbuf, sizeof(errbuf)), _("sh_socket_read: sendto")); return -1; } list_cmd = list_cmd->next; } send (talkfd, _("END"), 4, 0); return 0; } static void sh_socket_add2list (struct socket_cmd * in) { struct socket_cmd * new = cmdlist; struct socket_cmd * last = cmdlist; while (new) { /* Only skip identical commands. */ if (0 == sl_strcmp(new->clt, in->clt) && 0 == sl_strcmp(new->cmd, in->cmd)) { (void) sh_unix_time(0, new->cti, sizeof(new->cti)); return; } new = new->next; } new = SH_ALLOC(sizeof(struct socket_cmd)); sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd)); sl_strlcpy (new->clt, in->clt, sizeof(new->clt)); (void) sh_unix_time(0, new->cti, sizeof(new->cti)); new->next = NULL; if (last) { while (last->next) { last = last->next; } last->next = new; } else { cmdlist = new; } return; } static void sh_socket_add2run (struct socket_cmd * in) { struct socket_cmd * new = runlist; struct socket_cmd * last = runlist; while (new) { /* Only skip identical commands. First 5 will * make all 'DELTA' identical. */ if (0 == sl_strcmp(new->clt, in->clt) && 0 == sl_strncmp(new->cmd, in->cmd, 5)) { sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd)); (void) sh_unix_time(0, new->cti, sizeof(new->cti)); return; } new = new->next; } new = SH_ALLOC(sizeof(struct socket_cmd)); sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd)); sl_strlcpy (new->clt, in->clt, sizeof(new->clt)); #ifdef SH_DEBUG_SOCKET fprintf(stderr, "add2run: time set for %s\n", new->clt); #endif (void) sh_unix_time(0, new->cti, sizeof(new->cti)); new->next = NULL; if (last) { while (last->next) { last = last->next; } last->next = new; } else { runlist = new; } return; } static void sh_socket_rm2list (const char * client_name, int remove_all) { struct socket_cmd * old = cmdlist; struct socket_cmd * new = cmdlist; while (new) { if (0 == sl_strcmp(new->clt, client_name)) { if ((new == cmdlist) && (new->next == NULL)) { /* There is only one entry */ cmdlist = NULL; SH_FREE(new); return; } else if (new == cmdlist) { /* first entry: new = old = cmdlist */ cmdlist = new->next; SH_FREE(new); if (remove_all == S_FALSE) return; old = cmdlist; new = cmdlist; continue; } else { old->next = new->next; SH_FREE(new); if (remove_all == S_FALSE) return; new = old; } } old = new; new = new->next; } return; } /* poll the socket to gather input */ int sh_socket_poll() { struct socket_cmd cmd; char cancel_cmd[SH_MAXMSGLEN]; /* struct pollfd sh_poll = { pf_unix_fd, POLLIN, 0 }; */ if (pf_unix_fd < 0) return 0; sl_strlcpy(cancel_cmd, _("CANCEL"), sizeof(cancel_cmd)); while (sh_socket_read (&cmd) > 0) { if (0 == sl_strcmp(cmd.cmd, cancel_cmd)) sh_socket_rm2list (cmd.clt, S_TRUE); else sh_socket_add2list (&cmd); } return 0; } /* return the command associated with client_name and remove the corresponding entry */ char * sh_socket_check(const char * client_name) { struct socket_cmd * new = cmdlist; static char out[SH_MAXMSGLEN]; while (new) { if (0 == sl_strcmp(new->clt, client_name)) { sl_strlcpy(out, new->cmd, sizeof(out)); sh_socket_add2run (new); sh_socket_rm2list (client_name, S_FALSE); return out; } new = new->next; } return NULL; } /* #if defined (SH_WITH_SERVER) */ #endif #ifdef SH_CUTEST #include "CuTest.h" void Test_cmdlist (CuTest *tc) { #if defined (SH_WITH_SERVER) struct socket_cmd cmd; char * p; sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); p = sh_socket_check("one"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "RELOAD", p); p = sh_socket_check("one"); CuAssertPtrEquals(tc, NULL, p); sh_socket_add2list (&cmd); sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "DELTA", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); p = sh_socket_check("one"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "RELOAD", p); sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); p = sh_socket_check("one"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "STOP", p); p = sh_socket_check("one"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "DELTA", p); p = sh_socket_check("one"); CuAssertPtrEquals(tc, NULL, p); /* Test removal in correct order */ sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.cmd, "DELTA", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.cmd, "FOOBAR", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sh_socket_rm2list ("one", S_FALSE); p = sh_socket_check("one"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "STOP", p); sh_socket_rm2list ("one", S_FALSE); p = sh_socket_check("one"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "FOOBAR", p); p = sh_socket_check("one"); CuAssertPtrEquals(tc, NULL, p); sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt)); sl_strlcpy(cmd.cmd, "DELTA", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sl_strlcpy(cmd.cmd, "FOOBAR", sizeof(cmd.cmd)); sh_socket_add2list (&cmd); sh_socket_rm2list ("one", S_TRUE); p = sh_socket_check("one"); CuAssertPtrEquals(tc, NULL, p); p = sh_socket_check("two"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "STOP", p); p = sh_socket_check("two"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "RELOAD", p); p = sh_socket_check("two"); CuAssertPtrEquals(tc, NULL, p); p = sh_socket_check("three"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "STOP", p); p = sh_socket_check("three"); CuAssertPtrNotNull(tc, p); CuAssertStrEquals(tc, "RELOAD", p); p = sh_socket_check("three"); CuAssertPtrEquals(tc, NULL, p); p = sh_socket_check("four"); CuAssertPtrEquals(tc, NULL, p); #else (void) tc; #endif } #endif /* #ifdef SH_CUTEST */ samhain-4.1.4/src/sh_sub.c0000644000175000017500000002505012615253277012313 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2011 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" /* 0->1 for debug */ #if 0 #define SH_SUB_DBG 1 #endif #ifndef NULL #if !defined(__cplusplus) #define NULL ((void*)0) #else #define NULL (0) #endif #endif #include #include #include #include #include #include #include #include #include #include #include "samhain.h" #include "sh_pthread.h" #ifndef HAVE_LSTAT #define lstat stat #endif #define FIL__ _("sh_sub.c") static pid_t sh_child_pid = -1; static pid_t sh_wait_ret = 1; static int parent2child[2]; static int child2parent[2]; SH_MUTEX_STATIC(mutex_sub, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_STATIC(mutex_sub_work, PTHREAD_MUTEX_INITIALIZER); static void wait_for_command(); static ssize_t sh_sub_read(int fd, void *buf, size_t count); void sh_kill_sub() { SH_MUTEX_LOCK(mutex_sub); if (sh_child_pid != -1) { int status; #ifdef WCONTINUED int wflags = WNOHANG|WUNTRACED|WCONTINUED; #else int wflags = WNOHANG|WUNTRACED; #endif close (parent2child[1]); close (child2parent[0]); /* Let's be rude. */ kill(sh_child_pid, SIGKILL); retry_msleep(1,0); if (sh_wait_ret == 0) sh_wait_ret = waitpid( -1, &status, wflags); else sh_wait_ret = waitpid(sh_child_pid, &status, wflags); sh_child_pid = -1; } SH_MUTEX_UNLOCK(mutex_sub); return; } static int sh_create_sub() { pid_t res; volatile int retval = 0; SH_MUTEX_LOCK(mutex_sub); #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif if (sh_child_pid == -1) { sigset_t signal_set_new; sigset_t signal_set_old; sigfillset ( &signal_set_new ); sigemptyset( &signal_set_old ); /* Create pipes. */ res = pipe (parent2child); if (res == 0) res = pipe (child2parent); if (res != 0) goto out; SH_SETSIGMASK(SIG_BLOCK, &signal_set_new, &signal_set_old); res = fork(); if (res == 0) { /* Child process. */ #ifdef _SC_OPEN_MAX int fdlimit = sysconf (_SC_OPEN_MAX); #else #ifdef OPEN_MAX int fdlimit = OPEN_MAX; #else int fdlimit = _POSIX_OPEN_MAX; #endif #endif int sflags, i, fd = 0; struct sigaction act; /* zero private information */ memset(skey, 0, sizeof(sh_key_t)); close (parent2child[1]); close (child2parent[0]); sflags = fcntl(parent2child[0], F_GETFL, 0); fcntl(parent2child[0], F_SETFL, sflags | O_NONBLOCK); sflags = fcntl(child2parent[1], F_GETFL, 0); fcntl(child2parent[1], F_SETFL, sflags | O_NONBLOCK); /* close inherited file descriptors */ if (fdlimit < 0) fdlimit = 20; /* POSIX lower limit */ while (fd < fdlimit) { if (fd != parent2child[0] && fd != child2parent[1]) close(fd); ++fd; } /* for (i = 0; i < 3; ++i) { if ( fcntl(i, F_GETFL, 0) == (-1)) (void) open(_("/dev/null"), O_RDWR, 0); } */ /* reset signal handling */ act.sa_handler = SIG_DFL; act.sa_flags = 0; sigemptyset( &act.sa_mask ); for (i = 1; i < NSIG; ++i) sigaction(i, &act, NULL); SH_SETSIGMASK(SIG_UNBLOCK, &signal_set_new, NULL); wait_for_command(); _exit(0); } else if (res > 0) { /* Parent process. */ int sflags; SH_SETSIGMASK(SIG_SETMASK, &signal_set_old, NULL); close (parent2child[0]); close (child2parent[1]); sflags = fcntl(parent2child[1], F_GETFL, 0); fcntl(parent2child[1], F_SETFL, sflags | O_NONBLOCK); sflags = fcntl(child2parent[0], F_GETFL, 0); fcntl(child2parent[0], F_SETFL, sflags | O_NONBLOCK); sh_child_pid = res; } else { /* Failure. */ SH_SETSIGMASK(SIG_SETMASK, &signal_set_old, NULL); close (parent2child[0]); close (parent2child[1]); close (child2parent[0]); close (child2parent[1]); retval = -1; } } out: ; /* 'label at end of compound statement' */ SH_MUTEX_UNLOCK(mutex_sub); return retval; } #define SH_SUB_BUF (PIPE_BUF-1) struct sh_sub_in { char command; char path[SH_SUB_BUF]; }; struct sh_sub_out { int retval; int errnum; struct stat sbuf; }; #define SH_COM_STAT 0 #define SH_COM_LSTAT 1 static ssize_t sh_sub_write(int fd, const void *buf, size_t count) { const char * mbuf = (const char *) buf; ssize_t rcount; int ttl = 5; /* 0, 1, 9, 81, 729 millisec */ int tti = 1; do { rcount = write(fd, mbuf, count); if (rcount > 0) { count -= rcount; mbuf += rcount; --ttl; } if (count > 0) { if (ttl > 0) { retry_msleep(0, tti); tti *= 9; } else { return -1; } } } while (count > 0 && (errno == EAGAIN || errno == EWOULDBLOCK)); if (count > 0) return -1; return 0; } static void wait_for_command() { int ret; struct pollfd fds; struct sh_sub_in inbuf; struct sh_sub_out outbuf; fds.fd = parent2child[0]; fds.events = POLLIN; do { do { ret = poll(&fds, 1, -1); } while (ret < 0 && errno == EINTR); if (ret > 0) { ret = sh_sub_read(parent2child[0], &inbuf, sizeof(inbuf)); if (ret == 0) { if (inbuf.command == SH_COM_LSTAT) { do { outbuf.retval = lstat(inbuf.path, &(outbuf.sbuf)); } while (outbuf.retval < 0 && errno == EAGAIN); } else { do { outbuf.retval = stat(inbuf.path, &(outbuf.sbuf)); } while (outbuf.retval < 0 && errno == EAGAIN); } outbuf.errnum = errno; ret = sh_sub_write(child2parent[1], &outbuf, sizeof(outbuf)); if (ret < 0) { return; } } else /* sh_sub_read() < 0 */ { return; } } } while (1 == 1); } #ifndef ETIMEDOUT #define ETIMEDOUT EIO #endif static ssize_t sh_sub_read(int fd, void *buf, size_t count) { char * mbuf = (char *) buf; ssize_t rcount; int ttl = 5; /* 0, 1, 9, 81, 729 millisec */ int tti = 1; do { rcount = read(fd, mbuf, count); if (rcount > 0) { count -= rcount; mbuf += rcount; --ttl; } if (count > 0) { if (ttl > 0) { retry_msleep(0, tti); tti *= 9; } else { if (rcount >= 0) errno = ETIMEDOUT; return -1; } } } while (count > 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)); if (count > 0) return -1; return 0; } #ifdef SH_SUB_DBG #include static void debug_it (const char *fmt, ...) { char msg[256]; va_list ap; int fd = open("debug.it", O_CREAT|O_WRONLY|O_APPEND, 0666); va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); /* flawfinder: ignore */ va_end(ap); write(fd, msg, strlen(msg)); write(fd, "\n", 1); close(fd); return; } #endif static int sh_sub_stat_int(const char *path, struct stat *buf, char command) { int retval; volatile int sflag = 0; struct sh_sub_in inbuf; struct sh_sub_out outbuf; struct pollfd pfds; size_t len = strlen(path) + 1; if (len > SH_SUB_BUF) { if (command == SH_COM_LSTAT) { do { retval = lstat(path, buf); } while (retval < 0 && errno == EAGAIN); return retval; } else { do { retval = stat(path, buf); } while (retval < 0 && errno == EAGAIN); return retval; } } sl_strlcpy(inbuf.path, path, SH_SUB_BUF); inbuf.command = command; start: #ifdef SH_SUB_DBG debug_it("%d sh_child_pid %d\n", (int)getpid(), (int) sh_child_pid); #endif if (sh_child_pid == -1) sh_create_sub(); #ifdef SH_SUB_DBG debug_it("%d stat_sub %s (%d)\n", (int)getpid(), inbuf.path, (int) sh_child_pid); #endif SH_MUTEX_LOCK(mutex_sub_work); retval = sh_sub_write(parent2child[1], &inbuf, sizeof(inbuf)); if (retval < 0) { int error = errno; sh_kill_sub(); errno = error; sflag = 1; goto end; } #ifdef SH_SUB_DBG debug_it("%d stat_sub polling..\n", (int)getpid()); #endif pfds.fd = child2parent[0]; pfds.events = POLLIN; do { retval = poll(&pfds, 1, 300 * 1000); } while (retval < 0 && errno == EINTR); if (retval <= 0) { int error = errno; sh_kill_sub(); errno = (retval == 0) ? ETIMEDOUT : error; sflag = -1; goto end; } #ifdef SH_SUB_DBG debug_it("%d stat_sub reading..\n", (int)getpid()); #endif retval = sh_sub_read (child2parent[0], &outbuf, sizeof(outbuf)); if (retval < 0) { int error = errno; sh_kill_sub(); errno = error; sflag = 1; goto end; } end: ; /* 'label at end of compound statement' */ SH_MUTEX_UNLOCK(mutex_sub_work); if (sflag == 0) { #ifdef SH_SUB_DBG debug_it("%d stat_sub done..\n", (int)getpid()); #endif memcpy(buf, &(outbuf.sbuf), sizeof(struct stat)); errno = outbuf.errnum; return outbuf.retval; } else if (sflag == 1) { #ifdef SH_SUB_DBG debug_it("%d stat_sub error..\n", (int)getpid()); #endif /* could not read, thus subprocess may have gone */ sflag = 0; goto start; } return -1; } int sh_sub_stat (const char *path, struct stat *buf) { return sh_sub_stat_int(path, buf, SH_COM_STAT); } int sh_sub_lstat(const char *path, struct stat *buf) { return sh_sub_stat_int(path, buf, SH_COM_LSTAT); } samhain-4.1.4/src/cutest_sh_tiger0.c0000644000175000017500000003615312615253277014311 00000000000000 #include "config_xor.h" #include #include #include #include "CuTest.h" #include "sh_tiger.h" #include "sh_checksum.h" #if defined(HAVE_PTHREAD) && defined(SH_STEALTH) extern void sh_g_init(void); #endif static void init(void) { extern unsigned char TcpFlag[8][PW_LEN+1]; extern UINT32 ErrFlag[2]; unsigned char * dez = NULL; int i; #if defined(HAVE_PTHREAD) && defined(SH_STEALTH) sh_g_init(); #endif skey = (sh_key_t *) malloc (sizeof(sh_key_t)); if (skey != NULL) { skey->mlock_failed = S_FALSE; skey->rngI = BAD; /* properly initialized later */ skey->rng0[0] = 0x03; skey->rng0[1] = 0x09; skey->rng0[2] = 0x17; skey->rng1[0] = 0x03; skey->rng1[1] = 0x09; skey->rng1[2] = 0x17; skey->rng2[0] = 0x03; skey->rng2[1] = 0x09; skey->rng2[2] = 0x17; for (i = 0; i < KEY_BYT; ++i) skey->poolv[i] = '\0'; skey->poolc = 0; skey->ErrFlag[0] = ErrFlag[0]; ErrFlag[0] = 0; skey->ErrFlag[1] = ErrFlag[1]; ErrFlag[1] = 0; dez = &(TcpFlag[POS_TF-1][0]); for (i = 0; i < PW_LEN; ++i) { skey->pw[i] = (char) (*dez); (*dez) = '\0'; ++dez; } skey->sh_sockpass[0] = '\0'; skey->sigkey_old[0] = '\0'; skey->sigkey_new[0] = '\0'; skey->mailkey_old[0] = '\0'; skey->mailkey_new[0] = '\0'; skey->crypt[0] = '\0'; skey->session[0] = '\0'; skey->vernam[0] = '\0'; } else { perror(_("sh_init")); _exit (EXIT_FAILURE); } } void Test_tiger(CuTest *tc) { char * input; char * actual; char * expected; char hashbuf[KEYBUF_SIZE]; #if defined(HAVE_PTHREAD) && defined(SH_STEALTH) sh_g_init(); #endif input = ""; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A"; CuAssertStrEquals(tc, expected, actual); input = "abc"; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "F258C1E88414AB2A527AB541FFC5B8BF935F7B951C132951"; CuAssertStrEquals(tc, expected, actual); input = "Tiger"; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "9F00F599072300DD276ABB38C8EB6DEC37790C116F9D2BDF"; CuAssertStrEquals(tc, expected, actual); input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "87FB2A9083851CF7470D2CF810E6DF9EB586445034A5A386"; CuAssertStrEquals(tc, expected, actual); input = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "467DB80863EBCE488DF1CD1261655DE957896565975F9197"; CuAssertStrEquals(tc, expected, actual); input = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "0C410A042968868A1671DA5A3FD29A725EC1E457D3CDB303"; CuAssertStrEquals(tc, expected, actual); input = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge."; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "EBF591D5AFA655CE7F22894FF87F54AC89C811B6B0DA3193"; CuAssertStrEquals(tc, expected, actual); input = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996."; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "3D9AEB03D1BD1A6357B2774DFD6D5B24DD68151D503974FC"; CuAssertStrEquals(tc, expected, actual); input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; actual = sh_tiger_hash(input, TIGER_DATA, strlen(input), hashbuf, sizeof(hashbuf)); expected = "00B83EB4E53440C576AC6AAEE0A7485825FD15E70A59FFE4"; CuAssertStrEquals(tc, expected, actual); } void Test_tiger_file(CuTest *tc) { SL_TICKET rval_open; FILE * fp; int result; char * actual; char * expected; char hashbuf[KEYBUF_SIZE]; char hexdigest[SHA256_DIGEST_STRING_LENGTH]; UINT64 length; init(); fp = fopen("cutest_foo", "w"); CuAssertPtrNotNull(tc, fp); result = fprintf(fp, "%s\n", "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"); CuAssertTrue(tc, result >= 0); result = fclose(fp); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("TIGER192"); CuAssertTrue(tc, result == 0); /* same result as GnuPG 1.0.6 (gpg --load-extension tiger --print-md TIGER192) */ length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "0E9321614C966A33608C2A15F156E0435CACFD1213B9F095"; CuAssertStrEquals(tc, expected, actual); rval_open = sl_open_fastread (__FILE__, __LINE__, "cutest_foo", SL_YESPRIV); CuAssertTrue(tc, rval_open >= 0); length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "0E9321614C966A33608C2A15F156E0435CACFD1213B9F095"; CuAssertStrEquals(tc, expected, actual); result = sl_close(rval_open); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("MD5"); CuAssertTrue(tc, result == 0); rval_open = sl_open_fastread (__FILE__, __LINE__, "cutest_foo", SL_YESPRIV); CuAssertTrue(tc, rval_open >= 0); /* same result as GNU md5sum */ length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "AEEC4DDA496BCFBA691F4E8863BA84C00000000000000000"; CuAssertStrEquals(tc, expected, actual); result = sl_close(rval_open); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("SHA1"); CuAssertTrue(tc, result == 0); rval_open = sl_open_fastread (__FILE__, __LINE__, "cutest_foo", SL_YESPRIV); CuAssertTrue(tc, rval_open >= 0); /* same result as gpg --print-md SHA1 */ length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "2FE65D1D995B8F8BC8B13F798C07E7E935A787ED00000000"; CuAssertStrEquals(tc, expected, actual); result = sl_close(rval_open); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("SHA256"); CuAssertTrue(tc, result == 0); rval_open = sl_open_fastread (__FILE__, __LINE__, "cutest_foo", SL_YESPRIV); CuAssertTrue(tc, rval_open >= 0); /* same result as gpg --print-md SHA256 */ length = TIGER_NOLIM; { char * tmp = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); actual = SHA256_Base2Hex(tmp, hexdigest); } expected = "235790848f95e96b2c627f1bf58a2b8c05c535ada8c0a3326aac34ce1391ad40"; CuAssertStrEquals(tc, expected, actual); result = sl_close(rval_open); CuAssertTrue(tc, result == 0); result = remove("cutest_foo"); CuAssertTrue(tc, result == 0); /* --------------------------------------------------- */ fp = fopen("cutest_foo", "w"); CuAssertPtrNotNull(tc, fp); result = fprintf(fp, "\n"); CuAssertTrue(tc, result >= 0); result = fclose(fp); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("TIGER192"); CuAssertTrue(tc, result == 0); /* same result as GnuPG 1.0.6 (gpg --load-extension tiger --print-md TIGER192) */ length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "F987845A0EA784367BF9E4DB09014995810F27C99C891734"; CuAssertStrEquals(tc, expected, actual); result = remove("cutest_foo"); CuAssertTrue(tc, result == 0); /* --------------------------------------------------- */ fp = fopen("cutest_foo", "w"); CuAssertPtrNotNull(tc, fp); result = fprintf(fp, "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.\n"); CuAssertTrue(tc, result >= 0); result = fclose(fp); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("TIGER192"); CuAssertTrue(tc, result == 0); /* same result as GnuPG 1.0.6 (gpg --load-extension tiger --print-md TIGER192) */ length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "75B98A7AE257A230189828A40792E30B4038D286479CC7B8"; CuAssertStrEquals(tc, expected, actual); result = remove("cutest_foo"); CuAssertTrue(tc, result == 0); } /* test checksum of file upto some given length */ void Test_tiger_file_with_length(CuTest *tc) { SL_TICKET rval_open; FILE * fp; int result; char * actual; char * expected; char hashbuf[KEYBUF_SIZE]; UINT64 length; char * teststring = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.\n"; size_t testlen = strlen(teststring); init(); fp = fopen("cutest_foo", "w"); CuAssertPtrNotNull(tc, fp); result = fprintf(fp, "%s", teststring); CuAssertTrue(tc, result >= 0); result = fprintf(fp, "%s", teststring); CuAssertTrue(tc, result >= 0); result = fclose(fp); CuAssertTrue(tc, result == 0); result = sh_tiger_hashtype("TIGER192"); CuAssertTrue(tc, result == 0); /* same as GnuPG 1.0.6 (gpg --load-extension tiger --print-md TIGER192) */ length = 0; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 0 == length); length = testlen; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "75B98A7AE257A230189828A40792E30B4038D286479CC7B8"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, testlen == length); length = 2*testlen; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "B5B4FB97B01ADB58794D87A6A01B2368852FA764BD93AB90"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 2*testlen == length); length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "B5B4FB97B01ADB58794D87A6A01B2368852FA764BD93AB90"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 2*testlen == length); fp = fopen("cutest_foo", "a"); CuAssertPtrNotNull(tc, fp); result = fprintf(fp, "%s", teststring); CuAssertTrue(tc, result >= 0); result = fclose(fp); CuAssertTrue(tc, result == 0); length = testlen; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "75B98A7AE257A230189828A40792E30B4038D286479CC7B8"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, testlen == length); length = 2*testlen; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "B5B4FB97B01ADB58794D87A6A01B2368852FA764BD93AB90"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 2*testlen == length); length = 3*testlen; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "D0EE1A9956CAB22D84B51A5E0C093B724828C6A1F9CBDB7F"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 3*testlen == length); length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "D0EE1A9956CAB22D84B51A5E0C093B724828C6A1F9CBDB7F"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 3*testlen == length); length = 5; actual = sh_tiger_generic_hash("cutest_foo", TIGER_FILE, &length, 0, hashbuf, sizeof(hashbuf)); expected = "9F00F599072300DD276ABB38C8EB6DEC37790C116F9D2BDF"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 5 == length); /* same results as GNU md5sum */ result = sh_tiger_hashtype("MD5"); CuAssertTrue(tc, result == 0); rval_open = sl_open_fastread (__FILE__, __LINE__, "cutest_foo", SL_YESPRIV); CuAssertTrue(tc, rval_open >= 0); length = testlen; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "11E7E7EA486136273606BEE57C71F34B0000000000000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, testlen == length); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = 2*testlen; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "D49DAD474095D467E2E5EFCB2DC23A770000000000000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 2*testlen == length); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = 3*testlen; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "00A1F1C5EDDCCFC430D3862FDA94593E0000000000000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 3*testlen == length); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "00A1F1C5EDDCCFC430D3862FDA94593E0000000000000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 3*testlen == length); /* same result as gpg --print-md SHA1 */ result = sh_tiger_hashtype("SHA1"); CuAssertTrue(tc, result == 0); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = testlen; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "F37DB4344CCD140EE315179E9A27512FB4704F0F00000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, testlen == length); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = 2*testlen; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "D2AD5FC366452D81400BAC31F96269DEEF314BC200000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 2*testlen == length); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = 3*testlen; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "FAA937EF3389C7E786EB0F1006D049D7AEA7B7B600000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 3*testlen == length); result = sl_rewind(rval_open); CuAssertTrue(tc, rval_open >= 0); length = TIGER_NOLIM; actual = sh_tiger_generic_hash("cutest_foo", rval_open, &length, 0, hashbuf, sizeof(hashbuf)); expected = "FAA937EF3389C7E786EB0F1006D049D7AEA7B7B600000000"; CuAssertStrEquals(tc, expected, actual); CuAssertTrue(tc, 3*testlen == length); result = sl_close(rval_open); CuAssertTrue(tc, result == 0); result = remove("cutest_foo"); CuAssertTrue(tc, result == 0); } samhain-4.1.4/src/sh_sem.c0000664000175000017500000001626512615253277012320 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000, 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #if defined(HAVE_SYS_SEM_H) && defined(HAVE_UNISTD_H) #include "samhain.h" #include "sh_sem.h" #include "sh_error_min.h" #include #include #include #include #include #include #undef FIL__ #define FIL__ _("sh_sem.c") typedef enum { exit_ok = 0, exit_fail = 1, exit_time = 2, exit_err = 3 } sh_estat; #if 0 /* FreeBSD 6.1 defines this in too... */ #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; struct semid_ds *buf; unsigned short *array; }; #endif #endif #define SH_SEMVMX 32767 static int get_semaphore (void) { key_t key = ftok(DEFAULT_DATAROOT, '#'); int semid; if (key < 0) return -1; semid = semget (key, 0, IPC_PRIVATE); if (semid < 0) return -1; return semid; } static void sem_purge(int sem_id) { if (sem_id != -1) semctl(sem_id, 0, IPC_RMID, (int)0); return; } static void sem_purge_stale() { int stale_ID = get_semaphore(); if (stale_ID != -1) sem_purge(stale_ID); return; } static int report_err(int errnum, char * file, int line, char * func) { char errbuf[SH_ERRBUF_SIZE]; sh_error_message(errnum, errbuf, sizeof(errbuf)); sh_error_handle((-1), file, line, errnum, MSG_E_SUBGEN, errbuf, func); return -1; } static int init_semaphore (int nsems) { int i; mode_t mask; int semid; int errnum; key_t key = ftok(DEFAULT_DATAROOT, '#'); if (key < 0) return report_err(errno, FIL__, __LINE__, _("ftok")); mask = umask(0); semid = semget (key, nsems, IPC_CREAT | IPC_EXCL | 0660); errnum = errno; umask(mask); if (semid < 0) return report_err(errnum, FIL__, __LINE__, _("semget")); for (i=0; i= 0) { val = (val > SH_SEMVMX) ? SH_SEMVMX : val; /* signed short int maxval */ sem_set(sem_ID, 1, (int) val); } SH_SEMAPHORE_UNLOCK(sem_ID); return; } void sh_sem_close() { SH_SEMAPHORE_PURGE(sem_ID); return; } static volatile int alarm_triggered = 0; static void alarm_handler(int sig) { (void) sig; alarm_triggered = 1; return; } int sh_sem_wait(const char * wait) { int rc, flag = 0; int time_wait = atoi(wait); SH_SEMAPHORE_EXTERN(sem_id); if (time_wait < 0) { time_wait *= (-1); time_wait -= 1; flag = 1; } if (time_wait < 0 || time_wait > (24*3600)) { fprintf(stderr, _("Invalid argument <%d>.\n"), time_wait); _exit(exit_err); } if (sem_id == -1) { if (flag && errno == ENOENT) { do { retry_msleep(1, 0); rc = get_semaphore(); } while (rc == -1); sem_id = rc; } else { if (errno == ENOENT) { fputs(_("Samhain IPC not initialized.\n"), stderr); _exit(exit_err); } else if (errno == EACCES) fputs(_("No permission to access Samhain IPC.\n"), stderr); _exit(exit_err); } } retry_msleep(0, 50); if (time_wait > 0) { signal(SIGALRM, alarm_handler); alarm(time_wait); } rc = SH_SEMAPHORE_LOCK(sem_id); if (rc == -1 && errno == EINTR) { if (alarm_triggered) { fputs(_("Timeout on wait.\n"), stderr); _exit(exit_time); } } else if (rc == -1) { if (errno == EACCES) fputs(_("No permission to access Samhain IPC.\n"), stderr); else perror(_("semop")); _exit(exit_err); } rc = sem_get(sem_id, 1); if (rc == 0) _exit(exit_ok); else if (rc == SH_SEMVMX) fprintf(stdout, _("%d or more issues reported\n"), rc); else fprintf(stdout, _("%d issues reported\n"), rc); _exit(exit_fail); } #else void sh_sem_open() { return; } void sh_sem_trylock() { return; } void sh_sem_lock() { return; } void sh_sem_unlock(long val) { (void) val; return; } void sh_sem_close() { return; } int sh_sem_wait(const char * wait) { (void) wait; fputs(_("Function not implemented (OS does not support SysV semaphores).\n"), stderr); exit(exit_err); } #endif /* defined(HAVE_SYS_SEM_H) && defined(HAVE_UNISTD_H) */ samhain-4.1.4/src/sh_gpg.c0000644000175000017500000006710612615253277012307 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #if defined(WITH_GPG) || defined(WITH_PGP) #include #include #include #if defined(SH_WITH_SERVER) #include #endif #include #include #include #include #include #ifdef HAVE_MEMORY_H #include #endif #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif #include "samhain.h" #include "sh_utils.h" #include "sh_error.h" #include "sh_tiger.h" #if defined(SH_WITH_SERVER) #define SH_NEED_PWD_GRP 1 #include "sh_static.h" #endif #include "sh_gpg.h" static struct { char conf_id[SH_MINIBUF+1]; char conf_fp[SH_MINIBUF+1]; char data_id[SH_MINIBUF+1]; char data_fp[SH_MINIBUF+1]; } gp; typedef struct { pid_t pid; FILE * pipe; } sh_gpg_popen_t; #define SH_GPG_OK 0 #define SH_GPG_BAD 1 #define SH_GPG_BADSIGN 2 /* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.' * for debugging */ #if 0 #define PDGBFILE "/pdbg." #endif #if defined(PDGBFILE) FILE * pdbg; FILE * pdbgc; #define PDBG_OPEN pdbg = fopen(PDGBFILE"main", "a") #define PDBG_CLOSE sl_fclose (FIL__, __LINE__, pdbg) #define PDBG(arg) fprintf(pdbg, "PDBG: step %d\n", arg); fflush(pdbg) #define PDBG_D(arg) fprintf(pdbg, "PDBG: %d\n", arg); fflush(pdbg) #define PDBG_S(arg) fprintf(pdbg, "PDBG: %s\n", arg); fflush(pdbg) #define PDBGC_OPEN pdbgc = fopen(PDGBFILE"child", "a") #define PDBGC_CLOSE sl_fclose (FIL__, __LINE__, pdbgc) #define PDBGC(arg) fprintf(pdbgc, "PDBG: step %d\n", arg); fflush(pdbgc) #define PDBGC_D(arg) fprintf(pdbgc, "PDBG: %d\n", arg); fflush(pdbgc) #define PDBGC_S(arg) fprintf(pdbgc, "PDBG: %s\n", arg); fflush(pdbgc) #else #define PDBG_OPEN #define PDBG_CLOSE #define PDBG(arg) #define PDBG_D(arg) #define PDBG_S(arg) #define PDBGC_OPEN #define PDBGC_CLOSE #define PDBGC(arg) #define PDBGC_D(arg) #define PDBGC_S(arg) #endif #undef FIL__ #define FIL__ _("sh_gpg.c") #ifdef GPG_HASH static int sh_gpg_checksum (SL_TICKET checkfd, int flag) { char * test_gpg; char * test_ptr1 = NULL; char * test_ptr2 = NULL; char wstrip1[128]; char wstrip2[128]; int i, k; #include "sh_gpg_chksum.h" SL_ENTER(_("sh_gpg_checksum")); test_gpg = sh_tiger_hash_gpg (DEFAULT_GPG_PATH, checkfd, TIGER_NOLIM); test_ptr1 = strchr(GPG_HASH, ':'); if (test_gpg != NULL) test_ptr2 = strchr(test_gpg, ':'); if (test_ptr2 != NULL) test_ptr2 += 2; else test_ptr2 = test_gpg; if (test_ptr1 != NULL) test_ptr1 += 2; else test_ptr1 = GPG_HASH; /* Tue Jun 24 23:11:54 CEST 2003 (1.7.9) -- strip whitespace */ k = 0; for (i = 0; i < 127; ++i) { if (test_ptr1[i] == '\0') break; if (test_ptr1[i] != ' ') { wstrip1[k] = test_ptr1[i]; ++k; } } wstrip1[k] = '\0'; for(i = 0; i < KEY_LEN; ++i) { if (gpgchk[i] != wstrip1[i]) { sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_CHK, gpgchk, wstrip1); break; } } k = 0; if (test_ptr2) { for (i = 0; i < 127; ++i) { if (test_ptr2[i] == '\0') break; if (test_ptr2[i] != ' ') { wstrip2[k] = test_ptr2[i]; ++k; } } } wstrip2[k] = '\0'; if (0 != sl_strncmp(wstrip1, wstrip2, 127)) { TPT(((0), FIL__, __LINE__, _("msg=\n"), test_gpg)); TPT(((0), FIL__, __LINE__, _("msg=\n"), GPG_HASH)); TPT(((0), FIL__, __LINE__, _("msg=\n"), wstrip1)); TPT(((0), FIL__, __LINE__, _("msg=\n"), wstrip2)); if (flag == 1) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_GPG, GPG_HASH, test_gpg); dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the gpg binary\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), wstrip1, wstrip2); SH_FREE(test_gpg); SL_RETURN((-1), _("sh_gpg_checksum")); } SH_FREE(test_gpg); SL_RETURN( (0), _("sh_gpg_checksum")); } #endif struct startup_info { long line; char * program; long uid; char * path; char * key_uid; char * key_id; }; static struct startup_info startInfo = { 0, NULL, 0, NULL, NULL, NULL }; void sh_gpg_log_startup (void) { if (startInfo.program != NULL) { sh_error_handle ((-1), FIL__, startInfo.line, 0, MSG_START_GH, startInfo.program, startInfo.uid, startInfo.path, startInfo.key_uid, startInfo.key_id); } return; } static void sh_gpg_fill_startup (long line, char * program, long uid, char * path, char * key_uid, char * key_id) { startInfo.line = line; startInfo.program = sh_util_strdup(program); startInfo.uid = uid; startInfo.path = sh_util_strdup(path); startInfo.key_uid = sh_util_strdup(key_uid); startInfo.key_id = sh_util_strdup(key_id); return; } static FILE * sh_gpg_popen (sh_gpg_popen_t *source, int fd, int mode, char * id, char * homedir) { extern int flag_err_debug; int pipedes[2]; FILE * outf = NULL; char * envp[2]; size_t len; char path[256]; char cc1[32]; char cc2[32]; char cc0[2] = "-"; char cc3[32]; char cc4[SH_PATHBUF+32]; char cc5[32]; char * arg[9]; #if defined(HAVE_GPG_CHECKSUM) SL_TICKET checkfd = -1; int myrand; int i; #if defined(__linux__) int get_the_fd(SL_TICKET); char pname[128]; int pfd; int val_return; #endif #endif SL_ENTER(_("sh_gpg_popen")); /* -- GnuPG -- */ sl_strlcpy (path, DEFAULT_GPG_PATH, 256); sl_strlcpy (cc1, _("--status-fd"), 32); sl_strlcpy (cc2, _("--verify"), 32); sl_strlcpy (cc3, _("--homedir"), 32); /* sl_strlcpy (cc4, sh.effective.home, SH_PATHBUF+32); */ sl_strlcpy (cc4, homedir, SH_PATHBUF+32); sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32); sl_strlcpy (cc5, _("--no-tty"), 32); /* fprintf(stderr, "YULE: homedir=%s\n", homedir); */ #if defined(SH_WITH_SERVER) if (0 == sl_ret_euid()) /* privileges not dropped yet */ { struct stat lbuf; int status_stat = 0; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) struct passwd pwd; char * buffer = SH_ALLOC(SH_PWBUF_SIZE); struct passwd * tempres; sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres); #else struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT); #endif if (!tempres) { dlog(1, FIL__, __LINE__, _("User %s does not exist. Please add the user to your system.\n"), DEFAULT_IDENT); status_stat = -1; } if (!tempres->pw_dir || tempres->pw_dir[0] == '\0') { dlog(1, FIL__, __LINE__, _("User %s does not have a home directory.\nPlease add the home directory for this user to your system.\n"), DEFAULT_IDENT); status_stat = -2; } if (status_stat == 0) { sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32); status_stat = retry_lstat(FIL__, __LINE__, cc4, &lbuf); if (status_stat == -1) { dlog(1, FIL__, __LINE__, _("Gnupg directory %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"), cc4, DEFAULT_IDENT); status_stat = -3; } } if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid) { dlog(1, FIL__, __LINE__, _("Gnupg directory %s\nis not owned by user %s.\n"), cc4, DEFAULT_IDENT); status_stat = -4; } if (status_stat == 0) { sl_strlcat (cc4, _("/pubring.gpg"), SH_PATHBUF+32); status_stat = retry_lstat(FIL__, __LINE__, cc4, &lbuf); if (status_stat == -1) { dlog(1, FIL__, __LINE__, _("Gnupg public keyring %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"), cc4, DEFAULT_IDENT); status_stat = -5; } } if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid) { dlog(1, FIL__, __LINE__, _("Gnupg public keyring %s\nis not owned by user %s.\n"), cc4, DEFAULT_IDENT); status_stat = -6; } if (status_stat != 0) { sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1, sh.prg_name); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) SH_FREE(buffer); #endif } #endif arg[0] = path; arg[1] = cc1; arg[2] = "1"; arg[3] = cc2; arg[4] = cc3; arg[5] = cc4; arg[6] = cc5; arg[7] = cc0; arg[8] = NULL; /* catch 'unused parameter' compiler warning */ (void) mode; (void) id; /* use homedir of effective user */ len = sl_strlen(sh.effective.home) + 6; envp[0] = calloc(1, len); /* free() ok */ if (envp[0] != NULL) sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home); envp[1] = NULL; /* Create the pipe */ if (aud_pipe(FIL__, __LINE__, pipedes) < 0) { if (envp[0] != NULL) free(envp[0]); SL_RETURN( (NULL), _("sh_gpg_popen")); } fflush (NULL); source->pid = aud_fork(FIL__, __LINE__); /* Failure */ if (source->pid == (pid_t) - 1) { sl_close_fd(FIL__, __LINE__, pipedes[0]); sl_close_fd(FIL__, __LINE__, pipedes[1]); if (envp[0] != NULL) free(envp[0]); SL_RETURN( (NULL), _("sh_gpg_popen")); } if (source->pid == (pid_t) 0) { /* child - make read side of the pipe stdout */ if (retry_aud_dup2(FIL__, __LINE__, pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) { TPT(((0), FIL__, __LINE__, _("msg=\n"))); dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n")); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } /* close the pipe descriptors */ sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]); sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]); if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0) { TPT(((0), FIL__, __LINE__, _("msg=\n"))); dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n")); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } /* don't leak file descriptors */ sh_unix_closeall (3, -1, S_TRUE); /* in child process */ if (flag_err_debug != S_TRUE) { if (NULL == freopen(_("/dev/null"), "r+", stderr)) { dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n")); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } } /* We should become privileged if SUID, * to be able to read the keyring. * We have checked that gpg is OK, * AND that only a trusted user could overwrite * gpg. */ memset (skey, '\0', sizeof(sh_key_t)); aud_setuid(FIL__, __LINE__, geteuid()); PDBGC_OPEN; PDBGC_D((int)getuid()); PDBGC_D((int)geteuid()); { int i = 0; while (arg[i] != NULL) { PDBGC_S(arg[i]); ++i; } } PDBGC_CLOSE; /* exec the program */ #if defined(__linux__) && defined(HAVE_GPG_CHECKSUM) /* * -- emulate an fexecve with checksum testing */ checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV); if (0 != sh_gpg_checksum(checkfd, 0)) { sl_close(checkfd); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } pfd = get_the_fd(checkfd); do { val_return = dup (pfd); } while (val_return < 0 && errno == EINTR); pfd = val_return; sl_close(checkfd); /* checkfd = -1; *//* never read */ sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd); if (0 == access(pname, R_OK|X_OK)) /* flawfinder: ignore */ { fcntl (pfd, F_SETFD, FD_CLOEXEC); retry_aud_execve (FIL__, __LINE__, pname, arg, envp); dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"), pname); /* failed */ aud__exit(FIL__, __LINE__, EXIT_FAILURE); } /* procfs not working, go ahead */ #endif #if defined(HAVE_GPG_CHECKSUM) /* This is an incredibly ugly kludge to prevent an attacker * from knowing when it is safe to slip in a fake executable * between the integrity check and the execve */ myrand = (int) taus_get (); myrand = (myrand < 0) ? (-myrand) : myrand; myrand = (myrand % 32) + 2; for (i = 0; i < myrand; ++i) { checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV); if (0 != sh_gpg_checksum(checkfd, 0)) { aud__exit(FIL__, __LINE__, EXIT_FAILURE); } sl_close(checkfd); } #endif retry_aud_execve (FIL__, __LINE__, DEFAULT_GPG_PATH, arg, envp); dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"), DEFAULT_GPG_PATH); /* failed */ TPT(((0), FIL__, __LINE__, _("msg=\n"))); dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n")); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } /* parent */ if (envp[0] != NULL) free(envp[0]); sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]); retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL, O_NONBLOCK); outf = fdopen (pipedes[STDIN_FILENO], "r"); if (outf == NULL) { aud_kill (FIL__, __LINE__, source->pid, SIGKILL); sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]); waitpid (source->pid, NULL, 0); source->pid = 0; SL_RETURN( (NULL), _("sh_gpg_popen")); } SL_RETURN( (outf), _("sh_gpg_popen")); } static int sh_gpg_pclose (sh_gpg_popen_t *source) { int status = 0; SL_ENTER(_("sh_gpg_pclose")); status = sl_fclose(FIL__, __LINE__, source->pipe); if (status) SL_RETURN( (-1), _("sh_gpg_pclose")); if (waitpid(source->pid, NULL, 0) != source->pid) status = -1; source->pipe = NULL; source->pid = 0; SL_RETURN( (status), _("sh_gpg_pclose")); } static int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp, char * homedir, int whichfile) { struct stat buf; char line[256]; sh_gpg_popen_t source; int have_id = BAD, have_fp = BAD, status = 0; #ifdef HAVE_GPG_CHECKSUM SL_TICKET checkfd; #endif SL_ENTER(_("sh_gpg_check_file_sign")); /* check whether GnuPG exists and has the correct checksum */ TPT(((0), FIL__, __LINE__, _("msg=\n"))); TPT(((0), FIL__, __LINE__, _("msg=\n"), DEFAULT_GPG_PATH)); if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_GPG_PATH, &buf)) { char errbuf[SH_ERRBUF_SIZE]; status = errno; sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT, sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_GPG_PATH); SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign")); } if (0 != tf_trust_check (DEFAULT_GPG_PATH, SL_YESPRIV)) SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign")); #ifdef HAVE_GPG_CHECKSUM checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_YESPRIV); if (0 != sh_gpg_checksum(checkfd, 1)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Checksum mismatch"), _("gpg_check_file_sign")); sl_close(checkfd); SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign")); } sl_close(checkfd); #endif TPT(((0), FIL__, __LINE__, _("msg=\n"))); fflush(NULL); source.pipe = sh_gpg_popen ( &source, fd, 0, NULL, homedir ); if (NULL == source.pipe) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Could not open pipe"), _("gpg_check_file_sign")); SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign")); } TPT(((0), FIL__, __LINE__, _("msg=\n"))); xagain: errno = 0; while (NULL != fgets(line, sizeof(line), source.pipe)) { TPT(((0), FIL__, __LINE__, _("msg=\n"), line)); if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = ' '; sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, line, _("gpg_check_file_sign")); if (sl_strlen(line) < 18) continue; /* Sun May 27 18:40:05 CEST 2001 */ if (0 == sl_strncmp(_("BADSIG"), &line[9], 6) || 0 == sl_strncmp(_("ERRSIG"), &line[9], 6) || 0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6) || 0 == sl_strncmp(_("NODATA"), &line[9], 6) || 0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) { if (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) { dlog(1, FIL__, __LINE__, _("%s file is signed, but the signature is invalid."), ((whichfile == 1) ? _("Configuration") : _("Database"))); } else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) { dlog(1, FIL__, __LINE__, _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), ((whichfile == 1) ? _("Configuration") : _("Database")), homedir); } else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) { dlog(1, FIL__, __LINE__, _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), ((whichfile == 1) ? _("Configuration") : _("Database")), homedir); } else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) { dlog(1, FIL__, __LINE__, _("%s file is signed, but the public key to verify the signature has expired."), ((whichfile == 1) ? _("Configuration") : _("Database"))); } else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) { dlog(1, FIL__, __LINE__, _("%s file is not signed."), ((whichfile == 1) ? _("Configuration") : _("Database"))); } have_fp = BAD; have_id = BAD; break; } if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7)) { sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1); if (sign_id) sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing '"' */ have_id = GOOD; } if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8)) { strncpy (sign_fp, &line[18], 40); sign_fp[40] = '\0'; have_fp = GOOD; } } if (ferror(source.pipe) && errno == EAGAIN) { /* sleep 10 ms to avoid starving the gpg child writing to the pipe */ retry_msleep(0,10); clearerr(source.pipe); goto xagain; } sh_gpg_pclose (&source); TPT(((0), FIL__, __LINE__, _("msg=\n"))); if (have_id == GOOD) { TPT(((0), FIL__, __LINE__, _("msg=\n"))); } if (have_fp == GOOD) { TPT(((0), FIL__, __LINE__, _("msg=\n"))); } if (have_id == GOOD && have_fp == GOOD) SL_RETURN( SH_GPG_OK, _("sh_gpg_check_file_sign")); else { if (have_id == BAD) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("No good signature"), _("gpg_check_file_sign")); else sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("No fingerprint for key"), _("gpg_check_file_sign")); SL_RETURN( SH_GPG_BADSIGN, _("sh_gpg_check_file_sign")); } } int get_the_fd(SL_TICKET file_1); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && \ defined(HAVE_GETPWNAM_R) #define USE_GETPWNAM_R 1 #endif int sh_gpg_check_sign (long file, int what) { int status = SH_GPG_BAD; int fd = 0; static int smsg = S_FALSE; char * tmp; char * sig_id; char * sig_fp; char * homedir = sh.effective.home; #if defined(SH_WITH_SERVER) struct passwd * tempres; #if defined(USE_GETPWNAM_R) struct passwd pwd; char * buffer = SH_ALLOC(SH_PWBUF_SIZE); #endif #endif #ifdef USE_FINGERPRINT #include "sh_gpg_fp.h" #endif SL_ENTER(_("sh_gpg_check_sign")); if (what == SIG_CONF) fd = get_the_fd(file); if (what == SIG_DATA) fd = get_the_fd(file); if (fd < 0) { TPT(((0), FIL__, __LINE__, _("msg=\n"), fd)); dlog(1, FIL__, __LINE__, _("This looks like an unexpected internal error.\n")); #if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R) SH_FREE(buffer); #endif SL_RETURN( (-1), _("sh_gpg_check_sign")); } #if defined(SH_WITH_SERVER) #if defined(USE_GETPWNAM_R) sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres); #else tempres = sh_getpwnam(DEFAULT_IDENT); #endif if ((tempres != NULL) && (0 == sl_ret_euid())) { /* privileges not dropped yet*/ homedir = tempres->pw_dir; } #endif if (what == SIG_CONF) { TPT(((0), FIL__, __LINE__, _("msg=\n"), fd)); status = sh_gpg_check_file_sign(fd, gp.conf_id, gp.conf_fp, homedir, 1); TPT(((0), FIL__, __LINE__, _("msg=\n"), gp.conf_id)); TPT(((0), FIL__, __LINE__, _("msg=\n"), gp.conf_fp)); sig_id = gp.conf_id; sig_fp = gp.conf_fp; } if (what == SIG_DATA) { TPT(((0), FIL__, __LINE__, _("msg=\n"), fd)); status = sh_gpg_check_file_sign(fd, gp.data_id, gp.data_fp, homedir, 2); TPT(((0), FIL__, __LINE__, _("msg=\n"), gp.data_id)); TPT(((0), FIL__, __LINE__, _("msg=\n"), gp.data_fp)); sig_id = gp.data_id; sig_fp = gp.data_fp; } if (SH_GPG_OK == status) { #ifdef USE_FINGERPRINT if ((sl_strcmp(SH_GPG_FP, sig_fp) == 0)) { int i; for(i = 0; i < (int) sl_strlen(sig_fp); ++i) { if (gpgfp[i] != sig_fp[i]) { sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_FP, gpgfp, sig_fp); break; } } if (smsg == S_FALSE) { tmp = sh_util_safe_name(sig_id); sh_gpg_fill_startup (__LINE__, sh.prg_name, sh.real.uid, (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), tmp, sig_fp); SH_FREE(tmp); } smsg = S_TRUE; #if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R) SH_FREE(buffer); #endif SL_RETURN(0, _("sh_gpg_check_sign")); } else { /* fp mismatch */ dlog(1, FIL__, __LINE__, _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"), sig_fp, SH_GPG_FP); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Fingerprint mismatch"), _("gpg_check_sign")); status = SH_GPG_BADSIGN; } #else /* ifdef USE_FINGERPRINT */ if (smsg == S_FALSE) { tmp = sh_util_safe_name(sig_id); sh_gpg_fill_startup (__LINE__, sh.prg_name, sh.real.uid, (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), tmp, sig_fp); SH_FREE(tmp); } smsg = S_TRUE; #if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R) SH_FREE(buffer); #endif SL_RETURN(0, _("sh_gpg_check_sign")); #endif /* !ifdef USE_FINGERPRINT */ } if (status != SH_GPG_OK) { uid_t e_uid = sl_ret_euid(); char * e_home = sh.effective.home; #if defined(SH_WITH_SERVER) #if defined(USE_GETPWNAM_R) struct passwd e_pwd; char * e_buffer = SH_ALLOC(SH_PWBUF_SIZE); struct passwd * e_tempres; sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres); #else struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT); #endif if ((e_tempres != NULL) && (0 == sl_ret_euid())) { /* privileges not dropped yet */ e_uid = e_tempres->pw_uid; e_home = e_tempres->pw_dir; } #endif dlog(1, FIL__, __LINE__, _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - gpg binary (%s) not found\n - invalid signature\n - the signature key is not in the private keyring of UID %d,\n - there is no keyring in %s/.gnupg, or\n - the file is not signed - did you move /filename.asc to /filename ?\nTo create a signed file, use (remove old signatures before):\n gpg -a --clearsign --not-dash-escaped FILE\n mv FILE.asc FILE\n"), DEFAULT_GPG_PATH, (int) e_uid, e_home); #if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R) SH_FREE(e_buffer); #endif } TPT(((0), FIL__, __LINE__, _("msg=\n"), status)); return (-1); /* make compiler happy */ } #define FGETS_BUF 16384 SL_TICKET sh_gpg_extract_signed(SL_TICKET fd) { FILE * fin_cp = NULL; char * buf = NULL; int bufc; int flag_pgp = S_FALSE; int flag_nohead = S_FALSE; SL_TICKET fdTmp = (-1); SL_TICKET open_tmp (void); /* extract the data and copy to temporary file */ fdTmp = open_tmp(); if (SL_ISERROR(fdTmp)) { dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Error opening temporary file."), _("sh_gpg_extract_signed")); return -1; } fin_cp = fdopen(dup(get_the_fd(fd)), "rb"); buf = SH_ALLOC(FGETS_BUF); while (NULL != fgets(buf, FGETS_BUF, fin_cp)) { bufc = 0; while (bufc < FGETS_BUF) { if (buf[bufc] == '\n') { ++bufc; break; } ++bufc; } if (flag_pgp == S_FALSE && (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))|| 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n"))) ) { flag_pgp = S_TRUE; sl_write(fdTmp, buf, bufc); continue; } if (flag_pgp == S_TRUE && flag_nohead == S_FALSE) { if (buf[0] == '\n') { flag_nohead = S_TRUE; sl_write(fdTmp, buf, 1); continue; } else if (0 == sl_strncmp(buf, _("Hash:"), 5) || 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15)) { sl_write(fdTmp, buf, bufc); continue; } else continue; } if (flag_pgp == S_TRUE && buf[0] == '\n') { sl_write(fdTmp, buf, 1); } else if (flag_pgp == S_TRUE) { /* sl_write_line(fdTmp, buf, bufc); */ sl_write(fdTmp, buf, bufc); } if (flag_pgp == S_TRUE && 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n"))) break; } SH_FREE(buf); sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */ sl_rewind (fdTmp); return fdTmp; } /* #ifdef WITH_GPG */ #endif samhain-4.1.4/src/slib.c0000644000175000017500000021607212615253277011767 00000000000000#include "config_xor.h" #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) #define _XOPEN_SOURCE 600 #define _BSD_SOURCE #endif #include #include #include #include #include #ifdef HAVE_STDINT_H /* for SIZE_MAX */ #include #endif #include #include #include #include #include #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) #include #endif #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #ifdef HAVE_MEMORY_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifndef FD_SET #define NFDBITS 32 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #endif /* !FD_SET */ #ifndef FD_SETSIZE #define FD_SETSIZE 32 #endif #ifndef FD_ZERO #define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p))) #endif #define SH_REAL_SET #include "slib.h" #include "sh_calls.h" #define SH_NEED_PWD_GRP 1 #include "sh_static.h" #include "sh_pthread.h" #include "sh_string.h" #undef FIL__ #define FIL__ _("slib.c") const uid_t sh_uid_neg = ((uid_t) -1); const gid_t sh_gid_neg = ((gid_t) -1); #undef BREAKEXIT #if defined(SCREW_IT_UP) && defined(__linux__) && defined(__i386__) #ifdef SH_DEBUG #define BREAKEXIT(expr) \ do { \ int ixi; \ for (ixi = 0; ixi < 8; ++ixi) { \ if ((*(volatile unsigned *)((unsigned) expr + ixi) & 0xff) == 0xcc) \ { dlog(0, FIL__, __LINE__, _("BREAKEXIT")); _exit(EXIT_FAILURE); } \ } \ } \ while (1 == 0) #else #define BREAKEXIT(expr) \ do { \ int ixi; \ for (ixi = 0; ixi < 8; ++ixi) { \ if ((*(volatile unsigned *)((unsigned) expr + ixi) & 0xff) == 0xcc) \ _exit(EXIT_FAILURE); \ } \ } \ while (1 == 0) #endif #else #define BREAKEXIT(expr) #endif /**************************************************************** * * The debug/trace subsystem * ****************************************************************/ int slib_do_trace = 0; int slib_trace_fd = -1; static char trace_log[256] = { '\0' }; static int trace_level = 0; static FILE * trace_fp = NULL; int sl_trace_use (const char * dummy) { (void) dummy; slib_do_trace = 1; return 0; } int sl_trace_file (const char * str) { if (!str) return -1; if (str[0] != '/') return -1; sl_strlcpy(trace_log, str, 256); return 0; } FILE * sl_tracefile_open(const char * file, const char * mode) { FILE * xp = NULL; slib_trace_fd = open(file, O_WRONLY|O_CREAT|O_APPEND, 0600); if (slib_trace_fd >= 0) xp = fdopen(slib_trace_fd, mode); return xp; } void sl_trace_in(const char * str, const char * file, int line) { int i; if (trace_log[0] == '\0') { fprintf(stderr, "++ "); for (i = 0; i < trace_level; ++i) fprintf(stderr, ". "); fprintf(stderr, "[%2d] %s \t - File %c%s%c at line %d\n", trace_level, str, 0x22, file, 0x22, line); } else if (!sl_is_suid()) { if (!trace_fp) trace_fp = sl_tracefile_open(trace_log, "a"); if (trace_fp) { fprintf(trace_fp, "++ "); for (i = 0; i < trace_level; ++i) fprintf(trace_fp, ". "); fprintf(trace_fp, "[%2d] %s \t - File %c%s%c at line %d\n", trace_level, str, 0x22, file, 0x22, line); fflush(trace_fp); } else { perror(_("sl_trace_in: fopen")); _exit(1); } } ++trace_level; } void sl_trace_out(const char * str, const char * file, int line) { int i; --trace_level; if (trace_level < 0) trace_level = 0; if (trace_log[0] == '\0') { fprintf(stderr, "-- "); for (i = 0; i < trace_level; ++i) fprintf(stderr, ". "); fprintf(stderr, _("[%2d] %s \t - File %c%s%c at line %d\n"), trace_level, str, 0x22, file, 0x22, line); } else if (!sl_is_suid()) { if (!trace_fp) trace_fp = sl_tracefile_open(trace_log, "a"); if (trace_fp) { fprintf(trace_fp, "-- "); for (i = 0; i < trace_level; ++i) fprintf(trace_fp, ". "); fprintf(trace_fp, _("[%2d] %s \t - File %c%s%c at line %d\n"), trace_level, str, 0x22, file, 0x22, line); fflush(trace_fp); } else { perror(_("sl_trace_out: fopen")); _exit(1); } } } extern int sh_log_console (const char * msg); static int dlogActive = 0; /* this is called from sh_error_setprint() */ void dlog_set_active(int flag) { dlogActive = flag; } /* flag = 0 debug messages * = 1 descriptive error messages * = 3 backtrace */ int dlog (int flag, const char * file, int line, const char *fmt, ...) { va_list ap; char val[81]; char msg[512]; char tmp[512]; int retval = 0; int i; #ifdef SH_STEALTH /* * do not even print descriptive failure messages in stealth mode */ if (dlogActive == 0) return 0; if (dlogActive == 1 && flag == 0) /* debug requires debug level */ return 0; #else if (dlogActive <= 1 && flag == 0) /* debug requires debug level */ return 0; #endif if (flag == 1) { sl_snprintf (val, 81, _("\n--------- %10s "), file); sl_strlcpy (msg, val, 80); sl_snprintf (val, 81, _(" --- %6d ---------\n"), line); sl_strlcat (msg, val, 80); sh_log_console (msg); } va_start (ap, fmt); if (flag == 1) sl_strlcpy(tmp, fmt, 512); else sl_strlcpy(tmp, fmt, 256); retval = strlen(tmp); if (retval > 0 && tmp[retval-1] == '\n') tmp[retval-1] = '\0'; retval = 0; if (flag == 1) { sl_vsnprintf (msg, 511, tmp, ap); } else { sl_strlcpy (msg, "## ", 256); for (i = 0; i < trace_level; ++i) sl_strlcat (msg, ". ", 256); sprintf (val, _("[%2d] "), trace_level); sl_strlcat (msg, val, 256); sl_vsnprintf (&msg[strlen(msg)], 255, tmp, ap); sl_snprintf (tmp, 255, _(" \t - File %c%s%c at line %d"), 0x22, file, 0x22, line); sl_strlcat (msg, tmp, 512); } va_end (ap); if (flag != 0 || sl_is_suid()) retval = sh_log_console (msg); else { if (trace_log[0] == '\0') { /* sh_log_console (msg); */ fprintf(stderr, "%s\n", msg); } else { if (!trace_fp) trace_fp = sl_tracefile_open(trace_log, "a"); if (trace_fp) { fprintf(trace_fp, "%s\n", msg); } else { perror(_("dlog: fopen")); _exit(1); } } } if (flag == 1) sh_log_console (_("\n----------------------------------------------\n")); return retval; } extern char aud_err_message[64]; static char alt_err_message[64]; char * sl_get_errmsg() { if (aud_err_message[0] == '\0') { sl_strlcpy(alt_err_message, sl_error_string(sl_errno), 64); return &alt_err_message[0]; } return &aud_err_message[0]; } #if defined(SL_DEBUG) #define SL_MAX_MYSTACK 128 static char sl_mystack[SL_MAX_MYSTACK][32]; static int sl_mystack_count = 0; void sl_stack_push(char * c, char * file, int line ) { if (slib_do_trace) sl_trace_in(c, file, line); if (c && sl_mystack_count < SL_MAX_MYSTACK) { strncpy(sl_mystack[sl_mystack_count], c, 31); sl_mystack[sl_mystack_count][31] = '\0'; ++sl_mystack_count; /* fprintf(stderr, "#%03d %s\n", sl_mystack_count, sl_mystack[sl_mystack_count-1]); */ } return; } void sl_stack_pop(char * c, char * file, int line) { if (slib_do_trace) sl_trace_out(c, file, line); if (sl_mystack_count > 0) { /* fprintf(stderr, " <- #%03d %s\n", sl_mystack_count, sl_mystack[sl_mystack_count-1]); */ --sl_mystack_count; } return; } void sl_stack_print() { int i; /* FILE * dfile; */ if (sl_mystack_count > 0) { sh_log_console(_("\nBacktrace:\n")); /* dlog(3, FIL__, __LINE__, _("\nBacktrace:\n")); */ for (i = 0; i < sl_mystack_count; ++i) sh_log_console(sl_mystack[i]); /* dlog(3, FIL__, __LINE__, _("#%03d %s\n"), i, sl_mystack[i]); */ } return; } #endif /* * The global errno. * On error, this is set to the return value of the function. */ long int sl_errno; /* ---------------------------------------------------------------- * * Capability routines * * ---------------------------------------------------------------- */ int sl_useCaps = 0; #ifdef FANCY_LIBCAP #include /* * While these routines are tested and work, we don't use POSIX * capabilities, as they don't seem to be useful (root can write * to root-owned files anyway). Things would be more interesting * if we could switch to a non-root UID with just a few capabilities * enabled. */ int sl_drop_cap () { int error; cap_t caps; cap_flag_t capflag; cap_flag_value_t capfval = CAP_CLEAR; cap_value_t capvals_e[] = { CAP_CHOWN, CAP_FOWNER, CAP_FSETID, CAP_LINUX_IMMUTABLE, CAP_MKNOD, CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW, CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_CHROOT, CAP_SYS_PACCT, CAP_SYS_PTRACE, CAP_SYS_RAWIO, CAP_SYS_RESOURCE, CAP_SYS_TIME, CAP_SYS_TTY_CONFIG, CAP_SETGID, CAP_SETUID, CAP_KILL, CAP_DAC_OVERRIDE, #if !defined(WITH_MESSAGE_QUEUE) CAP_IPC_OWNER, #endif CAP_SYS_MODULE, CAP_LEASE }; cap_value_t capvals_p[] = { CAP_CHOWN, CAP_LEASE, CAP_FSETID, CAP_LINUX_IMMUTABLE, CAP_MKNOD, CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW, CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_CHROOT, CAP_SYS_PACCT, CAP_SYS_PTRACE, CAP_SYS_RAWIO, CAP_SYS_RESOURCE, CAP_SYS_TIME, CAP_SYS_TTY_CONFIG, #if !defined(WITH_EXTERNAL) && !defined(HAVE_UNIX_RANDOM) CAP_SETGID, CAP_SETUID, CAP_KILL, #endif #if !defined(SH_USE_SUIDCHK) CAP_DAC_OVERRIDE, CAP_FOWNER, #endif #if !defined(WITH_MESSAGE_QUEUE) CAP_IPC_OWNER, #endif CAP_SYS_MODULE }; if (0 == sl_useCaps) /* 0 = S_FALSE */ { return 0; } if(NULL == (caps = cap_get_proc())) { return errno; } capflag = CAP_EFFECTIVE; if (0 != cap_set_flag(caps, capflag, sizeof(capvals_e)/sizeof(cap_value_t), capvals_e, capfval)) { error = errno; cap_free(caps); return error; } if (0 != cap_set_proc(caps)) { error = errno; cap_free(caps); return error; } capflag = CAP_PERMITTED; if (0 != cap_set_flag(caps, capflag, sizeof(capvals_p)/sizeof(cap_value_t), capvals_p, capfval)) { error = errno; cap_free(caps); return error; } if (0 != cap_set_proc(caps)) { error = errno; cap_free(caps); return error; } cap_free(caps); return 0; } int sl_drop_cap_int(int what) { #if defined(SL_DEBUG) char * captext; #endif cap_flag_t capflag = CAP_EFFECTIVE; cap_flag_value_t capfval = CAP_CLEAR; cap_value_t capvals_a[] = { CAP_SETGID, CAP_SETUID, CAP_KILL }; cap_value_t capvals_b[] = { CAP_DAC_OVERRIDE, CAP_FOWNER }; cap_value_t * capvals; int nvals; int error = 0; cap_t caps = cap_get_proc(); if (0 == sl_useCaps) /* 0 = S_FALSE */ { return 0; } if (caps == NULL) { return errno; } switch (what) { case 1: capvals = capvals_a; nvals = 3; capfval = CAP_CLEAR; break; case 2: capvals = capvals_a; nvals = 3; capfval = CAP_SET; break; case 3: capvals = capvals_b; nvals = 2; capfval = CAP_CLEAR; break; case 4: capvals = capvals_b; nvals = 2; capfval = CAP_SET; break; default: return (0); } if (0 != cap_set_flag(caps, capflag, nvals, capvals, capfval)) { error = errno; cap_free(caps); return error; } if (0 != cap_set_proc(caps)) { error = errno; cap_free(caps); return error; } #if defined(SL_DEBUG) captext = cap_to_text(caps, NULL); TPT(( 0, FIL__, __LINE__, _("msg=\n"), what, captext)); cap_free(captext); #endif cap_free(caps); return 0; } int sl_drop_cap_sub() { return sl_drop_cap_int(1); } int sl_get_cap_sub() { return sl_drop_cap_int(2); } int sl_drop_cap_qdel() { return sl_drop_cap_int(3); } int sl_get_cap_qdel() { return sl_drop_cap_int(4); } #else int sl_drop_cap () { return 0; } int sl_drop_cap_sub() { return 0; } int sl_get_cap_sub() { return 0; } int sl_drop_cap_qdel() { return 0; } int sl_get_cap_qdel() { return 0; } #endif /* ---------------------------------------------------------------- * * String handling routines * * ---------------------------------------------------------------- */ /* * Have memset in a different translation unit (i.e. this) to prevent * it to get optimized away */ void *sl_memset(void *s, int c, size_t n) { return memset(s, c,n); } #if !defined (VA_COPY) #if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32)) #define VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) #elif defined (VA_COPY_AS_ARRAY) #define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list)) #else /* va_list is a pointer */ #define VA_COPY(ap1, ap2) ((ap1) = (ap2)) #endif #endif #if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF) static size_t sl_printf_count (const char * fmt, va_list vl) { size_t length = 1; int fini = 0; int islong = 0; int islonglong = 0; int islongdouble = 0; char * string_arg; SL_ENTER(_("sl_printf_count")); if (fmt == NULL) SL_IRETURN(SL_ENULL, _("sl_printf_count")); while (*fmt) { if ( (*fmt) == '%' ) { /* a format specifier */ fmt++; /* point to first char after '%' */ fini = 0; islong = 0; islongdouble = 0; while (*fmt && (fini == 0) ) { switch (*fmt) { case '*': /* field width supplied by an integer */ length = length + va_arg (vl, int); ++fmt; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': length = length + strtol (fmt, (char**) &fmt, 10); /* strtol makes FastForward to first invalid char */ break; case 'l': /* 'long' modifier */ if (islong == 0) islong = 1; else { islonglong = 1; islong = 0; } ++fmt; break; case 'L': /* 'long double' modifier */ #ifdef HAVE_LONG_DOUBLE islongdouble = 1; #else islong = 1; #endif ++fmt; break; case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (islonglong == 1) #ifdef HAVE_LONG_LONG (void) va_arg (vl, long long); #else (void) va_arg (vl, long); #endif else if (islong == 1) (void) va_arg (vl, long); else (void) va_arg (vl, int); islong = 0; islonglong = 0; length = length + 24; ++fmt; fini = 1; break; case 'D': case 'O': case 'U': (void) va_arg (vl, long); length = length + 24; fmt++; fini = 1; break; case 'e': case 'E': case 'f': case 'g': #ifdef HAVE_LONG_DOUBLE if (islongdouble == 1) { (void) va_arg (vl, long double); islongdouble = 0; length = length + 20; } else #endif (void) va_arg (vl, double); length = length + 20; fini = 1; ++fmt; break; case 's': string_arg = va_arg (vl, char *); if (string_arg != NULL) length = length + sl_strlen (string_arg); else length = length + 16; fini = 1; ++fmt; break; case 'c': (void) va_arg (vl, int); length = length + 1; fini = 1; ++fmt; break; case 'p': case 'n': (void) va_arg (vl, void * ); length = length + 32; fini = 1; ++fmt; break; case '%': /* %% will print '%' */ length = length + 1; fini = 1; ++fmt; break; default: length = length + 1; ++fmt; break; } /* end switch */ } /* end parsing a single format specifier */ } else { length = length + 1; fmt++; } } SL_IRETURN(length, _("sl_printf_count")); } #endif /* #ifndef HAVE_VSNPRINTF */ /* * An implementation of vsnprintf. va_start/va_end are in the caller * function. * Returns C99 (#bytes that would heve been written) on success. */ int sl_vsnprintf(char *str, size_t n, const char *format, va_list vl ) { int len = 0; #if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF) size_t total; va_list vl2; #endif SL_ENTER(_("sl_vsnprintf")); if (str == NULL || format == NULL) SL_IRETURN(0, _("sl_vsnprintf")); #if defined(HAVE_VSNPRINTF) && !defined(HAVE_BROKEN_VSNPRINTF) len = vsnprintf (str, n, format, vl); /* flawfinder: ignore */ str[n-1] = '\0'; #else VA_COPY (vl2, vl); /* save the argument list */ total = sl_printf_count (format, vl); len = (int) total; if (total < n) { /* flawfinder: ignore */ vsprintf (str, format, vl2); /* program has checked that it fits */ str[n-1] = '\0'; } else { sl_strlcpy (str, format, n); va_end(vl2); SL_IRETURN(len, _("sl_vsnprintf")); } va_end(vl2); #endif SL_IRETURN(len, _("sl_vsnprintf")); } /* * An implementation of snprintf. * Returns SL_ENONE on success. * ENULL: src || format == NULL * ERANGE: n out of range * ETRUNC: truncated (unimplemented) */ int sl_snprintf(char *str, size_t n, const char *format, ... ) { va_list vl; #if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF) size_t total = 0; va_list vl2; #endif SL_ENTER(_("sl_snprintf")); if (str == NULL || format == NULL) SL_IRETURN(SL_ENULL, _("sl_snprintf")); va_start (vl, format); #if defined(HAVE_VSNPRINTF) && !defined(HAVE_BROKEN_VSNPRINTF) /* flawfinder: ignore */ vsnprintf (str, n, format, vl); str[n-1] = '\0'; #else VA_COPY (vl2, vl); /* save the argument list */ total = sl_printf_count (format, vl); if (total < n) { /* flawfinder: ignore */ vsprintf (str, format, vl2); /* program has checked that it fits */ str[n-1] = '\0'; } else { sl_strlcpy (str, format, n); va_end(vl2); va_end(vl); SL_IRETURN(SL_ETRUNC, _("sl_snprintf")); } va_end(vl2); #endif va_end(vl); SL_IRETURN(SL_ENONE, _("sl_snprintf")); } /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns SL_NONE on success, errcode on failure. * * ENULL: dst == NULL * ERANGE: siz out of range * ETRUNC: src truncated */ int sl_strlcat(char * dst, /*@null@*/const char *src, size_t siz) { register size_t dst_end; register size_t dst_free; register char * p; register const char * q; if (!(dst == NULL || src == NULL || *src == '\0')) { if (siz > 0) { /* How much free space do we have ? */ dst_end = strlen(dst); dst_free = siz - dst_end - 1; p = &dst[dst_end]; q = src; while (dst_free > 0 && *q != '\0') { *p++ = *q++; --dst_free; } /* NULL terminate dst. */ *p = '\0'; if (*q == '\0') return SL_ENONE; else return SL_ETRUNC; } } return SL_ENONE; } /* * An alternative implementation of the OpenBSD strlcpy() function. * * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns SL_NONE on success, errcode on failure. * * ENULL: dst == NULL * ERANGE: siz out of range * ETRUNC: src truncated */ int sl_strlcpy(char * dst, /*@null@*/const char * src, size_t siz) { /* SL_ENTER(_("sl_strlcpy")); */ if (!((dst == NULL) || (src == NULL))) { if (siz > 0) { /* copy siz-1 characters */ (void) strncpy(dst, src, siz-1); /* NULL terminate */ dst[siz-1] = '\0'; } return SL_ENONE; } else if (src == NULL) { if (dst && siz > 0) dst[0] = '\0'; return SL_ENONE; } else { return SL_ENULL; } } /* * A robust drop-in replacement of strncpy. strlcpy is preferable. */ char * sl_strncpy(char *dst, const char *src, size_t size) { #ifdef SL_FAIL_ON_ERROR SL_REQUIRE(dst != NULL, _("dst != NULL")); SL_REQUIRE(src != NULL, _("src != NULL")); SL_REQUIRE(size > 0, _("size > 0")); #endif if (dst == NULL) { sl_errno = SL_ENULL; return (NULL); } if (size < 1) { sl_errno = SL_ERANGE; return (dst); } if (!src) { sl_errno = SL_ENULL; dst[0] = '\0'; } else if (src[0] == '\0') dst[0] = '\0'; else strncpy(dst, src, size); if (sl_strlen(src) >= size) { errno = ENOSPC; dst[size-1] = '\0'; } return (dst); } /* * A robust drop-in replacement of strncat. strlcat is preferable. */ char * sl_strncat(char *dst, const char *src, size_t n) { #ifdef SL_FAIL_ON_ERROR SL_REQUIRE(dst != NULL, _("dst != NULL")); SL_REQUIRE(src != NULL, _("src != NULL")); SL_REQUIRE(n > 0, _("n > 0")); #endif if (dst == NULL) { sl_errno = SL_ENULL; return (NULL); } if (n < 1) { sl_errno = SL_ERANGE; return (dst); } if (!src) { sl_errno = SL_ENULL; return (dst); } else if (src[0] == '\0') dst[0] = '\0'; else strncat(dst, src, n); return (dst); } #include int sl_strcasecmp(const char * one, const char * two) { #ifdef SL_FAIL_ON_ERROR SL_REQUIRE (one != NULL, _("one != NULL")); SL_REQUIRE (two != NULL, _("two != NULL")); #endif if (one && two) { do { if (*one && *two) { if (tolower((int) *one) == tolower((int) *two)) { ++one; ++two; } else if (tolower((int) *one) < tolower((int) *two)) return -1; else return 1; } else if (*one == '\0' && *two == '\0') return 0; else if (*one == '\0') return -1; else return 1; } while (1 == 1); } else if (one == NULL && two != NULL) return -1; else if (one != NULL && two == NULL) return 1; else return -7; /* default to not equal */ } int sl_strcmp(const char * a, const char * b) { #ifdef SL_FAIL_ON_ERROR SL_REQUIRE (a != NULL, _("a != NULL")); SL_REQUIRE (b != NULL, _("b != NULL")); #endif if (a != NULL && b != NULL) return (strcmp(a, b)); else if (a == NULL && b != NULL) return (-1); else if (a != NULL && b == NULL) return (1); else return (-7); /* default to not equal */ } int sl_strncmp(const char * a, const char * b, size_t n) { #ifdef SL_FAIL_ON_ERROR SL_REQUIRE (a != NULL, _("a != NULL")); SL_REQUIRE (b != NULL, _("b != NULL")); SL_REQUIRE (n > 0, _("n > 0")); #endif if (a != NULL && b != NULL) return (strncmp(a, b, n)); else if (a == NULL && b != NULL) return (-1); else if (a != NULL && b == NULL) return (1); else return (-7); /* default to not equal */ } int sl_strncasecmp(const char * a, const char * b, size_t n) { #ifdef SL_FAIL_ON_ERROR SL_REQUIRE (a != NULL, _("a != NULL")); SL_REQUIRE (b != NULL, _("b != NULL")); SL_REQUIRE (n > 0, _("n > 0")); #endif if (a != NULL && b != NULL) return (strncasecmp(a, b, n)); else if (a == NULL && b != NULL) return (-1); else if (a != NULL && b == NULL) return (1); else return (-7); /* default to not equal */ } /* string searching */ char * sl_strstr (const char * haystack, const char * needle) { #ifndef HAVE_STRSTR unsigned int i; size_t needle_len; size_t haystack_len; #endif if (haystack == NULL || needle == NULL) return NULL; if (*needle == '\0' || *haystack == '\0') return NULL; #if defined(HAVE_STRSTR) return (strstr(haystack, needle)); #else needle_len = strlen(needle); haystack_len = strlen(haystack); for (i = 0; i <= (haystack_len-needle_len); ++i) if (0 == sl_strncmp(&haystack[i], needle, needle_len)) return (needle); return NULL; #endif } /* ---------------------------------------------------------------- * * Privilege handling routines * * ---------------------------------------------------------------- */ static uid_t euid; static uid_t ruid; static uid_t ruid_orig; static gid_t egid; static gid_t rgid; static gid_t rgid_orig; static int uids_are_stored = S_FALSE; static int suid_is_set = S_TRUE; #ifdef HAVE_SETRESUID extern int setresuid (uid_t truid, uid_t teuid, uid_t tsuid); extern int setresgid (gid_t trgid, gid_t tegid, gid_t tsgid); #endif /* * This function returns true if the program is SUID. * It calls abort() if the uid's are not saved already. */ int sl_is_suid() { if (uids_are_stored == S_FALSE) { if (getuid() == geteuid() && getgid() == getegid()) return (0); /* FALSE */ else return (1); /* TRUE */ } else { if (euid == ruid && egid == rgid) return (0); /* FALSE */ else return (1); /* TRUE */ } } /* * This function returns the saved euid. * It calls abort() if the uid's are not saved already. */ int sl_get_euid(uid_t * ret) { SL_ENTER(_("sl_get_euid")); /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) *ret = euid; else *ret = geteuid(); SL_IRETURN (SL_ENONE, _("sl_get_euid")); } uid_t sl_ret_euid() { /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) return (euid); else return (geteuid()); } /* * This function returns the saved egid. * It calls abort() if the uid's are not saved already. */ int sl_get_egid(gid_t * ret) { SL_ENTER(_("sl_get_egid")); /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) *ret = egid; else *ret = getegid(); SL_IRETURN (SL_ENONE, _("sl_get_egid")); } /* * This function returns the saved ruid. * It calls abort() if the uid's are not saved already. */ int sl_get_ruid(uid_t * ret) { SL_ENTER(_("sl_get_ruid")); /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) *ret = ruid; else *ret = getuid(); SL_IRETURN (SL_ENONE, _("sl_get_ruid")); } /* * This function returns the saved rgid. * It calls abort() if the uid's are not saved already. */ int sl_get_rgid(gid_t * ret) { SL_ENTER(_("sl_get_rgid")); /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) *ret = rgid; else *ret = getgid(); SL_IRETURN (SL_ENONE, _("sl_get_rgid")); } /* * This function returns the saved original ruid. * It calls abort() if the uid's are not saved already. */ int sl_get_ruid_orig(uid_t * ret) { SL_ENTER(_("sl_get_ruid_orig")); /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) *ret = ruid_orig; else *ret = getuid(); SL_IRETURN (SL_ENONE, _("sl_get_ruid_orig")); } /* * This function returns the saved original rgid. * It calls abort() if the uid's are not saved already. */ int sl_get_rgid_orig(gid_t * ret) { SL_ENTER(_("sl_get_rgid_orig")); /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/ if (uids_are_stored == S_TRUE) *ret = rgid_orig; else *ret = getgid(); SL_IRETURN (SL_ENONE, _("sl_get_rgid_orig")); } static int suid_warn_flag = 1; static void suid_warn(int a) { fprintf(stderr, _("ERROR: open set/unset suid !!! %d\n"), a); return; } /* * This function sets the effective uid * to the saved effective uid. * It will abort on failure. */ int sl_set_suid () { int retval; SL_ENTER(_("sl_set_suid")); if (uids_are_stored == S_FALSE) { SL_IRETURN(SL_ENONE, _("sl_set_suid")); } SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE")); if (ruid == euid && rgid == egid) { suid_is_set = S_TRUE; SL_IRETURN(SL_ENONE, _("sl_set_suid")); } SL_REQUIRE(suid_is_set == S_FALSE, _("suid_is_set == S_FALSE")); #if defined(HAVE_SETRESUID) retval = setresuid (sh_uid_neg, euid, sh_uid_neg); if (retval == 0) retval = setresgid (sh_gid_neg, egid, sh_gid_neg); #elif defined(HAVE_SETEUID) retval = seteuid (egid); if (retval == 0) retval = setegid (euid); /* on AIX, setreuid does not behave well for non-root users. */ #elif defined(HAVE_SETREUID) retval = setreuid (ruid, euid); if (retval == 0) retval = setregid (rgid, egid); #else retval = setuid (euid); if (retval == 0) retval = setgid (egid); #endif if (suid_warn_flag == 1) suid_warn(1); suid_warn_flag = 1; SL_REQUIRE(retval == 0, _("retval == 0")); suid_is_set = S_TRUE; SL_IRETURN(SL_ENONE, _("sl_set_suid")); } /* * This function sets the effective uid to the real uid. * It will abort on failure. */ int sl_unset_suid () { register int retval; SL_ENTER(_("sl_unset_suid")); if (uids_are_stored == S_FALSE) { SL_IRETURN(SL_ENONE, _("sl_unset_suid")); } SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE")); if (ruid == euid && rgid == egid) { suid_is_set = S_FALSE; SL_IRETURN(SL_ENONE, _("sl_unset_suid")); } SL_REQUIRE(suid_is_set == S_TRUE, _("suid_is_set == S_TRUE")); #if defined(HAVE_SETRESUID) retval = setresgid (sh_gid_neg, rgid, sh_gid_neg); if (retval == 0) retval = setresuid (sh_uid_neg, ruid, sh_uid_neg); #elif defined(HAVE_SETEUID) retval = setegid (rgid); if (retval == 0) retval = seteuid (ruid); #elif defined(HAVE_SETREUID) retval = setregid (egid, rgid); if (retval == 0) retval = setreuid (euid, ruid); #else retval = setgid (rgid); if (retval == 0) retval = setuid (ruid); #endif if (suid_warn_flag == 0) suid_warn(0); suid_warn_flag = 0; SL_REQUIRE(retval == 0, _("retval == 0")); suid_is_set = S_FALSE; SL_IRETURN(SL_ENONE, _("sl_unset_suid")); } /* * This function saves the uid's. */ int sl_save_uids() { SL_ENTER(_("sl_save_uids")); if (uids_are_stored == S_TRUE) SL_IRETURN(SL_EREPEAT, _("sl_save_uids")); ruid_orig = getuid(); rgid_orig = getgid(); egid = getegid(); euid = geteuid(); ruid = ruid_orig; rgid = rgid_orig; uids_are_stored = S_TRUE; SL_IRETURN(SL_ENONE, _("sl_save_uids")); } /* * This function drops SUID privileges irrevocably. * It set the effective uid to the original real uid. */ extern int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid); int sl_drop_privileges() { SL_ENTER(_("sl_drop_privileges")); SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE")); SL_REQUIRE(setgid(rgid_orig) == 0, _("setgid(rgid_orig) == 0")); SL_REQUIRE(sh_unix_initgroups2(ruid_orig, rgid_orig) == 0, _("sh_unix_initgroups2(ruid_orig,rgid_orig) == 0")); SL_REQUIRE(setuid(ruid_orig) == 0, _("setuid(ruid_orig) == 0")); /* make sure that setuid(0) fails */ SL_REQUIRE(setuid(0) < 0, _("setuid(0) < 0")); euid = ruid_orig; egid = rgid_orig; ruid = ruid_orig; rgid = rgid_orig; SL_IRETURN(SL_ENONE, _("sl_drop_privileges")); } /* * Define a policy: Stay root. * Do nothing if not SUID. */ int sl_policy_get_root() { SL_ENTER(_("sl_policy_get_root")); SL_REQUIRE(uids_are_stored == S_FALSE, _("uids_are_stored == S_FALSE")); SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE")); if (euid != ruid || egid != rgid) { SL_REQUIRE(setgid(egid) == 0, _("setgid(egid) == 0")); SL_REQUIRE(setuid(euid) == 0, _("setuid(euid) == 0")); SL_REQUIRE(ruid == getuid() && rgid == getgid(), _("ruid == getuid() && rgid == getgid()")); ruid = euid; rgid = egid; } suid_is_set = S_TRUE; if (euid == 0) { SL_REQUIRE(sh_unix_initgroups2(euid, egid) == 0, _("sh_unix_initgroups2(euid,egid) == 0")); } SL_IRETURN(SL_ENONE, _("sl_policy_get_root")); } #include /* * Define a policy: Get real (irrevocably). * This function drops SUID privileges irrevocably. * Do nothing if not SUID (? not true - drops if root). */ int sl_policy_get_real(char * user) { SL_ENTER(_("sl_policy_get_real")); SL_REQUIRE(uids_are_stored == S_FALSE, _("uids_are_stored == S_FALSE")); SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE")); if (euid == 0 || ruid == 0) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) struct passwd pwd; char * buffer; struct passwd * tempres; buffer = calloc(1,SH_PWBUF_SIZE); SL_REQUIRE (buffer != NULL, _("buffer != NULL")); sh_getpwnam_r(user, &pwd, buffer, SH_PWBUF_SIZE, &tempres); #else struct passwd * tempres = sh_getpwnam(user); #endif SL_REQUIRE (NULL != tempres, _("tempres != NULL")); rgid_orig = tempres->pw_gid; ruid_orig = tempres->pw_uid; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) free(buffer); #endif } else { rgid_orig = rgid; ruid_orig = ruid; } SL_REQUIRE (sl_drop_privileges() == SL_ENONE, _("sl_drop_privileges() == SL_ENONE")); suid_is_set = S_TRUE; SL_IRETURN(SL_ENONE, _("sl_policy_get_real")); } /* * Define a policy: Get user. * Drops privileges. * Do nothing if not SUID. */ int sl_policy_get_user(const char * user) { SL_ENTER(_("sl_policy_get_user")); SL_REQUIRE(user != NULL, _("user != NULL")); SL_REQUIRE(uids_are_stored == S_FALSE, _("uids_are_stored == S_FALSE")); SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE")); #ifndef SH_ALLOW_SUID if (euid != ruid || egid != rgid) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) struct passwd pwd; char * buffer; struct passwd * tempres; buffer = calloc(1,SH_PWBUF_SIZE); SL_REQUIRE (buffer != NULL, _("buffer != NULL")); sh_getpwnam_r(user, &pwd, buffer, SH_PWBUF_SIZE, &tempres); #else struct passwd * tempres = sh_getpwnam(user); #endif SL_REQUIRE (NULL != tempres, _("tempres != NULL")); SL_REQUIRE (sl_drop_privileges() == SL_ENONE, _("sl_drop_privileges() == SL_ENONE")); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) free(buffer); #endif } #endif SL_IRETURN(SL_ENONE, _("sl_policy_get_user")); } /* ---------------------------------------------------------------- * * File access routines * * ---------------------------------------------------------------- */ #define TOFFSET 0x1234 /* this would prevent opening files if the first 16 fds are open :( */ /* #define MAXFD FOPEN_MAX */ #define MAXFD 1024 typedef struct openfiles { SL_TICKET ticket; /* The unique ID. */ int fd; /* The file descriptor. */ FILE * stream; /* The file descriptor. */ char * path; /* The file path. */ int flush; /* Whether we want to flush the cache */ char ofile[SL_OFILE_SIZE]; /* origin file */ int oline; /* origin line */ sh_string * content; /* The file content */ } SL_OFILE; static SL_OFILE * ofiles[MAXFD]; static char stale_orig_file[64] = { '\0' }; static int stale_orig_line = -1; static char stale_orig_mesg[128]; static char badfd_orig_file[64] = { '\0' }; static int badfd_orig_line = -1; static char badfd_orig_mesg[128]; char * sl_check_stale() { if (stale_orig_line == -1) return NULL; sl_snprintf(stale_orig_mesg, sizeof(stale_orig_mesg), _("stale handle, %s, %d"), stale_orig_file, stale_orig_line); stale_orig_file[0] = '\0'; stale_orig_line = -1; return stale_orig_mesg; } char * sl_check_badfd() { if (badfd_orig_line == -1) return NULL; sl_snprintf(badfd_orig_mesg, sizeof(badfd_orig_mesg), _("close on file descriptor with allocated handle, %s, %d"), badfd_orig_file, badfd_orig_line); badfd_orig_file[0] = '\0'; badfd_orig_line = -1; return badfd_orig_mesg; } typedef struct { volatile unsigned int atom; } atomic_t; static atomic_t nonce_counter = { TOFFSET }; #if defined(__GNUC__) && (defined(__i486__) || defined(__x86_64__)) /* from linux/include/asm-i386/atomic.h */ static unsigned int atomic_add ( unsigned int i, atomic_t *var) { unsigned int j = i; __asm__ __volatile__ ("lock; xaddl %0, %1" : "+r" (i), "+m" (var->atom) : : "memory"); return j+i; } #else SH_MUTEX_STATIC(mutex_ticket, PTHREAD_MUTEX_INITIALIZER); static unsigned int atomic_add ( unsigned int i, atomic_t *var) { volatile unsigned int j; SH_MUTEX_LOCK_UNSAFE(mutex_ticket); var->atom += i; j = var->atom; SH_MUTEX_UNLOCK_UNSAFE(mutex_ticket); return j; } #endif static SL_TICKET sl_create_ticket (unsigned int myindex) { unsigned int high; /* index */ unsigned int low; /* nonce */ SL_TICKET retval = SL_EINTERNAL; unsigned int nonce;/* nonce */ SL_ENTER(_("sl_create_ticket")); if (myindex >= MAXFD) { retval = SL_EINTERNAL01; goto out_ticket; } /* mask out the high bit and check that it is not used * -> verify that it fits into 16 bits as positive */ high = (myindex + TOFFSET) & 0x7fff; if (high != myindex + TOFFSET) { retval = SL_EINTERNAL02; goto out_ticket; } nonce = atomic_add(1, &nonce_counter); /* Wrap around the nonce counter. * This is a dirty trick. */ if (nonce > 0x7fff) { nonce_counter.atom = TOFFSET; nonce = atomic_add(1, &nonce_counter); } low = nonce & 0xffff; /* Overflow -> nonce too big. */ if ((low != nonce) || low == 0) { retval = SL_EINTERNAL03; goto out_ticket; } retval = (SL_TICKET) ((high << 16) | low); out_ticket: SL_RETURN (retval, _("sl_create_ticket")); } static int sl_read_ticket (SL_TICKET fno) { register unsigned myindex; register SL_OFILE *of; myindex = ((fno >> 16) & 0xffff) - TOFFSET; if (myindex >= MAXFD) return (SL_ETICKET); if (ofiles[myindex] == NULL) return (SL_ETICKET); if (ofiles[myindex]->ticket != fno) return (SL_ETICKET); if ((of = ofiles[myindex])->fd < 0 || of->fd >= MAXFD ) return (SL_EINTERNAL04); if (((of->ticket) & 0xffff) == 0) return (SL_EINTERNAL05); return (myindex); } SL_TICKET sl_make_ticket (const char * ofile, int oline, int fd, const char * filename, FILE * stream) { size_t len; SL_TICKET ticket; SL_ENTER(_("sl_make_ticket")); /* Make entry. */ /* cppcheck-suppress arrayIndexOutOfBoundsCond */ if (fd >= MAXFD || fd < 0) { SL_IRETURN(SL_TOOMANY, _("sl_make_ticket")); } if (ofiles[fd] != NULL) /* stale entry */ { /* SL_IRETURN(SL_EINTERNAL06, _("sl_make_ticket")); */ sl_strlcpy(stale_orig_file, ofiles[fd]->ofile, sizeof(stale_orig_file)); stale_orig_line = ofiles[fd]->oline; if (ofiles[fd]->content) sh_string_destroy(&(ofiles[fd]->content)); (void) free (ofiles[fd]->path); (void) free (ofiles[fd]); ofiles[fd] = NULL; } if ( (ofiles[fd] = calloc(1,sizeof(SL_OFILE))) == NULL) { SL_IRETURN(SL_EMEM, _("sl_make_ticket")); } len = sl_strlen(filename)+1; if ( (ofiles[fd]->path = calloc(1,len) ) == NULL) { free (ofiles[fd]); ofiles[fd] = NULL; SL_IRETURN(SL_EMEM, _("sl_make_ticket")); } /* Get a ticket. */ ticket = sl_create_ticket((unsigned int)fd); if (SL_ISERROR(ticket)) { (void) free (ofiles[fd]->path); (void) free (ofiles[fd]); ofiles[fd] = NULL; SL_IRETURN(ticket, _("sl_make_ticket")); } sl_strlcpy (ofiles[fd]->path, filename, len); ofiles[fd]->ticket = ticket; ofiles[fd]->fd = fd; ofiles[fd]->content = NULL; ofiles[fd]->stream = stream; ofiles[fd]->flush = S_FALSE; sl_strlcpy(ofiles[fd]->ofile, ofile, SL_OFILE_SIZE); ofiles[fd]->oline = oline; SL_IRETURN(ticket, _("sl_make_ticket")); } #define SL_OPEN_MIN 113 #define SL_OPEN_FOR_READ 113 #define SL_OPEN_FOR_WRITE 114 #define SL_OPEN_FOR_RDWR 115 #define SL_OPEN_FOR_WTRUNC 116 #define SL_OPEN_FOR_RWTRUNC 117 #define SL_OPEN_SAFE_RDWR 118 #define SL_OPEN_FOR_FASTREAD 119 #define SL_OPEN_MAX 119 #if !defined(O_NOATIME) #if defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) #define O_NOATIME 01000000 #else /* * bitwise 'or' with zero does not modify any bit */ #define O_NOATIME 0 #endif #endif static int o_noatime = O_NOATIME; static mode_t open_mode = (S_IWUSR|S_IRUSR|S_IRGRP); static int sl_open_file (const char * ofile, int oline, const char *filename, int mode, int priv) { struct stat lbuf; struct stat buf; int errval = 0; int lstat_return; int stat_return; int fd; int sflags; size_t len; SL_TICKET ticket; #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif SL_ENTER(_("sl_open_file")); if (filename == NULL) SL_IRETURN(SL_ENULL, _("sl_open_file")); if (mode < SL_OPEN_MIN || mode > SL_OPEN_MAX) SL_IRETURN(SL_EINTERNAL07, _("sl_open_file")); /* "This system call always succeeds and the previous value of * the mask is returned." */ (void) umask (0); if (mode == SL_OPEN_FOR_FASTREAD) { fd = aud_open_noatime (FIL__, __LINE__, priv, filename, O_RDONLY|O_NONBLOCK, 0, &o_noatime); /* if (fd >= 0) { sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags & ~O_NONBLOCK); } */ if (fd < 0) SL_IRETURN(SL_EBADFILE, _("sl_open_file")); goto createTicket; } #ifdef USE_SUID if (priv == SL_YESPRIV) sl_set_suid(); #endif if (mode == SL_OPEN_FOR_READ) lstat_return = retry_stat (FIL__, __LINE__, filename, &lbuf); else lstat_return = retry_lstat(FIL__, __LINE__, filename, &lbuf); errval = errno; #ifdef USE_SUID if (priv == SL_YESPRIV) sl_unset_suid(); #endif if (lstat_return == -1) { lstat_return = ENOENT; if ( (mode == SL_OPEN_FOR_READ && lstat_return == ENOENT) || (errval != ENOENT)) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>\n"), filename, errval)); errno = errval; SL_IRETURN(SL_ESTAT, _("sl_open_file")); } } if ( (mode != SL_OPEN_FOR_READ) && (lstat_return != ENOENT) && ( S_ISDIR(lbuf.st_mode) || (S_IWOTH & lbuf.st_mode) ) ) { int retval = S_ISDIR(lbuf.st_mode) ? SL_EISDIR : SL_EBADOTH; errno = 0; SL_IRETURN(retval, _("sl_open_file")); } /* O_NOATIME has an effect for read(). But write() ?. */ switch (mode) { case SL_OPEN_FOR_READ: fd = aud_open_noatime (FIL__, __LINE__, priv, filename, O_RDONLY|O_NONBLOCK, 0, &o_noatime); errval = errno; if (fd >= 0) { sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags & ~O_NONBLOCK); } break; case SL_OPEN_FOR_WRITE: if (lstat_return == ENOENT) fd = aud_open (FIL__, __LINE__, priv, filename, O_WRONLY|O_CREAT|O_EXCL, open_mode); else fd = aud_open (FIL__, __LINE__, priv, filename, O_WRONLY, open_mode); errval = errno; break; case SL_OPEN_SAFE_RDWR: if (lstat_return == ENOENT) { fd = aud_open (FIL__, __LINE__, priv, filename, O_RDWR|O_CREAT|O_EXCL, open_mode); errval = errno; } else { errno = errval; SL_IRETURN(SL_EBADFILE, _("sl_open_file")); } break; case SL_OPEN_FOR_RDWR: if (lstat_return == ENOENT) fd = aud_open (FIL__, __LINE__, priv, filename, O_RDWR|O_CREAT|O_EXCL, open_mode); else fd = aud_open (FIL__, __LINE__, priv, filename, O_RDWR, open_mode); errval = errno; break; case SL_OPEN_FOR_WTRUNC: if (lstat_return == ENOENT) fd = aud_open (FIL__, __LINE__, priv, filename, O_WRONLY|O_CREAT|O_EXCL, open_mode); else fd = aud_open (FIL__, __LINE__, priv, filename, O_WRONLY|O_TRUNC, open_mode); errval = errno; break; case SL_OPEN_FOR_RWTRUNC: if (lstat_return == ENOENT) fd = aud_open (FIL__, __LINE__, priv, filename, O_RDWR|O_CREAT|O_EXCL, open_mode); else fd = aud_open (FIL__, __LINE__, priv, filename, O_RDWR|O_TRUNC, open_mode); errval = errno; break; default: errno = 0; SL_IRETURN(SL_EINTERNAL08, _("sl_open_file")); } if (fd < 0) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>\n"), filename, errval)); errno = errval; SL_IRETURN(SL_EBADFILE, _("sl_open_file")); } #ifdef USE_SUID if (priv == SL_YESPRIV) sl_set_suid(); #endif stat_return = retry_fstat(FIL__, __LINE__, fd, &buf); errval = errno; #ifdef USE_SUID if (priv == SL_YESPRIV) sl_unset_suid(); #endif if (stat_return < 0) { sl_close_fd (FIL__, __LINE__, fd); errno = errval; SL_IRETURN(SL_EFSTAT, _("sl_open_file")); } errno = 0; if (lstat_return != ENOENT && buf.st_ino != lbuf.st_ino) { sl_close_fd (FIL__, __LINE__, fd); SL_IRETURN(SL_EBOGUS, _("sl_open_file")); } createTicket: /* Make entry. */ /* cppcheck-suppress arrayIndexOutOfBoundsCond */ if (fd >= MAXFD) { sl_close_fd(FIL__, __LINE__, fd); SL_IRETURN(SL_TOOMANY, _("sl_open_file")); } if (ofiles[fd] != NULL) /* stale entry */ { /* sl_close_fd(FIL__, __LINE__, fd); SL_IRETURN(SL_EINTERNAL09, _("sl_open_file")); */ sl_strlcpy(stale_orig_file, ofiles[fd]->ofile, sizeof(stale_orig_file)); stale_orig_line = ofiles[fd]->oline; if (ofiles[fd]->content) sh_string_destroy(&(ofiles[fd]->content)); (void) free (ofiles[fd]->path); (void) free (ofiles[fd]); ofiles[fd] = NULL; } if ( (ofiles[fd] = calloc(1,sizeof(SL_OFILE))) == NULL) { sl_close_fd(FIL__, __LINE__, fd); SL_IRETURN(SL_EMEM, _("sl_open_file")); } len = sl_strlen(filename)+1; if ( (ofiles[fd]->path = calloc(1,len) ) == NULL) { free (ofiles[fd]); ofiles[fd] = NULL; sl_close_fd(FIL__, __LINE__, fd); SL_IRETURN(SL_EMEM, _("sl_open_file")); } /* Get a ticket. */ ticket = sl_create_ticket(fd); if (SL_ISERROR(ticket)) { (void) free (ofiles[fd]->path); (void) free (ofiles[fd]); ofiles[fd] = NULL; sl_close_fd(FIL__, __LINE__, fd); SL_IRETURN(ticket, _("sl_open_file")); } sl_strlcpy (ofiles[fd]->path, filename, len); ofiles[fd]->ticket = ticket; ofiles[fd]->fd = fd; ofiles[fd]->content = NULL; ofiles[fd]->stream = NULL; ofiles[fd]->flush = S_FALSE; sl_strlcpy(ofiles[fd]->ofile, ofile, SL_OFILE_SIZE); ofiles[fd]->oline = oline; SL_IRETURN(ticket, _("sl_open_file")); } FILE * sl_stream (SL_TICKET ticket, char * mode) { int fd; if (SL_ISERROR(fd = sl_read_ticket(ticket))) return (NULL); if (ofiles[fd] == NULL || fd != ofiles[fd]->fd || ticket != ofiles[fd]->ticket || fd < 0) return (NULL); if (!ofiles[fd]->stream) ofiles[fd]->stream = fdopen(fd, mode); return ofiles[fd]->stream; } int get_the_fd (SL_TICKET ticket) { int fd; if (SL_ISERROR(fd = sl_read_ticket(ticket))) return (fd); if (ofiles[fd] == NULL || fd != ofiles[fd]->fd || ticket != ofiles[fd]->ticket || fd < 0) return (SL_EINTERNAL10); return (fd); } static int check_fname_priv (const char * fname, int priv) { SL_ENTER(_("check_fname_priv")); if (fname == NULL) SL_IRETURN(SL_ENULL, _("check_fname_priv")); if (priv != SL_YESPRIV && priv != SL_NOPRIV) SL_IRETURN(SL_EINTERNAL11, _("check_fname_priv")); SL_IRETURN(SL_ENONE, _("check_fname_priv")); } SL_TICKET sl_open_write (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_write")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) SL_IRETURN(status, _("sl_open_write")); status = sl_open_file(ofile, oline, fname, SL_OPEN_FOR_WRITE, priv); SL_IRETURN(status, _("sl_open_write")); } SL_TICKET sl_open_read (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_read")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) { TPT(( 0, FIL__, __LINE__, _("msg= status=<%ld>\n"), status)); SL_IRETURN(status, _("sl_open_read")); } status = sl_open_file(ofile, oline, fname, SL_OPEN_FOR_READ, priv); SL_IRETURN(status, _("sl_open_read")); } #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) && defined(POSIX_FADV_DONTNEED) static int sl_check_mincore(int fd) { /* Idea from Tobias Oetiker (http://insights.oetiker.ch/linux/fadvise.html) */ struct stat fbuf; int retval = -1; if (0 == fstat(fd, &fbuf)) { void *f_map; f_map = mmap((void *)0, fbuf.st_size, PROT_NONE, MAP_SHARED, fd, 0); if (MAP_FAILED != f_map) { extern int sh_unix_pagesize(void); size_t i; size_t page_size = sh_unix_pagesize(); size_t vec_size = (fbuf.st_size+page_size-1)/page_size; unsigned char * vec = calloc(1, vec_size); if (vec) { mincore(f_map, fbuf.st_size, vec); /* imax = fbuf.st_size/page_size; */ for (i = 0; i <= vec_size; ++i) { if (vec[i]&1) { goto incore; } } retval = 0; incore: free(vec); } munmap(f_map, fbuf.st_size); } } return retval; } #endif static int sl_drop_cache = S_FALSE; int sl_set_drop_cache(const char * str) { extern int sh_util_flagval(const char * c, int * fval); return sh_util_flagval(str, &sl_drop_cache); } SL_TICKET sl_open_fastread (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_fastread")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) SL_IRETURN(status, _("sl_open_read")); status = sl_open_file(ofile, oline, fname, SL_OPEN_FOR_FASTREAD, priv); #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) && defined(POSIX_FADV_DONTNEED) if (S_FALSE != sl_drop_cache && !SL_ISERROR(status)) { int fd = get_the_fd(status); if (fd >= 0) { if (0 == sl_check_mincore(fd)) ofiles[fd]->flush = S_TRUE; } } #endif SL_IRETURN(status, _("sl_open_fastread")); } SL_TICKET sl_open_rdwr (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_rdwr")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) SL_IRETURN(status, _("sl_open_rdwr")); status = sl_open_file(ofile, oline, fname, SL_OPEN_FOR_RDWR, priv); SL_IRETURN(status, _("sl_open_rdwr")); } SL_TICKET sl_open_safe_rdwr (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_safe_rdwr")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) SL_IRETURN(status, _("sl_open_safe_rdwr")); status = sl_open_file(ofile, oline, fname, SL_OPEN_SAFE_RDWR, priv); SL_IRETURN(status, _("sl_open_safe_rdwr")); } SL_TICKET sl_open_write_trunc (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_write_trunc")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) SL_IRETURN(status, _("sl_open_write_trunc")); status = sl_open_file(ofile, oline, fname, SL_OPEN_FOR_WTRUNC, priv); SL_IRETURN(status, _("sl_open_write_trunc")); } SL_TICKET sl_open_rdwr_trunc (const char * ofile, int oline, const char * fname, int priv) { long status; SL_ENTER(_("sl_open_rdwr_trunc")); if (SL_ENONE != (status = check_fname_priv (fname, priv))) SL_IRETURN(status, _("sl_open_rdwr_trunc")); status = sl_open_file(ofile, oline, fname, SL_OPEN_FOR_RWTRUNC, priv); SL_IRETURN(status, _("sl_open_rdwr_trunc")); } int sl_init_content (SL_TICKET ticket, size_t size) { int fd; if (SL_ISERROR(fd = sl_read_ticket(ticket))) return (fd); if (ofiles[fd] == NULL || fd != ofiles[fd]->fd || ticket != ofiles[fd]->ticket || fd < 0) return (SL_EINTERNAL12); if (ofiles[fd]->content) sh_string_destroy(&(ofiles[fd]->content)); ofiles[fd]->content = sh_string_new(size); return SL_ENONE; } sh_string * sl_get_content (SL_TICKET ticket) { int fd; if (SL_ISERROR(fd = sl_read_ticket(ticket))) return (NULL); if (ofiles[fd] == NULL || fd != ofiles[fd]->fd || ticket != ofiles[fd]->ticket || fd < 0) return (NULL); return (ofiles[fd]->content); } int sl_lock (SL_TICKET ticket) { int fd; struct flock lock; int retval; SL_ENTER(_("sl_lock")); if (SL_ISERROR(fd = get_the_fd (ticket))) SL_IRETURN(fd, _("sl_lock")); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; /* F_SETLK returns if the lock cannot be obtained */ do { retval = fcntl(fd, F_SETLK, &lock); } while (retval < 0 && errno == EINTR); if (retval < 0 && errno == EBADF) SL_IRETURN(SL_ETICKET, _("sl_lock")); else if (retval < 0) SL_IRETURN(SL_EBADFILE, _("sl_lock")); else SL_IRETURN(SL_ENONE, _("sl_lock")); } int sl_close (SL_TICKET ticket) { register int fd; FILE * fp = NULL; SL_ENTER(_("sl_close")); if (SL_ISERROR(fd = get_the_fd (ticket))) SL_IRETURN(fd, _("sl_close")); if (ofiles[fd] != NULL) { #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) && defined(POSIX_FADV_DONTNEED) if (ofiles[fd]->flush == S_TRUE) { posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); } #endif if (ofiles[fd]->content) sh_string_destroy(&(ofiles[fd]->content)); (void) free (ofiles[fd]->path); fp = ofiles[fd]->stream; (void) free (ofiles[fd]); ofiles[fd] = NULL; } /* This may fail, but what to do then ? */ if (fp) { if (0 != fclose (fp)) /* within sl_close */ { TPT((0, FIL__, __LINE__, _("msg=, fd=<%d>, err=<%s>\n"), fd, strerror(errno))); } } else { if (0 != close(fd)) /* within sl_close */ { TPT((0, FIL__, __LINE__, _("msg=, fd=<%d>, err=<%s>\n"), fd, strerror(errno))); } } SL_IRETURN(SL_ENONE, _("sl_close")); } int sl_close_fd (const char * file, int line, int fd) { int ret = -1; SL_ENTER(_("sl_close_fd")); if (fd >= 0 && fd < MAXFD && ofiles[fd] != NULL) /* stale ofiles[fd] handle */ { sl_strlcpy(badfd_orig_file, file, sizeof(badfd_orig_file)); badfd_orig_line = line; } ret = close(fd); /* within sl_close_fd wrapper */ SL_IRETURN(ret, _("sl_close_fd")); } int sl_fclose (const char * file, int line, FILE * fp) { int ret = -1; int fd; SL_ENTER(_("sl_fclose")); fd = fileno(fp); if (fd >= 0 && fd < MAXFD && ofiles[fd] != NULL) /* stale ofiles[fd] handle */ { sl_strlcpy(badfd_orig_file, file, sizeof(badfd_orig_file)); badfd_orig_line = line; } ret = fclose(fp); /* within sl_fclose wrapper */ SL_IRETURN(ret, _("sl_fclose")); } int sl_dropall(int fd, int except) { while (fd < MAXFD) { if (ofiles[fd] != NULL && fd != except) { if (ofiles[fd]->content) sh_string_destroy(&(ofiles[fd]->content)); if (ofiles[fd]->path != NULL) (void) free (ofiles[fd]->path); (void) free (ofiles[fd]); ofiles[fd] = NULL; } ++fd; } return 0; } int sl_dropall_dirty(int fd, int except) { while (fd < MAXFD) { if (ofiles[fd] != NULL && fd != except) { ofiles[fd] = NULL; } ++fd; } return 0; } int sl_unlink (SL_TICKET ticket) { register int fd; SL_ENTER(_("sl_unlink")); if (SL_ISERROR(fd = get_the_fd(ticket))) SL_IRETURN(fd, _("sl_unlink")); if (retry_aud_unlink(FIL__, __LINE__, ofiles[fd]->path) < 0) SL_IRETURN(SL_EUNLINK, _("sl_unlink")); SL_IRETURN(SL_ENONE, _("sl_unlink")); } int sl_seek (SL_TICKET ticket, off_t off_data) { register int fd; SL_ENTER(_("sl_seek")); if (SL_ISERROR(fd = get_the_fd(ticket))) SL_IRETURN(fd, _("sl_seek")); if (lseek(fd, off_data, SEEK_SET) == (off_t)-1) SL_IRETURN(SL_EREWIND, _("sl_seek")); SL_IRETURN(SL_ENONE, _("sl_seek")); } int sl_rewind (SL_TICKET ticket) { register int fd; SL_ENTER(_("sl_rewind")); if (SL_ISERROR(fd = get_the_fd(ticket))) SL_IRETURN(fd, _("sl_rewind")); if (lseek (fd, 0L, SEEK_SET) == (off_t)-1) SL_IRETURN(SL_EREWIND, _("sl_rewind")); SL_IRETURN(SL_ENONE, _("sl_rewind")); } int sl_forward (SL_TICKET ticket) { register int fd; SL_ENTER(_("sl_forward")); if (SL_ISERROR(fd = get_the_fd(ticket))) SL_IRETURN(fd, _("sl_forward")); if (lseek (fd, 0L, SEEK_END) == (off_t)-1) SL_IRETURN(SL_EFORWARD, _("sl_forward")); SL_IRETURN(SL_ENONE, _("sl_forward")); } int sl_sync (SL_TICKET ticket) { register int fd; SL_ENTER(_("sl_sync")); if (SL_ISERROR(fd = get_the_fd(ticket))) SL_IRETURN(fd, _("sl_sync")); if (fsync (fd) == -1) SL_IRETURN(SL_ESYNC, _("sl_sync")); SL_IRETURN(SL_ENONE, _("sl_sync")); } int sl_read_timeout_prep (SL_TICKET ticket) { int fd; int sflags; SL_ENTER(_("sl_read_timeout_prep")); if (SL_ISERROR(fd = get_the_fd(ticket))) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>"), fd)); SL_IRETURN(fd, _("sl_read_timeout_prep")); } /* set to non-blocking mode */ sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags | O_NONBLOCK); SL_IRETURN(SL_ENONE, _("sl_read_timeout_prep")); } int sl_read_timeout_fd (int fd, void * buf_in, size_t count, int timeout, int is_nonblocking) { int sflags = 0; fd_set readfds; struct timeval tv; /* int sflags; */ int retval; int error; int byteread = 0; int bytes = 0; char * buf; time_t tnow; time_t tstart; time_t tdiff; extern volatile int sig_termfast; if (is_nonblocking == S_FALSE) { /* set to non-blocking mode */ sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags | O_NONBLOCK); } buf = (char *) buf_in; tstart = time(NULL); tdiff = 0; while (count > 0) { FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = timeout - tdiff; tv.tv_usec = 0; retval = select (fd+1, &readfds, NULL, NULL, &tv); if (retval > 0) { byteread = read (fd, buf, count); if (byteread > 0) { bytes += byteread; count -= byteread; buf += byteread; if (count == 0) break; } else if (byteread == 0) { /* zero indicates end of file */ break; } else { if (errno == EINTR || errno == EAGAIN) { retry_msleep(1, 0); tnow = time(NULL); tdiff = tnow - tstart; continue; } else { error = errno; if (is_nonblocking == S_FALSE) retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags); TPT(( 0, FIL__, __LINE__, _("msg="))); errno = error; return (SL_EREAD); } } } else if ((retval == -1) && (errno == EINTR || errno == EAGAIN)) { retry_msleep(1, 0); tnow = time(NULL); tdiff = tnow - tstart; continue; } else if (retval == 0) { if (is_nonblocking == S_FALSE) retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags); TPT(( 0, FIL__, __LINE__, _("msg="))); errno = 0; if (bytes > 0) return ((int) bytes); return (SL_TIMEOUT); } else { error = errno; if (is_nonblocking == S_FALSE) retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags); TPT(( 0, FIL__, __LINE__, _("msg="))); errno = error; return (SL_EREAD); } if (sig_termfast == 1) { if (is_nonblocking == S_FALSE) retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags); TPT(( 0, FIL__, __LINE__, _("msg="))); errno = 0; return (SL_EREAD); } tnow = time(NULL); tdiff = tnow - tstart; if (tdiff > timeout) { if (is_nonblocking == S_FALSE) retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags); TPT(( 0, FIL__, __LINE__, _("msg="))); errno = 0; if (bytes > 0) return ((int) bytes); return (SL_TIMEOUT); } } if (is_nonblocking == S_FALSE) retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags); return ((int) bytes); } int sl_read_timeout (SL_TICKET ticket, void * buf_in, size_t count, int timeout, int is_nonblocking) { int fd, retval; SL_ENTER(_("sl_read_timeout")); if (buf_in == NULL || SL_ISERROR(fd = get_the_fd(ticket))) { if (buf_in == NULL) { TPT(( 0, FIL__, __LINE__, _("msg="))); SL_IRETURN((SL_ENULL), _("sl_read_timeout")); } if (SL_ISERROR(fd = get_the_fd(ticket))) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>"), fd)); SL_IRETURN((fd), _("sl_read_timeout")); } } retval = sl_read_timeout_fd (fd, buf_in, count, timeout, is_nonblocking); SL_IRETURN((retval), _("sl_read_timeout")); } int sl_read (SL_TICKET ticket, void * buf_in, size_t count) { int fd; int byteread = 0; int bytes = 0; char * buf; SL_ENTER(_("sl_read")); if (count < 1) { TPT(( 0, FIL__, __LINE__, _("msg="))); SL_IRETURN((SL_ERANGE), _("sl_read")); } if (buf_in == NULL) { TPT(( 0, FIL__, __LINE__, _("msg="))); SL_IRETURN((SL_ENULL), _("sl_read")); } if (SL_ISERROR(fd = get_the_fd(ticket))) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>"), fd)); SL_IRETURN((fd), _("sl_read")); } buf = (char *) buf_in; do { byteread = read (fd, buf, count); if (byteread > 0) { bytes += byteread; count -= byteread; buf += byteread; } } while ( byteread > 0 || ( byteread == -1 && (errno == EINTR || errno == EAGAIN)) ); if (byteread == (-1)) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>\n"), errno)); SL_IRETURN((SL_EREAD), _("sl_read")); } SL_IRETURN((bytes), _("sl_read")); } int sl_read_fast (SL_TICKET ticket, void * buf_in, size_t count) { int fd; int byteread = 0; char * buf; SL_ENTER(_("sl_read_fast")); if (count < 1) { TPT(( 0, FIL__, __LINE__, _("msg="))); SL_IRETURN((SL_ERANGE), _("sl_read_fast")); } if (buf_in == NULL) { TPT(( 0, FIL__, __LINE__, _("msg="))); SL_IRETURN((SL_ENULL), _("sl_read_fast")); } if (SL_ISERROR(fd = get_the_fd(ticket))) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>"), fd)); SL_IRETURN((fd), _("sl_read_fast")); } buf = (char *) buf_in; do { byteread = read (fd, buf, count); if (byteread >= 0) { SL_IRETURN((byteread), _("sl_read_fast")); } } while ( byteread == -1 && (errno == EINTR || errno == EAGAIN)); if (byteread == (-1)) { TPT(( 0, FIL__, __LINE__, _("msg= errno=<%d>\n"), errno)); SL_IRETURN((SL_EREAD), _("sl_read_fast")); } SL_IRETURN((0), _("sl_read_fast")); } int sl_write (SL_TICKET ticket, const void * msg_in, long nbytes) { long bytewritten; long bytecount; int fd; const char * msg; SL_ENTER(_("sl_write")); if (nbytes < 1) SL_IRETURN(SL_ERANGE, _("sl_write")); if (msg_in == NULL) SL_IRETURN(SL_ENULL, _("sl_write")); if (SL_ISERROR(fd = get_the_fd(ticket))) SL_IRETURN(fd, _("sl_write")); msg = (const char *) msg_in; /* write */ bytecount = 0; while (bytecount < nbytes) { bytewritten = write (fd, msg, nbytes-bytecount); if (bytewritten > 0) { bytecount += bytewritten; msg += bytewritten; /* move buffer pointer forward */ } else if (bytewritten <= 0) { if ( errno == EINTR || errno == EAGAIN) /* try again */ continue; else SL_IRETURN(SL_EWRITE, _("sl_write")); } } SL_IRETURN(SL_ENONE, _("sl_write")); } int sl_write_line (SL_TICKET ticket, const void * msg, long nbytes) { int status; SL_ENTER(_("sl_write_line")); status = sl_write(ticket, msg, nbytes); if (!SL_ISERROR(status)) status = sl_write(ticket, "\n", 1); SL_IRETURN(status, _("sl_write_line")); } int sl_write_line_fast (SL_TICKET ticket, void * msg, long nbytes) { int status; char * p = (char *) msg; SL_ENTER(_("sl_write_line_fast")); /* Here nbytes is strlen(msg), so p[nbytes] is the terminating '\0' * Overwrite the terminator, write out, then write back the terminator. */ p[nbytes] = '\n'; status = sl_write(ticket, msg, nbytes+1); p[nbytes] = '\0'; SL_IRETURN(status, _("sl_write_line_fast")); } /* ---------------------------------------------------------------- * * Trustfile interface * * ---------------------------------------------------------------- */ extern uid_t rootonly[]; extern unsigned int EUIDSLOT; extern unsigned int ORIG_EUIDSLOT; extern char tf_path[MAXFILENAME]; /* Error path for trust function. */ extern uid_t tf_euid; /* Space for EUID of process. */ char * sl_error_string(int errorcode) { switch (errorcode) { case SL_EBOGUS: return _("Bogus file, modified during access"); case SL_EWRITE: return _("Write error"); case SL_EREAD: return _("Read error"); case SL_ESYNC: return _("Error in fsync()"); case SL_EFORWARD: return _("Error in lseek()"); case SL_EREWIND: return _("Error in lseek()"); case SL_EUNLINK: return _("Error in unlink()"); case SL_EMEM: return _("Out of memory"); case SL_EINTERNAL: return _("Internal error"); case SL_EINTERNAL01: return _("Internal error 01"); case SL_EINTERNAL02: return _("Internal error 02"); case SL_EINTERNAL03: return _("Internal error 03"); case SL_EINTERNAL04: return _("Internal error 04"); case SL_EINTERNAL05: return _("Internal error 05"); case SL_EINTERNAL06: return _("Internal error 06"); case SL_EINTERNAL07: return _("Internal error 07"); case SL_EINTERNAL08: return _("Internal error 08"); case SL_EINTERNAL09: return _("Internal error 09"); case SL_EINTERNAL10: return _("Internal error 10"); case SL_EINTERNAL11: return _("Internal error 11"); case SL_EINTERNAL12: return _("Internal error 12"); case SL_ETICKET: return _("Bad ticket"); case SL_EREPEAT: return _("Illegal repeated use of function"); case SL_ERANGE: return _("Argument out of range"); case SL_ENULL: return _("Dereferenced NULL pointer"); case SL_EBADUID: return _("Owner not trustworthy"); case SL_EBADGID: return _("Group writeable and member not trustworthy"); case SL_EBADOTH: return _("World writeable"); case SL_EISDIR: return _("Is a directory"); case SL_EBADFILE: return _("File access error"); case SL_EBADNAME: return _("Invalid filename (prob. too long or null)"); case SL_ETRUNC: return _("Truncation occured"); case SL_ESTAT: return _("stat() failed"); case SL_EFSTAT: return _("fstat() failed"); default: return _("Unknown error"); } } char * sl_trust_errfile(void) { return &tf_path[0]; } extern uid_t tf_baduid; uid_t sl_trust_baduid(void) { return tf_baduid; } extern gid_t tf_badgid; gid_t sl_trust_badgid(void) { return tf_badgid; } static int trust_count = 0; int sl_trust_purge_user (void) { unsigned int i; EUIDSLOT = ORIG_EUIDSLOT; trust_count = 0; for (i = EUIDSLOT; i < (EUIDSLOT + 15); ++i) rootonly[i] = sh_uid_neg; return 0; } int sl_trust_add_user (uid_t pwid) { SL_ENTER(_("sl_trust_add_user")); if (trust_count == 15) SL_IRETURN(SL_ERANGE, _("sl_trust_add_user")); rootonly[EUIDSLOT] = pwid; ++EUIDSLOT; ++trust_count; SL_IRETURN(SL_ENONE, _("sl_trust_add_user")); } #include "sh_mem.h" extern char * sh_util_strdup (const char * str); struct sl_trustfile_store { char * filename; uid_t teuid; struct sl_trustfile_store * next; }; static struct sl_trustfile_store * sl_trusted_files = NULL; static void sl_add_trusted_file(const char * filename, uid_t teuid) { struct sl_trustfile_store *new = SH_ALLOC(sizeof(struct sl_trustfile_store)); new->filename = sh_util_strdup (filename); new->teuid = teuid; new->next = sl_trusted_files; sl_trusted_files = new; return; } static const char * sl_check_trusted_file(const char * filename, uid_t teuid) { struct sl_trustfile_store *new = sl_trusted_files; while (new) { if ((new->teuid == teuid) && (0 == strcmp(new->filename, filename))) return filename; new = new->next; } return NULL; } static void sl_clear_trusted_file(struct sl_trustfile_store * file) { if (file) { if (file->next != NULL) sl_clear_trusted_file(file->next); SH_FREE(file->filename); SH_FREE(file); } return; } int sl_trustfile_euid(const char * filename, uid_t teuid) { long status; static size_t old = 0; static size_t now; SL_ENTER(_("sl_trustfile_euid")); tf_path[0] = '\0'; if (filename == NULL || filename[0] == '\0') SL_IRETURN(SL_EBADNAME, _("sl_trustfile_euid")); now = time(NULL); if (now < (old + 300)) { if (NULL != sl_check_trusted_file(filename, teuid)) { sl_strlcpy(tf_path, filename, sizeof(tf_path)); SL_IRETURN(SL_ENONE, _("sl_trustfile_euid")); } } else { sl_clear_trusted_file(sl_trusted_files); sl_trusted_files = NULL; old = now; } tf_euid = teuid; status = sl_trustfile(filename, NULL, NULL); if (status == SL_ENONE) sl_add_trusted_file(filename, teuid); SL_IRETURN(status, _("sl_trustfile_euid")); } /* ---------------------------------------------------------------- * * Overflow tests * * ---------------------------------------------------------------- */ #ifndef SIZE_MAX #define SIZE_MAX (4294967295U) #endif int sl_ok_muli (int a, int b) /* a*b */ { if ((b == 0) || (a >= (INT_MIN / b) && a <= (INT_MAX / b))) return S_TRUE; /* no overflow */ return S_FALSE; } int sl_ok_muls (size_t a, size_t b) /* a*b */ { if ((b == 0) || (a <= (SIZE_MAX / b))) return S_TRUE; /* no overflow */ return S_FALSE; } int sl_ok_divi (int a, int b) /* a/b */ { (void) a; if (b != 0) return S_TRUE; /* no overflow */ return S_FALSE; } int sl_ok_addi (int a, int b) /* a+b */ { if (a >= 0 && b >= 0) { if (a <= (INT_MAX - b)) return S_TRUE; /* no overflow */ else return S_FALSE; } else if (a < 0 && b < 0) { if (a >= (INT_MIN - b)) return S_TRUE; /* no overflow */ else return S_FALSE; } return S_TRUE; } int sl_ok_adds (size_t a, size_t b) /* a+b */ { if (a <= (SIZE_MAX - b)) return S_TRUE; /* no overflow */ else return S_FALSE; } int sl_ok_subi (int a, int b) /* a-b */ { if (a >= 0 && b < 0) { if (a <= (INT_MAX + b)) return S_TRUE; /* no overflow */ else return S_FALSE; } else if (a < 0 && b >= 0) { if (a >= (INT_MIN + b)) return S_TRUE; /* no overflow */ else return S_FALSE; } return S_TRUE; } samhain-4.1.4/src/sh_log_parse_syslog.c0000644000175000017500000000775112615253277015105 00000000000000/************************************** ** ** PARSER RULES ** ** (a) must set record->host ** (eventually to dummy value) ** ** (b) must set record->prefix ** (eventually to dummy value) ** ** **************************************/ /* for strptime */ #define _XOPEN_SOURCE #include "config_xor.h" #include #include #include #if defined(HOST_IS_SOLARIS) /* For 'struct timeval' in */ #define __EXTENSIONS__ #endif #include #include #ifdef USE_LOGFILE_MONITOR #include "samhain.h" #include "sh_pthread.h" #include "sh_log_check.h" #include "sh_utils.h" #include "sh_string.h" #undef FIL__ #define FIL__ _("sh_log_parse_syslog.c") static int hidepid = 0; extern int flag_err_debug; int sh_get_hidepid() { return hidepid; } int sh_set_hidepid(const char *s) { return sh_util_flagval(s, &hidepid); } struct sh_logrecord * sh_parse_syslog (sh_string * logline, void * fileinfo) { static const char * format0_1 = N_("%b %d %T"); static const char * format0_2 = N_("%Y-%m-%dT%T"); static char format_1[16]; static char format_2[16]; static int format_init = 0; static struct tm old_tm; static time_t old_time; const unsigned int Tpos = 10; volatile unsigned int tlen = 16; (void) fileinfo; if (!format_init) { sl_strlcpy(format_1, _(format0_1), sizeof(format_1)); sl_strlcpy(format_2, _(format0_2), sizeof(format_2)); format_init = 1; } if (flag_err_debug == S_TRUE && sh_string_len(logline) > 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, logline->str, _("sh_parse_syslog")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } if (logline && sh_string_len(logline) > tlen) { struct tm btime; char * ptr; int flag; size_t lengths[3]; memset(&btime, '\0', sizeof(struct tm)); btime.tm_isdst = -1; /* This is RFC 3164. */ if (logline->str[Tpos] != 'T') { logline->str[tlen-1] = '\0'; ptr = /*@i@*/strptime(logline->str, format_1, &btime); } /* RFC 3339 describes an alternative timestamp format. * Unfortunately, POSIX strptime() does not support reading * the TZ offset. */ else { ptr = strptime(logline->str, format_2, &btime); if (ptr) { tlen = 20; if (*ptr && *ptr != ' ') { do { ++ptr; ++tlen; } while (*ptr && *ptr != ' '); if (*ptr == ' ') *ptr = '\0'; } } } if (ptr && *ptr == '\0') /* no error, whole string consumed */ { unsigned int fields = 3; /* host program(\[pid\])+: message */ char ** array = split_array_ws(&(logline->str[tlen]), &fields, lengths); if (fields == 3) { struct sh_logrecord * record = SH_ALLOC(sizeof(struct sh_logrecord)); record->timestamp = conv_timestamp(&btime, &old_tm, &old_time); record->timestr = sh_string_new_from_lchar(logline->str, (tlen-1)); /* host */ record->host = sh_string_new_from_lchar(array[0], lengths[0]); /* program and pid */ if (NULL != (ptr = strchr(array[1], '['))) { *ptr = '\0'; ++ptr; record->pid = (pid_t) atoi(ptr); if (hidepid == 0 || !*ptr) { --ptr; *ptr = '['; } else { *ptr = '\0'; /* overwrite first digit */ --ptr; *ptr = ':'; /* overwrite ex-':' */ lengths[1] = strlen(array[1]); } } else { flag = 0; ptr = array[1]; if (ptr[lengths[1]] == ':') { ptr[lengths[1]] = '\0'; flag = 1; } record->pid = PID_INVALID; if (flag == 1) { ptr[lengths[1]] = ':'; } } /* message */ record->message = sh_string_new_from_lchar3(array[1], lengths[1], " ", 1, array[2], lengths[2]); SH_FREE(array); return record; } SH_FREE(array); } } /* corrupted logline */ return NULL; } /* USE_LOGFILE_MONITOR */ #endif samhain-4.1.4/src/sh_registry.c0000644000175000017500000006074012615253277013377 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2010 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*************************************************************************** * * This file provides a module for samhain to check the MS Windows registry. * */ #include "config_xor.h" #ifdef USE_REGISTRY_CHECK #include #include #include #define FIL__ _("sh_registry.c") /* We don't want to build this into yule */ #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) #include #include #include "samhain.h" #include "sh_pthread.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_modules.h" #include "sh_hash.h" #include "sh_tiger.h" static int check_key (char * name, int isSingle); static int sh_reg_set_active (const char *s); static int sh_reg_set_interval (const char * c); static int sh_reg_set_severity (const char *s); static int sh_reg_add_key (const char *s); static int sh_reg_add_hierarchy (const char *s); static int sh_reg_add_stop (const char *s); static int sh_reg_add_ign (const char *s); static int sh_reg_ign_time (const char *s); #define STOP_FALSE 0 #define STOP_CHECK 1 #define STOP_IGN 2 sh_rconf sh_reg_check_table[] = { { N_("severitychange"), sh_reg_set_severity, }, { N_("registrycheckactive"), sh_reg_set_active, }, { N_("registrycheckinterval"), sh_reg_set_interval, }, { N_("ignoretimestamponly"), sh_reg_ign_time, }, { N_("singlekey"), sh_reg_add_key, }, { N_("hierarchy"), sh_reg_add_hierarchy, }, { N_("stopatkey"), sh_reg_add_stop, }, { N_("ignorekey"), sh_reg_add_ign, }, { NULL, NULL } }; /* Runtime configuration */ #define SH_REGISTRY_INTERVAL 300 static int ShRegCheckActive = S_FALSE; static time_t sh_reg_check_interval = SH_REGISTRY_INTERVAL; static int sh_reg_check_severity = SH_ERR_SEVERE; static int ShRegIgnTime = S_FALSE; struct regkeylist { char * name; int stop; int single; #ifdef HAVE_REGEX_H regex_t preg; #endif struct regkeylist *next; }; static struct regkeylist * keylist = NULL; static int sh_reg_set_active(const char *s) { int value; SL_ENTER(_("sh_reg_set_active")); value = sh_util_flagval(s, &ShRegCheckActive); SL_RETURN((value), _("sh_reg_set_active")); } static int sh_reg_ign_time(const char *s) { int value; SL_ENTER(_("sh_reg_ign_time")); value = sh_util_flagval(s, &ShRegIgnTime); SL_RETURN((value), _("sh_reg_ign_time")); } static int sh_reg_set_interval (const char * c) { int retval = 0; long val; SL_ENTER(_("sh_reg_set_interval")); val = strtol (c, (char **)NULL, 10); if (val <= 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("registry check interval"), c); SH_MUTEX_UNLOCK(mutex_thread_nolog); retval = -1; } sh_reg_check_interval = (time_t) val; SL_RETURN(0, _("sh_reg_set_interval")); } static int sh_reg_set_severity (const char *s) { char tmp[32]; tmp[0] = '='; tmp[1] = '\0'; sl_strlcat (tmp, s, 32); return sh_error_set_level (tmp, &sh_reg_check_severity); } static int sh_reg_add_key_int (const char *s, int isSingle, int isStop) { struct regkeylist * newkey; size_t len = sl_strlen(s); if (len > 0) { newkey = SH_ALLOC(sizeof(struct regkeylist)); newkey->single = isSingle; newkey->stop = isStop; newkey->name = NULL; if (STOP_FALSE == isStop) { newkey->name = SH_ALLOC(len + 1); sl_strlcpy(newkey->name, s, len+1); } else { #ifdef HAVE_REGEX_H int status = regcomp(&(newkey->preg), s, REG_NOSUB|REG_EXTENDED); if (status != 0) { char errbuf[512]; char *p; regerror(status, &(newkey->preg), errbuf, sizeof(errbuf)); sl_strlcat(errbuf, ": ", sizeof(errbuf)); p = sh_util_safe_name_keepspace(s); sl_strlcat(errbuf, p, sizeof(errbuf)); SH_FREE(p); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, errbuf, _("sh_reg_add_key_int")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(newkey); return -1; } #else newkey->name = SH_ALLOC(len + 1); sl_strlcpy(newkey->name, s, len+1); #endif } newkey->next = keylist; keylist = newkey; return 0; } return -1; } static int sh_reg_add_key (const char *s) { return sh_reg_add_key_int (s, S_TRUE, STOP_FALSE); } static int sh_reg_add_hierarchy (const char *s) { return sh_reg_add_key_int (s, S_FALSE, STOP_FALSE); } static int sh_reg_add_stop (const char *s) { return sh_reg_add_key_int (s, S_FALSE, STOP_CHECK); } static int sh_reg_add_ign (const char *s) { return sh_reg_add_key_int (s, S_FALSE, STOP_IGN); } /* Module functions */ int sh_reg_check_init(struct mod_type * arg) { #ifndef HAVE_PTHREAD (void) arg; #endif if (ShRegCheckActive == S_FALSE) return SH_MOD_FAILED; #ifdef HAVE_PTHREAD if (arg != NULL && arg->initval < 0 && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg)) return SH_MOD_THREAD; else return SH_MOD_FAILED; } else if (arg != NULL && arg->initval == SH_MOD_THREAD && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { return SH_MOD_THREAD; } #endif return 0; } int sh_reg_check_timer(time_t tcurrent) { static time_t lastcheck = 0; SL_ENTER(_("sh_reg_check_timer")); if ((time_t) (tcurrent - lastcheck) >= sh_reg_check_interval) { lastcheck = tcurrent; SL_RETURN((-1), _("sh_reg_check_timer")); } SL_RETURN(0, _("sh_reg_check_timer")); } #define SH_REGFORM_NEW 1 #define SH_REGFORM_OLD 2 static char * format_changes(int flag, char * buf, size_t len, time_t time_old, unsigned long size_old, unsigned long keys_old, unsigned long values_old, char * hash_old, time_t time_new, unsigned long size_new, unsigned long keys_new, unsigned long values_new, char * hash_new) { char timestr1[32]; char timestr2[32]; char timestr3[32]; char buf_old[512] = ""; char buf_new[512] = ""; if ((0 != (flag & SH_REGFORM_NEW)) && (NULL != hash_new)) { (void) sh_unix_gmttime (time_new, timestr1, sizeof(timestr1)); (void) sh_unix_gmttime (keys_new, timestr2, sizeof(timestr2)); (void) sh_unix_gmttime (values_new, timestr3, sizeof(timestr3)); #ifdef SH_USE_XML sl_snprintf(buf_new, sizeof(buf_new), "size_new=\"%lu\" mtime_new=\"%s\" ctime_new=\"%s\" atime_new=\"%s\" chksum_new=\"%s\"", size_new, timestr1, timestr2, timestr3, hash_new); #else sl_snprintf(buf_new, sizeof(buf_new), "size_new=<%lu>, mtime_new=<%s>, ctime_new=<%s>, atime_new=<%s>, chksum_new=<%s>", size_new, timestr1, timestr2, timestr3, hash_new); #endif } if ((0 != (flag & SH_REGFORM_OLD)) && (NULL != hash_old)) { (void) sh_unix_gmttime (time_old, timestr1, sizeof(timestr1)); (void) sh_unix_gmttime (keys_old, timestr2, sizeof(timestr2)); (void) sh_unix_gmttime (values_old, timestr3, sizeof(timestr3)); #ifdef SH_USE_XML sl_snprintf(buf_old, sizeof(buf_old), " size_old=\"%lu\" mtime_old=\"%s\" ctime_old=\"%s\" atime_old=\"%s\" chksum_old=\"%s\"", size_old, timestr1, timestr2, timestr3, hash_old); #else sl_snprintf(buf_old, sizeof(buf_old), " size_old=<%lu>, mtime_old=<%s>, ctime_old=<%s>, atime_old=<%s>, chksum_old=<%s>", size_old, timestr1, timestr2, timestr3, hash_old); #endif } sl_strlcpy(buf, buf_new, len); sl_strlcat(buf, buf_old, len); return buf; } static void report_missing_entry(const char * path) { char * infobuf = SH_ALLOC(1024); char * errbuf = SH_ALLOC(1024); char * tmp = sh_util_safe_name (path); char timestr[32]; struct store2db save; memset(&save, '\0', sizeof(struct store2db)); sh_hash_db2pop (path, &save); (void) sh_unix_gmttime (save.val1, timestr, sizeof(timestr)); sl_snprintf(infobuf, 1024, _("mtime=%s size=%lu subkeys=%lu values=%lu"), timestr, (unsigned long) save.val0, (unsigned long) save.val2, (unsigned long) save.val3); (void) format_changes (SH_REGFORM_OLD, errbuf, 1024, save.val1, save.val0, save.val2, save.val3, save.checksum, 0, 0, 0, 0, NULL); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_reg_check_severity, FIL__, __LINE__, 0, MSG_REG_MISS, infobuf, tmp, errbuf); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmp); SH_FREE(errbuf); SH_FREE(infobuf); return; } int sh_reg_check_run(void) { struct regkeylist *this = keylist; if (this) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Checking the registry"), _("sh_reg_check_run")); SH_MUTEX_UNLOCK(mutex_thread_nolog); while (this) { if (STOP_FALSE == this->stop) { /* * -- Check key -- */ check_key (this->name, this->single); } this = this->next; } } sh_hash_unvisited_custom ('H', report_missing_entry); return 0; } int sh_reg_check_reconf(void) { struct regkeylist *this; while (keylist) { this = keylist; keylist = keylist->next; if (this->name) SH_FREE(this->name); #ifdef HAVE_REGEX_H if (STOP_FALSE != this->stop) regfree(&(this->preg)); #endif SH_FREE(this); } sh_reg_check_interval = SH_REGISTRY_INTERVAL; return 0; } int sh_reg_check_cleanup(void) { sh_reg_check_reconf(); return 0; } /* >>>>>>>>>>>> Main check function <<<<<<<<<<<< */ #include #define MAX_KEY_LENGTH (2*256) #define MAX_VALUE_NAME (2*16384) CHAR achValue[MAX_VALUE_NAME]; unsigned long nKeys = 0; unsigned long nVals = 0; static int CheckThisSubkey (HKEY key, char * subkey, char * path, int isSingle, int view); static time_t convertTime(FILETIME * ft) { time_t result; /* Shift high part up by 2^32 */ UINT64 date = ((UINT64)ft->dwHighDateTime) << 32; /* Add low part */ date |= (UINT64)ft->dwLowDateTime; /* Subtract difference between Jan 1, 1601 and Jan 1, 1970 */ date -= ((UINT64)116444736) * ((UINT64)100) * ((UINT64)10000000); /* Divide by number of 100-nanosecond intervals per second */ date /= ((UINT64)10000000); /* Convert to a time_t */ result = (time_t) date; return result; } #if !defined(KEY_WOW64_64KEY) #define KEY_WOW64_64KEY 0x0100; #endif #if !defined(KEY_WOW64_32KEY) #define KEY_WOW64_32KEY 0x0200; #endif #define SH_KEY_NULL _("000000000000000000000000000000000000000000000000") int QueryKey(HKEY hKey, char * path, size_t pathlen, int isSingle) { CHAR achKey[MAX_KEY_LENGTH]; /* buffer for subkey name */ DWORD cbName; /* size of name string */ /* CHAR achClass[MAX_PATH] = ""; *//* buffer for class name */ /* DWORD cchClassName = MAX_PATH/2;*//* size of class string */ DWORD cSubKeys=0; /* number of subkeys */ DWORD cbMaxSubKey; /* longest subkey size */ DWORD cchMaxClass; /* longest class string */ DWORD cValues; /* number of values for key */ DWORD cchMaxValue; /* longest value name */ DWORD cbMaxValueData; /* longest value data */ DWORD cbSecurityDescriptor; /* size of security descriptor */ FILETIME ftLastWriteTime; /* last write time */ DWORD lpType; /* type of data stored in value */ BYTE lpData[256]; /* buffer for data in value */ DWORD lpcbData; /* size of lpData buffer */ DWORD i, retCode; DWORD cchValue = MAX_VALUE_NAME/2; char hashbuf[KEYBUF_SIZE]; unsigned long totalSize = 0; time_t fTime = 0; char * tPath = NULL; int doUpdate = S_FALSE; retCode = RegQueryInfoKey( hKey, /* key handle */ NULL /* achClass */, /* buffer for class name */ NULL /* &cchClassName */,/* size of class string */ NULL, /* reserved */ &cSubKeys, /* number of subkeys */ &cbMaxSubKey, /* longest subkey size */ &cchMaxClass, /* longest class string */ &cValues, /* number of values for this key */ &cchMaxValue, /* longest value name */ &cbMaxValueData, /* longest value data */ &cbSecurityDescriptor, /* security descriptor */ &ftLastWriteTime); /* last write time */ if (retCode != ERROR_SUCCESS) { return -1; } ++nKeys; fTime = convertTime (&ftLastWriteTime); /* Enumerate the subkeys, until RegEnumKeyEx fails. */ if (cSubKeys) { /* * printf( "\nNumber of subkeys: %lu\n", (unsigned long) cSubKeys); */ for (i=0; i (PATH_MAX-1)) { char hashbuf2[KEYBUF_SIZE]; char * p = strchr(path, '\\'); if (p) { char *q = p; ++p; tPath = SH_ALLOC(256 + KEYBUF_SIZE); *q = '\0'; sl_strlcpy(tPath, path, 256); /* truncates */ *q = '\\'; sl_strlcat(tPath, "\\", 257); (void) sh_tiger_hash(p, TIGER_DATA, sl_strlen(p), hashbuf2, sizeof(hashbuf2)); sl_strlcat(tPath, hashbuf2, 256 + KEYBUF_SIZE); } } if (sh.flag.checkSum == SH_CHECK_CHECK || sh.flag.update == S_TRUE) { struct store2db save; memset(&save, '\0', sizeof(struct store2db)); if (tPath) { sh_hash_db2pop (tPath, &save); } else { sh_hash_db2pop (path, &save); } if (save.size == -1) { /* Not in database */ char * infobuf = SH_ALLOC(1024); char * errbuf = SH_ALLOC(1024); char * tmp = sh_util_safe_name ((tPath == NULL) ? path : tPath); char timestr[32]; (void) sh_unix_gmttime (fTime, timestr, sizeof(timestr)); sl_snprintf(infobuf, 1024, _("mtime=%s size=%lu subkeys=%lu values=%lu"), timestr, (unsigned long) totalSize, (unsigned long) cSubKeys, (unsigned long) cValues); (void) format_changes (SH_REGFORM_NEW, errbuf, 1024, 0, 0, 0, 0, NULL, fTime, totalSize, cSubKeys, cValues, hashbuf); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_reg_check_severity, FIL__, __LINE__, 0, MSG_REG_NEW, infobuf, tmp, errbuf); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmp); SH_FREE(errbuf); SH_FREE(infobuf); doUpdate = S_TRUE; } else if (save.val0 != totalSize || save.val2 != cSubKeys || save.val3 != cValues || 0 != strcmp(save.checksum, hashbuf) || ( (((time_t) save.val1) != fTime) && (ShRegIgnTime == S_FALSE)) ) { /* Change detected */ char * infobuf = SH_ALLOC(1024); char * errbuf = SH_ALLOC(1024); char * tmp = sh_util_safe_name ((tPath == NULL) ? path : tPath); char timestr_new[32]; (void) sh_unix_gmttime (fTime, timestr_new, sizeof(timestr_new)); sl_snprintf(infobuf, 1024, _("mtime=%s size %lu->%lu subkeys %lu->%lu values %lu->%lu checksum %s"), timestr_new, (unsigned long) save.val0, (unsigned long) totalSize, (unsigned long) save.val2, (unsigned long) cSubKeys, (unsigned long) save.val3, (unsigned long) cValues, (0 == strcmp(save.checksum, hashbuf)) ? _("good") : _("bad")); (void) format_changes (SH_REGFORM_OLD|SH_REGFORM_NEW, errbuf, 1024, save.val1, save.val0, save.val2, save.val3, save.checksum, fTime, totalSize, cSubKeys, cValues, hashbuf); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_reg_check_severity, FIL__, __LINE__, 0, MSG_REG_CHANGE, infobuf, tmp, errbuf); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmp); SH_FREE(errbuf); SH_FREE(infobuf); doUpdate = S_TRUE; } } if ( sh.flag.checkSum == SH_CHECK_INIT || doUpdate == S_TRUE /* change detected */ ) { struct store2db save; memset(&save, '\0', sizeof(struct store2db)); save.val0 = totalSize; save.val1 = fTime; save.val2 = cSubKeys; save.val3 = cValues; sl_strlcpy(save.checksum, hashbuf, KEY_LEN+1); if (tPath) { sh_hash_push2db (tPath, &save); } else { sh_hash_push2db (path, &save); } } /* Without this, freshly updated entries would get deleted * as 'not seen'. */ if (sh.flag.checkSum != SH_CHECK_INIT) { if (tPath) sh_hash_set_visited (tPath); else sh_hash_set_visited (path); } if (tPath) { SH_FREE(tPath); } return 0; } static int check_for_stop (char * name) { struct regkeylist *this = keylist; while (this) { if (STOP_FALSE != this->stop) { #ifdef HAVE_REGEX_H if (0 == regexec(&(this->preg), name, 0, NULL, 0)) return this->stop; #else if (0 == strcmp(this->name, name)) return this->stop; #endif } this = this->next; } return STOP_FALSE; } int CheckThisSubkey (HKEY key, char * subkey, char * path, int isSingle, int view) { HKEY hTestKey; LONG qError; char * newpath; size_t len; int retval = -1; len = strlen(path) + 1 + strlen(subkey) + 1; newpath = SH_ALLOC(len); snprintf(newpath, len, "%s\\%s", path, subkey); /* Check for stop condition, if not single key. * Set flag to isSingle = S_TRUE if we should stop here. */ if (S_TRUE != isSingle) { int isStop = check_for_stop(newpath); if (STOP_CHECK == isStop) { isSingle = S_TRUE; } else if (STOP_IGN == isStop) { SH_FREE(newpath); return 0; } } len = strlen(path) + 1 + strlen(subkey) + 1; newpath = SH_ALLOC(len); snprintf(newpath, len, "%s\\%s", path, subkey); qError = RegOpenKeyEx( key, subkey, 0, (KEY_READ | view), &hTestKey); if (qError == ERROR_SUCCESS) { QueryKey(hTestKey, newpath, len-1, isSingle); RegCloseKey(hTestKey); retval = 0; } else { /* Error message */ LPVOID lpMsgBuf; char * tmp = sh_util_safe_name (newpath); size_t tlen = sl_strlen(tmp); if (S_TRUE == sl_ok_adds(64, tlen)) { char * errbuf; size_t elen; tlen += 64; elen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, qError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); if (elen > 0 && S_TRUE == sl_ok_adds(elen, tlen)) { tlen += elen; errbuf = SH_ALLOC(elen + tlen); sl_snprintf(errbuf, 64+tlen, _("Failed to open key %s: %s"), tmp, lpMsgBuf); LocalFree(lpMsgBuf); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, errbuf, _("CheckThisSubkey")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(errbuf); } } sh_reg_add_ign (newpath); SH_FREE(tmp); } SH_FREE(newpath); return retval; } int check_key (char * key, int isSingle) { HKEY topKey; char * subkey; char path[20] = ""; int pos = 0; if (0 == strncmp(key, _("HKEY_CLASSES_ROOT"), 17)) { topKey = HKEY_CLASSES_ROOT; pos = 17; strncpy(path, _("HKEY_CLASSES_ROOT"), sizeof(path)); } else if (0 == strncmp(key, _("HKEY_CURRENT_USER"), 17)) { topKey = HKEY_CURRENT_USER; pos = 17; strncpy(path, _("HKEY_CURRENT_USER"), sizeof(path)); } else if (0 == strncmp(key, _("HKEY_LOCAL_MACHINE"), 18)) { topKey = HKEY_LOCAL_MACHINE; pos = 18; strncpy(path, _("HKEY_LOCAL_MACHINE"), sizeof(path)); } else if (0 == strncmp(key, _("HKEY_USERS"), 10)) { topKey = HKEY_USERS; pos = 10; strncpy(path, _("HKEY_USERS"), sizeof(path)); } if (pos > 0) { if (key[pos] == '\\') { ++pos; subkey = &key[pos]; } } else { char * tmp = sh_util_safe_name_keepspace(key); size_t tlen = sl_strlen(tmp); if (S_TRUE == sl_ok_adds(64, tlen)) { char * errbuf = SH_ALLOC(64 + tlen); sl_snprintf(errbuf, 64+tlen, _("Invalid key %s"), tmp); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, errbuf, _("check_key")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(errbuf); } SH_FREE(tmp); return -1; } /************************ if (ShCheckBothViews) { CheckThisSubkey (topKey, subkey, path, isSingle, KEY_WOW64_32KEY); return CheckThisSubkey (topKey, subkey, path, isSingle, KEY_WOW64_64KEY); } *************************/ return CheckThisSubkey (topKey, subkey, path, isSingle, 0); } /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */ #endif /* #ifdef USE_REGISTRY_CHECK */ #endif samhain-4.1.4/src/cutest_sh_tools.c0000644000175000017500000000776712615253277014270 00000000000000 #include "config_xor.h" #include #include "CuTest.h" #include "samhain.h" #include "sh_tools.h" #include "sh_ipvx.h" void Test_sh_tools_safe_name_01(CuTest *tc) { /* xml specific */ char* input = strdup("hellorld\"foo&"); char* actual = sh_tools_safe_name(input, 1); #ifdef SH_USE_XML char* expected = "hello=3cwo=3erld=22foo=26"; #else char* expected = "hellorld\"foo&"; #endif CuAssertStrEquals(tc, expected, actual); } void Test_sh_tools_safe_name_02(CuTest *tc) { /* html entities */ char* input = strdup("hello&"><"); char* actual = sh_tools_safe_name(input, 0); char* expected = "hello=26=22=3e=3c"; CuAssertStrEquals(tc, expected, actual); } void Test_sh_tools_safe_name_03(CuTest *tc) { char* input = strdup("\\\'hello\\"); char* actual = sh_tools_safe_name(input, 0); char* expected = "=27hello"; CuAssertStrEquals(tc, expected, actual); input = strdup("hello \"world\\\""); actual = sh_tools_safe_name(input, 0); expected = "hello \"world=22"; CuAssertStrEquals(tc, expected, actual); input = strdup("hello\\\\"); actual = sh_tools_safe_name(input, 0); expected = "hello=5c"; CuAssertStrEquals(tc, expected, actual); input = strdup("hello\\n"); actual = sh_tools_safe_name(input, 0); expected = "hello=0a"; CuAssertStrEquals(tc, expected, actual); } void Test_sh_tools_safe_name_04(CuTest *tc) { /* invalid and valid octal code */ char* input = strdup("hello\\\n"); char* actual = sh_tools_safe_name(input, 0); char* expected = "hello"; CuAssertStrEquals(tc, expected, actual); input = strdup("hello\\100"); actual = sh_tools_safe_name(input, 0); expected = "hello=40"; CuAssertStrEquals(tc, expected, actual); input = strdup("h\\\"ello\\100a"); actual = sh_tools_safe_name(input, 0); expected = "h=22ello=40a"; CuAssertStrEquals(tc, expected, actual); } void Test_sh_tools_safe_name_05(CuTest *tc) { /* encoding of '=' */ char* input = strdup("he=llo=\"foo\""); char* actual = sh_tools_safe_name(input, 0); char* expected = "he=3dllo=\"foo\""; CuAssertStrEquals(tc, expected, actual); input = strdup("he=llo="); actual = sh_tools_safe_name(input, 0); expected = "he=3dllo="; CuAssertStrEquals(tc, expected, actual); } void Test_sh_tools_safe_name_06(CuTest *tc) { /* line break removal */ char* input = strdup("hello\nworld"); char* actual = sh_tools_safe_name(input, 0); char* expected = "hello world"; CuAssertStrEquals(tc, expected, actual); } void Test_sh_tools_safe_name_07(CuTest *tc) { /* non-printable chars */ char* input = strdup("hello world"); char* actual; char* expected; input[0] = 0x01; input[5] = 0xFF; input[10] = 0xF0; actual = sh_tools_safe_name(input, 0); expected = "=01ello=ffworl=f0"; CuAssertStrEquals(tc, expected, actual); } void Test_is_numeric_01(CuTest *tc) { char* input = strdup("hello world"); CuAssertTrue(tc, !sh_ipvx_is_numeric(input)); input = strdup("127.0.0.1"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("127.0.0.de"); CuAssertTrue(tc, !sh_ipvx_is_numeric(input)); input = strdup("127"); CuAssertTrue(tc, !sh_ipvx_is_numeric(input)); #if defined(USE_IPVX) input = strdup("::1"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("2002:c0a8:101::42"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("2003:dead:beef:4dad:23:46:bb:101"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("::192:168:0:1::"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("1:1:192:168:0:1:1:1"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("1:1:192:168:0:1:1:1:0"); CuAssertTrue(tc, !sh_ipvx_is_numeric(input)); input = strdup("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("2001:db8:85a3:0:0:8a2e:370:7334"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); input = strdup("2001:db8:85a3::8a2e:370:7334"); CuAssertTrue(tc, sh_ipvx_is_numeric(input)); #endif } samhain-4.1.4/src/sh_log_parse_samba.c0000644000175000017500000000430112615253277014634 00000000000000/************************************** ** ** PARSER RULES ** ** (a) must set record->host ** (eventually to dummy value) ** ** (b) must set record->prefix ** (command) ** ** **************************************/ /* for strptime */ #define _XOPEN_SOURCE #include "config_xor.h" #include #if defined(HOST_IS_SOLARIS) /* For 'struct timeval' in */ #define __EXTENSIONS__ #endif #include #if defined(USE_LOGFILE_MONITOR) #include "samhain.h" #include "sh_pthread.h" #include "sh_log_check.h" #include "sh_string.h" #undef FIL__ #define FIL__ _("sh_log_parse_samba.c") sh_string * sh_read_samba (sh_string * record, struct sh_logfile * logfile) { return sh_cont_reader (record, logfile, " \t"); } struct sh_logrecord * sh_parse_samba (sh_string * logline, void * fileinfo) { static struct tm old_tm; static time_t old_time; struct sh_logrecord * record = NULL; static const char * format0_1 = N_("[%Y/%m/%d %T"); static char format_1[16]; static int format_init = 0; (void) fileinfo; if (!format_init) { sl_strlcpy(format_1, _(format0_1), sizeof(format_1)); format_init = 1; } if (logline && sh_string_len(logline) > 0) { size_t lengths[3]; unsigned int fields = 3; char ** array; char * p = strchr(sh_string_str(logline), ','); *p = '\0'; ++p; array = split_array_ws(p, &fields, lengths); if (fields == 3) { struct tm btime; char * ptr; memset(&btime, '\0', sizeof(struct tm)); btime.tm_isdst = -1; ptr = strptime(sh_string_str(logline), format_1, &btime); if (ptr && *ptr == '\0') /* no error, whole string consumed */ { record = SH_ALLOC(sizeof(struct sh_logrecord)); record->timestamp = conv_timestamp(&btime, &old_tm, &old_time); p = sh_string_str(logline); ++p; record->timestr = sh_string_new_from_lchar(p, strlen(p)); record->message = sh_string_new_from_lchar(array[2], lengths[2]); record->pid = 0; record->host = sh_string_new_from_lchar(sh.host.name, strlen(sh.host.name)); } } SH_FREE(array); } return record; } #endif samhain-4.1.4/src/sh_tiger1.c0000644000175000017500000002261512615253277012721 00000000000000/* Do not include ANY system headers here. The implementation is */ /* somehow flawed - maybe something gets overlayed by definitions */ /* in the system headers. Results will become incorrect. */ #include "config_xor.h" /* we already inline in the function used for file checksums */ /* #define UNROLL_COMPRESS */ #undef UNROLL_COMPRESS #if !defined(TIGER_64_BIT) /* Tiger: A Fast New Hash Function * * Ross Anderson and Eli Biham * * From the homepage (http://www.cs.technion.ac.il/~biham/Reports/Tiger/): * * Tiger has no usage restrictions nor patents. It can be used freely, * with the reference implementation, with other implementations or with * a modification to the reference implementation (as long as it still * implements Tiger). We only ask you to let us know about your * implementation and to cite the origin of Tiger and of the reference * implementation. * * * The authors' home pages can be found both in * http://www.cs.technion.ac.il/~biham/ and in * http://www.cl.cam.ac.uk/users/rja14/. * The authors' email addresses are biham@cs.technion.ac.il * and rja14@cl.cam.ac.uk. */ #if defined(HAVE_INT_32) typedef unsigned int sh_word32; #elif defined(HAVE_LONG_32) typedef unsigned long sh_word32; #elif defined(HAVE_SHORT_32) typedef unsigned short sh_word32; #else #error No 32 bit type found ! #endif typedef unsigned char sh_byte; /* Big endian: */ #ifdef WORDS_BIGENDIAN #define BIG_ENDIAN #endif /* The number of passes of the hash function. */ /* Three passes are recommended. */ /* Use four passes when you need extra security. */ /* Must be at least three. */ #define PASSES 3 extern sh_word32 tiger_table[4*256][2]; #define t1 (tiger_table) #define t2 (tiger_table+256) #define t3 (tiger_table+256*2) #define t4 (tiger_table+256*3) #define sub64(s0, s1, p0, p1) \ temps0 = (p0); \ tcarry = s0 < temps0; \ s0 -= temps0; \ s1 -= (p1) + tcarry; #define add64(s0, s1, p0, p1) \ temps0 = (p0); \ s0 += temps0; \ tcarry = s0 < temps0; \ s1 += (p1) + tcarry; #define xor64(s0, s1, p0, p1) \ s0 ^= (p0); \ s1 ^= (p1); #define mul5(s0, s1) \ tempt0 = s0<<2; \ tempt1 = (s1<<2)|(s0>>30); \ add64(s0, s1, tempt0, tempt1); #define mul7(s0, s1) \ tempt0 = s0<<3; \ tempt1 = (s1<<3)|(s0>>29); \ sub64(tempt0, tempt1, s0, s1); \ s0 = tempt0; \ s1 = tempt1; #define mul9(s0, s1) \ tempt0 = s0<<3; \ tempt1 = (s1<<3)|(s0>>29); \ add64(s0, s1, tempt0, tempt1); #define save_abc \ aa0 = a0; \ aa1 = a1; \ bb0 = b0; \ bb1 = b1; \ cc0 = c0; \ cc1 = c1; #define roundX(a0,a1,b0,b1,c0,c1,x0,x1) \ xor64(c0, c1, x0, x1); \ temp0 = t1[((c0)>>(0*8))&0xFF][0] ; \ temp1 = t1[((c0)>>(0*8))&0xFF][1] ; \ temp0 ^= t2[((c0)>>(2*8))&0xFF][0] ; \ temp1 ^= t2[((c0)>>(2*8))&0xFF][1] ; \ temp0 ^= t3[((c1)>>(0*8))&0xFF][0] ; \ temp1 ^= t3[((c1)>>(0*8))&0xFF][1] ; \ temp0 ^= t4[((c1)>>(2*8))&0xFF][0] ; \ temp1 ^= t4[((c1)>>(2*8))&0xFF][1] ; \ sub64(a0, a1, temp0, temp1); \ temp0 = t4[((c0)>>(1*8))&0xFF][0] ; \ temp1 = t4[((c0)>>(1*8))&0xFF][1] ; \ temp0 ^= t3[((c0)>>(3*8))&0xFF][0] ; \ temp1 ^= t3[((c0)>>(3*8))&0xFF][1] ; \ temp0 ^= t2[((c1)>>(1*8))&0xFF][0] ; \ temp1 ^= t2[((c1)>>(1*8))&0xFF][1] ; \ temp0 ^= t1[((c1)>>(3*8))&0xFF][0] ; \ temp1 ^= t1[((c1)>>(3*8))&0xFF][1] ; \ add64(b0, b1, temp0, temp1); #define round5(a0,a1,b0,b1,c0,c1,x0,x1) \ roundX(a0,a1,b0,b1,c0,c1,x0,x1); \ mul5(b0, b1); #define round7(a0,a1,b0,b1,c0,c1,x0,x1) \ roundX(a0,a1,b0,b1,c0,c1,x0,x1); \ mul7(b0, b1); #define round9(a0,a1,b0,b1,c0,c1,x0,x1) \ roundX(a0,a1,b0,b1,c0,c1,x0,x1); \ mul9(b0, b1); /* mixed with key_schedule */ #define pass5(a0,a1,b0,b1,c0,c1) \ round5(a0,a1,b0,b1,c0,c1,x00,x01); \ sub64(x00, x01, x70^0xA5A5A5A5, x71^0xA5A5A5A5); \ round5(b0,b1,c0,c1,a0,a1,x10,x11); \ xor64(x10, x11, x00, x01); \ round5(c0,c1,a0,a1,b0,b1,x20,x21); \ add64(x20, x21, x10, x11); \ round5(a0,a1,b0,b1,c0,c1,x30,x31); \ sub64(x30, x31, x20^((~x10)<<19), ~x21^(((x11)<<19)|((x10)>>13))); \ round5(b0,b1,c0,c1,a0,a1,x40,x41); \ xor64(x40, x41, x30, x31); \ round5(c0,c1,a0,a1,b0,b1,x50,x51); \ add64(x50, x51, x40, x41); \ round5(a0,a1,b0,b1,c0,c1,x60,x61); \ sub64(x60, x61, ~x50^(((x40)>>23)|((x41)<<9)), x51^((~x41)>>23)); \ round5(b0,b1,c0,c1,a0,a1,x70,x71); /* mixed with key_schedule */ #define pass7(a0,a1,b0,b1,c0,c1) \ round7(a0,a1,b0,b1,c0,c1,x00,x01); \ sub64(x00, x01, x70^0xA5A5A5A5, x71^0xA5A5A5A5); \ round7(b0,b1,c0,c1,a0,a1,x10,x11); \ xor64(x10, x11, x00, x01); \ round7(c0,c1,a0,a1,b0,b1,x20,x21); \ add64(x20, x21, x10, x11); \ round7(a0,a1,b0,b1,c0,c1,x30,x31); \ sub64(x30, x31, x20^((~x10)<<19), ~x21^(((x11)<<19)|((x10)>>13))); \ round7(b0,b1,c0,c1,a0,a1,x40,x41); \ xor64(x40, x41, x30, x31); \ round7(c0,c1,a0,a1,b0,b1,x50,x51); \ add64(x50, x51, x40, x41); \ round7(a0,a1,b0,b1,c0,c1,x60,x61); \ sub64(x60, x61, ~x50^(((x40)>>23)|((x41)<<9)), x51^((~x41)>>23)); \ round7(b0,b1,c0,c1,a0,a1,x70,x71); /* mixed with key_schedule */ #define pass9(a0,a1,b0,b1,c0,c1) \ round9(a0,a1,b0,b1,c0,c1,x00,x01); \ sub64(x00, x01, x70^0xA5A5A5A5, x71^0xA5A5A5A5); \ round9(b0,b1,c0,c1,a0,a1,x10,x11); \ xor64(x10, x11, x00, x01); \ round9(c0,c1,a0,a1,b0,b1,x20,x21); \ add64(x20, x21, x10, x11); \ round9(a0,a1,b0,b1,c0,c1,x30,x31); \ sub64(x30, x31, x20^((~x10)<<19), ~x21^(((x11)<<19)|((x10)>>13))); \ round9(b0,b1,c0,c1,a0,a1,x40,x41); \ xor64(x40, x41, x30, x31); \ round9(c0,c1,a0,a1,b0,b1,x50,x51); \ add64(x50, x51, x40, x41); \ round9(a0,a1,b0,b1,c0,c1,x60,x61); \ sub64(x60, x61, ~x50^(((x40)>>23)|((x41)<<9)), x51^((~x41)>>23)); \ round9(b0,b1,c0,c1,a0,a1,x70,x71); #define key_schedule \ xor64(x70, x71, x60, x61); \ add64(x00, x01, x70, x71); \ sub64(x10, x11, x00^((~x70)<<19), ~x01^(((x71)<<19)|((x70)>>13))); \ xor64(x20, x21, x10, x11); \ add64(x30, x31, x20, x21); \ sub64(x40, x41, ~x30^(((x20)>>23)|((x21)<<9)), x31^((~x21)>>23)); \ xor64(x50, x51, x40, x41); \ add64(x60, x61, x50, x51); \ sub64(x70, x71, x60^0x89ABCDEF, x61^0x01234567); #define feedforward \ xor64(a0, a1, aa0, aa1); \ sub64(b0, b1, bb0, bb1); \ add64(c0, c1, cc0, cc1); #define compress \ pass5(a0,a1,b0,b1,c0,c1); \ key_schedule; \ pass7(c0,c1,a0,a1,b0,b1); \ key_schedule; \ pass9(b0,b1,c0,c1,a0,a1); \ feedforward #define tiger_compress_macro(str, state) \ { \ register sh_word32 a0, a1, b0, b1, c0, c1; \ sh_word32 aa0, aa1, bb0, bb1, cc0, cc1; \ sh_word32 x00, x01, x10, x11, x20, x21, x30, x31, \ x40, x41, x50, x51, x60, x61, x70, x71; \ sh_word32 temp0, temp1, tempt0, tempt1, temps0, tcarry; \ \ a0 = state[0]; \ a1 = state[1]; \ b0 = state[2]; \ b1 = state[3]; \ c0 = state[4]; \ c1 = state[5]; \ \ save_abc \ \ x00=str[0*2]; x01=str[0*2+1]; x10=str[1*2]; x11=str[1*2+1]; \ x20=str[2*2]; x21=str[2*2+1]; x30=str[3*2]; x31=str[3*2+1]; \ x40=str[4*2]; x41=str[4*2+1]; x50=str[5*2]; x51=str[5*2+1]; \ x60=str[6*2]; x61=str[6*2+1]; x70=str[7*2]; x71=str[7*2+1]; \ \ compress; \ \ state[0] = a0; \ state[1] = a1; \ state[2] = b0; \ state[3] = b1; \ state[4] = c0; \ state[5] = c1; \ } #if defined(UNROLL_COMPRESS) /* The compress function is inlined */ #define tiger_compress(str, state) \ tiger_compress_macro(((sh_word32*)str), ((sh_word32*)state)) #else void tiger_compress(sh_word32 *str, sh_word32 state[6]) { tiger_compress_macro(((sh_word32*)str), ((sh_word32*)state)); } #endif void tiger_t(const sh_word32 *str, sh_word32 length, sh_word32 res[6]) { register sh_word32 i; #ifdef BIG_ENDIAN register sh_word32 j; sh_byte temp[64]; #endif for(i=length; i>=64; i-=64) { #ifdef BIG_ENDIAN for(j=0; j<64; j++) temp[j^3] = ((sh_byte*)str)[j]; tiger_compress_macro(((sh_word32*)temp), res); #else tiger_compress_macro(str, res); #endif str += 16; } } void tiger(sh_word32 *str, sh_word32 length, sh_word32 res[6]) { register sh_word32 i, j; sh_byte temp[64]; /* * res[0]=0x89ABCDEF; * res[1]=0x01234567; * res[2]=0x76543210; * res[3]=0xFEDCBA98; * res[4]=0xC3B2E187; * res[5]=0xF096A5B4; */ for(i=length; i>=64; i-=64) { #ifdef BIG_ENDIAN for(j=0; j<64; j++) temp[j^3] = ((sh_byte*)str)[j]; tiger_compress(((sh_word32*)temp), res); #else tiger_compress(str, res); #endif str += 16; } #ifdef BIG_ENDIAN for(j=0; j56) { for(; j<64; j++) temp[j] = 0; tiger_compress(((sh_word32*)temp), res); j=0; } for(; j<56; j++) temp[j] = 0; ((sh_word32*)(&(temp[56])))[0] = ((sh_word32)length)<<3; ((sh_word32*)(&(temp[56])))[1] = 0; tiger_compress(((sh_word32*)temp), res); } #endif samhain-4.1.4/src/sh_portcheck.c0000644000175000017500000015555312631253334013510 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2006 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*************************************************************************** * * This file provides a module for samhain to check for open ports * on the local machine. * */ /* #define TEST_ONLY */ #ifndef TEST_ONLY #include "config_xor.h" #endif #include #include #include #include #include #include #include #include #include #define PORTCHK_VERSION "1.0" #if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))) #define PORTMAP #ifdef HAVE_RPC_RPC_H #include #ifdef HAVE_RPC_RPCENT_H #include #endif #include #include #endif #include /* * struct pmaplist { * struct pmap pml_map; * struct pmaplist *pml_next; * }; */ /* struct pmap { * long unsigned pm_prog; * long unsigned pm_vers; * long unsigned pm_prot; * long unsigned pm_port; * }; */ /* TIME_WAIT ? 60-240 seconds */ #if !defined(TEST_ONLY) #define FIL__ _("sh_portcheck.c") #include "samhain.h" #include "sh_error.h" #include "sh_mem.h" #include "sh_calls.h" #include "sh_utils.h" #include "sh_modules.h" #define SH_NEED_GETHOSTBYXXX #include "sh_static.h" #include "sh_pthread.h" #include "sh_ipvx.h" /* the size of an interface string */ #define SH_INTERFACE_SIZE SH_IP_BUF #define SH_PORT_NOT 0 #define SH_PORT_REQ 1 #define SH_PORT_OPT 2 #define SH_PORT_IGN 3 #define SH_PORT_BLACKLIST 4 static char * sh_port_type2str (int type) { if (type == 0) return _("not"); if (type == 1) return _("req"); if (type == 2) return _("opt"); if (type == 3) return _("ign"); if (type == 4) return _("blc"); return _("???"); } #define SH_PORT_MISS 0 #define SH_PORT_ISOK 1 #define SH_PORT_UNKN 2 #define SH_PORT_NOREPT 0 #define SH_PORT_REPORT 1 #define SH_PROTO_TCP 0 #define SH_PROTO_UDP 1 #define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp")) struct sh_portentry { int port; char interface[SH_INTERFACE_SIZE]; char * service; char * error; int flag; /* required or not */ int status; /* missing or not */ struct sh_portentry * next; }; static struct sh_portentry * portlist_tcp = NULL; static struct sh_portentry * portlist_udp = NULL; #define SH_PORTCHK_INTERVAL 300 static int sh_portchk_check_udp = 1; static int sh_portchk_active = 1; static int sh_portchk_interval = SH_PORTCHK_INTERVAL; static int sh_portchk_minport = -1; static int sh_portchk_maxport = -1; struct sh_port { int port; struct sh_sockaddr * paddr; struct sh_port * next; }; static struct sh_port * blacklist_tcp = NULL; static struct sh_port * blacklist_udp = NULL; SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER); static int sh_portchk_severity = SH_ERR_SEVERE; extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport, unsigned long * pid, char * user, size_t userlen); extern int sh_port2proc_prepare(); extern void sh_port2proc_finish(); #endif /* Exported interface to add ignoreable ports as 'iface:portlist' */ static int sh_portchk_add_ignore (const char * str); /* Exported interface to add required ports as 'iface:portlist' */ static int sh_portchk_add_required (const char * str); /* Exported interface to add optional ports as 'iface:portlist' */ static int sh_portchk_add_optional (const char * str); /* Exported interface to add blacklisted ports as 'iface:portlist' */ static int sh_portchk_add_blacklist (const char * str); /* Exported interface to add an ethernet interface */ static int sh_portchk_add_interface (const char * str); /* verify whether port/interface is blacklisted (do not check) */ static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto); #ifndef TEST_ONLY static int sh_portchk_set_interval (const char * c) { int retval = 0; long val; SL_ENTER(_("sh_portchk_set_interval")); val = strtol (c, (char **)NULL, 10); if (val <= 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("port check interval"), c); SH_MUTEX_UNLOCK(mutex_thread_nolog); retval = -1; } else { sh_portchk_interval = (time_t) val; } SL_RETURN(retval, _("sh_portchk_set_interval")); } static int sh_portchk_set_port_minmax (const char * c, int * setthis) { int retval = 0; long val; SL_ENTER(_("sh_portchk_set_port_minmax")); val = strtol (c, (char **)NULL, 10); if (val < 0 || val > 65535) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("port check port minmax"), c); SH_MUTEX_UNLOCK(mutex_thread_nolog); retval = -1; } else { *setthis = (int) val; } SL_RETURN(retval, _("sh_portchk_set_port_minmax")); } static int sh_portchk_set_minport (const char * str) { return sh_portchk_set_port_minmax (str, &sh_portchk_minport); } static int sh_portchk_set_maxport (const char * str) { return sh_portchk_set_port_minmax (str, &sh_portchk_maxport); } static int sh_portchk_set_active (const char * str) { return sh_util_flagval(str, &sh_portchk_active); } static int sh_portchk_set_udp (const char * str) { return sh_util_flagval(str, &sh_portchk_check_udp); } static int sh_portchk_set_severity (const char * str) { char tmp[32]; tmp[0] = '='; tmp[1] = '\0'; sl_strlcat (tmp, str, 32); return sh_error_set_level (tmp, &sh_portchk_severity); } sh_rconf sh_portchk_table[] = { { N_("severityportcheck"), sh_portchk_set_severity, }, { N_("portcheckrequired"), sh_portchk_add_required, }, { N_("portcheckoptional"), sh_portchk_add_optional, }, { N_("portcheckignore"), sh_portchk_add_ignore, }, { N_("portcheckskip"), sh_portchk_add_blacklist, }, { N_("portcheckactive"), sh_portchk_set_active, }, { N_("portcheckinterface"), sh_portchk_add_interface, }, { N_("portcheckinterval"), sh_portchk_set_interval, }, { N_("portcheckminport"), sh_portchk_set_minport, }, { N_("portcheckmaxport"), sh_portchk_set_maxport, }, { N_("portcheckudp"), sh_portchk_set_udp, }, { NULL, NULL } }; #endif /* Interface to initialize port check */ int sh_portchk_init (struct mod_type * arg); /* Interface to reset port check */ int sh_portchk_reset (void); /* Interface to run port check */ int sh_portchk_check (void); static char * check_services (int port, int proto); #ifdef TEST_ONLY static int portchk_debug = 0; #define SH_ALLOC malloc #define SH_FREE free #define sh_util_strdup strdup #define sl_strlcpy strncpy #define _(a) a #else static int portchk_debug = 0; #endif #ifdef HAVE_RPC_RPC_H static char * sh_getrpcbynumber (int number, char * buf, size_t len) { FILE * fp; if (NULL != (fp = fopen(_("/etc/rpc"), "r"))) { sh_string * s = sh_string_new(0); while (0 < sh_string_read(s, fp, 1024)) { char * p = sh_string_str(s); while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */ if (*p == '\0' || *p == '#') continue; /* skip comment */ else { size_t lengths[3]; unsigned int fields = 3; char * q = sh_string_str(s); char ** splits = split_array_ws(q, &fields, lengths); if (fields >= 2) { int n = atoi(splits[1]); if (n == number) { sl_strlcpy(buf, splits[0], len); SH_FREE(splits); sh_string_destroy(&s); sl_fclose(FIL__, __LINE__, fp); return buf; } } SH_FREE(splits); } } sh_string_destroy(&s); sl_fclose(FIL__, __LINE__, fp); } return NULL; } #endif static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len) { FILE * fp; char proto[8]; sl_strlcpy(proto, proto_in, sizeof(proto)); if (NULL != (fp = fopen(_("/etc/services"), "r"))) { sh_string * s = sh_string_new(0); while (0 < sh_string_read(s, fp, 1024)) { char * p = sh_string_str(s); while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */ if (*p == '\0' || *p == '#') continue; /* skip comment */ else { size_t lengths[3]; unsigned int fields = 3; char * q = sh_string_str(s); char ** splits = split_array_ws(q, &fields, lengths); if (fields >= 2) { char * end; long n = strtol(splits[1], &end, 10); if (n == port && end && (*end == '/' || *end == ',')) { ++end; if (0 == strcmp(end, proto)) { sl_strlcpy(buf, splits[0], len); SH_FREE(splits); sh_string_destroy(&s); sl_fclose(FIL__, __LINE__, fp); return buf; } } } SH_FREE(splits); } } sh_string_destroy(&s); sl_fclose(FIL__, __LINE__, fp); } return NULL; } static void sh_portchk_add_to_list (int proto, int port, struct sh_sockaddr * paddr, char * service, int flag, int status) { struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry)); new->port = port; sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr); new->status = status; new->flag = flag; new->error = NULL; if (portchk_debug) fprintf(stderr, _("add to list: port %d/%s %d %d (%s) %s\n"), port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"), new->interface); if (service) new->service = sh_util_strdup (service); else new->service = NULL; if (proto == IPPROTO_TCP) { new->next = portlist_tcp; portlist_tcp = new; } else { new->next = portlist_udp; portlist_udp = new; } return; } /* Reset the list by setting all entries to UNKN. * In the next cycle we will check, and set found ports to ISOK. * Thereafter, we check for entries that are still UNKN. */ static void sh_portchk_reset_lists (void) { struct sh_portentry * portlist; portlist = portlist_tcp; while (portlist) { if (portlist->status != SH_PORT_MISS) portlist->status = SH_PORT_UNKN; portlist = portlist->next; } portlist = portlist_udp; while (portlist) { if (portlist->status != SH_PORT_MISS) portlist->status = SH_PORT_UNKN; portlist = portlist->next; } return; } static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head) { if (head) { if (head->next) sh_portchk_kill_list (head->next); if (head->service) SH_FREE(head->service); SH_FREE(head); } return NULL; } static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head) { if (head) { if (head->next) sh_portchk_kill_blacklist (head->next); SH_FREE(head->paddr); SH_FREE(head); } return NULL; } /* These variables are not used anywhere. They only exist * to assign &pre, &ptr to them, which keeps gcc from * putting it into a register, and avoids the 'clobbered * by longjmp' warning. And no, 'volatile' proved insufficient. */ void * sh_dummy_531_pre = NULL; void * sh_dummy_532_ptr = NULL; /* check the list of open ports for any that are marked as UNKN */ static void sh_portchk_check_list (struct sh_portentry ** head, int proto, int report) { struct sh_portentry * ptr = *head; struct sh_portentry * pre = *head; char errbuf[256]; /* Take the address to keep gcc from putting them into registers. * Avoids the 'clobbered by longjmp' warning. */ sh_dummy_531_pre = (void*) ⪯ sh_dummy_532_ptr = (void*) &ptr; while (ptr) { if (portchk_debug && report) fprintf(stderr, _("check list: port %d/%s %d %d\n"), ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status); if (ptr->status == SH_PORT_UNKN) { /* Don't report missing ports that are marked as optional */ if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN) { snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), ptr->interface, ptr->port, SH_PROTO_STR(proto), ptr->service ? ptr->service : check_services(ptr->port, proto)); #ifdef TEST_ONLY if (report == SH_PORT_REPORT) fprintf(stderr, _("%s\n"), errbuf); #else if (report == SH_PORT_REPORT) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, MSG_PORT_MISS, errbuf); SH_MUTEX_UNLOCK(mutex_thread_nolog); } #endif } ptr->status = SH_PORT_MISS; if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN)) { if (portchk_debug && report) fprintf(stderr, _("removing: port %d/%s %d %d\n"), ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status); if (ptr == *head) { *head = ptr->next; if (ptr->service) SH_FREE(ptr->service); SH_FREE(ptr); ptr = *head; pre = *head; continue; } else if (ptr->next == NULL) { pre->next = NULL; if (ptr->service) SH_FREE(ptr->service); SH_FREE(ptr); return; } else { pre->next = ptr->next; if (ptr->service) SH_FREE(ptr->service); SH_FREE(ptr); ptr = pre->next; continue; } } } pre = ptr; ptr = ptr->next; } sh_dummy_532_ptr = NULL; sh_dummy_531_pre = NULL; return; } static struct sh_portentry * sh_portchk_get_from_list (int proto, int port, struct sh_sockaddr * paddr, char * service) { struct sh_portentry * portlist; char str_addr[SH_IP_BUF]; if (proto == IPPROTO_TCP) portlist = portlist_tcp; else portlist = portlist_udp; sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr); if (service) { while (portlist) { if (portlist->service && 0 == strcmp(service, portlist->service) && ( 0 == strcmp(portlist->interface, str_addr) || sh_ipvx_isany(paddr) )) return portlist; portlist = portlist->next; } } else { while (portlist) { if (port == portlist->port && (0 == strcmp(portlist->interface, str_addr) || sh_ipvx_isany(paddr) )) return portlist; portlist = portlist->next; } } return NULL; } static void sh_portchk_cmp_to_list (int proto, int port, struct sh_sockaddr * paddr, char * service) { struct sh_portentry * portent; char errbuf[256]; portent = sh_portchk_get_from_list (proto, port, paddr, service); if (service) { if (!portent) { char * path; unsigned long qpid; char user[USER_MAX]; char saddr[SH_IP_BUF]; sh_ipvx_ntoa(saddr, sizeof(saddr), paddr); snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), saddr, port, SH_PROTO_STR(proto), service); if (portchk_debug) fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s)\n"), saddr, port, SH_PROTO_STR(proto), service); #ifndef TEST_ONLY path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, MSG_PORT_NEW, errbuf, path, qpid, user); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(path); #endif /* * was not there, thus it is not in 'required' or 'optional' list */ sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK); } else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN) { char * path; unsigned long qpid; char user[USER_MAX]; char saddr[SH_IP_BUF]; sh_ipvx_ntoa(saddr, sizeof(saddr), paddr); snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto)); #ifdef TEST_ONLY fprintf(stderr, _("service: %s\n"), errbuf); #else path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, MSG_PORT_RESTART, errbuf, path, qpid, user); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(path); #endif portent->status = SH_PORT_ISOK; } else if (port != portent->port && (-1) != portent->port) { char * path; unsigned long qpid; char user[USER_MAX]; char saddr[SH_IP_BUF]; sh_ipvx_ntoa(saddr, sizeof(saddr), paddr); snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto)); #ifdef TEST_ONLY fprintf(stderr, _("service: %s\n"), errbuf); #else path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, MSG_PORT_NEWPORT, errbuf, path, qpid, user); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(path); #endif portent->port = port; portent->status = SH_PORT_ISOK; } else { portent->status = SH_PORT_ISOK; } } else { if (!portent) { char * path; unsigned long qpid; char user[USER_MAX]; char saddr[SH_IP_BUF]; if (portchk_debug) fprintf(stderr, _("call to sh_ipvx_ntoa (port %d)\n"), port); sh_ipvx_ntoa(saddr, sizeof(saddr), paddr); snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), saddr, port, SH_PROTO_STR(proto), check_services(port, proto)); if (portchk_debug) fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s) check_services\n"), saddr, port, SH_PROTO_STR(proto), check_services(port, proto)); #ifndef TEST_ONLY path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, MSG_PORT_NEW, errbuf, path, qpid, user); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(path); #endif /* was not there, thus it is not in 'required' or 'optional' list */ sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK); } else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN) { char * path; unsigned long qpid; char user[USER_MAX]; char saddr[SH_IP_BUF]; sh_ipvx_ntoa(saddr, sizeof(saddr), paddr); snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), saddr, port, SH_PROTO_STR(proto), check_services(port, proto)); #ifdef TEST_ONLY fprintf(stderr, _("port : %s\n"), errbuf); #else path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, MSG_PORT_RESTART, errbuf, path, qpid, user); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(path); #endif portent->status = SH_PORT_ISOK; } else { portent->status = SH_PORT_ISOK; } } return; } /* Returns a static buffer containing the name of the service * running on port (from /etc/services) * Returns NULL on failure */ static char * check_services (int port, int proto) { static char buf[256]; char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf)); if (!service) { snprintf (buf, sizeof(buf), "%s",_("unknown")); } return buf; } /* Returns a static buffer containing the name of the service * running on port at
(from portmap daemon) * Returns NULL on failure */ static char * check_rpc_list (int port, struct sockaddr_in * address, unsigned long prot) { #if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS) struct pmaplist * head; char *r; static char buf[256]; head = pmap_getmaps(address); if (head) { do /* while (head != NULL) */ { if ((head->pml_map.pm_prot == prot) && (port == (int)head->pml_map.pm_port)) { r = sh_getrpcbynumber((int)head->pml_map.pm_prog, buf, sizeof(buf)); if (r) { return buf; } else { snprintf (buf, sizeof(buf), "RPC_%lu", (unsigned long)head->pml_map.pm_prog); return buf; } } head = head->pml_next; } while (head != NULL); } #else (void) port; (void) address; (void) prot; #endif return NULL; } static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr) { int retval; char * p = NULL; char buf[8]; #ifndef TEST_ONLY char errmsg[256]; int nerr; #endif char errbuf[SH_ERRBUF_SIZE]; char ipbuf[SH_IP_BUF]; sh_ipvx_set_port(paddr, port); do { retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr)); } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS)); if (retval == -1) { #ifdef TEST_ONLY if (portchk_debug) perror(_("connect")); #else sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); nerr = errno; sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"), port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf))); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, errmsg, _("connect")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif } else { do { retval = send (fd, buf, 0, 0); } while (retval < 0 && errno == EINTR); if (retval == -1 && errno == ECONNREFUSED) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); if (portchk_debug) fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"), port, ipbuf); } else { /* Only the second send() may catch the error */ do { retval = send (fd, buf, 0, 0); } while (retval < 0 && errno == EINTR); if (retval == -1 && errno == ECONNREFUSED) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); if (portchk_debug) fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"), port, ipbuf); } else if (retval != -1) { /* Try to get service name from portmap */ if (paddr->ss_family == AF_INET) { p = check_rpc_list (port, (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), IPPROTO_UDP); } sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL); /* If not an RPC service, try to get name from /etc/services */ if (!p) p = check_services(port, IPPROTO_UDP); if (portchk_debug) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"), port, ipbuf, p); } } else { if (portchk_debug) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"), port, ipbuf, errno); } } } } sl_close_fd (FIL__, __LINE__, fd); return 0; } static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr) { int retval; int flags; char * p = NULL; #ifndef TEST_ONLY char errmsg[256]; int nerr; #endif char errbuf[SH_ERRBUF_SIZE]; char ipbuf[SH_IP_BUF]; sh_ipvx_set_port(paddr, port); do { retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr)); } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS)); if (retval == -1 && errno == ECONNREFUSED) { if (portchk_debug) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"), port, ipbuf); } } else if (retval == -1) { #ifdef TEST_ONLY if (portchk_debug) perror(_("connect")); #else sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); nerr = errno; sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"), port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf))); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, errmsg, _("connect")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif } else { /* Try to get service name from portmap */ if (paddr->ss_family == AF_INET) { p = check_rpc_list (port, (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), IPPROTO_TCP); } sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL); /* If not an RPC service, try to get name from /etc/services */ if (!p) p = check_services(port, IPPROTO_TCP); if (portchk_debug) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr); fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"), port, ipbuf, p); } #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif /* prepare to close connection gracefully */ if (port == 22) /* ssh */ { flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK); retval = write (fd, _("SSH-2.0-Foobar"), 14); if (retval > 0) retval = write (fd, "\r\n", 2); } else if (port == 25) /* smtp */ { flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK); retval = write (fd, _("QUIT"), 4); if (retval > 0) retval = write (fd, "\r\n", 2); } else if (port == 79) /* finger */ { flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK); retval = write (fd, "\r\n", 2); } else if (port == 110) /* pop3 */ { flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK); retval = write (fd, _("QUIT"), 4); if (retval > 0) retval = write (fd, "\r\n", 2); } else if (port == 143) /* imap */ { flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0); retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK); retval = write (fd, _("A01 LOGOUT"), 10); if (retval > 0) retval = write (fd, "\r\n", 2); } if (portchk_debug && retval < 0) fprintf(stderr, _("check port: error writing to port %5d\n"), port); } sl_close_fd (FIL__, __LINE__, fd); return 0; } /* typedef uint32_t in_addr_t; * struct in_addr * { * in_addr_t s_addr; * }; */ #define SH_IFACE_MAX 16 struct portchk_interfaces { struct sh_sockaddr iface[SH_IFACE_MAX]; int used; }; static struct portchk_interfaces iface_list; static int iface_initialized = 0; #ifdef TEST_ONLY static char * portchk_hostname = NULL; #else static char * portchk_hostname = sh.host.name; #endif static int sh_portchk_init_internal (void) { volatile int i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/ char errbuf[256]; #if defined(USE_IPVX) struct addrinfo hints; struct addrinfo *res; #else struct hostent * hent; #endif char ipbuf[SH_IP_BUF]; if (portchk_debug) fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL")); if (!portchk_hostname) return -1; if (sh_portchk_active == S_FALSE) return -1; SH_MUTEX_LOCK(mutex_port_check); if (iface_initialized == 0) { iface_list.used = 0; iface_initialized = 1; } #if !defined(USE_IPVX) SH_MUTEX_LOCK(mutex_resolv); hent = sh_gethostbyname(portchk_hostname); i = 0; while (hent && hent->h_addr_list[i] && (iface_list.used < SH_IFACE_MAX)) { struct sockaddr_in sin; struct sh_sockaddr iface_tmp; memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t)); sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin); for (j = 0; j < iface_list.used; ++j) { if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list.iface[j]))) { goto next_iface; } } sh_ipvx_save(&(iface_list.iface[iface_list.used]), AF_INET, (struct sockaddr *)&sin); if (portchk_debug) { char buf[256]; sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used])); fprintf(stderr, _("added interface[%d]: %s\n"), i, buf); } ++iface_list.used; next_iface: ++i; } SH_MUTEX_UNLOCK(mutex_resolv); #else memset(&hints, '\0', sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res)) { struct addrinfo *p = res; struct sh_sockaddr iface_tmp; while ((p != NULL) && (iface_list.used < SH_IFACE_MAX)) { sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr); for (j = 0; j < iface_list.used; ++j) { if (portchk_debug) { char buf1[256], buf2[256]; sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list.iface[j])); sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp); fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2); } if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list.iface[j]))) { if (portchk_debug) fprintf(stderr, _("skipping interface[%d]\n"), j); goto next_iface; } } sh_ipvx_save(&(iface_list.iface[iface_list.used]), p->ai_family, p->ai_addr); if (portchk_debug) { char buf[256]; sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used])); fprintf(stderr, _("added interface[%d]: %s\n"), iface_list.used, buf); } ++iface_list.used; next_iface: p = p->ai_next; } freeaddrinfo(res); } #endif for (i = 0; i < iface_list.used; ++i) { sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list.iface[i])); sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, errbuf, _("sh_portchk_init")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } SH_MUTEX_UNLOCK(mutex_port_check); return 0; } int sh_portchk_init (struct mod_type * arg) { #ifndef HAVE_PTHREAD (void) arg; #endif if (sh_portchk_active == S_FALSE) return SH_MOD_FAILED; if (!portchk_hostname) return SH_MOD_FAILED; #ifdef HAVE_PTHREAD if (arg != NULL && arg->initval < 0 && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg)) return SH_MOD_THREAD; else return SH_MOD_FAILED; } else if (arg != NULL && arg->initval == SH_MOD_THREAD && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { return SH_MOD_THREAD; } #endif return sh_portchk_init_internal(); } #if !defined(TEST_ONLY) int sh_portchk_reconf (void) { SH_MUTEX_LOCK(mutex_port_check); iface_initialized = 0; sh_portchk_active = 1; sh_portchk_check_udp = 1; sh_portchk_interval = SH_PORTCHK_INTERVAL; sh_portchk_minport = -1; sh_portchk_maxport = -1; portlist_udp = sh_portchk_kill_list (portlist_udp); portlist_tcp = sh_portchk_kill_list (portlist_tcp); blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp); blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp); sh_port2proc_finish(); SH_MUTEX_UNLOCK(mutex_port_check); return 0; } int sh_portchk_cleanup (void) { return sh_portchk_reconf (); } int sh_portchk_timer (time_t tcurrent) { static time_t lastcheck = 0; SL_ENTER(_("sh_portchk_timer")); if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval) { lastcheck = tcurrent; SL_RETURN((-1), _("sh_portchk_timer")); } SL_RETURN(0, _("sh_portchk_timer")); } #endif static int check_port_generic (int port, int domain, int type, int protocol) { volatile int i = 0; int sock = -1; int flag = 1; /* non-zero to enable an option */ struct sh_sockaddr paddr; char errbuf[SH_ERRBUF_SIZE]; /* Check all interfaces for this host */ while (i < iface_list.used) { memcpy(&paddr, &(iface_list.iface[i]), sizeof(paddr)); if (paddr.ss_family != domain) { ++i; continue; } if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol)) { ++i; continue; } if ((sock = socket(paddr.ss_family, type, protocol)) < 0 ) { ++i; #ifdef TEST_ONLY if (portchk_debug) perror(_("socket")); #else #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT 0 #endif #ifndef EAFNOSUPPORT #define EAFNOSUPPORT 0 #endif if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } #endif continue; } if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &flag, sizeof(flag)) < 0 ) { ++i; #ifdef TEST_ONLY if (portchk_debug) perror(_("setsockopt")); #else SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif continue; } if (protocol == IPPROTO_TCP) check_port_tcp_internal(sock, port, &paddr); else check_port_udp_internal(sock, port, &paddr); ++i; } return 0; } static int check_port_udp (int port, int domain) { return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP); } static int check_port_tcp (int port, int domain) { return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP); } static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg, int domain, int type, int protocol) { /* int min_port = 1024; int max_port = 65535; */ volatile int port; /* might be clobbered by ‘longjmp’ or ‘vfork’*/ volatile int max_port = max_port_arg; int retval; int sock = -1; #if 0 int flag = 1; /* non-zero to enable an option */ #endif struct sockaddr_in addr4; struct sockaddr_in6 addr6; int addrlen4 = sizeof(addr4); int addrlen6 = sizeof(addr6); struct in6_addr anyaddr = IN6ADDR_ANY_INIT; char errbuf[SH_ERRBUF_SIZE]; if (min_port == -1) min_port = 0; if (max_port == -1) max_port = 65535; if (portchk_debug) fprintf(stderr, _("scan_ports_generic %d-%d %s %s\n"), min_port, max_port, (domain == AF_INET6) ? _("AF_INET6") : _("AF_INET"), (protocol == IPPROTO_TCP) ? _("tcp") : _("udp")); for (port = min_port; port <= max_port; ++port) { if ((sock = socket(domain, type, protocol)) < 0 ) { #ifdef TEST_ONLY if (portchk_debug) perror(_("socket")); #else #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT 0 #endif #ifndef EAFNOSUPPORT #define EAFNOSUPPORT 0 #endif if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } #endif continue; } #if 0 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &flag, sizeof(flag)) < 0 ) { #ifdef TEST_ONLY if (portchk_debug) perror(_("setsockopt")); #else SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif continue; } #endif if (domain == AF_INET) { addr4.sin_family = AF_INET; addr4.sin_port = htons(port); addr4.sin_addr.s_addr = INADDR_ANY; retval = bind (sock, (struct sockaddr *) &addr4, addrlen4); } else { addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(port); memcpy(&(addr6.sin6_addr.s6_addr), &anyaddr, sizeof(anyaddr)); retval = bind (sock, (struct sockaddr *) &addr6, addrlen6); } if (retval == 0) { /* we can bind the port, thus it is unused */ sl_close_fd (FIL__, __LINE__, sock); } else { if (errno == EINVAL || errno == EADDRINUSE) { /* try to connect to the port */ if (protocol == IPPROTO_TCP) check_port_tcp(port, domain); else check_port_udp(port, domain); } else { #ifdef TEST_ONLY if (portchk_debug) perror(_("bind")); #else SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif } sl_close_fd (FIL__, __LINE__, sock); } } return 0; } static int sh_portchk_scan_ports_tcp (int min_port, int max_port) { #if defined(USE_IPVX) sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6, SOCK_STREAM, IPPROTO_TCP); #endif return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET, SOCK_STREAM, IPPROTO_TCP); } static int sh_portchk_scan_ports_udp (int min_port, int max_port) { #if defined(USE_IPVX) sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6, SOCK_DGRAM, IPPROTO_UDP); #endif return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET, SOCK_DGRAM, IPPROTO_UDP); } /* Subroutine to add an interface */ void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */ static int sh_portchk_add_interface (const char * str) { struct sh_sockaddr saddr; char errbuf[256]; char buf[64]; sh_dummy_1564_str = (void*) &str; if (iface_initialized == 0) { iface_list.used = 0; iface_initialized = 1; } do { while (*str == ',' || *str == ' ' || *str == '\t') ++str; if (*str) { char ipbuf[SH_IP_BUF]; unsigned int i = 0; while (*str && i < (sizeof(buf)-1) && *str != ',' && *str != ' ' && *str != '\t') { buf[i] = *str; ++str; ++i; } buf[i] = '\0'; if (0 == sh_ipvx_aton(buf, &saddr)) return -1; if (iface_list.used == SH_IFACE_MAX) return -1; sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr); sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, errbuf, _("sh_portchk_add_interface")); SH_MUTEX_UNLOCK(mutex_thread_nolog); memcpy (&(iface_list.iface[iface_list.used]), &(saddr), sizeof(saddr)); ++iface_list.used; } } while (*str); sh_dummy_1564_str = NULL; return 0; } /* verify whether port/interface is blacklisted (do not check) */ static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr, int proto) { struct sh_port * head; if (proto == IPPROTO_TCP) head = blacklist_tcp; else head = blacklist_udp; while (head) { if (head->port == port) { if (sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr)) return 1; else return 0; } head = head->next; } return 0; } static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto) { struct sh_port * black; struct sh_port * head; if (proto == IPPROTO_TCP) head = blacklist_tcp; else head = blacklist_udp; black = head; while (black) { if (black->port == port && 0 == sh_ipvx_cmp(head->paddr, saddr)) return -1; black = black->next; } black = SH_ALLOC (sizeof(struct sh_port)); black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr)); black->port = port; memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr)); black->next = head; if (proto == IPPROTO_TCP) blacklist_tcp = black; else blacklist_udp = black; if (portchk_debug) { int checkit = sh_portchk_is_blacklisted(port, saddr, proto); fprintf(stderr, _("port blacklisted: %d %s\n"), port, (checkit == 1) ? _("ok") : _("fail")); } return 0; } /* Subroutine to add a required or optional port/service */ static int sh_portchk_add_required_port_generic (char * service, char * interface, int type) { char buf[256] = { '\0' }; int proto; char * p; char * endptr; unsigned long int port; struct sh_sockaddr saddr; struct sh_portentry * portent; if (0 == sh_ipvx_aton(interface, &saddr)) return -1; sl_strlcpy (buf, service, sizeof(buf)); p = strchr(buf, '/'); if (!p) return -1; if (0 == strcmp(p, _("/tcp"))) proto = IPPROTO_TCP; else if (0 == strcmp(p, _("/udp"))) proto = IPPROTO_UDP; else return -1; *p = '\0'; port = strtoul(buf, &endptr, 0); if (portchk_debug) { char buf[SH_IP_BUF]; sh_ipvx_ntoa(buf, sizeof(buf), &saddr); fprintf(stderr, _("add_port_generic: %s (%s) %d %s (%s)\n"), interface, buf, (int) port, (proto == IPPROTO_TCP) ? _("tcp") : _("udp"), sh_port_type2str(type)); } /* Blacklisted ports */ if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST) return (sh_portchk_blacklist(port, &saddr, proto)); if (*endptr != '\0') { portent = sh_portchk_get_from_list (proto, -1, &saddr, buf); if (!portent) { if (portchk_debug) fprintf(stderr, _("add_required_port %d\n"), (int) port); sh_portchk_add_to_list (proto, -1, &saddr, buf, type, SH_PORT_UNKN); } else { #ifdef TEST_ONLY fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto)); #else SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("duplicate port definition"), _("sh_portchk_add_required_port_generic")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif return -1; } } else if (port <= 65535) { portent = sh_portchk_get_from_list (proto, port, &saddr, NULL); if (!portent) { if (portchk_debug) fprintf(stderr, _("add_required_port: open port: %d/%s\n"), (int) port, SH_PROTO_STR(proto)); sh_portchk_add_to_list (proto, port, &saddr, NULL, type, SH_PORT_UNKN); } else { #ifdef TEST_ONLY fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto)); #else SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("duplicate port definition"), _("sh_portchk_add_required_port_generic")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif return -1; } } else return -1; return 0; } /* Internal interface to add required or optional ports as 'iface:portlist' */ static int sh_portchk_add_required_generic (const char * str, int type) { size_t ll = 0; int status; char * interface = NULL; char * list; char * p; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) char * saveptr; #endif if (!str) return -1; if (strchr(str, ':')) { char *last = strrchr(str, ':'); if (last != NULL) { size_t tolast = (last - str); interface = SH_ALLOC(tolast+1); sl_strlcpy(interface, str, tolast+1); interface[tolast] = '\0'; ll = tolast; while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t') ++ll; } } else { interface = SH_ALLOC(8); sl_strlcpy(interface, _("0.0.0.0"), 8); interface[7] = '\0'; while (str[ll] == ' ' || str[ll] == '\t') ++ll; } if (!interface) return -1; if (str[ll] == '\0') { SH_FREE(interface); return -1; } if (portchk_debug) fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type)); list = sh_util_strdup(&str[ll]); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) p = strtok_r (list, " ,\t", &saveptr); #else p = strtok (list, " ,\t"); #endif if (!p) { SH_FREE(interface); SH_FREE(list); return -1; } while (p) { status = sh_portchk_add_required_port_generic (p, interface, type); if (-1 == status) { SH_FREE(interface); SH_FREE(list); return -1; } #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) p = strtok_r (NULL, " ,\t", &saveptr); #else p = strtok (NULL, " ,\t"); #endif } SH_FREE(interface); SH_FREE(list); return 0; } /* User interface to add required ports as 'iface:portlist' */ static int sh_portchk_add_required (const char * str) { return sh_portchk_add_required_generic (str, SH_PORT_REQ); } /* User interface to add optional ports as 'iface:portlist' */ static int sh_portchk_add_optional (const char * str) { return sh_portchk_add_required_generic (str, SH_PORT_OPT); } /* User interface to add ignoreable ports as 'iface:portlist' */ static int sh_portchk_add_ignore (const char * str) { return sh_portchk_add_required_generic (str, SH_PORT_IGN); } /* User interface to add ports that should not be checked as 'iface:portlist' */ static int sh_portchk_add_blacklist (const char * str) { return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST); } /* Interface to run port check */ int sh_portchk_check () { volatile int min_port; static int noprivports = 0; SH_MUTEX_LOCK(mutex_port_check); min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport; if (sh_portchk_active != S_FALSE) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Checking for open ports"), _("sh_portchk_check")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_portchk_reset_lists(); if ((0 != geteuid()) && (min_port < 1024)) { min_port = 1024; if (noprivports == 0) { #ifdef TEST_ONLY fprintf(stderr, "** WARNING not scanning ports < 1024\n"); #else SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("not scanning ports below 1024"), _("sh_portchk_check")); SH_MUTEX_UNLOCK(mutex_thread_nolog); #endif noprivports = 1; } } sh_port2proc_prepare(); if (sh_portchk_check_udp == 1) sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport); sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport); sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT); if (sh_portchk_check_udp == 1) sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT); } SH_MUTEX_UNLOCK(mutex_port_check); return 0; } #endif #ifdef SH_CUTEST #include "CuTest.h" void Test_portcheck_lists (CuTest *tc) { #if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)) struct sh_sockaddr haddr_local; struct sh_portentry * portent; char buf[256]; char * p; #ifdef HAVE_RPC_RPC_H p = sh_getrpcbynumber(0, buf, sizeof(buf)); CuAssertTrue(tc, p == NULL); p = sh_getrpcbynumber(100000, buf, sizeof(buf)); CuAssertPtrNotNull(tc, p); CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind"))); CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind"))); p = sh_getrpcbynumber(100007, buf, sizeof(buf)); CuAssertPtrNotNull(tc, p); CuAssertTrue(tc, 0 == strcmp(p, "ypbind")); CuAssertTrue(tc, 0 == strcmp(buf, "ypbind")); #endif p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf)); CuAssertTrue(tc, p == NULL); #if !defined(HOST_IS_CYGWIN) p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf)); CuAssertPtrNotNull(tc, p); CuAssertTrue(tc, 0 == strcmp(p, "ssh")); CuAssertTrue(tc, 0 == strcmp(buf, "ssh")); #endif p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf)); CuAssertPtrNotNull(tc, p); CuAssertTrue(tc, 0 == strcmp(p, "daytime")); CuAssertTrue(tc, 0 == strcmp(buf, "daytime")); CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local)); sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL); CuAssertPtrNotNull(tc, portent); CuAssertTrue(tc, portent->port == 8000); CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface)); CuAssertTrue(tc, portent->status == SH_PORT_UNKN); CuAssertTrue(tc, portent->flag == SH_PORT_NOT); sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT); CuAssertTrue(tc, NULL == portlist_tcp); sh_portchk_add_to_list (IPPROTO_TCP, 8000, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, 8001, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, 8002, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, 8003, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, 8004, &haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN); sh_portchk_add_to_list (IPPROTO_TCP, -1, &haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN); sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT); CuAssertPtrNotNull(tc, portlist_tcp); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, NULL); CuAssertPtrNotNull(tc, portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8001, &haddr_local, NULL); CuAssertTrue(tc, NULL == portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8002, &haddr_local, NULL); CuAssertPtrNotNull(tc, portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8003, &haddr_local, NULL); CuAssertTrue(tc, NULL == portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8004, &haddr_local, NULL); CuAssertPtrNotNull(tc, portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo1"); CuAssertTrue(tc, NULL == portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo2"); CuAssertPtrNotNull(tc, portent); CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2")); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo3"); CuAssertTrue(tc, NULL == portent); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo4"); CuAssertPtrNotNull(tc, portent); CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4")); portent = sh_portchk_get_from_list(IPPROTO_TCP, 8000, &haddr_local, "foo5"); CuAssertPtrNotNull(tc, portent); CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5")); CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_UDP)); CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_TCP)); CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_TCP)); #else (void) tc; /* fix compiler warning */ #endif return; } #endif #ifdef TEST_ONLY void usage (char * pname) { printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname); printf (" Check local host for open ports; Version %s\n\n", PORTCHK_VERSION); printf (" Interface: Numeric address for an interface, e.g. 127.0.0.1\n"); printf (" Portlist: List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n"); printf (" required -> must be open\n"); printf (" optional -> may be open or closed\n"); printf (" RPC services must be specified with service **name**, others with **port number**\n\n"); printf (" Example:\n"); printf (" %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname); return; } int main(int argc, char *argv[]) { char * pname = argv[0]; /* test_lists(); portlist_tcp = sh_portchk_kill_list (portlist_tcp); portlist_udp = sh_portchk_kill_list (portlist_udp); */ /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */ while (argc > 1 && argv[1][0] == '-') { if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")) { usage(pname); exit (0); } else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r")) { if (argc < 3) { usage(pname); exit (1); } sh_portchk_add_required (argv[2]); --argc; ++argv; } else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o")) { if (argc < 3) { usage(pname); exit (1); } sh_portchk_add_optional (argv[2]); --argc; ++argv; } else if (0 == strcmp(argv[1], "--no-udp")) { sh_portchk_check_udp = 0; } else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d")) { portchk_debug = 1; } else { usage(pname); exit (1); } --argc; ++argv; } if (argc < 2) { usage(pname); exit (1); } portchk_hostname = argv[1]; if (0 != sh_portchk_init ()) { usage(pname); exit (1); } sh_portchk_check(); return 0; } #endif samhain-4.1.4/src/sh_mail.c0000644000175000017500000013116112615253277012445 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include #include #include #include #include #if defined(SH_WITH_MAIL) #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #ifdef HAVE_MEMORY_H #include #endif #include "samhain.h" #include "sh_error.h" #include "sh_unix.h" #include "sh_tiger.h" #include "sh_mail.h" #include "sh_utils.h" #include "sh_fifo.h" #include "sh_tools.h" #include "sh_pthread.h" #include "sh_filter.h" #include "sh_mail_int.h" #include "sh_nmail.h" #include "sh_ipvx.h" #undef FIL__ #define FIL__ _("sh_mail.c") #undef GOOD #undef BAD static int failedMail = S_FALSE; static dnsrep * return_mx (char *domain); /********************************************* * utility function for verifying mails *********************************************/ typedef struct mail_trail_struct { char trail_id[2*SH_MINIBUF]; char trail_key[KEY_LEN+1]; struct mail_trail_struct * next; } mail_trail_type; static mail_trail_type * mail_trail = NULL; int sh_mail_sigverify (const char * s) { SL_TICKET fd; long i; char * buf; char * bufc; char key[81]; char number[2*SH_MINIBUF]; char audit_id[2 * SH_MINIBUF]; long numsig; char key2[KEY_LEN+1]; char * theSig; mail_trail_type * mail_trail_ptr = NULL; sh_error_logoff(); ASSERT((s != NULL && sl_strlen(s) < PATH_MAX), _("(s != NULL && sl_strlen(s) < PATH_MAX)")); if (s == NULL || sl_strlen(s) >= PATH_MAX) _exit (EXIT_FAILURE); /* open the file, then check it */ if (0 != sl_is_suid()) { fprintf(stderr, _("Cannot open file %s in suid mode\n"), s); _exit (EXIT_FAILURE); } if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, s, SL_NOPRIV))) { fprintf(stderr, _("Could not open file %s\n"), s); _exit (EXIT_FAILURE); } buf = SH_ALLOC( (size_t)(SH_MSG_BUF+SH_BUFSIZE+1)); bufc = SH_ALLOC( (size_t)(SH_MSG_BUF+SH_MAXBUF+1)); while (1 == 1) { buf[0] = '\0'; bufc[0] = '\0'; /* find start of next message */ while (0 != sl_strncmp(buf, _("-----BEGIN MESSAGE-----"), sizeof("-----BEGIN MESSAGE-----")-1)) { (void) sh_unix_getline (fd, buf, SH_MSG_BUF+SH_BUFSIZE); if (buf[0] == '\0') { /* End of mailbox reached, exit. */ (void) fflush(stdout); _exit (EXIT_SUCCESS); /* Fix for AIX cc complaint. */ /*@notreached@*/ return 0; } } /* Read message, compress into bufc. */ while (1 == 1) { (void) sh_unix_getline (fd, buf, SH_MSG_BUF+SH_BUFSIZE); if (0 == sl_strncmp(buf, _("-----BEGIN SIGNATURE-----"), sizeof("-----BEGIN SIGNATURE-----")-1)) break; if (buf[0] == '\0') _exit (EXIT_FAILURE); (void) sh_util_compress(bufc, buf, SH_MSG_BUF+SH_MAXBUF-KEY_LEN); } /* get signature and number */ (void) sh_unix_getline (fd, key, (int)sizeof(key)); key[KEY_LEN] = '\0'; (void) sh_unix_getline (fd, number, (int)sizeof(number)); number[(2*SH_MINIBUF) - 2] = '\0'; numsig = atol (number); (void) sl_strlcpy (audit_id, &number[7], 2*SH_MINIBUF); fprintf(stderr, _("Message %06ld Trail %s\n"), numsig, /*@-usedef@*/ audit_id /*@+usedef@*/); mail_trail_ptr = mail_trail; while (mail_trail_ptr) { if (0 == sl_strcmp(mail_trail_ptr->trail_id, audit_id)) break; mail_trail_ptr = mail_trail_ptr->next; } if (!mail_trail_ptr) { if (numsig > 0) { fprintf (stderr, "%s",_("ERROR (no key -- cannot check)\n")); continue; } else { mail_trail_ptr = SH_ALLOC (sizeof(mail_trail_type)); mail_trail_ptr->next = mail_trail; mail_trail = mail_trail_ptr; (void) sl_strlcpy (mail_trail_ptr->trail_id, audit_id, 2*SH_MINIBUF); } } else if (numsig == 0) { fprintf (stderr, "%s",_("ERROR (repeated audit trail)\n")); continue; } if (numsig == 0) { sh_util_encode(key, bufc, 1, 'A'); (void) sl_strlcpy (mail_trail_ptr->trail_key, key, KEY_LEN+1); fprintf (stderr, "%s",_("(unchecked)\n")); } else { char sigbuf[KEYBUF_SIZE]; /* iterate key */ (void) sl_strlcpy(key2, mail_trail_ptr->trail_key, KEY_LEN+1); for (i = 0; i < numsig; ++i) { char hashbuf[KEYBUF_SIZE]; (void) sl_strlcpy (key2, sh_tiger_hash (key2, TIGER_DATA, KEY_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } theSig = sh_util_siggen (key2, bufc, sl_strlen(bufc), sigbuf, sizeof(sigbuf)); if (sl_strncmp (key, theSig, KEY_LEN) != 0) { fprintf (stderr, "%s",_("(FAILED)\n")); } else { fprintf (stderr, "%s",_("(passed)\n")); } } } /* end scan mailbox */ /*@notreached@*/ } int sh_mail_setNum (const char * str) { int i = atoi (str); SL_ENTER(_("sh_mail_setNum")); if (i >= 0 && i < SH_FIFO_MAX) sh.mailNum.alarm_interval = (time_t) i; else SL_RETURN ((-1), _("sh_mail_setNum")); SL_RETURN( (0), _("sh_mail_setNum")); } int sh_mail_all_in_one = S_FALSE; int sh_mail_setFlag (const char * str) { int i; SL_ENTER(_("sh_mail_setFlag")); i = sh_util_flagval(str, &sh_mail_all_in_one); SL_RETURN(i, _("sh_mail_setFlag")); } static char * mail_subject = NULL; int set_mail_subject (const char * str) { SL_ENTER(_("set_mail_subject")); if (!str) SL_RETURN( (-1), _("set_mail_subject")); if (mail_subject != NULL) SH_FREE(mail_subject); if (0 == sl_strncmp(str, _("NULL"), 4)) { mail_subject = NULL; SL_RETURN( 0, _("set_mail_subject")); } mail_subject = sh_util_strdup(str); SL_RETURN( (0), _("set_mail_subject")); } SH_MUTEX_INIT(mutex_fifo_mail, PTHREAD_MUTEX_INITIALIZER); SH_FIFO * fifo_mail = NULL; static void sh_mail_emptystack (void) { char * msg; size_t len; SL_ENTER(_("sh_mail_emptystack")); if (fifo_mail == NULL) SL_RET0(_("sh_mail_emptystack")); SH_MUTEX_LOCK(mutex_fifo_mail); while (NULL != (msg = pop_list(fifo_mail))) { len = sl_strlen(msg); memset(msg, 0, len); SH_FREE(msg); } SH_MUTEX_UNLOCK(mutex_fifo_mail); SL_RET0(_("sh_mail_emptystack")); } /* insert "\r\n" after each 998 char */ static char * split_string(const char * str); /* fixes warning: variable ‘p’ might be clobbered by ‘longjmp’ or ‘vfork’*/ static char ** p_dummy; int sh_mail_pushstack (int severity, const char * msg, const char * alias) { char * p; volatile int retval = 0; int status; SL_ENTER(_("sh_mail_pushstack")); if (msg == NULL || failedMail == S_TRUE /* || sh.srvmail.name[0] == '\0' */) SL_RETURN((0), (_("sh_mail_pushstack"))); p = split_string(msg); /* fixes "variable ‘p’ might be clobbered by ‘longjmp’ or ‘vfork’" */ p_dummy = &p; SH_MUTEX_LOCK(mutex_fifo_mail); if (fifo_mail == NULL) { fifo_mail = SH_ALLOC(sizeof(SH_FIFO)); fifo_init(fifo_mail); } status = push_list (fifo_mail, p, severity, alias); SH_MUTEX_UNLOCK(mutex_fifo_mail); if (status >= 0) ++sh.mailNum.alarm_last; SH_FREE(p); if (sh.mailNum.alarm_last >= sh.mailNum.alarm_interval) { BREAKEXIT(sh_nmail_flush); retval = sh_nmail_flush (); } if (status == SH_FIFO_MAX) retval = -2; SL_RETURN(retval, (_("sh_mail_pushstack"))); } /* The mailer. */ static int sh_mail_end_conn (FILE * connfile, int fd); static FILE * sh_mail_start_conn (struct alias * address, int * fd, int * anum); static void sh_mail_get_subject(const char * message, char * mheader, size_t len) { st_format rep_serv_tab[] = { { 'T', S_FMT_TIME, 0, 0, NULL}, { 'H', S_FMT_STRING, 0, 0, NULL}, { 'M', S_FMT_STRING, 0, 0, NULL}, { 'S', S_FMT_STRING, 0, 0, NULL}, {'\0', S_FMT_ULONG, 0, 0, NULL}, }; char * p; char * mptr; char sev[8]; char * msg; SL_ENTER(_("sh_mail_get_subject")); (void) sl_strlcpy(mheader, _("Subject: "), len); if (NULL == strchr(mail_subject, '%')) { (void) sl_strlcat(mheader, mail_subject, len); SL_RET0(_("sh_mail_get_subject")); } rep_serv_tab[0].data_ulong = (unsigned long) time(NULL); rep_serv_tab[1].data_str = sh.host.name; /* fast forward to the important part */ msg = sh_util_strdup(message); mptr = sl_strstr(msg, _("msg=")); if (mptr) { mptr += 4; rep_serv_tab[2].data_str = mptr; } else rep_serv_tab[2].data_str = msg; mptr = sl_strstr(msg, _("sev=")); if (mptr) { mptr += 5; sev[0] = *mptr; ++mptr; sev[1] = *mptr; ++mptr; sev[2] = *mptr; ++mptr; sev[3] = *mptr; ++mptr; sev[4] = '\0'; } else { mptr = msg; sev[0] = *mptr; ++mptr; sev[1] = *mptr; ++mptr; sev[2] = *mptr; ++mptr; sev[3] = *mptr; ++mptr; if (*mptr == ' ') { sev[4] = '\0'; } else { sev[4] = *mptr; ++mptr; if (*mptr == ' ') { sev[5] = '\0'; } else { sev[5] = *mptr; sev[6] = '\0'; } } } rep_serv_tab[3].data_str = sev; p = sh_util_formatted(mail_subject, rep_serv_tab); (void) sl_strlcat(mheader, p, len); SH_FREE(p); SH_FREE(msg); SL_RET0(_("sh_mail_get_subject")); } sh_string * sh_mail_signature_block (sh_string * sigMsg, char * recipient, char * bufcompress) { time_t id_audit; char * theSig; char ibuf[80]; unsigned int count; /* ------ signature block ------------------------------------ */ sigMsg = sh_string_add_from_char(sigMsg, _("-----BEGIN SIGNATURE-----\r\n")); count = sh_nmail_get_mailkey (recipient, skey->mailkey_new, KEY_LEN+1, &id_audit); if (count != 0) { char sigbuf[KEYBUF_SIZE]; /* Sign the message with the signature key. */ theSig = sh_util_siggen (skey->mailkey_new, bufcompress, sl_strlen(bufcompress), sigbuf, sizeof(sigbuf)); sigMsg = sh_string_add_from_char(sigMsg, theSig); } else { /* reveal first signature key */ /* flawfinder: ignore */ (void) sl_strlcpy(skey->crypt, skey->mailkey_new, KEY_LEN+1); BREAKEXIT(sh_util_encode); /* flawfinder: ignore */ sh_util_encode(skey->crypt, bufcompress, 0, 'A'); /* flawfinder: ignore */ sigMsg = sh_string_add_from_char(sigMsg, skey->crypt); /* flawfinder: ignore */ memset (skey->crypt, 0, KEY_LEN); } sigMsg = sh_string_add_from_char(sigMsg, "\r\n"); sl_snprintf(ibuf, sizeof(ibuf), _("%06u %010lu::%s\r\n"), count, (unsigned long) id_audit, sh.host.name); sigMsg = sh_string_add_from_char(sigMsg, ibuf); sigMsg = sh_string_add_from_char(sigMsg, _("-----END MESSAGE-----")); return sigMsg; } int sh_mail_msg (const char * message) { char subject[32+32+SH_MINIBUF+2+3+SH_PATHBUF]; char mheader[32+32+SH_MINIBUF+2+3]; sh_string * mailMsg; sh_string * compMsg; int status = 0; volatile int errcount; size_t wrlen; volatile int retval = -1; char * bufcompress; size_t compressed; static int failcount = 0; FILE * connfile = NULL; static time_t fail_time = 0; static time_t success_time = 0; int ma_socket = -1; int address_num = 0; sh_string * theMsg = NULL; /* #define SH_MAILBUF (256) */ #define SH_MAILBUF 4096 char timebuf[81]; SL_ENTER(_("sh_mail_msg")); /* * Return if we cannot mail. */ if (failedMail == S_TRUE) SL_RETURN((-1), _("sh_mail_msg")); /* * Final failure, can't mail for SH_MAX_FAIL hours. */ if ( (success_time > 0) && (fail_time > 0) && (time(NULL) - success_time) > 3600*SH_MAX_FAIL) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL, _("mail"), sh_string_str(all_recipients->recipient)); sh_mail_emptystack(); sh.mailNum.alarm_last = 0; failedMail = S_TRUE; SL_RETURN((-1), _("sh_mail_msg")); } /* * Try at most every three seconds to mail if there was a failure. */ if ((fail_time > 0) && (time(NULL) - fail_time) < 3/*600*/) { if (failcount > 3) { /* -- Save for later. Changed: done by caller. -- * sh_nmail_pushstack (severity, message, alias); */ ++failcount; SL_RETURN((-2), _("sh_mail_msg")); } else { (void) retry_msleep(2, 0); ++failcount; } } /* -- Reset time of last failure. -- */ fail_time = 0; /* --------- Build complete message. ------------------------ */ /* Don't flush the queue here, because tag_list doesn't know * how to filter messages. */ theMsg = sh_string_new_from_lchar(message, sl_strlen(message)); if (!theMsg) { SL_RETURN((-1), _("sh_mail_msg")); } /* ---------- Header ---------------------------------------- */ if (mail_subject == NULL) { (void) sl_strlcpy(mheader, _("Subject: "), sizeof(mheader)-5); (void) sl_strlcat(mheader, sh_unix_time (0, timebuf, sizeof(timebuf)), sizeof(mheader)-5); (void) sl_strlcat(mheader, " ", sizeof(mheader)-5); (void) sl_strlcat(mheader, sh.host.name, sizeof(mheader)-5); } else { if (message) { sh_mail_get_subject(message, mheader, sizeof(mheader)-5); } else { (void) sl_strlcpy(mheader, _("Subject: "), sizeof(mheader)-5); (void) sl_strlcat(mheader, sh_unix_time (0, timebuf, sizeof(timebuf)), sizeof(mheader)-5); (void) sl_strlcat(mheader, " ", sizeof(mheader)-5); (void) sl_strlcat(mheader, sh.host.name, sizeof(mheader)-5); } } /* RFC 821: Header is terminated by an empty line */ (void) sl_strlcat(mheader, "\015\012\015\012", sizeof(mheader)); /* ---------- Message --------------------------------------- */ (void) sl_strlcpy(subject, sh_unix_time (0, timebuf, sizeof(timebuf)), sizeof(subject)); (void) sl_strlcat(subject, " ", sizeof(subject)); (void) sl_strlcat(subject, sh.host.name, sizeof(subject)); (void) sl_strlcat(subject, "\r\n", sizeof(subject)); mailMsg = sh_string_new (SH_MAILBUF); compMsg = sh_string_new (SH_MAILBUF); mailMsg = sh_string_add_from_char(mailMsg, mheader); mailMsg = sh_string_add_from_char(mailMsg, _("-----BEGIN MESSAGE-----\r\n")); mailMsg = sh_string_add_from_char(mailMsg, subject); mailMsg = sh_string_add (mailMsg, theMsg); mailMsg = sh_string_add_from_char(mailMsg, "\r\n"); /* ---------- Compressed Message ---------------------------- */ compMsg = sh_string_add_from_char(compMsg, subject); compMsg = sh_string_add (compMsg, theMsg); compMsg = sh_string_add_from_char(compMsg, "\r\n"); bufcompress = SH_ALLOC(sh_string_len(compMsg) + KEY_LEN + 1); bufcompress[0] = '\0'; compressed = sh_util_compress (bufcompress, sh_string_str(compMsg), sh_string_len(compMsg) + 1); /* ---------- Connect ---------------------------------------- */ errcount = 0; if (sh_mail_all_in_one == S_FALSE) { struct alias * address_list; address_list = all_recipients; while (address_list) { if (address_list->send_mail == 1) { connfile = sh_mail_start_conn (address_list, &ma_socket, &address_num); if (NULL != connfile) { wrlen = fwrite (sh_string_str(mailMsg), 1, sh_string_len(mailMsg), connfile); wrlen -= sh_string_len(mailMsg); if (wrlen == 0) { sh_string * sigMsg = sh_string_new (0); sigMsg = sh_mail_signature_block (sigMsg, sh_string_str(address_list->recipient), bufcompress); wrlen = fwrite (sh_string_str(sigMsg), 1, sh_string_len(sigMsg), connfile); wrlen -= sh_string_len(sigMsg); sh_string_destroy(&sigMsg); } if (wrlen == 0) status = sh_mail_end_conn (connfile, ma_socket); else status = -1; } if (NULL == connfile || status != 0) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL, _("mail"), sh_string_str(address_list->recipient)); ++errcount; ++sh.statistics.mail_failed; } else { ++sh.statistics.mail_success; } if (connfile != NULL) { (void) sl_fclose (FIL__, __LINE__, connfile); connfile = NULL; } } address_list = address_list->all_next; } } else { connfile = sh_mail_start_conn (NULL, &ma_socket, &address_num); if (NULL != connfile) { wrlen = fwrite (sh_string_str(mailMsg), 1, sh_string_len(mailMsg), connfile); wrlen -= sh_string_len(mailMsg); if (wrlen == 0) { sh_string * sigMsg = sh_string_new (0); sigMsg = sh_mail_signature_block (sigMsg, NULL, bufcompress); wrlen = fwrite (sh_string_str(sigMsg), 1, sh_string_len(sigMsg), connfile); wrlen -= sh_string_len(sigMsg); sh_string_destroy(&sigMsg); } if (wrlen == 0) status = sh_mail_end_conn (connfile, ma_socket); else status = -1; } if (NULL == connfile || status != 0) { struct alias* ma_address = all_recipients; while (ma_address) { if (ma_address->send_mail == 1) break; ma_address = ma_address->all_next; } if (ma_address) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL, _("mail"), sh_string_str(ma_address->recipient)); errcount = address_num; ++sh.statistics.mail_failed; } else { ++sh.statistics.mail_success; } if (connfile != NULL) { (void) sl_fclose (FIL__, __LINE__, connfile); connfile = NULL; } } memset (bufcompress, 0, compressed); SH_FREE(bufcompress); memset (sh_string_str(mailMsg), 0, sh_string_len(mailMsg)); memset (sh_string_str(compMsg), 0, sh_string_len(compMsg)); memset (sh_string_str(theMsg), 0, sh_string_len(theMsg)); sh_string_destroy(&mailMsg); sh_string_destroy(&compMsg); sh_string_destroy(&theMsg); /* --- Stay responsible for delivery in case of failure --- */ if (errcount == address_num) { rollback_list(fifo_mail); retval = -3; } else { mark_list(fifo_mail); } if (errcount == address_num) { fail_time = time(NULL); SL_RETURN((retval), _("sh_mail_msg")); } success_time = time(NULL); failcount = 0; SL_RETURN((0), _("sh_mail_msg")); } /* * * SMTP CODE BELOW * * */ #include #ifdef HOST_IS_HPUX #define _XOPEN_SOURCE_EXTENDED #endif #include #include #include #include #ifndef S_SPLINT_S #include #else #define AF_INET 2 #endif #define SH_NEED_GETHOSTBYXXX #include "sh_static.h" /* missing on HP-UX 10.20 */ #ifndef IPPORT_SMTP #define IPPORT_SMTP 25 #endif static int sh_mail_wait(int code, int ma_socket); static char * relay_host = NULL; int sh_mail_set_relay (const char * str_s) { SL_ENTER(_("sh_mail_set_relay")); if (str_s == NULL) SL_RETURN( -1, _("sh_mail_set_relay")); if (relay_host != NULL) { SH_FREE (relay_host); relay_host = NULL; } if (0 == sl_strncmp(str_s, _("NULL"), 4)) { SL_RETURN( 0, _("sh_mail_set_relay")); } relay_host = sh_util_strdup(str_s); SL_RETURN( 0, _("sh_mail_set_relay")); } static char * mail_sender = NULL; int sh_mail_set_sender (const char *str) { if (mail_sender != NULL) { SH_FREE (mail_sender); mail_sender = NULL; } if (str != NULL) { mail_sender = sh_util_strdup (str); } if (mail_sender == NULL) { return -1; } return 0; } static int sh_mail_port = IPPORT_SMTP; int sh_mail_set_port (const char * str) { int i = atoi (str); SL_ENTER(_("sh_mail_set_port")); if (i >= 0 && i < 65535) { sh_mail_port = i; } else { sh_mail_port = IPPORT_SMTP; SL_RETURN ((-1), _("sh_mail_set_port")); } SL_RETURN( (0), _("sh_mail_set_port")); } /************************* * * start connection * for details on SMTP, see RFC 821 * * If ma_address == NULL, will send to all marked with * send_mail=1 in recipient list, else to ma_address. */ static time_t time_wait = 300; static void report_smtp (char * reply); static FILE * sh_mail_start_conn (struct alias * ma_address, int * ma_socket, int * anum) { char * address; int aFlag = 0; int ecount; char this_address[256]; char ma_machine[256]; char ma_user[256]; char error_msg[256]; char error_call[SH_MINIBUF]; int error_num = 0; register int i, j, k; FILE * connFile = NULL; struct tm * my_tm; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) struct tm time_tm; #endif time_t my_time; char my_tbuf[128]; int fd; dnsrep * answers; mx * result; SL_ENTER(_("sh_mail_start_conn")); *ma_socket = -1; time_wait = 300; if (ma_address == NULL) { aFlag = 1; ma_address = all_recipients; while (ma_address) { if (ma_address->send_mail == 1) break; ma_address = ma_address->all_next; } } if (!ma_address) { SL_RETURN( NULL, _("sh_mail_start_conn")); } address = sh_string_str(ma_address->recipient); TPT(( 0, FIL__, __LINE__, _("msg=
\n"), address)); /* ------- split adress ------------------ */ if (strchr (address, '@') == NULL) { (void) sl_strlcpy(ma_user, address, 256); (void) sl_strlcpy(ma_machine, _("localhost"), 256); } else { i = 0; while (i < 255 && address[i] != '@') { ma_user[i] = address[i]; ++i; } /* adress[i] = '@' */ ma_user[i] = '\0'; j = i + 1; k = i; i = 0; while (i < 255 && address[i+j] != '\0') { ma_machine[i] = address[i+j]; ++i; } ma_machine[i] = '\0'; if (address[k] != '@' || address[k+i+1] != '\0') { SL_RETURN( NULL, _("sh_mail_start_conn")); } } if (relay_host != NULL) { (void) sl_strlcpy (ma_machine, relay_host, sizeof(ma_machine)); TPT((0, FIL__, __LINE__, _("msg=\n"), ma_user, ma_machine)); fd = connect_port (ma_machine, sh_mail_port, error_call, &error_num, error_msg, 256); } else { answers = ma_address->mx_list; if (!answers) { answers = return_mx (ma_machine); ma_address->mx_list = answers; } if (answers) { result = answers->reply; fd = -1; for (i = 0; i < answers->count; ++i) { (void) sl_strlcpy(ma_machine, result[i].address, sizeof(ma_machine)); TPT((0, FIL__, __LINE__, _("msg=\n"), ma_user, ma_machine, result[i].pref)); fd = connect_port (ma_machine, sh_mail_port, error_call, &error_num, error_msg, 256); if (fd >= 0) break; } } else { (void) sl_strlcpy(error_call, _("return_mx"), SH_MINIBUF); (void) sl_strlcpy(error_msg, _("The specified host is unknown: "), 256); (void) sl_strlcat(error_msg, ma_machine, 256); fd = -1; } } if (fd < 0) { sh_error_handle ((-1), FIL__, __LINE__, error_num, MSG_E_NET, error_msg, error_call, _("email"), ma_machine); SL_RETURN( NULL, _("sh_mail_start_conn")); } /* associate a FILE structure with it */ connFile = fdopen (fd, "r+"); if (connFile == NULL) { TPT(( 0, FIL__, __LINE__, _("msg=\n"))); (void) sl_close_fd(FIL__, __LINE__, fd); SL_RETURN( NULL, _("sh_mail_start_conn")); } /* say HELO to the other socket */ if (0 == sh_mail_wait (220, fd)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("Timeout on SMTP session init"), _("sh_mail_start_conn"), _("mail"), sh.host.name); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); (void) sl_fclose(FIL__, __LINE__, connFile); SL_RETURN( NULL, _("sh_mail_start_conn")); } (void) fflush(connFile); if (0 != sh_ipvx_is_numeric(sh.host.name)) { sl_snprintf(error_msg, sizeof(error_msg), "HELO [%s]", sh.host.name); } else { sl_snprintf(error_msg, sizeof(error_msg), "HELO %s", sh.host.name); } report_smtp(error_msg); if (0 != sh_ipvx_is_numeric(sh.host.name)) fprintf(connFile, _("HELO [%s]%c%c"), sh.host.name, 13, 10); else fprintf(connFile, _("HELO %s%c%c"), sh.host.name, 13, 10); (void) fflush(connFile); if (0 == sh_mail_wait(250, fd)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("HELO failed"), _("sh_mail_start_conn"), _("mail"), sh.host.name); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); (void) sl_fclose(FIL__, __LINE__, connFile); SL_RETURN( NULL, _("sh_mail_start_conn")); } /* tell them who we are */ (void) sl_strlcpy (this_address, mail_sender ? mail_sender : DEFAULT_SENDER, 256); if (NULL == strchr(this_address, '@')) { (void) sl_strlcat (this_address, "@", 256); if (0 != sh_ipvx_is_numeric(sh.host.name)) (void) sl_strlcat (this_address, _("example.com"), 256); else (void) sl_strlcat (this_address, sh.host.name, 256); } sl_snprintf(error_msg, sizeof(error_msg), "MAIL FROM:<%s>", this_address); report_smtp(error_msg); (void) fflush(connFile); /*@-usedef@*/ fprintf(connFile, _("MAIL FROM:<%s>%c%c"), this_address, 13, 10); /*@+usedef@*/ (void) fflush(connFile); if (0 == sh_mail_wait(250, fd)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("MAIL FROM failed"), _("sh_mail_start_conn"), _("mail"), this_address); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); (void) sl_fclose(FIL__, __LINE__, connFile); SL_RETURN( NULL, _("sh_mail_start_conn")); } /* tell them who to send mail to */ if (aFlag == 0) { sl_snprintf(error_msg, sizeof(error_msg), "RCPT TO:<%s>", address); report_smtp(error_msg); (void) fflush(connFile); fprintf(connFile, _("RCPT TO:<%s>%c%c"), address, 13, 10); (void) fflush(connFile); if (0 == sh_mail_wait(250, fd)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("RCPT TO failed"), _("sh_mail_start_conn"), _("mail"), address); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); (void) sl_fclose(FIL__, __LINE__, connFile); SL_RETURN( NULL, _("sh_mail_start_conn")); } *anum = 1; } else { int address_num = 0; ecount = 0; ma_address = all_recipients; while (ma_address) { if (ma_address->send_mail != 1) { ma_address = ma_address->next; continue; } ++address_num; sl_snprintf(error_msg, sizeof(error_msg), "RCPT TO:<%s>", sh_string_str(ma_address->recipient)); report_smtp(error_msg); (void) fflush(connFile); fprintf(connFile, _("RCPT TO:<%s>%c%c"), sh_string_str(ma_address->recipient), 13, 10); (void) fflush(connFile); if (0 == sh_mail_wait(250, fd)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("RCPT TO failed"), _("sh_mail_start_conn"), _("mail"), sh_string_str(ma_address->recipient)); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); ++ecount; } ma_address = ma_address->next; } *anum += address_num; if (ecount == address_num) { (void) sl_fclose(FIL__, __LINE__, connFile); SL_RETURN( NULL, _("sh_mail_start_conn")); } } /* Send the message */ report_smtp(_("DATA")); (void) fflush(connFile); fprintf(connFile, _("DATA%c%c"), 13, 10); (void) fflush(connFile); if (0 == sh_mail_wait(354, fd)) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("DATA failed"), _("sh_mail_start_conn"), _("mail"), address); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); (void) sl_fclose(FIL__, __LINE__, connFile); SL_RETURN( NULL, _("sh_mail_start_conn")); } my_time = time(NULL); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) my_tm = localtime_r(&my_time, &time_tm); #else my_tm = localtime(&my_time); #endif if (!my_tm) { sl_strlcpy(my_tbuf, _("Thu, 01 Jan 1970 00:00:00 +00:00"), sizeof(my_tbuf)); } else { #if defined(HAVE_STRFTIME_Z) (void) strftime(my_tbuf, 127, _("%a, %d %b %Y %H:%M:%S %z"), my_tm); #else (void) strftime(my_tbuf, 127, _("%a, %d %b %Y %H:%M:%S %Z"), my_tm); #endif } TPT(( 0, FIL__, __LINE__, _("msg=%c%cTo: <%s>%c%cDate: %s>%c%c"), this_address, 13, 10, address, 13, 10, my_tbuf, 13, 10)); report_smtp(_("sending data..")); (void) fflush(connFile); fprintf(connFile, _("From: <%s>%c%c"\ "To: <%s>%c%c"\ "Date: %s%c%c"), this_address, 13, 10, address, 13, 10, my_tbuf, 13, 10); *ma_socket = fd; SL_RETURN( connFile, _("sh_mail_start_conn")); } /************************* * * end connection * */ static int sh_mail_end_conn (FILE * connFile, int fd) { SL_ENTER(_("sh_mail_end_conn")); time_wait = 300; report_smtp(_(".")); (void) fflush(connFile); fprintf(connFile, _("%c%c.%c%c"), 13, 10, 13, 10); (void) fflush(connFile); if (0 != sh_mail_wait(250, fd)) { (void) fflush(connFile); fprintf(connFile, _("QUIT%c%c"), 13, 10); (void) fflush(connFile); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN (0, _("sh_mail_end_conn")); } sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, _("QUIT failed"), _("sh_mail_end_conn"), _("mail"), _("SMTP server")); TPT(( 0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN ((-1), _("sh_mail_end_conn")); } /**************************** * * Handle server replies * * */ extern int flag_err_debug; static void report_smtp (char * reply) { char * tmp; if (flag_err_debug == S_TRUE) { tmp = sh_util_safe_name_keepspace(reply); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, tmp, _("report_smtp") ); SH_FREE(tmp); } return; } static int sh_mail_wait(int code, int ma_socket) { int rcode, g; char c; char errmsg[194]; char reply[128]; unsigned int ireply = 0; enum { WAIT_CODE_START, WAIT_CODE, WAIT_NL, WAIT_NL_CONT } state; time_t waited_time; SL_ENTER(_("mail_wait")); waited_time = time(NULL); /* timeout after 5 minutes */ rcode = 0; state = WAIT_CODE_START; reply[0] = '\0'; while (sl_read_timeout_fd (ma_socket, &c, 1, time_wait, S_FALSE) > 0) { if (ireply < (sizeof(reply) - 1)) { if (c != '\n' && c != '\r') { reply[ireply] = c; ++ireply; reply[ireply] = '\0'; } } g = (int) c; /* if (g == EOF) { TPT((0, FIL__, __LINE__, _("msg=\n"))); SL_RETURN( 0, _("mail_wait")); } */ switch(state) { /* wait for start of a numerical code */ case WAIT_CODE_START: if (0 != isspace(g)) break; /* Skip white space */ if (0 == isdigit(g)) { report_smtp(reply); SL_RETURN( 0, _("mail_wait")); /* No leading number */ } rcode = g-(int)'0'; /* convert to number */ state = WAIT_CODE; break; /* wait for completion of numerical code */ case WAIT_CODE: if (0 != isdigit(g)) { rcode = rcode * 10 + (g-(int)'0'); /* next digit */ break; } /*@+charintliteral@*/ state = ((g == '-') ? WAIT_NL_CONT : WAIT_NL); /*@-charintliteral@*/ break; /* wait for newline, then return with status code */ case WAIT_NL: /*@+charintliteral@*/ if (g != '\n') break; /*@-charintliteral@*/ TPT((0, FIL__, __LINE__, _("msg=\n"), rcode, (int)(rcode/100), code, (int)(code/100) )); g = ((int)(rcode/100) == (int)(code/100)) ? 1 : 0; if (g != 1) { char * tmp = sh_util_safe_name_keepspace(reply); sl_snprintf(errmsg, sizeof(errmsg), _("Bad response (%s), expected %d"), tmp, code); SH_FREE(tmp); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, errmsg, _("sh_mail_wait"), _("mail"), _("SMTP server")); } else { report_smtp(reply); } waited_time = time(NULL) - waited_time; time_wait -= waited_time; TPT((0, FIL__, __LINE__, _("msg=\n"), (int) time_wait)); SL_RETURN( (g), _("mail_wait")) ; /* wait for continuation line */ /*@fallthrough@*//* no, but splint doesn't understand */ case WAIT_NL_CONT: /*@+charintliteral@*/ if (g == '\n') state = WAIT_CODE_START; /* There is a continuation line */ /*@-charintliteral@*/ break; default: TPT((0, FIL__, __LINE__, _("msg=\n"))); report_smtp(reply); SL_RETURN( 0, _("mail_wait")); } } TPT((0, FIL__, __LINE__, _("msg=\n"))); /* Failed, EOF or error on socket */ report_smtp(reply); SL_RETURN( 0, _("mail_wait")); } /* -- function to insert "\r\n" after each 998 chars -- */ #define SPLIT_AT 998 static char * split_string(const char * str) { size_t size; size_t blocks; int count = 0; char * p, * p0; const char * q; if (!str) return NULL; size = strlen(str) + 1; blocks = 1 + (size / SPLIT_AT); if (sl_ok_muls(2, blocks) && sl_ok_adds(size, (2*blocks))) { size = size + (2*blocks); } else { /* integer overflow, do not split */ p = sh_util_strdup(str); return p; } p = SH_ALLOC(size); memset(p, 0, size); p0 = p; q = str; while (*q != '\0') { *p = *q; ++p; ++q; ++count; if (0 == (count % SPLIT_AT)) { count = 0; *p = '\r'; ++p; *p = '\n'; ++p; } } /* fprintf(stderr, "used = %d\n", strlen(p0)); */ return p0; } /***************************************************************** * * MX Resolver Routines * *****************************************************************/ #if defined(HAVE_ARPA_NAMESER_H) #include #ifdef __APPLE__ #define BIND_8_COMPAT 1 #endif #ifndef S_SPLINT_S #include #include #endif #include #include #ifndef S_SPLINT_S #include #endif #include "sh_tools.h" #ifndef HFIXEDSZ #define HFIXEDSZ 12 #endif #ifndef QFIXEDSZ #define QFIXEDSZ 4 #endif /*@unused@*//* used in get_mx() which is not parsed by splint */ static unsigned int get_short (unsigned char * loc) { unsigned int retval = 0; if (loc) { /* byte order: MSB first */ /*@+charint@*/ retval = (((unsigned char) * loc) * 256) | ((unsigned char) * (loc + 1)); /*@-charint@*/ } return (retval); } /* parser errors with splint */ #ifndef S_SPLINT_S static dnsrep * get_mx (char *hostname) { int ret, length, status; mx * result; size_t len; typedef union { HEADER head; unsigned char buffer[4096]; } querybuf; querybuf * reply; char expanded[1024]; unsigned char * comp_dn, * eom; HEADER * header; int type, rdlength, pref; unsigned int count, theindex; dnsrep * retval; SL_ENTER(_("get_mx")); if (0 != res_init ()) SL_RETURN (NULL, _("get_mx")); reply = SH_ALLOC(sizeof(querybuf)); errno = 0; length = res_query (hostname, C_IN, T_MX, (unsigned char *) reply, 4095); if (length < 1) { char errbuf[SH_ERRBUF_SIZE]; /* error handling */ if (length == -1) { if (errno == ECONNREFUSED) status = ECONNREFUSED; else status = h_errno; #ifdef FIL__ sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, (errno == ECONNREFUSED) ? sh_error_message (status, errbuf, sizeof(errbuf)) : sh_tools_errmessage(status, errbuf, sizeof(errbuf)), _("res_query")); #else if (errno == ECONNREFUSED) fprintf(stderr, " ERROR: %s: \n", strerror(errno)); /* TESTONLY */ else fprintf(stderr, "HERROR: %s\n", hstrerror(h_errno));/* TESTONLY */ #endif } SH_FREE(reply); SL_RETURN (NULL, _("get_mx")); } header = (HEADER *) reply; /* start of data section */ comp_dn = (unsigned char *) reply + HFIXEDSZ; /* end-of-message */ eom = (unsigned char *) reply + length; /* HEADER NAME -- must be skipped or decompressed * TYPE -- type of data we got back, 16 bit integer * CLASS -- class we got back, also a 16 bit integer * TTL -- 32 bit time-to-live. just skip this * RDLENGTH -- length of the data to follow * RDATA -- the data: * PREF -- 16 bit preference * MX -- name of mail exchanger, must be decompressed */ /* Skip the query data. * QDCOUNT is the number of entries (unsigned 16 bit int). */ count = ntohs (header->qdcount); for (theindex = 0; theindex < count; ++theindex) { ret = dn_skipname (comp_dn, eom); comp_dn += ret + QFIXEDSZ; if (ret < 1 || comp_dn >= eom) { SH_FREE(reply); SL_RETURN (NULL, _("get_mx")); } } count = ntohs (header->ancount); if (count < 1) { SH_FREE(reply); SL_RETURN (NULL, _("get_mx")); } retval = SH_ALLOC (sizeof (dnsrep)); if (!retval) { SH_FREE(reply); SL_RETURN (NULL, _("get_mx")); } retval->count = count; /* allocate space for the results */ if (!sl_ok_muls(count, sizeof (mx))) { SH_FREE(reply); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } result = SH_ALLOC (count * sizeof (mx)); if (!result) { SH_FREE(reply); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } retval->reply = result; do { /* HEADER NAME */ ret = dn_expand ((unsigned char *) reply, eom, comp_dn, (char *) expanded, 1023); comp_dn += ret; if (ret < 1 || comp_dn >= eom) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } /* TYPE */ type = get_short (comp_dn); comp_dn += 2; if (type != T_MX || comp_dn >= eom) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } /* CLASS (re-use 'type' var) */ /* type = get_short (comp_dn); *//* don't care */ comp_dn += 2; if (comp_dn >= eom) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } /* TTL */ comp_dn += 4; if (comp_dn >= eom) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } /* RDLENGTH */ rdlength = get_short (comp_dn); comp_dn += 2; if (rdlength < 1 || comp_dn >= eom) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } /* RDATA */ pref = get_short (comp_dn); comp_dn += 2; if (comp_dn >= eom) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } ret = dn_expand ((unsigned char *) reply, eom, comp_dn, (char *) expanded, 1023); comp_dn += ret; if (ret < 1) { SH_FREE(reply); SH_FREE (result); SH_FREE (retval); SL_RETURN (NULL, _("get_mx")); } count--; /* fill in the struct */ result[count].pref = pref; len = strlen (expanded) + 1; result[count].address = SH_ALLOC (len); sl_strlcpy (result[count].address, expanded, len); } while (ret > 0 && comp_dn < eom && count); SH_FREE(reply); SL_RETURN (retval, _("get_mx")); } /* ifndef S_SPLINT_S */ #endif /* #if defined(HAVE_ARPA_NAMESER_H) */ #endif static int comp_mx_pref (const void * a, const void * b) { const mx * ax = (const mx *) a; const mx * bx = (const mx *) b; if (ax->pref > bx->pref) return 1; else if (ax->pref < bx->pref) return -1; else return 0; } /* * return_mx returns a list of valid mail exchangers for domain */ static dnsrep * return_mx (char *domain) { dnsrep * answers = NULL; mx * result; dnsrep * retval; char * address = NULL; char errmsg[128]; SL_ENTER(_("return_mx")); #if defined(HAVE_ARPA_NAMESER_H) if (domain != NULL) answers = /*@-unrecog@*/get_mx (domain)/*@+unrecog@*/; #endif if (answers != NULL && answers->count > 0) { qsort(answers->reply, (size_t) answers->count, sizeof(mx), comp_mx_pref); SL_RETURN (answers, _("return_mx")); } else { char numeric[SH_IP_BUF]; if (domain != NULL) { #if defined(HAVE_ARPA_NAMESER_H) #ifdef FIL__ (void) sl_strlcpy (errmsg, _("No MX record for domain "), 127); (void) sl_strlcat (errmsg, domain, 127); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, errmsg, _("get_mx")); #else /* flawfinder: ignore *//* test code only */ strcpy (errmsg, /* known to fit */ _("No MX record for domain ")); strncat (errmsg, domain, 100); errmsg[122] = '\0'; fprintf(stderr, "Warning: %s\n", errmsg); #endif #endif } retval = NULL; if (domain != NULL) address = sh_ipvx_canonical(domain, numeric, sizeof(numeric)); if (address) { result = SH_ALLOC (sizeof (mx)); retval = SH_ALLOC (sizeof (dnsrep)); retval->reply = result; retval->count = 1; result->pref = 0; result->address = address; } else { #ifdef FIL__ (void) sl_strlcpy (errmsg, _("Unknown host "), 127); (void) sl_strlcat (errmsg, domain, 127); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, errmsg, _("return_mx")); #endif SL_RETURN (NULL, _("return_mx")); } SL_RETURN (retval, _("return_mx")); } } int free_mx (dnsrep * answers) { mx * result; int i; SL_ENTER(_("free_mx")); if (!answers) SL_RETURN (0, _("return_mx")); result = answers->reply; for (i = 0; i < answers->count; ++i) { SH_FREE (result[i].address); } SH_FREE(result); SH_FREE(answers); SL_RETURN (0, _("return_mx")); } #ifdef TEST_ONLY int main(int argc, char * argv[]) { int i; dnsrep * answers; mx * result; if (argc < 2) { fprintf(stderr, "Usage: dns \n"); return -1; } answers = return_mx(argv[1]); if (!answers) { fprintf(stderr, "No answer\n"); return -1; } if (answers->count > 0) { result = answers->reply; for (i = 0; i < answers->count; ++i) { fprintf(stderr, "Record %3d: [%3d] %s\n", i, result[i].pref, result[i].address); } } else { fprintf(stderr, "No answer\n"); free_mx(answers); return -1; } free_mx(answers); return (0); } #endif /* if defined(SH_WITH_MAIL) */ #endif samhain-4.1.4/src/sh_audit.c0000644000175000017500000003300312615253277012625 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2010 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) #include #include #include #include #include #include #include #include "samhain.h" #include "sh_error.h" #undef FIL__ #define FIL__ _("sh_audit.c") #if !defined(SH_COMPILE_STATIC) && defined(__linux__) && defined(HAVE_AUPARSE_H) && defined(HAVE_AUPARSE_LIB) #include #include "sh_extern.h" #include "sh_utils.h" #define REC_SIZE_SYSCALL 32 #define REC_SIZE_EXE 64 #define REC_SIZE_SUCCESS 32 struct recordState { char syscall[REC_SIZE_SYSCALL]; char exe[REC_SIZE_EXE]; char success[REC_SIZE_SUCCESS]; unsigned int auid; unsigned int uid; unsigned int gid; unsigned int euid; unsigned int egid; unsigned int fsuid; unsigned int fsgid; time_t time; unsigned int milli; }; static int listRecords (auparse_state_t * au, struct recordState * state) { if (auparse_first_record(au) != 1) return -1; state->time = auparse_get_time(au); state->milli = auparse_get_milli(au); if (auparse_find_field(au, _("syscall"))) sl_strlcpy(state->syscall, auparse_interpret_field(au), REC_SIZE_SYSCALL); if (auparse_find_field(au, _("success"))) strncpy(state->success, auparse_interpret_field(au), REC_SIZE_SUCCESS); if (auparse_find_field(au, "uid")) state->uid = auparse_get_field_int(au); if (auparse_find_field(au, "gid")) state->gid = auparse_get_field_int(au); if (auparse_find_field(au, _("euid"))) state->euid = auparse_get_field_int(au); if (auparse_find_field(au, _("fsuid"))) state->fsuid = auparse_get_field_int(au); auparse_first_field(au); if (auparse_find_field(au, _("auid"))) state->auid = auparse_get_field_int(au); auparse_first_field(au); if (auparse_find_field(au, _("egid"))) state->egid = auparse_get_field_int(au); if (auparse_find_field(au, _("fsgid"))) state->fsgid = auparse_get_field_int(au); auparse_first_field(au); if (auparse_find_field(au, "exe")) sl_strlcpy(state->exe, auparse_interpret_field(au), REC_SIZE_EXE); return 0; } static char * doAuparse (const char * file, time_t time, int tol, char * result, size_t rsize, int redo_flag) { struct recordState state; struct recordState stateFetched; unsigned int found_flag = 0; auparse_state_t * au = auparse_init(AUSOURCE_LOGS, NULL); if (!au) { char ebuf[SH_ERRBUF_SIZE]; int errnum = errno; sl_snprintf(ebuf, sizeof(ebuf), _("Error in auparse_init() - %s\n"), strerror(errnum)); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("doAuparse") ); return NULL; } if (ausearch_add_interpreted_item(au, _("name"), "=", file, AUSEARCH_RULE_CLEAR) != 0) { goto err; } if (time != 0) { ausearch_add_timestamp_item(au, ">=", time-tol, 0, AUSEARCH_RULE_AND); ausearch_add_timestamp_item(au, "<=", time+tol, 0, AUSEARCH_RULE_AND); } if (ausearch_set_stop(au, AUSEARCH_STOP_RECORD) != 0) { sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Error in ausearch_set_stop\n"), _("doAuparse") ); goto err; } memset(&state, '\0', sizeof(state)); while (ausearch_next_event(au) == 1) { memset(&stateFetched, '\0', sizeof(state)); listRecords(au, &stateFetched); if (0 == strcmp(stateFetched.success, "yes")) { memcpy(&state, &stateFetched, sizeof(state)); ++found_flag; } auparse_next_event(au); } if (found_flag == 0 && redo_flag == S_FALSE) { size_t len = strlen(file); char * path = SH_ALLOC(len + 2); char * altres; sl_strlcpy(path, file, len+2); path[len] = '/'; path[len+1] = '\0'; auparse_destroy(au); altres = doAuparse(path, time, tol, result, rsize, S_TRUE); SH_FREE(path); return altres; } if (0 == strcmp(state.success, "yes")) { char * tmp_exe = sh_util_safe_name(state.exe); sl_snprintf(result, rsize, _("time=%lu.%u, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"), (unsigned long) state.time, state.milli, state.syscall, state.auid, state.uid, state.gid, state.euid, state.egid, state.fsuid, state.fsgid, tmp_exe); SH_FREE(tmp_exe); auparse_destroy(au); return result; } err: auparse_destroy(au); return NULL; } static int sh_audit_checkdaemon(); static int actl_pnum = -1; static char * actl_paths[4] = { N_("/sbin/auditctl"), N_("/usr/sbin/auditctl"), N_("/bin/auditctl"), N_("/usr/bin/auditctl") }; /* Public function to fetch an audit record for path 'file', time 'time' * The 'result' array should be sized ~256 char. */ char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize) { char * res = NULL; if (sh_audit_checkdaemon() >= 0) { time_t new; if (mtime >= ctime) { new = mtime; } else { new = ctime; } res = doAuparse (file, new, 1, result, rsize, S_FALSE); if (!res) { res = doAuparse (file, new, 3, result, rsize, S_FALSE); } } return res; } void sh_audit_delete_all () { int p = sh_audit_checkdaemon(); if (p >= 0) { char ctl[64]; sl_snprintf(ctl, sizeof(ctl), _("%s -D -k samhain"), _(actl_paths[p])); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Deleting audit daemon rules with key samhain"), _("sh_audit_delete_all") ); sl_strlcpy(ctl, _(actl_paths[p]), sizeof(ctl)); sh_ext_system(ctl, ctl, "-D", "-k", _("samhain"), NULL); } return; } static int sh_audit_isdir(const char * file) { struct stat buf; if ( (0 == lstat (file, &buf)) && S_ISDIR(buf.st_mode)) return S_TRUE; return S_FALSE; } static void sh_audit_mark_int (const char * file) { static int flushRules = 0; int p = sh_audit_checkdaemon(); /* Flush all rules at startup. */ if (flushRules == 0) { sh_audit_delete_all (); flushRules = 1; } if (p >= 0) { size_t len = strlen(file) + 64; char * command = SH_ALLOC(len); char * safe; char ctl[64]; char a1[32]; char a2[32]; char a3[32]; sl_snprintf(command, len, _("%s -w %s -p wa -k samhain"), _(actl_paths[p]), file); safe = sh_util_safe_name_keepspace(command); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, safe, _("sh_audit_mark") ); SH_FREE(safe); sl_strlcpy(ctl, _(actl_paths[p]), sizeof(ctl)); sl_strlcpy(command, file, len); sl_strlcpy(a3, _("samhain"), sizeof(a3)); sh_ext_system(ctl, ctl, "-w", command, "-p", "wa", "-k", a3, NULL); /* Placing a watch on a directory will not place a watch on the * directory inode, so we do this explicitely. */ if (S_TRUE == sh_audit_isdir(file)) { safe = sh_util_safe_name(file); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Add path watch for directory"), _("sh_audit_mark_int"), safe ); SH_FREE(safe); sl_strlcpy(command, _("path="), len); sl_strlcat(command, file, len); sl_strlcpy(a1, _("always,exit"), sizeof(a1)); sl_strlcpy(a2, _("perm=wa"), sizeof(a2)); sh_ext_system(ctl, ctl, "-a", a1, "-F", command, "-F", a2, "-k", a3, NULL); } SH_FREE(command); } return; } struct aud_list { char * file; struct aud_list * next; }; struct aud_list * mark_these = NULL; static void add_this (char * file) { struct aud_list * this = SH_ALLOC(sizeof(struct aud_list)); size_t len = strlen(file); this->file = sh_util_strdup(file); if ((len > 1) && (file[len-1] == '/')) this->file[len-1] = '\0'; this->next = mark_these; mark_these = this; return; } /* Check whether it is already covered by a higher directory */ static int test_exchange (struct aud_list * this, char * file) { size_t len0 = sl_strlen(this->file); size_t len1 = sl_strlen(file); int ret = -1; if (len0 == len1) { return strcmp(this->file, file); } else { char * s0 = SH_ALLOC(len0 + 2); char * s1 = SH_ALLOC(len1 + 2); sl_strlcpy(s0, this->file, len0 + 2); sl_strlcpy(s1, file, len1 + 2); if (s0 < s1) { sl_strlcat(s0, "/", len0 + 2); ret = strncmp(s0, s1, len0 + 1); } else { sl_strlcat(s1, "/", len1 + 2); if (0 == strncmp(s0, s1, len1 + 1)) { size_t len = strlen(file); SH_FREE(this->file); this->file = sh_util_strdup(file); if ((len > 1) && (file[len-1] == '/')) this->file[len-1] = '\0'; ret = 0; } } SH_FREE(s0); SH_FREE(s1); } return ret; } /* Place a path on the list of of paths to be watched */ void sh_audit_mark (char * file) { struct aud_list * this = mark_these; if (!mark_these) { add_this (file); return; } while (this) { /* Check whether it is already covered by a higher * directory */ if (0 == test_exchange(this, file)) return; this = this->next; } add_this (file); return; } void sh_audit_commit () { struct aud_list * next; struct aud_list * this = mark_these; mark_these = NULL; while (this) { sh_audit_mark_int (this->file); next = this->next; SH_FREE(this->file); SH_FREE(this); this = next; } } static int sh_audit_checkdaemon() { int i; static int flag = 0; char command[64]; char * p; if (flag != 0) return -1; if (actl_pnum >= 0) return actl_pnum; for (i = 0; i < 4; ++i) { if (0 == access(_(actl_paths[i]), F_OK))/* flawfinder: ignore */ { if (0 == access(_(actl_paths[i]), X_OK))/* flawfinder: ignore */ { actl_pnum = i; break; } else { char ebuf[SH_ERRBUF_SIZE]; int errnum = errno; sl_snprintf(ebuf, sizeof(ebuf), _("Cannot execute auditctl - %s\n"), strerror(errnum)); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("sh_audit_checkdaemon") ); flag = 1; actl_pnum = -1; return -1; } } } if (actl_pnum == -1 && flag == 0) { char ebuf[SH_ERRBUF_SIZE]; int errnum = errno; sl_snprintf(ebuf, sizeof(ebuf), _("Cannot find auditctl - %s\n"), strerror(errnum)); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("sh_audit_checkdaemon") ); flag = 1; actl_pnum = -1; return -1; } /* We found an executable auditctl */ sl_snprintf(command, sizeof(command), _("%s -s"), _(actl_paths[actl_pnum])); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, command, _("sh_audit_checkdaemon") ); p = sh_ext_popen_str (command); if (p) { int retval = -1; if (strstr(p, _(" pid=0 "))) { sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Audit daemon for Linux kernel audit system is not running"), _("sh_audit_checkdaemon") ); flag = 1; actl_pnum = -1; } else { retval = actl_pnum; sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, retval, MSG_E_SUBGEN, _("Audit daemon is running"), _("sh_audit_checkdaemon") ); } SH_FREE(p); return retval; } sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errno, MSG_E_SUBGEN, _("No output from auditctl -s"), _("sh_audit_checkdaemon") ); flag = 1; actl_pnum = -1; return -1; } /* HAVE_AUPARSE_H */ #else char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize) { (void) file; (void) mtime; (void) ctime; (void) result; (void) rsize; return 0; } void sh_audit_mark (const char * file) { (void) file; sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, _("Setting audit watch not supported"), _("sh_audit_mark")); return; } void sh_audit_delete_all () { return; } void sh_audit_commit () { return; } #endif /* client || standalone */ #endif samhain-4.1.4/src/sh_mounts.c0000644000175000017500000004712712615253277013060 00000000000000/* * File: sh_mounts.c * Desc: A module for Samhain; checks for mounts present and options on them. * Auth: Cian Synnott * */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" /* Used in the call tracing macros to keep track of where we are in the code */ #undef FIL__ #define FIL__ _("sh_mounts.c") #include "samhain.h" #include "sh_utils.h" #include "sh_error.h" #include "sh_modules.h" #include "sh_mounts.h" #ifdef SH_USE_MOUNTS #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) /* * #ifdef HAVE_STRING_H * #include * #endif */ #ifdef TM_IN_SYS_TIME #include #else #include #endif /* Prototypes for configuration functions */ int sh_mounts_config_activate (const char * opt); int sh_mounts_config_timer (const char * opt); int sh_mounts_config_mount (const char * opt); int sh_mounts_config_sevmnt (const char * opt); int sh_mounts_config_sevopt (const char * opt); /* Prototype for the function to read info on mounted filesystems */ static struct sh_mounts_mnt *readmounts(void); /* Table for configuration options, and pointers to the functions that will * configure them. Each function is passed the string resulting from stripping * the option and the "equals" from the config file; e.g. MountCheckActive=1 in * the configuration file will result in the string "1" being passed to * sh_mounts_config_activate() */ sh_rconf sh_mounts_table[] = { { N_("mountcheckactive"), sh_mounts_config_activate }, { N_("mountcheckinterval"), sh_mounts_config_timer }, { N_("checkmount"), sh_mounts_config_mount }, { N_("severitymountmissing"), sh_mounts_config_sevmnt }, { N_("severityoptionmissing"), sh_mounts_config_sevopt }, { NULL, NULL }, }; /* Structures for storing my configuration information, and functions for * manipulating them */ struct sh_mounts_mnt { char * path; struct sh_mounts_opt * opts; struct sh_mounts_mnt * next; }; struct sh_mounts_opt { char * opt; struct sh_mounts_opt * next; }; /* Return the mount structure whose path matches 'mnt' or NULL if not found */ static struct sh_mounts_mnt *sh_mounts_mnt_member(struct sh_mounts_mnt *m, char *mnt) { struct sh_mounts_mnt *it; for (it = m; it != NULL; it = it->next) { if (0 == sl_strcmp(it->path, mnt)) { return it; } } return NULL; } /* Return the opt structure whose option matches 'opt' or NULL if not found */ static struct sh_mounts_opt *sh_mounts_opt_member(struct sh_mounts_opt *o, char *opt) { struct sh_mounts_opt *it; for (it = o; it != NULL; it = it->next) { /* if (!strcmp(it->opt, opt)) { */ if (0 == sl_strcmp(it->opt, opt)) { return it; } } return NULL; } static void sh_mounts_opt_free(struct sh_mounts_opt *o) { if (o != NULL) { sh_mounts_opt_free(o->next); SH_FREE(o->opt); SH_FREE(o); } } static void sh_mounts_mnt_free(struct sh_mounts_mnt *m) { if (m != NULL) { sh_mounts_mnt_free(m->next); sh_mounts_opt_free(m->opts); SH_FREE(m->path); SH_FREE(m); } } /* Some configuration variables I'll be using */ static time_t lastcheck = (time_t) 0; static int ShMountsActive = S_FALSE; static time_t ShMountsInterval = 86400; static int ShMountsSevMnt = SH_ERR_ERR; static int ShMountsSevOpt = SH_ERR_ERR; static struct sh_mounts_mnt *mountlist = NULL; /* Module initialisation * This is called once at the start of each samhain run. * Non-configuration setup code should be placed here. */ int sh_mounts_init (struct mod_type * arg) { (void) arg; SL_ENTER(_("sh_mounts_init")); /* This is a little odd. Because we've built the configured mount list at * this point, if we've set the module inactive, we need to free the list - * otherwise when we reconf() with it set active, we'll end up with a * duplicated list. Interesting. */ if (ShMountsActive == S_FALSE) { sh_mounts_mnt_free(mountlist); mountlist = NULL; SL_RETURN(-1, _("sh_mounts_init")); } SL_RETURN(0, _("sh_mounts_init")); } /* Module timer * This timer function is called periodically with the current time to see if * it is time to run the module's "check" function. On nonzero return, the * check is run. */ int sh_mounts_timer (time_t tcurrent) { SL_ENTER(_("sh_mounts_timer")); if ((time_t) (tcurrent - lastcheck) >= ShMountsInterval) { lastcheck = tcurrent; SL_RETURN(-1, _("sh_mounts_timer")); } SL_RETURN(0, _("sh_mounts_timer")); } /* Module check * The business end of things. This is the actual check code for this module. * Everything you want to do periodically should go here. */ int sh_mounts_check () { struct sh_mounts_mnt *memlist; struct sh_mounts_mnt *cfgmnt, *mnt; struct sh_mounts_opt *cfgopt, *opt; SL_ENTER(_("sh_mounts_check")); /* Log the check run. For each message type you want, you need to define it * as an enum in sh_cat.h, and then set it up in terms of priority and format * string in sh_cat.c */ sh_error_handle(-1, FIL__, __LINE__, 0, MSG_MNT_CHECK); /* Read the list of mounts from memory */ memlist = readmounts(); if (memlist == NULL) { sh_error_handle(-1, FIL__, __LINE__, 0, MSG_MNT_MEMLIST); } /* For each mount we are configured to check, run through the list of mounted * filesystems and compare the pathnames */ for (cfgmnt = mountlist; cfgmnt != NULL; cfgmnt = cfgmnt->next) { mnt = sh_mounts_mnt_member(memlist, cfgmnt->path); if (mnt) { for (cfgopt = cfgmnt->opts; cfgopt != NULL; cfgopt = cfgopt->next) { opt = sh_mounts_opt_member(mnt->opts, cfgopt->opt); if (!opt) { sh_error_handle(ShMountsSevOpt, FIL__, __LINE__, 0, MSG_MNT_OPTMISS, cfgmnt->path, cfgopt->opt); } } } else { sh_error_handle(ShMountsSevMnt, FIL__, __LINE__, 0, MSG_MNT_MNTMISS, cfgmnt->path); } } /* Make sure to clean up after ourselves */ sh_mounts_mnt_free(memlist); SL_RETURN(0, _("sh_mounts_check")); } /* Module cleanup * The end of the tour - when samhain is shutting down, this is run. */ int sh_mounts_cleanup () { SL_ENTER(_("sh_mounts_cleanup")); sh_mounts_mnt_free(mountlist); mountlist = NULL; SL_RETURN( (0), _("sh_mounts_cleanup")); } /* Module reconfiguration * Run on receipt of a HUP. */ int sh_mounts_reconf() { SL_ENTER(_("sh_mounts_null")); sh_mounts_mnt_free(mountlist); mountlist = NULL; /* re-set defaults */ ShMountsActive = S_FALSE; ShMountsInterval = 86400; ShMountsSevMnt = 7; ShMountsSevOpt = 7; SL_RETURN( (0), _("sh_mounts_null")); } /* Module configuration * These functions are called when the configuration file is being parsed. */ /* Configure to check a particular mount */ int sh_mounts_config_mount (const char * opt_in) { struct sh_mounts_mnt *m; struct sh_mounts_opt *o; char *sp, *temp, *opt; SL_ENTER(_("sh_mounts_config_mount")); /* It's probably best to make a copy of opt before messing about with it * via string functions. Good practice and all that. */ temp = sh_util_strdup(opt_in); /* Since we're going to "consume" this new buffer, it'll be good to have a * reference to it's allocated memory so we can free it later. Let's use * temp for that, and "opt" for consumption */ opt = temp; m = (struct sh_mounts_mnt *) SH_ALLOC(sizeof(struct sh_mounts_mnt)); /* First, strip out the mount path. */ m->path = sh_util_strdup(sh_util_strsep(&opt, " \t")); m->opts = NULL; /* Now get all of the mount options - they can be delimited by comma or * whitespace */ while (opt != NULL) { sp = sh_util_strsep(&opt, ", \t"); /* This just catches multiple separators appearing together */ if (*sp == '\0') { continue; } o = (struct sh_mounts_opt *) SH_ALLOC(sizeof(struct sh_mounts_opt)); o->next = m->opts; m->opts = o; o->opt = sh_util_strdup(sp); } /* Add to the list of configured mounts */ m->next = mountlist; mountlist = m; /* Free the string buffer we allocated earlier */ SH_FREE(temp); SL_RETURN(0, _("sh_mounts_config_mount")); } /* Simply sets our boolean as to whether this module is active */ int sh_mounts_config_activate (const char * opt) { int i; SL_ENTER(_("sh_mounts_config_activate")); i = sh_util_flagval(opt, &ShMountsActive); SL_RETURN(i, _("sh_mounts_config_activate")); } /* Sets up our timer */ int sh_mounts_config_timer (const char * opt) { long val; int retval = 0; SL_ENTER(_("sh_mounts_config_timer")); val = strtol (opt, (char **)NULL, 10); if (val <= 0) { sh_error_handle (-1, FIL__, __LINE__, EINVAL, MSG_EINVALS, _("mounts timer"), opt); retval = -1; } val = (val <= 0 ? 86400 : val); ShMountsInterval = (time_t) val; SL_RETURN(retval, _("sh_mounts_config_timer")); } /* Configure severity for "mount missing" messages */ int sh_mounts_config_sevmnt (const char * opt) { int retval = 0; char tmp[32]; SL_ENTER(_("sh_mounts_config_sevmnt")); tmp[0] = '='; tmp[1] = '\0'; (void) sl_strlcat (tmp, opt, 32); retval = sh_error_set_level (tmp, &ShMountsSevMnt); SL_RETURN(retval, _("sh_mounts_config_sevmnt")); } int sh_mounts_config_sevopt (const char * opt) { int retval = 0; char tmp[32]; SL_ENTER(_("sh_mounts_config_sevopt")); tmp[0] = '='; tmp[1] = '\0'; (void) sl_strlcat (tmp, opt, 32); retval = sh_error_set_level (tmp, &ShMountsSevOpt); SL_RETURN(retval, _("sh_mounts_config_sevopt")); } /* * Below here we have the code for actually reading options on mounted fs's * I've just got code here to work on FreeBSD, Linux and Solaris. I'm sure * others could be added. Note that some small bits of the OS-specific code * are from mountlist.c in GNU fileutils. */ /* FreeBSD includes */ #if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) #include #include #include #endif /* Linux includes */ #ifdef HOST_IS_LINUX #include #include #endif /* Solaris includes */ #ifdef HOST_IS_SOLARIS #include #include #endif /* HP_UX includes */ #ifdef HOST_IS_HPUX #include #include #endif /* AIX includes and helper routines (from gnome-vfs-unix-mounts.c */ #if 0 #ifdef HOST_IS_AIX #include #include #include /* gnome-vfs-unix-mounts.c - read and monitor fstab/mtab Copyright (C) 2003 Red Hat, Inc The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Author: Alexander Larsson */ /* read character, ignoring comments (begin with '*', end with '\n' */ static int aix_fs_getc (FILE *fd) { int c; while ((c = getc (fd)) == '*') { while (((c = getc (fd)) != '\n') && (c != EOF)) {} /* do nothing */ } } /* eat all continuous spaces in a file */ static int aix_fs_ignorespace (FILE *fd) { int c; while ((c = aix_fs_getc (fd)) != EOF) { if (! (isascii(c) && isspace (c)) ) { ungetc (c,fd); return c; } } return EOF; } /* read one word from file */ static int aix_fs_getword (FILE *fd, char *word, int len) { int c; int i = 0; --len; aix_fs_ignorespace (fd); while (((c = aix_fs_getc (fd)) != EOF) && !( isascii(c) && isspace(c) )) { if (c == '"') { while (((c = aix_fs_getc (fd)) != EOF) && (c != '"')) { *word++ = c; ++i; if (i == len) break; } } else { *word++ = c; ++i; } if (i == len) break; } *word = 0; return c; } /* PATH_MAX is in sys/limits.h, included via stdio.h */ typedef struct { char mnt_mount[PATH_MAX]; char mnt_special[PATH_MAX]; char mnt_fstype[16]; char mnt_options[128]; } AixMountTableEntry; /* read mount points properties */ static int aix_fs_get (FILE *fd, AixMountTableEntry *prop) { /* Need space for PATH_MAX + ':' (terminating '\0' is in PATH_MAX; SUSv3) */ static char word[PATH_MAX+1] = { 0 }; char value[PATH_MAX]; /* reset */ if (fd == NULL) { word[0] = '\0'; return 0; } /* read stanza */ if (word[0] == 0) { if (aix_fs_getword (fd, word, (PATH_MAX+1)) == EOF) return EOF; } word[strlen(word) - 1] = 0; sl_strlcpy (prop->mnt_mount, word, PATH_MAX); /* read attributes and value */ while (aix_fs_getword (fd, word, (PATH_MAX+1)) != EOF) { /* test if is attribute or new stanza */ if (word[strlen(word) - 1] == ':') { return 0; } /* read "=" */ aix_fs_getword (fd, value, PATH_MAX); /* read value */ aix_fs_getword (fd, value, PATH_MAX); if (strcmp (word, "dev") == 0) { sl_strlcpy (prop->mnt_special, value, PATH_MAX); } else if (strcmp (word, "vfs") == 0) { sl_strlcpy (prop->mnt_fstype, value, 16); } else if (strcmp (word, "options") == 0) { sl_strlcpy(prop->mnt_options, value, 128); } } return 0; } /* end AIX helper routines */ #endif #endif #if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) /* FreeBSD returns flags instead of strings as mount options, so we'll convert * them here. */ static struct sh_mounts_opt * getoptlist(int flags) { struct sh_mounts_opt *list, *o; int i; struct {char *opt; int flag;} table[] = { #ifdef MNT_RDONLY {"ro", MNT_RDONLY}, #endif #ifdef MNT_NOEXEC {"noexec", MNT_NOEXEC}, #endif #ifdef MNT_NOSUID {"nosuid", MNT_NOSUID}, #endif #ifdef MNT_NODEV {"nodev", MNT_NODEV}, #endif #ifdef MNT_SYNCHRONOUS {"sync", MNT_SYNCHRONOUS}, #endif #ifdef MNT_ASYNC {"async", MNT_ASYNC}, #endif #ifdef MNT_LOCAL {"local", MNT_LOCAL}, #endif #ifdef MNT_QUOTA {"quota", MNT_QUOTA}, #endif #ifdef MNT_NOATIME {"noatime", MNT_NOATIME}, #endif {"bound", -1} }; SL_ENTER(_("getoptlist")); list = NULL; /* Add any flags found to the list */ for (i = 0; table[i].flag != -1; i++) { if (flags & table[i].flag) { o = (struct sh_mounts_opt *) SH_ALLOC(sizeof(struct sh_mounts_opt)); o->opt = sh_util_strdup(table[i].opt); o->next = list; list = o; } } SL_RETURN(list, _("getoptlist")); } /* Solaris & Linux return identical option string formats */ #else /* We just separate the options out by parsing for commas */ static struct sh_mounts_opt * getoptlist(char *opt) { struct sh_mounts_opt *list, *o; char *sp, *temp; SL_ENTER(_("getoptlist")); /* See the comments in sh_mounts_config_mount() above for the reasons for * this arcane little zig-zag */ temp = sh_util_strdup(opt); opt = temp; list = NULL; /* For each option, add to the list */ while (opt != NULL) { sp = sh_util_strsep(&opt, ", \t"); if (*sp == '\0') { continue; } o = (struct sh_mounts_opt *) SH_ALLOC(sizeof(struct sh_mounts_opt)); o->next = list; list = o; o->opt = sh_util_strdup(sp); } SH_FREE(temp); SL_RETURN(list, _("getoptlist")); } #endif /* Read the list of mounts from whereever is appropriate to the OS and return * it. Return NULL on error. */ static struct sh_mounts_mnt * readmounts(void) { struct sh_mounts_mnt *list, *m; SL_ENTER(_("readmounts")); m = NULL; /* use it to avoid compiler warning */ list = m; /* The Open/FreeBSD way */ #if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) { struct statfs *fsp; int entries; entries = getmntinfo(&fsp, MNT_NOWAIT); if (entries < 0) { SL_RETURN((NULL), _("readmounts")); } for (; entries-- > 0; fsp++) { m = (struct sh_mounts_mnt *) SH_ALLOC(sizeof (struct sh_mounts_mnt)); m->path = sh_util_strdup(fsp->f_mntonname); m->opts = getoptlist(fsp->f_flags); m->next = list; list = m; } } #endif /* The Linux way */ #ifdef HOST_IS_LINUX { struct mntent *mp; FILE *tab = setmntent(_PATH_MOUNTED, "r"); if (tab == NULL) { SL_RETURN((NULL), _("readmounts")); } mp = getmntent(tab); while (mp != NULL) { m = (struct sh_mounts_mnt *) SH_ALLOC(sizeof (struct sh_mounts_mnt)); m->path = sh_util_strdup(mp->mnt_dir); m->opts = getoptlist(mp->mnt_opts); m->next = list; list = m; mp = getmntent(tab); } (void) endmntent(tab); } #endif /* The Solaris way */ #ifdef HOST_IS_SOLARIS { struct mnttab mp; FILE *tab = fopen(MNTTAB, "r"); if (tab == NULL) { SL_RETURN((NULL), _("readmounts")); } while (!getmntent(tab, &mp)) { m = (struct sh_mounts_mnt *) SH_ALLOC(sizeof (struct sh_mounts_mnt)); m->path = sh_util_strdup(mp.mnt_mountp); m->opts = getoptlist(mp.mnt_mntopts); m->next = list; list = m; } sl_fclose(FIL__, __LINE__, tab); } #endif /* The HP-UX way */ #ifdef HOST_IS_HPUX { struct mntent *mp; FILE *tab = setmntent(MNT_MNTTAB, "r"); if (tab == NULL) { SL_RETURN((NULL), _("readmounts")); } mp = getmntent(tab); while (mp != NULL) { m = (struct sh_mounts_mnt *) SH_ALLOC(sizeof (struct sh_mounts_mnt)); m->path = sh_util_strdup(mp->mnt_dir); m->opts = getoptlist(mp->mnt_opts); m->next = list; list = m; mp = getmntent(tab); } (void) endmntent(tab); } #endif /* The AIX way */ #if 0 #ifdef HOST_IS_AIX { AixMountTableEntry mntent; FILE *tab = fopen("/etc/filesystems", "r"); if (tab == NULL) { SL_RETURN((NULL), _("readmounts")); } while (!aix_fs_get (tab, &mntent)) { m = (struct sh_mounts_mnt *) SH_ALLOC(sizeof (struct sh_mounts_mnt)); m->path = sh_util_strdup(mntent.mnt_mount); m->opts = getoptlist(mntent.mnt_options); m->next = list; list = m; mntent.mnt_mount[0] = '\0'; mntent.mnt_special[0] = '\0'; mntent.mnt_fstype[0] = '\0'; mntent.mnt_options[0] = '\0'; } (void) sl_fclose(FIL__, __LINE__, tab); aix_fs_get (NULL, NULL); /* reset */ } #endif #endif SL_RETURN((list), _("readmounts")); } /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */ #endif /* #ifdef SH_USE_MOUNTS */ #endif samhain-4.1.4/src/sh_string.c0000644000175000017500000006327212615253277013040 00000000000000 #include "config_xor.h" #include #include #include #include "sh_string.h" #include "sh_mem.h" #undef FIL__ #define FIL__ _("sh_string.c") extern int sl_ok_adds (size_t a, size_t b); #define S_TRUE 1 #define S_FALSE 0 #include #include /* Split array at delim in at most nfields fields. * Empty fields are returned as empty (zero-length) strings. * Leading and trailing WS are removed from token. * The number of fields is returned in 'nfields', their * lengths in 'lengths'. * A single delimiter will return two empty fields. */ char ** split_array(char *line, unsigned int * nfields, char delim, size_t * lengths) { char *a, *e, *s; unsigned int i = 0; int flag = 0; char **arr; unsigned int maxfields = (*nfields); arr = SH_ALLOC((maxfields+1) * sizeof (char*)); e = line; do { /* skip leading WS */ for (s=e; *s && isspace((int)*s); ++s) /* nothing */; if (*s) { /* move a to next delim */ for (a=s; *a && *a != delim; ++a) /* nothing */; /* set e to next after delim */ if (*a == delim) { e = a+1; flag = 1; } else /* (!*a) */ { e = a; flag = 0; } if (a != line) { if (i < (maxfields -1)) { /* chop off trailing WS */ for (a--; isspace((int)*a) && a > s; a--) /* do nothing */; /* terminate string */ ++a; *a = '\0'; } else { /* If nfields < actual fields, last string * will be remainder, therefore skip to end. */ if ( *a ) { do { a++; } while ( *a ); } } } else { *a = '\0'; } } else /* (!*s) */ { a = s; /* (i == 0) handles the special case of splitting the empty string */ if (flag || i == 0) { flag = 0; goto setnext; } break; } setnext: lengths[i] = (size_t) (a-s); /* a >= s always */ arr[i] = s; ++i; } while (i < maxfields); *nfields = i; arr[i] = NULL; return arr; } /* Split array at whitespace in at most nfields fields. * Multiple whitespaces are collapsed. * Empty fields are returned as empty (zero-length) strings. * The number of fields is returned in nfields. * An empty string will return zero fields. * If nfields < actual fields, last string will be remainder. */ #define SH_SPLIT_LIST 0 #define SH_SPLIT_WS 1 char ** split_array_ws_int (char *line, unsigned int * nfields, size_t * lengths, const char *delim, int isList) { char *a, *e, *s; unsigned int i = 0; char **arr; unsigned int maxfields = (*nfields); arr = SH_ALLOC((maxfields+1) * sizeof (char*)); e = line; do { s = e; /* skip leading WS */ if (isList == SH_SPLIT_WS) { if ( *s && isspace((int)*s) ) { do { ++s; } while ( *s && isspace((int)*s) ); } } else { if ( *s && strchr(delim, (int)*s)) { do { ++s; } while ( *s && strchr(delim, (int)*s)); } } if (*s) { /* s is at non-ws, move a to next ws */ a = s; if (isList == SH_SPLIT_WS) { do { a++; } while ( *a && (!isspace((int)*a)) ); } else { do { a++; } while ( *a && NULL == strchr(delim, (int)*a)); } /* next token, *a is either ws or '\0' */ e = ( (*a) ? a+1 : a); /* terminate and set arr[i] */ if (i < (maxfields-1)) { *a = '\0'; } else { /* If nfields < actual fields, last * string will be remainder. Therefore * skip to end. */ if ( *a ) { do { a++; } while ( *a ); } } lengths[i] = (size_t)(a-s); /* a >= s always */ arr[i] = s; ++i; } else /* if (!*s) */ { break; } } while (i < maxfields); *nfields = i; arr[i] = NULL; return arr; } char ** split_array_ws (char *line, unsigned int * nfields, size_t * lengths) { return split_array_ws_int (line, nfields, lengths, NULL, SH_SPLIT_WS); } char ** split_array_list (char *line, unsigned int * nfields, size_t * lengths) { return split_array_ws_int (line, nfields, lengths, ", \t", SH_SPLIT_LIST); } char ** split_array_token (char *line, unsigned int * nfields, size_t * lengths, const char * token) { return split_array_ws_int (line, nfields, lengths, token, SH_SPLIT_LIST); } /* return a split() of a list contained in 'PREFIX\s*( list ).*' */ char ** split_array_braced (char *line, const char * prefix, unsigned int * nfields, size_t * lengths) { char * s = line; char * p; unsigned int sind = (prefix) ? strlen(prefix) : 0; while ( *s && isspace((int)*s) ) ++s; if (prefix && 0 != strncmp(s, prefix, strlen(prefix))) return NULL; s = &s[sind]; while ( *s && isspace((int)*s) ) ++s; if (!s || (*s != '(')) return NULL; ++s; p = strchr(s, ')'); if (!p || (*p == *s)) return NULL; *p = '\0'; return split_array_list (s, nfields, lengths); } #define SH_STRING_PARCEL 120 static size_t sh_string_read_int(sh_string * s, FILE * fp, size_t maxlen, char *start); size_t sh_string_read(sh_string * s, FILE * fp, size_t maxlen) { return sh_string_read_int(s, fp, maxlen, NULL); } size_t sh_string_read_cont(sh_string * s, FILE * fp, size_t maxlen, char *cont) { return sh_string_read_int(s, fp, maxlen, cont); } static char * sh_str_fgets (char *s, int size, FILE *fp) { char * ret; do { clearerr(fp); ret = fgets(s, size, fp); } while (ret == NULL && ferror(fp) && errno == EAGAIN); return ret; } size_t sh_string_read_int(sh_string * s, FILE * fp, size_t maxlen, char *start) { /* case 0) start != NULL and first char not in 'start' */ if (start) { int first; do { clearerr(fp); first = fgetc(fp); } while (first == EOF && ferror(fp) && errno == EAGAIN); if (first == EOF) { sh_string_truncate(s, 0); if (ferror(fp)) return -1; return 0; } if (NULL == strchr(start, first)) { ungetc(first, fp); return 0; } ungetc(first, fp); } /* case 1) EOF or error */ if (sh_str_fgets(s->str, s->siz, fp) == NULL) { sh_string_truncate(s, 0); if (ferror(fp)) return -1; return 0; } /* case 2) end of line reached. strlen should always be > 0 * because of the '\n', but we check. */ s->len = strlen(s->str); if (s->len > 0 && (s->str)[s->len-1] == '\n') { (s->str)[s->len-1] = '\0'; --(s->len); return (s->len + 1); } /* case 3) incomplete string */ for (;;) { if (maxlen > 0 && (s->siz+SH_STRING_PARCEL) > maxlen) { if (s->siz < maxlen) sh_string_grow(s, (maxlen-s->siz)); else return -2; } else { sh_string_grow(s, 0); } if (sh_str_fgets(&(s->str[s->len]), (s->siz - s->len), fp) == NULL) { if (ferror(fp)) { sh_string_truncate(s, 0); return -1; } return s->len; } s->len += strlen( &(s->str[s->len]) ); if (s->len > 0 && s->str[s->len-1] == '\n') { (s->str)[s->len-1] = '\0'; --(s->len); return (s->len + 1); } } /* notreached */ } sh_string * sh_string_cat_lchar(sh_string * s, const char * str, size_t len) { if (sl_ok_adds(len, s->siz) == S_TRUE) { if ((len + 1 + s->len) > s->siz) { sh_string_grow(s, ((len+1+s->len) - s->siz) ); } memcpy(&(s->str[s->len]), str, len); s->len += len; s->str[s->len] = '\0'; return s; } return NULL; } sh_string * sh_string_set_from_char(sh_string * s, const char * str) { size_t len = strlen(str); if ((len+1) > s->siz) { sh_string_grow(s, ((len+1) - s->siz) ); } memcpy(s->str, str, (len+1)); s->len = len; return s; } sh_string * sh_string_add_from_char(sh_string * s, const char * str) { size_t len = strlen(str); size_t avail = (s->siz - s->len); if ((len+1) > avail) { (void) sh_string_grow(s, ((len+1) - avail) ); } memcpy(&(s->str[s->len]), str, (len+1)); s->len += len; return s; } sh_string * sh_string_new_from_lchar(const char * str, size_t len) { sh_string * s; s = SH_ALLOC(sizeof(sh_string)); s->str = SH_ALLOC(len+1); if (str) memcpy(s->str, str, len); else s->str[0] = '\0'; s->str[len] = '\0'; s->siz = len+1; s->len = len; return s; } sh_string * sh_string_new_from_lchar3(const char * str1, size_t len1, const char * str2, size_t len2, const char * str3, size_t len3) { sh_string * s; size_t len = 0; if (sl_ok_adds(len1, len2) == S_TRUE) len = len1 + len2; else return NULL; if (sl_ok_adds( len, len3) == S_TRUE) len = len + len3; else return NULL; s = SH_ALLOC(sizeof(sh_string)); s->str = SH_ALLOC(len+1); memcpy(s->str, str1, len1); memcpy(&s->str[len1], str2, len2); memcpy(&s->str[len1+len2], str3, len3); s->str[len] = '\0'; s->siz = len+1; s->len = len; return s; } sh_string * sh_string_grow(sh_string * s, size_t increase) { char * new; if (increase == 0) increase = SH_STRING_PARCEL; if (s && sl_ok_adds(s->siz, increase) == S_TRUE) { new = SH_ALLOC(s->siz + increase); if (s->str) { memcpy(new, s->str, s->len+1); SH_FREE(s->str); } else { new[0] = '\0'; } s->str = new; s->siz += increase; return s; } return NULL; } sh_string * sh_string_truncate(sh_string * s, size_t len) { if (s) { if (s->str && (s->len > len) ) { s->len = len; (s->str)[len] = '\0'; } return s; } return NULL; } void sh_string_destroy(sh_string ** s) { if (s) { if ((*s) && (*s)->str) SH_FREE ((*s)->str); SH_FREE(*s); *s = NULL; } return; } sh_string * sh_string_new(size_t size) { sh_string * s; s = SH_ALLOC (sizeof(sh_string)); if (size == 0) size = SH_STRING_PARCEL; s->str = SH_ALLOC (size); s->str[0] = '\0'; s->siz = size; s->len = 0; return s; } /* Replaces fields in s with 'replacement'. Fields are given * in the ordered array ovector, comprising ovecnum pairs * ovector[i], ovector[i+1] which list offset of first char * of field, offset of first char after field (this is how * the pcre library does it). */ sh_string * sh_string_replace(const sh_string * s, const int * ovector, int ovecnum, const char * replacement, size_t rlen) { sh_string * r = NULL; char * p; long tlen; size_t len; int end = 0; int start = 0; size_t oldlen = 0; size_t newlen = 0; long diff; int i, curr, last; for (i = 0; i < ovecnum; ++i) { start = ovector[2*i]; /* offset of first char of substring */ if (start >= end) { end = ovector[2*i+1]; /* offset of first char after substring end*/ if (end > start && (unsigned int)end <= (s->len + 1)) { oldlen += (end - start); newlen += rlen; } else /* inconsistency detected */ { return NULL; } } else /* overlap detected */ { return NULL; } } diff = newlen - oldlen; if ((diff > 0) && ((s->len + 1 + diff) > s->siz)) { r = sh_string_new_from_lchar(sh_string_str(s), sh_string_len(s)); r = sh_string_grow(r, diff); } else { r = sh_string_new_from_lchar(sh_string_str(s), sh_string_len(s)); } curr = -1; for (i = 0; i < ovecnum; ++i) { if (ovector[2*i] >= 0) { curr = 2*i; break; } } if (r && ovecnum > 0 && ovector[curr] >= 0) { r->len = 0; r->str[0] = '\0'; p = r->str; /* First part, until start of first replacement */ if (r->siz > (unsigned int)ovector[curr]) { memcpy(p, s->str, (size_t)ovector[curr]); p += ovector[curr]; r->len += ovector[curr]; } if (r->siz > (r->len + rlen)) { memcpy(p, replacement, rlen); p += rlen; r->len += rlen; } *p = '\0'; last = curr + 1; for (i = 1; i < ovecnum; ++i) { if (ovector[2*i] < 0) continue; curr = 2*i; /* From end of last replacement to start of this */ tlen = (long)(ovector[curr] - ovector[last]); if (tlen >= 0) { len = (size_t) tlen; if (tlen > 0 && r->siz > (r->len + len)) { memcpy(p, &(s->str[ovector[last]]), (size_t)len); p += len; r->len += len; } /* The replacement */ if (r->siz > (r->len + rlen)) { memcpy(p, replacement, rlen); p += rlen; r->len += rlen; } /* null terminate */ *p = '\0'; last = curr + 1; } } /* Last part, after last replacement; includes terminating null */ if (last > 0) { /* If not, nothing has been replaced, and r is still a copy of s */ tlen = (long)((s->len + 1) - ovector[last]); if (tlen > 0) { len = (size_t)tlen; if (r->siz >= (r->len + len)) { memcpy(p, &(s->str[ovector[2*i -1]]), (size_t)len); p += (len - 1); r->len += (len - 1); *p = '\0'; } } } } return r; } #ifdef SH_CUTEST #include #include "CuTest.h" void Test_string (CuTest *tc) { int status, i, max = 120; FILE * fp; sh_string * s = NULL; sh_string * t; static char template[] = "/tmp/xtest.XXXXXX"; char ** array; char test[128]; size_t lengths[16]; unsigned int iarr; int ovector[16]; int ovecnum; s = sh_string_new(0); CuAssertPtrNotNull(tc, s); sh_string_destroy(&s); CuAssertTrue(tc, s == NULL); s = sh_string_new(0); CuAssertPtrNotNull(tc, s); status = mkstemp(template); CuAssertTrue(tc, status >= 0); fp = fdopen(status, "r+"); CuAssertPtrNotNull(tc, fp); for (i = 0; i < 80; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 0 */ for (i = 0; i < 118; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 1 */ for (i = 0; i < 119; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 2 */ for (i = 0; i < 120; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 3 */ for (i = 0; i < 121; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 4 */ for (i = 0; i < 238; ++i) { fputc ('a', fp); } fputc ('\n', fp); for (i = 0; i < 239; ++i) { fputc ('a', fp); } fputc ('\n', fp); for (i = 0; i < 240; ++i) { fputc ('a', fp); } fputc ('\n', fp); for (i = 0; i < 241; ++i) { fputc ('a', fp); } fputc ('\n', fp); rewind(fp); for (i = 0; i < 9; ++i) { status = sh_string_read(s, fp, max); switch (i) { case 0: CuAssertTrue(tc, s->len == 80); CuAssertTrue(tc, s->siz == 120); CuAssertTrue(tc, status == 81); break; case 1: CuAssertTrue(tc, s->len == 118); CuAssertTrue(tc, s->siz == 120); CuAssertTrue(tc, status == 119); break; case 2: CuAssertTrue(tc, s->len == 119); CuAssertTrue(tc, s->siz == 120); CuAssertTrue(tc, status == -2); /* no terminating '\n', truncated */ break; case 3: CuAssertTrue(tc, s->len == 120); CuAssertTrue(tc, s->siz == 240); CuAssertTrue(tc, status == 121); break; case 4: CuAssertTrue(tc, s->len == 121); CuAssertTrue(tc, s->siz == 240); CuAssertTrue(tc, status == 122); break; case 5: CuAssertTrue(tc, s->len == 238); CuAssertTrue(tc, s->siz == 240); CuAssertTrue(tc, status == 239); break; case 6: CuAssertTrue(tc, s->len == 239); CuAssertTrue(tc, s->siz == 240); CuAssertTrue(tc, status == -2); /* no terminating '\n', truncated */ break; default: CuAssertTrue(tc, s->len == 239); CuAssertTrue(tc, s->siz == 240); CuAssertTrue(tc, status == -2); } if (status == -2) /* read in rest of string */ { max = 240; sh_string_read(s, fp, max); } } rewind(fp); sh_string_truncate(s, 0); CuAssertTrue(tc, s->len == 0); for (i = 0; i < 9; ++i) { status = sh_string_read(s, fp, 240); if (status == -2) sh_string_read(s, fp, 240); else { for (status = 0; status < (int)s->len; ++status) { if (s->str[status] != 'a') { CuFail(tc, "unexpected character"); } } } } status = fclose(fp); CuAssertTrue(tc, status == 0); status = remove(template); CuAssertTrue(tc, status == 0); iarr = 10; strcpy(test, "|a1|| a2| |a3 |a4|a5|"); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,9,(int)iarr); CuAssertStrEquals(tc,"", array[0]); CuAssertStrEquals(tc,"a1", array[1]); CuAssertStrEquals(tc,"", array[2]); CuAssertStrEquals(tc,"a2", array[3]); CuAssertStrEquals(tc,"", array[4]); CuAssertStrEquals(tc,"a3", array[5]); CuAssertStrEquals(tc,"a4", array[6]); CuAssertStrEquals(tc,"a5", array[7]); CuAssertStrEquals(tc,"", array[8]); CuAssertIntEquals(tc, 0, (int)lengths[0]); CuAssertIntEquals(tc, 2, (int)lengths[1]); CuAssertIntEquals(tc, 0, (int)lengths[2]); CuAssertIntEquals(tc, 2, (int)lengths[3]); CuAssertIntEquals(tc, 0, (int)lengths[4]); CuAssertIntEquals(tc, 2, (int)lengths[5]); CuAssertIntEquals(tc, 2, (int)lengths[6]); CuAssertIntEquals(tc, 2, (int)lengths[7]); CuAssertIntEquals(tc, 0, (int)lengths[8]); iarr = 10; strcpy(test, "a1|| a2| |a3 |a4|a5|"); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,8,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertStrEquals(tc,"", array[1]); CuAssertStrEquals(tc,"a2", array[2]); CuAssertStrEquals(tc,"", array[3]); CuAssertStrEquals(tc,"a3", array[4]); CuAssertStrEquals(tc,"a4", array[5]); CuAssertStrEquals(tc,"a5", array[6]); CuAssertStrEquals(tc,"", array[7]); CuAssertIntEquals(tc, 2, (int)lengths[0]); CuAssertIntEquals(tc, 0, (int)lengths[1]); CuAssertIntEquals(tc, 2, (int)lengths[2]); CuAssertIntEquals(tc, 0, (int)lengths[3]); CuAssertIntEquals(tc, 2, (int)lengths[4]); CuAssertIntEquals(tc, 2, (int)lengths[5]); CuAssertIntEquals(tc, 2, (int)lengths[6]); CuAssertIntEquals(tc, 0, (int)lengths[7]); iarr = 10; strcpy(test, " a1|| a2 | |a3 |a4|a5"); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,7,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertStrEquals(tc,"", array[1]); CuAssertStrEquals(tc,"a2", array[2]); CuAssertStrEquals(tc,"", array[3]); CuAssertStrEquals(tc,"a3", array[4]); CuAssertStrEquals(tc,"a4", array[5]); CuAssertStrEquals(tc,"a5", array[6]); CuAssertIntEquals(tc, 2, (int)lengths[0]); CuAssertIntEquals(tc, 0, (int)lengths[1]); CuAssertIntEquals(tc, 2, (int)lengths[2]); CuAssertIntEquals(tc, 0, (int)lengths[3]); CuAssertIntEquals(tc, 2, (int)lengths[4]); CuAssertIntEquals(tc, 2, (int)lengths[5]); CuAssertIntEquals(tc, 2, (int)lengths[6]); iarr = 10; strcpy(test, "a1|| a2 | |a3 |a4|a5 "); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,7,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertStrEquals(tc,"", array[1]); CuAssertStrEquals(tc,"a2", array[2]); CuAssertStrEquals(tc,"", array[3]); CuAssertStrEquals(tc,"a3", array[4]); CuAssertStrEquals(tc,"a4", array[5]); CuAssertStrEquals(tc,"a5", array[6]); CuAssertIntEquals(tc, 2, (int)lengths[0]); CuAssertIntEquals(tc, 0, (int)lengths[1]); CuAssertIntEquals(tc, 2, (int)lengths[2]); CuAssertIntEquals(tc, 0, (int)lengths[3]); CuAssertIntEquals(tc, 2, (int)lengths[4]); CuAssertIntEquals(tc, 2, (int)lengths[5]); CuAssertIntEquals(tc, 2, (int)lengths[6]); iarr = 10; strcpy(test, "|"); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,2,(int)iarr); CuAssertStrEquals(tc,"", array[0]); CuAssertStrEquals(tc,"", array[1]); CuAssertIntEquals(tc, 0, (int)lengths[0]); CuAssertIntEquals(tc, 0, (int)lengths[1]); iarr = 10; strcpy(test, "|||"); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,4,(int)iarr); CuAssertStrEquals(tc,"", array[0]); CuAssertStrEquals(tc,"", array[1]); CuAssertStrEquals(tc,"", array[2]); CuAssertStrEquals(tc,"", array[3]); CuAssertIntEquals(tc, 0, (int)lengths[0]); CuAssertIntEquals(tc, 0, (int)lengths[1]); CuAssertIntEquals(tc, 0, (int)lengths[2]); CuAssertIntEquals(tc, 0, (int)lengths[3]); iarr = 10; strcpy(test, " a1 "); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,1,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertIntEquals(tc, 2, (int)lengths[0]); iarr = 10; strcpy(test, ""); array = split_array(test, &iarr, '|', lengths); CuAssertIntEquals(tc,1,(int)iarr); CuAssertStrEquals(tc,"", array[0]); CuAssertIntEquals(tc, 0, (int)lengths[0]); /* WS separated */ iarr = 10; strcpy(test, "a1"); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,1,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertIntEquals(tc, 2, (int)lengths[0]); iarr = 10; strcpy(test, " a1"); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,1,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertIntEquals(tc, 2, (int)lengths[0]); iarr = 10; strcpy(test, " a1 "); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,1,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertIntEquals(tc, 2, (int)lengths[0]); iarr = 10; strcpy(test, " "); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,0,(int)iarr); CuAssertTrue(tc, array[0] == NULL); iarr = 10; strcpy(test, " a1 a2"); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,2,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertStrEquals(tc,"a2", array[1]); CuAssertIntEquals(tc, 2, (int)lengths[0]); CuAssertIntEquals(tc, 2, (int)lengths[1]); iarr = 10; strcpy(test, " a1 a2 "); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,2,(int)iarr); CuAssertStrEquals(tc,"a1", array[0]); CuAssertStrEquals(tc,"a2", array[1]); CuAssertIntEquals(tc, 2, (int)lengths[0]); CuAssertIntEquals(tc, 2, (int)lengths[1]); iarr = 10; strcpy(test, ""); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,0,(int)iarr); CuAssertTrue(tc, array[0] == NULL); iarr = 3; strcpy(test, " this is a test for remainder"); array = split_array_ws (test, &iarr, lengths); CuAssertIntEquals(tc,3,(int)iarr); CuAssertStrEquals(tc,"this", array[0]); CuAssertStrEquals(tc,"is", array[1]); CuAssertStrEquals(tc,"a test for remainder", array[2]); for (i = 0; i < 3; ++i) { CuAssertIntEquals(tc, (int)strlen(array[i]), lengths[i] ); } /* split_array_list */ iarr = 6; strcpy(test, " this(a) is_a(test);for(b),remainder(test)foo(bar)"); array = split_array_list (test, &iarr, lengths); CuAssertIntEquals(tc,3,(int)iarr); CuAssertStrEquals(tc,"this(a)", array[0]); CuAssertStrEquals(tc,"is_a(test);for(b)", array[1]); CuAssertStrEquals(tc,"remainder(test)foo(bar)", array[2]); for (i = 0; i < 3; ++i) { CuAssertIntEquals(tc, (int)strlen(array[i]), lengths[i] ); } /* string replace */ s = sh_string_new_from_lchar3 ("abc ", 4, "def ", 4, "ghi ", 4); ovecnum = 2; ovector[0] = 0; ovector[1] = 2; ovector[2] = 4; ovector[3] = 11; t = sh_string_replace(s, ovector, ovecnum, "___", 3); CuAssertPtrNotNull(tc, t); CuAssertStrEquals(tc, "___c ___ ", t->str); CuAssertIntEquals(tc, 9, (int)t->len); ovector[0] = 0; ovector[1] = 2; ovector[2] = 4; ovector[3] = 12; t = sh_string_replace(s, ovector, ovecnum, "___", 3); CuAssertPtrNotNull(tc, t); CuAssertStrEquals(tc, "___c ___", t->str); CuAssertIntEquals(tc, 8, (int)t->len); ovector[0] = 0; ovector[1] = 0; ovector[2] = 0; ovector[3] = 0; t = sh_string_replace(s, ovector, ovecnum, "___", 3); CuAssertTrue(tc, t == NULL); ovector[0] = 0; ovector[1] = 3; ovector[2] = 3; ovector[3] = 6; t = sh_string_replace(s, ovector, ovecnum, "___", 3); CuAssertPtrNotNull(tc, t); CuAssertStrEquals(tc, "______f ghi ", t->str); CuAssertIntEquals(tc, 12, (int)t->len); ovector[0] = 4; ovector[1] = 5; ovector[2] = 11; ovector[3] = 12; t = sh_string_replace(s, ovector, ovecnum, "___", 3); CuAssertPtrNotNull(tc, t); CuAssertStrEquals(tc, "abc ___ef ghi___", t->str); CuAssertIntEquals(tc, 16, (int)t->len); t = sh_string_replace(s, ovector, 0, "___", 3); CuAssertPtrNotNull(tc, t); CuAssertStrEquals(tc, s->str, t->str); CuAssertIntEquals(tc, (int)s->len, (int)t->len); } #endif samhain-4.1.4/src/sh_guid.c0000664000175000017500000002221712615253277012456 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include "samhain.h" #include "sh_utils.h" #include #include /* * gen_uuid.c --- generate a DCE-compatible uuid * * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. * * %Begin-Header% * 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, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * %End-Header% */ #define UUID_SIZE 36 struct uuid { UINT32 time_low; UINT16 time_mid; UINT16 time_hi_and_version; UINT16 clock_seq; UBYTE node[6]; }; typedef unsigned char uuid_t[16]; static void uuid_pack(const struct uuid *uu, uuid_t ptr) { UINT32 tmp; unsigned char *out = ptr; tmp = uu->time_low; out[3] = (unsigned char) tmp; tmp >>= 8; out[2] = (unsigned char) tmp; tmp >>= 8; out[1] = (unsigned char) tmp; tmp >>= 8; out[0] = (unsigned char) tmp; tmp = uu->time_mid; out[5] = (unsigned char) tmp; tmp >>= 8; out[4] = (unsigned char) tmp; tmp = uu->time_hi_and_version; out[7] = (unsigned char) tmp; tmp >>= 8; out[6] = (unsigned char) tmp; tmp = uu->clock_seq; out[9] = (unsigned char) tmp; tmp >>= 8; out[8] = (unsigned char) tmp; memcpy(out+10, uu->node, 6); return; } static void uuid_unpack(const uuid_t in, struct uuid *uu) { const uint8_t *ptr = in; uint32_t tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; tmp = (tmp << 8) | *ptr++; tmp = (tmp << 8) | *ptr++; uu->time_low = tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; uu->time_mid = tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; uu->time_hi_and_version = tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; uu->clock_seq = tmp; memcpy(uu->node, ptr, 6); return; } static void get_random_bytes(unsigned char * buf, size_t len) { unsigned int j; union { UINT32 i; char c[sizeof(UINT32)]; } u; do { u.i = taus_get(); for (j= 0; j < sizeof(UINT32); j++) { if (len) { --len; *buf = u.c[j]; ++buf; } } } while (len); return; } static void uuid_generate_random(uuid_t out) { uuid_t buf; struct uuid uu; get_random_bytes(buf, sizeof(buf)); uuid_unpack(buf, &uu); /* Version and variant */ uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; uuid_pack(&uu, out); return; } static const char *fmt_lower = N_("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"); static void uuid_unparse(const uuid_t uu, char *out, size_t len) { struct uuid uuid; char fmt[80]; sl_strlcpy(fmt, _(fmt_lower), sizeof(fmt)); uuid_unpack(uu, &uuid); sl_snprintf (out, len, fmt, uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, uuid.node[0], uuid.node[1], uuid.node[2], uuid.node[3], uuid.node[4], uuid.node[5]); return; } #if defined(__linux__) static char * uuid_generate_random_linux(char * out, size_t len) { FILE * fd = fopen(_("/proc/sys/kernel/random/uuid"), "r"); if (fd) { if (NULL != fgets(out, len, fd)) { size_t ll = strlen(out); if (ll > 0 && out[ll-1] == '\n') { --ll; out[ll] = '\0'; } } fclose(fd); } return out; } #endif static char * uuid_generate_random_gen(char * out, size_t len) { uuid_t u; uuid_generate_random(u); uuid_unparse(u, out, len); return out; } char * sh_uuid_generate_random(char * out, size_t len) { *out = '\0'; #if defined(__linux__) uuid_generate_random_linux(out, len); if (UUID_SIZE == strlen(out)) return out; #endif uuid_generate_random_gen(out, len); return out; } #include int sh_uuid_check(const char * in) { int i; const char *cp; if (strlen(in) != UUID_SIZE) return -1; for (i=0, cp = in; i <= UUID_SIZE; i++,cp++) { if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { if (*cp == '-') continue; else return -1; } if (i== UUID_SIZE) if (*cp == 0) continue; if (!isxdigit(*cp)) return -1; } return 0; } #ifdef SH_CUTEST #include "CuTest.h" #include static int uuid_type(const uuid_t uu) { struct uuid uuid; uuid_unpack(uu, &uuid); return ((uuid.time_hi_and_version >> 12) & 0xF); } #define UUID_VARIANT_NCS 0 #define UUID_VARIANT_DCE 1 #define UUID_VARIANT_MICROSOFT 2 #define UUID_VARIANT_OTHER 3 #define UUID_TYPE_DCE_TIME 1 #define UUID_TYPE_DCE_RANDOM 4 static int uuid_variant(const uuid_t uu) { struct uuid uuid; int var; uuid_unpack(uu, &uuid); var = uuid.clock_seq; if ((var & 0x8000) == 0) return UUID_VARIANT_NCS; if ((var & 0x4000) == 0) return UUID_VARIANT_DCE; if ((var & 0x2000) == 0) return UUID_VARIANT_MICROSOFT; return UUID_VARIANT_OTHER; } static int uuid_parse(const char *in, uuid_t uu) { struct uuid uuid; int i; const char *cp; char buf[3]; if (sh_uuid_check(in) < 0) return -1; uuid.time_low = strtoul(in, NULL, 16); uuid.time_mid = strtoul(in+9, NULL, 16); uuid.time_hi_and_version = strtoul(in+14, NULL, 16); uuid.clock_seq = strtoul(in+19, NULL, 16); cp = in+24; buf[2] = 0; for (i=0; i < 6; i++) { buf[0] = *cp++; buf[1] = *cp++; uuid.node[i] = strtoul(buf, NULL, 16); } uuid_pack(&uuid, uu); return 0; } void Test_uuid (CuTest *tc) { char * p; int res; char out[80]; size_t len = sizeof(out); uuid_t uu; int type, variant; p = uuid_generate_random_gen(out, len); CuAssertPtrNotNull(tc, p); res = strlen(p); CuAssertIntEquals(tc,UUID_SIZE,res); res = uuid_parse(p, uu); CuAssertIntEquals(tc,0,res); type = uuid_type(uu); CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type); variant = uuid_variant(uu); CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant); #if defined(__linux__) p = uuid_generate_random_linux(out, len); CuAssertPtrNotNull(tc, p); res = strlen(p); CuAssertIntEquals(tc,UUID_SIZE,res); res = uuid_parse(p, uu); CuAssertIntEquals(tc,0,res); type = uuid_type(uu); CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type); variant = uuid_variant(uu); CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant); #endif p = sh_uuid_generate_random(out, len); CuAssertPtrNotNull(tc, p); res = strlen(p); CuAssertIntEquals(tc,UUID_SIZE,res); res = uuid_parse(p, uu); CuAssertIntEquals(tc,0,res); type = uuid_type(uu); CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type); variant = uuid_variant(uu); CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant); } #endif samhain-4.1.4/src/sh_log_parse_pacct.c0000644000175000017500000001737512615253277014662 00000000000000/************************************** ** ** PARSER RULES ** ** (a) must set record->host ** (eventually to dummy value) ** ** (b) must set record->prefix ** (command) ** ** **************************************/ /* Based on the GNU Accounting Utilities, which is distributed with the * following copyright: */ /* Copyright (C) 1993, 1996, 1997, 2003, 2005 Free Software Foundation, Inc. * * This file is part of the GNU Accounting Utilities * * The GNU Accounting Utilities are free software; you can redistribute * them and/or modify them 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. * * The GNU Accounting Utilities are distributed in the hope that they 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 the GNU Accounting Utilities; see the file COPYING. If * not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, * MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include #include #include #if defined(USE_LOGFILE_MONITOR) && defined(HAVE_SYS_ACCT_H) #include #include "samhain.h" #include "sh_pthread.h" #include "sh_log_check.h" #include "sh_utils.h" #include "sh_string.h" #undef FIL__ #define FIL__ _("sh_log_parse_pacct.c") extern int flag_err_debug; #ifndef ACCT_COMM #define ACCT_COMM 16 #endif #ifndef AHZ #define AHZ 100 #endif #if defined(ACUTIME_COMPT) || defined(ACSTIME_COMPT) || defined(ACETIME_COMPT) static double comp_t_2_double (comp_t ct) { unsigned long out = 0; out = ct & 017777; ct >>= 13; while (ct) { ct--; out <<= 3; } return (double) out; } #endif #ifdef ACUTIME_COMPT # define ACUTIME_2_DOUBLE(x) (comp_t_2_double(x)) #else # define ACUTIME_2_DOUBLE(x) ((double)(x)) #endif #ifdef ACSTIME_COMPT # define ACSTIME_2_DOUBLE(x) (comp_t_2_double(x)) #else # define ACSTIME_2_DOUBLE(x) ((double)(x)) #endif #ifdef ACETIME_COMPT # define ACETIME_2_DOUBLE(x) (comp_t_2_double(x)) #else # define ACETIME_2_DOUBLE(x) ((double)(x)) #endif static void expand_flags(char flag, char * out) { int i = 0; #define BIT(flg, ch) if (flag & flg) out[i] = ch; else out[i] = ' '; ++i BIT(ASU, 'S'); BIT(AFORK, 'F'); #ifdef ACOMPAT BIT(ACOMPAT, 'C'); #endif #ifdef ACORE BIT(ACORE, 'D'); #endif #ifdef AXSIG BIT(AXSIG, 'X'); #endif out[i] = '\0'; return; } static char * uid_name (int uid) { static int userid = 0; static char user[16] = ""; if (uid == userid && user[0] != '\0') { return user; } else { struct passwd *thispw = getpwuid (uid); if (thispw) sl_strlcpy (user, thispw->pw_name, sizeof(user)); else sl_snprintf(user, sizeof(user), "%d", uid); user[sizeof(user)-1] = '\0'; userid = uid; } return user; } struct dev_struct { char * device; long dev_id; struct dev_struct * next; }; static struct dev_struct * devicelist = NULL; static void add_devices(const char * dir) { DIR * mdir; char dirl[256]; sl_strlcpy(dirl, dir, sizeof(dirl)); dirl[sizeof(dirl)-1] = '\0'; mdir = opendir(dir); if (mdir) { char * path; size_t len; struct dirent * dent; struct stat buf; while (NULL != (dent = readdir(mdir))) { if (0 == strcmp(dent->d_name, ".")) continue; if (0 == strcmp(dent->d_name, "..")) continue; len = strlen(dir) + strlen(dent->d_name) + 2; path = SH_ALLOC(len); snprintf(path, len, "%s/%s", dir, dent->d_name); if (0 == lstat(path, &buf) && S_ISCHR(buf.st_mode)) { struct dev_struct * dstruct; dstruct = SH_ALLOC(sizeof(struct dev_struct)); /* eliminate leading '/dev/' */ memmove(path, &path[5], strlen(path)-4); dstruct->device = path; dstruct->dev_id = buf.st_rdev; dstruct->next = devicelist; devicelist = dstruct; } else { SH_FREE(path); } } closedir(mdir); } return; } static char * dev_name(long tty) { struct dev_struct * dstruct; if (!devicelist) { add_devices("/dev"); add_devices("/dev/pts"); add_devices("/dev/pty"); add_devices("/dev/ptym"); } dstruct = devicelist; while (dstruct) { if (dstruct->dev_id == tty) return dstruct->device; dstruct = dstruct->next; } return "??"; } #if defined(__linux__) && defined(HAVE_ACCT_V3) # define STRUCT_ACCT struct acct_v3 #elif defined(__FreeBSD__) && defined(HAVE_ACCTV2) # define STRUCT_ACCT struct acctv2 #else # define STRUCT_ACCT struct acct #endif /* This looks strange, but it's real ANSI C. */ extern STRUCT_ACCT pacct_rd_never_used; #define COMM_LEN ((int) sizeof (pacct_rd_never_used.ac_comm)) sh_string * sh_read_pacct (sh_string * record, struct sh_logfile * logfile) { STRUCT_ACCT rec; if (NULL != sh_binary_reader ((void*) &rec, sizeof(STRUCT_ACCT), logfile)) { time_t btime = (time_t) rec.ac_btime; double ut = ACUTIME_2_DOUBLE (rec.ac_utime); double st = ACSTIME_2_DOUBLE (rec.ac_stime); char fl[6]; char comm[COMM_LEN+1]; int i; char out[64+COMM_LEN+1+5+8+8+32+4+19+7]; /* see printf format below */ #if defined(ac_flagx) expand_flags(rec.ac_flagx, fl); #else expand_flags(rec.ac_flag, fl); #endif /* ac_comm may not be null terminated */ for (i = 0; i < COMM_LEN; i++) { if (rec.ac_comm[i] == '\0') { comm[i] = '\0'; break; } if (! isprint (rec.ac_comm[i])) comm[i] = '?'; else comm[i] = rec.ac_comm[i]; } comm[COMM_LEN] = '\0'; sl_snprintf (out, sizeof(out), "%ld:%-*.*s %5.5s %-8.8s %-8.8s %6.2f secs %-19.19s", btime, COMM_LEN, COMM_LEN, comm, fl, uid_name(rec.ac_uid), dev_name((long)rec.ac_tty), ((ut + st) / (double) AHZ), ctime (&btime)); sh_string_set_from_char(record, out); return record; } if (record) sh_string_destroy(&record); return NULL; } void * sh_dummy_294_record = NULL; struct sh_logrecord * sh_parse_pacct (sh_string * logline, void * fileinfo) { char * p; char * endptr; unsigned long ltime; struct sh_logrecord * record = NULL; (void) fileinfo; sh_dummy_294_record = (void *) &record; if (sh_string_len(logline) > 0 && flag_err_debug == S_TRUE) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(logline), _("sh_parse_pacct")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } p = strchr(sh_string_str(logline), ':'); if (!p || p == sh_string_str(logline)) return NULL; ltime = strtoul(sh_string_str(logline), &endptr, 10); if (p != endptr) return NULL; ++p; /* points to first char of pacct record */ if (*p != '\0') { size_t lengths[7]; unsigned int fields = 7; char ** array; sh_string * message = sh_string_new_from_lchar(p, strlen(p)); array = split_array_ws(p, &fields, lengths); if (fields == 7) { record = SH_ALLOC(sizeof(struct sh_logrecord)); record->timestamp = ltime; record->timestr = sh_string_new_from_lchar(array[6], lengths[6]); record->message = message; record->pid = 0; record->host = sh_string_new_from_lchar(sh.host.name, strlen(sh.host.name)); } else { sh_string_destroy(&message); } SH_FREE(array); } return record; } /* USE_LOGFILE_MONITOR */ #endif samhain-4.1.4/src/sh_srp.c0000644000175000017500000004115312615253277012330 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include "samhain.h" #ifdef USE_SRP_PROTOCOL #if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)) #include "sh_tiger.h" #include "sh_mem.h" #include "sh_utils.h" #include "sh_srp.h" #if !defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H) #include "bignum.h" #else #include #define BIG_OK 0 #define bigerr_t int int big_errno = BIG_OK; #define bignum MP_INT inline int big_create (bignum * a) { mpz_init(a); return 0; } inline int big_zerop (bignum * a) { mpz_t b; int i; mpz_init_set_str(b, "0", 10); i = mpz_cmp(a, b); mpz_clear(b); if (i) return 0; else return 1; } inline int big_trunc (bignum * a, bignum * b, bignum * q, bignum *r) { mpz_tdiv_qr(q, r, a, b); return 0; } inline int big_exptmod (bignum * a, bignum * b, bignum * c, bignum *d) { mpz_powm(d, a, b, c); return 0; } char * get_str_internal = NULL; int siz_str_internal = 0; static char * big_string (bignum * a, int base) { char * str = NULL; int size; int i; str = mpz_get_str (str, base, a); if (get_str_internal == NULL) { get_str_internal = calloc(1,512); /* only once */ if (get_str_internal) { siz_str_internal = 512; } else { if (str != NULL) free(str); return 0; } get_str_internal[0] = '\0'; } if (str != NULL) { size = strlen(str) + 1; if (size > siz_str_internal) { char * ptr = realloc (get_str_internal, size); if (ptr) get_str_internal = ptr; else { free(get_str_internal); get_str_internal = NULL; } } if (get_str_internal == NULL) { free(str); return NULL; } siz_str_internal = size; sl_strlcpy (get_str_internal, str, siz_str_internal); for (i = 0; i < (size-1); ++i) if (get_str_internal[i] >= 'a' && get_str_internal[i] <= 'f' ) get_str_internal[i] = get_str_internal[i] - 'a' + 'A'; free (str); } return get_str_internal; } inline int big_add(bignum * a, bignum * b, bignum * c) { mpz_add(c, a, b); return 0; } inline int big_sub(bignum * a, bignum * b, bignum * c) { mpz_sub(c, a, b); return 0; } inline int big_mul(bignum * a, bignum * b, bignum * c) { mpz_mul(c, a, b); return 0; } inline int big_greaterp(bignum * a, bignum * b) { return mpz_cmp(a, b) > 0; } inline int big_set_big(bignum * a, bignum * b) { mpz_set(b, a); return 0; } inline int big_set_string(const char * str, int base, bignum * a) { mpz_set_str (a, str, base); return 0; } #define big_init_pkg() 0 #define big_release_pkg() #define big_destroy mpz_clear /* #if defined(HAVE_LIBGMP) */ #endif #undef FIL__ #define FIL__ _("sh_srp.c") typedef struct sh_srp_struc { char x[KEY_LEN+1]; bignum a; bignum p; bignum g; } sh_srp_t; static sh_srp_t sh_srp; void sh_srp_x (char * salt, char * password) { char *combi; size_t len, l2; register int i; unsigned char * dez = NULL; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_srp_x")); /* patch by Andreas Piesk */ if (password == NULL) dez = (unsigned char *) &(skey->pw[0]); else dez = (unsigned char *) password; for (i = 0; i < PW_LEN; ++i) { skey->vernam[i] = (char)(*dez); ++dez; } skey->vernam[PW_LEN] = '\0'; (void) sl_strlcpy (skey->vernam, sh_tiger_hash(skey->vernam, TIGER_DATA, PW_LEN, hashbuf, sizeof(hashbuf)), KEY_LEN); skey->vernam[KEY_LEN] = '\0'; len = sl_strlen(salt) + 1; l2 = sl_strlen(skey->vernam); if (sl_ok_adds(len, l2)) len += l2; /* H(s,P) */ combi = SH_ALLOC(len); (void) sl_strlcpy (combi, salt, len); (void) sl_strlcat (combi, skey->vernam, len); (void) sl_strlcpy (sh_srp.x, sh_tiger_hash(combi, TIGER_DATA, (unsigned long) sl_strlen(combi), hashbuf, sizeof(hashbuf)), KEY_LEN+1); SH_FREE (combi); SL_RET0(_("sh_srp_x")); } char * sh_srp_M (char * x1, char * x2, char * x3, char * hash, size_t size) { char *combi; size_t len, l2, l3; SL_ENTER(_("sh_srp_M")); ASSERT_RET((x1 != NULL && x2 != NULL && x3 !=NULL), _("x1 != NULL && x2 != NULL && x3 !=NULL"), NULL); len = sl_strlen(x1) + 1; l2 = sl_strlen(x2); l3 = sl_strlen(x3); if (sl_ok_adds(len, l2)) len += l2; if (sl_ok_adds(len, l3)) len += l3; /* H(x1,x2,x3) */ combi = SH_ALLOC(len); (void) sl_strlcpy (combi, x1, len); (void) sl_strlcat (combi, x2, len); (void) sl_strlcat (combi, x3, len); (void) sh_tiger_hash(combi, TIGER_DATA, (unsigned long) (len-1), hash, size); SH_FREE (combi); SL_RETURN(hash, _("sh_srp_M")); } void sh_srp_exit() { SL_ENTER(_("sh_srp_exit")); big_destroy(&sh_srp.g); big_destroy(&sh_srp.p); big_destroy(&sh_srp.a); big_release_pkg(); big_errno = BIG_OK; SL_RET0(_("sh_srp_exit")); } int sh_srp_init() { bigerr_t res; char modulus[80*4]; SL_ENTER(_("sh_srp_init")); big_errno = BIG_OK; res = big_init_pkg(); if (res == BIG_OK) { res = big_create(&sh_srp.p); if (res == BIG_OK) res = big_create(&sh_srp.g); if (res == BIG_OK) res = big_create(&sh_srp.a); if (res == BIG_OK) { (void) sl_strlcpy(modulus, SRP_MODULUS_1024_1, sizeof(modulus)); (void) sl_strlcat(modulus, SRP_MODULUS_1024_2, sizeof(modulus)); (void) sl_strlcat(modulus, SRP_MODULUS_1024_3, sizeof(modulus)); (void) sl_strlcat(modulus, SRP_MODULUS_1024_4, sizeof(modulus)); } if (res == BIG_OK) res = big_set_string (modulus, 16, &sh_srp.p); if (res == BIG_OK) res = big_set_string (SRP_GENERATOR_1024, 16, &sh_srp.g); if (res == BIG_OK) { SL_RETURN (0, _("sh_srp_init")); } else sh_srp_exit(); } SL_RETURN ((-1), _("sh_srp_init")); } int sh_srp_make_a () { UINT32 randl[6]; int i; int res; char hash[KEY_LEN+1]; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_srp_make_a")); for (i = 0; i < 6; ++i) randl[i] = (UINT32) taus_get (); (void) sl_strlcpy (hash, sh_tiger_hash((char *)&randl[0], TIGER_DATA, (unsigned long) 6*sizeof(UINT32), hashbuf, sizeof(hashbuf)), KEY_LEN+1); hash[KEY_LEN] = '\0'; res = big_set_string (hash, 16, &sh_srp.a); if (res == BIG_OK) { SL_RETURN((0), _("sh_srp_make_a")); } else { SL_RETURN((-1), _("sh_srp_make_a")); } } /* return 0 if AB is NOT zero */ int sh_srp_check_zero (char * AB_str) { bignum AB, q, r; bigerr_t res; int val; SL_ENTER(_("sh_srp_check_zero")); ASSERT_RET((AB_str != NULL), _("AB_str != NULL"), (-1)); res = big_create(&AB); if (res == BIG_OK) res = big_create(&q); if (res == BIG_OK) res = big_create(&r); if (res == BIG_OK) res = big_set_string (AB_str, 16, &AB); if (res == BIG_OK) res = big_trunc(&AB, &sh_srp.p, &q, &r); /* is last one the remainder ? */ if (res != BIG_OK) val = (-1); else if (0 != big_zerop(&AB) ) val = (-1); /* 0 != (sign == 0) */ else if (0 != big_zerop(&r) ) val = (-1); /* 0 != (sign == 0) */ else val = 0; big_destroy(&AB); big_destroy(&q); big_destroy(&r); SL_RETURN((val), _("sh_srp_check_zero")); } #if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) char * sh_srp_A () { bignum A; char *str; char *combi; bigerr_t res; SL_ENTER(_("sh_srp_A")); res = big_create(&A); if (res == BIG_OK) res = big_exptmod (&sh_srp.g, &sh_srp.a, &sh_srp.p, &A); if (res == BIG_OK) str = big_string (&A, 16); else str = NULL; if (str != NULL) combi = sh_util_strdup(str); else combi = NULL; big_destroy(&A); SL_RETURN(combi, _("sh_srp_A")); } /* #ifdef SH_WITH_CLIENT */ #endif #ifdef SH_WITH_SERVER char * sh_srp_B (char * verifier) { bignum B, v, t, dummy; char *str; char *combi; bigerr_t res; SL_ENTER(_("sh_srp_B")); ASSERT_RET((verifier != NULL), _("verifier != NULL"), (NULL)); res = big_create(&dummy); if (res == BIG_OK) res = big_create(&t); if (res == BIG_OK) res = big_create(&v); if (res == BIG_OK) res = big_create(&B); if (res == BIG_OK) res = big_exptmod (&sh_srp.g, &sh_srp.a, &sh_srp.p, &t); if (res == BIG_OK) big_set_string (verifier, 16, &v); if (res == BIG_OK) res = big_add (&t, &v, &dummy); if (res == BIG_OK) { if ( big_greaterp(&dummy, &sh_srp.p) ) res = big_sub(&dummy, &sh_srp.p, &B); else res = big_set_big(&dummy, &B); } if (res == BIG_OK) str = big_string (&B, 16); else str = NULL; if (str != NULL) combi = sh_util_strdup(str); else combi = NULL; big_destroy(&B); big_destroy(&v); big_destroy(&t); big_destroy(&dummy); SL_RETURN(combi, _("sh_srp_B")); } /* #ifdef SH_WITH_SERVER */ #endif #if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) char * sh_srp_S_c (char * u_str, char * B_str) { bignum u, B, x, t, base, z1, z2; char *str; char *combi; bigerr_t res; SL_ENTER(_("sh_srp_S_c")); ASSERT_RET((u_str != NULL && B_str != NULL), _("u_str != NULL && B_str != NULL"), (NULL)); big_errno = BIG_OK; res = big_create(&z2); if (res == BIG_OK) res = big_create(&z1); if (res == BIG_OK) res = big_create(&base); if (res == BIG_OK) res = big_create(&t); if (res == BIG_OK) res = big_create(&x); if (res == BIG_OK) res = big_create(&B); if (res == BIG_OK) res = big_create(&u); if (res == BIG_OK) res = big_set_string (B_str, 16, &B); if (res == BIG_OK) res = big_set_string (sh_srp.x, 16, &x); if (res == BIG_OK) res = big_set_string (u_str, 16, &u); /* the base (B - g^x) */ if (res == BIG_OK) res = big_exptmod (&sh_srp.g, &x, &sh_srp.p, &t); if (res == BIG_OK) { if ( big_greaterp(&B, &t) != 0) { res = big_sub(&B, &t, &base); } else { res = big_add(&B, &sh_srp.p, &z2); if (res == BIG_OK) res = big_sub(&z2, &t, &base); } } /* the exponent (a + ux) */ if (res == BIG_OK) res = big_mul (&u, &x, &t); if (res == BIG_OK) res = big_trunc(&t, &sh_srp.p, &z1, &z2); /* is last one the remainder ? */ if (res == BIG_OK) res = big_add(&sh_srp.a, &z2, &z1); if (res == BIG_OK) { if ( big_greaterp(&z1, &sh_srp.p) != 0) res = big_sub(&z1, &sh_srp.p, &z2); else res = big_set_big(&z1, &z2); } if (res == BIG_OK) res = big_exptmod (&base, &z2, &sh_srp.p, &t); if (res == BIG_OK) str = big_string (&t, 16); else str = NULL; if (str != NULL) combi = sh_util_strdup(str); else combi = NULL; big_destroy(&z1); big_destroy(&z2); big_destroy(&base); big_destroy(&t); big_destroy(&x); big_destroy(&B); big_destroy(&u); SL_RETURN(combi, _("sh_srp_S_c")); } /* #ifdef SH_WITH_CLIENT */ #endif #ifdef SH_WITH_SERVER char * sh_srp_S_s (char * u_str, char * A_str, char * v_str) { bignum u, A, v, t, base, z1, z2; char *str; char *combi; bigerr_t res; SL_ENTER(_("sh_srp_S_s")); ASSERT_RET((u_str != NULL && A_str != NULL && v_str != NULL), _("u_str != NULL && A_str != NULL && v_str != NULL"), (NULL)); big_errno = BIG_OK; res = big_create(&z2); if (res == BIG_OK) res = big_create(&z1); if (res == BIG_OK) res = big_create(&base); if (res == BIG_OK) res = big_create(&t); if (res == BIG_OK) res = big_create(&v); if (res == BIG_OK) res = big_create(&A); if (res == BIG_OK) res = big_create(&u); if (res == BIG_OK) res = big_set_string (A_str, 16, &A); if (res == BIG_OK) res = big_set_string (v_str, 16, &v); if (res == BIG_OK) res = big_set_string (u_str, 16, &u); /* the base (Av^u) */ if (res == BIG_OK) res = big_exptmod (&v, &u, &sh_srp.p, &t); if (res == BIG_OK) res = big_mul (&A, &t, &z1); if (res == BIG_OK) res = big_trunc(&z1, &sh_srp.p, &z2, &base); /* is last the remainder ? */ if (res == BIG_OK) res = big_exptmod (&base, &sh_srp.a, &sh_srp.p, &t); if (res == BIG_OK) str = big_string (&t, 16); else str = NULL; if (str != NULL) combi = sh_util_strdup(str); else combi = NULL; big_destroy(&z1); big_destroy(&z2); big_destroy(&base); big_destroy(&t); big_destroy(&v); big_destroy(&A); big_destroy(&u); SL_RETURN(combi, _("sh_srp_S_s")); } /* #ifdef SH_WITH_SERVER */ #endif char * sh_srp_verifier (void) { bignum x, v; char *combi; char *str; bigerr_t res; SL_ENTER(_("sh_srp_verifier")); res = big_create(&x); if (res == BIG_OK) res = big_create(&v); if (res == BIG_OK) res = big_set_string (sh_srp.x, 16, &x); if (res == BIG_OK) res = big_exptmod (&sh_srp.g, &x, &sh_srp.p, &v); if (res == BIG_OK) str = big_string (&v, 16); else str = NULL; if (str != NULL) combi = sh_util_strdup(str); else combi = NULL; big_destroy(&x); big_destroy(&v); SL_RETURN(combi, _("sh_srp_verifier")); } /* #if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)) */ #endif /* #ifdef USE_SRP_PROTOCOL */ #endif #ifdef SH_CUTEST #include "CuTest.h" void Test_srp (CuTest *tc) { #if defined(USE_SRP_PROTOCOL) && (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)) int result; char modulus[80*4]; bignum a, b, c; bigerr_t res; char *str = NULL; res = sh_srp_init(); CuAssertTrue(tc, res == 0); (void) sl_strlcpy(modulus, SRP_MODULUS_1024_1, sizeof(modulus)); (void) sl_strlcat(modulus, SRP_MODULUS_1024_2, sizeof(modulus)); (void) sl_strlcat(modulus, SRP_MODULUS_1024_3, sizeof(modulus)); (void) sl_strlcat(modulus, SRP_MODULUS_1024_4, sizeof(modulus)); res = big_create(&a); CuAssertTrue(tc, res == BIG_OK); /* Check plain zero */ result = sh_srp_check_zero ("0"); CuAssertTrue(tc, result != 0); res = big_set_string ("0", 16, &a); CuAssertTrue(tc, res == BIG_OK); result = sh_srp_check_zero (big_string(&a, 16)); CuAssertTrue(tc, result != 0); /* Check modulus (equals 0 % M) */ result = sh_srp_check_zero (modulus); CuAssertTrue(tc, result != 0); res = big_set_string (modulus, 16, &a); CuAssertTrue(tc, res == BIG_OK); result = sh_srp_check_zero (big_string(&a, 16)); CuAssertTrue(tc, result != 0); /* Check non-zero */ modulus[0] = 'a'; result = sh_srp_check_zero (modulus); CuAssertTrue(tc, result == 0); res = big_set_string (modulus, 16, &a); CuAssertTrue(tc, res == BIG_OK); result = sh_srp_check_zero (big_string(&a, 16)); CuAssertTrue(tc, result == 0); modulus[0] = 'f'; /* Check multiple of modulus */ res = big_set_string (modulus, 16, &a); CuAssertTrue(tc, res == BIG_OK); res = big_create(&b); CuAssertTrue(tc, res == BIG_OK); res = big_create(&c); CuAssertTrue(tc, res == BIG_OK); res = big_set_string ("deadbeef", 16, &b); CuAssertTrue(tc, res == BIG_OK); res = big_mul (&a, &b, &c); CuAssertTrue(tc, res == BIG_OK); str = strdup(big_string (&c, 16)); CuAssertPtrNotNull(tc, str); result = sh_srp_check_zero (str); CuAssertTrue(tc, result != 0); #else (void) tc; /* fix compiler warning */ #endif return; } #endif samhain-4.1.4/src/zAVLTree.c0000644000175000017500000003461112615253277012467 00000000000000/* * zAVLTree.c: Source code for zAVLTrees. * Copyright (C) 1998,2001 Michael H. Buselli * This is version 0.1.3 (alpha). * Generated from $Id: xAVLTree.c.sh,v 1.5 2001/06/07 06:58:28 cosine Exp $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The author of this library can be reached at the following address: * Michael H. Buselli * 30051 N. Waukegan Rd. Apt. 103 * Lake Bluff, IL 60044-5412 * * Or you can send email to . * The official web page for this product is: * http://www.cosine.org/project/AVLTree/ */ #include #include #include "zAVLTree.h" /* Interface for handling "string only" items rw 2014-06-26 */ static zAVLKey zstring_key (void const * arg) { return (zAVLKey) arg; } char * dummy_zfree_string; #ifdef __clang__ char * dummy_zfree_str; #endif static void zfree_string (void * inptr) { #ifdef __clang__ dummy_zfree_str = (char *) inptr; #else char * str = (char *) inptr; #endif /* Take the address to circumvent gcc 4.9 optimizer bug */ dummy_zfree_string = (char *) &inptr; #ifdef __clang__ dummy_zfree_str[0] = '\0'; free (dummy_zfree_str); #else str[0] = '\0'; free (inptr); #endif return; } void zAVL_string_reset (zAVLTree * tree) { if (tree) zAVLFreeTree (tree, zfree_string); return; } int zAVL_string_set (zAVLTree ** tree, const char * key) { if (tree && key) { zAVLTree * itree = (*tree); if (!itree) { itree = zAVLAllocTree (zstring_key, zAVL_KEY_STRING); if (!itree) { return -1; } } *tree = itree; return zAVLInsert (itree, strdup(key)); } return -1; } char * zAVL_string_get (zAVLTree * tree, const char * key) { /* zAVLSearch() checks for NULL tree */ if (key) { return ((char *) zAVLSearch (tree, key)); } return NULL; } void zAVL_string_del (zAVLTree * tree, const char * key) { /* zAVLSearch() checks for NULL tree */ if (key) { char * item = ((char *) zAVLSearch (tree, key)); if (item) { zAVLDelete(tree, key); zfree_string(item); } } return; } /* Wed Nov 23 17:57:42 CET 2005 rw: introduce third argument in * zAVLCloseSearchNode() to avoid redundant strcmp */ static zAVLNode *zAVLCloseSearchNode (zAVLTree const *avltree, zAVLKey key, int * ok); static void zAVLRebalanceNode (zAVLTree *avltree, zAVLNode *avlnode); static void zAVLFreeBranch (zAVLNode *avlnode, void (freeitem)(void *item)); static void zAVLFillVacancy (zAVLTree *avltree, zAVLNode *origparent, zAVLNode **superparent, zAVLNode *left, zAVLNode *right); #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define L_DEPTH(n) ((n)->left ? (n)->left->depth : 0) #define R_DEPTH(n) ((n)->right ? (n)->right->depth : 0) #define CALC_DEPTH(n) (MAX(L_DEPTH(n), R_DEPTH(n)) + 1) #define ZAVL_OK 1 #define ZAVL_NO 0 /* The comparison function. Was a macro, but this allows for more * flexibility (non-string keys). The key is a (void *) now, and * the type is stored in the zAVLTree struct. Oct 21, 2011, rw */ static int zAVLKey_cmp(const zAVLTree * tree, zAVLKey a, zAVLKey b) { if (tree->keytype == zAVL_KEY_STRING) { return (strcmp((const char*)a, (const char *)b)); } else /* zAVL_KEY_INT */ { const int x = *((const int *)a); const int y = *((const int *)b); if (x > y) return 1; else if (x < y) return -1; else return 0; } } /* * AVLAllocTree: * Allocate memory for a new AVL tree and set the getkey function for * that tree. The getkey function should take an item and return an * AVLKey that is to be used for indexing this object in the AVL tree. * On success, a pointer to the malloced AVLTree is returned. If there * was a malloc failure, then NULL is returned. */ zAVLTree *zAVLAllocTree (zAVLKey (*getkey)(void const *item), int keytype) { zAVLTree *rc; rc = calloc(1, sizeof(zAVLTree)); if (rc == NULL) return NULL; rc->top = NULL; rc->count = 0; rc->getkey = getkey; rc->keytype = keytype; return rc; } /* * AVLFreeTree: * Free all memory used by this AVL tree. If freeitem is not NULL, then * it is assumed to be a destructor for the items reference in the AVL * tree, and they are deleted as well. */ void zAVLFreeTree (zAVLTree *avltree, void (freeitem)(void *item)) { if (NULL == avltree) /* R.W. Mon Nov 19 21:15:44 CET 2001 */ return; if (avltree->top) zAVLFreeBranch(avltree->top, freeitem); free(avltree); } /* * AVLInsert: * Create a new node and insert an item there. * * Returns 0 on success, * -1 on malloc failure, * 3 if duplicate key. */ int zAVLInsert (zAVLTree *avltree, void *item) { zAVLNode *newnode; zAVLNode *node; zAVLNode *balnode; zAVLNode *nextbalnode; int ok; newnode = calloc(1, sizeof(zAVLNode)); if (newnode == NULL) return -1; newnode->key = avltree->getkey(item); newnode->item = item; newnode->depth = 1; newnode->left = NULL; newnode->right = NULL; newnode->parent = NULL; if (avltree->top != NULL) { node = zAVLCloseSearchNode(avltree, newnode->key, &ok); if (ok == ZAVL_OK) { /* exists already */ free(newnode); return 3; } newnode->parent = node; if (zAVLKey_cmp(avltree, newnode->key, node->key) < 0) { node->left = newnode; node->depth = CALC_DEPTH(node); } else { node->right = newnode; node->depth = CALC_DEPTH(node); } for (balnode = node->parent; balnode; balnode = nextbalnode) { nextbalnode = balnode->parent; zAVLRebalanceNode(avltree, balnode); } } else { avltree->top = newnode; } avltree->count++; return 0; } /* * zAVLSearch: * Return a pointer to the item with the given key in the AVL tree. If * no such item is in the tree, then NULL is returned. */ void *zAVLSearch (zAVLTree const *avltree, zAVLKey key) { zAVLNode *node; int ok; if (NULL == avltree) /* R.W. Mon Nov 19 21:15:44 CET 2001 */ return NULL; node = zAVLCloseSearchNode(avltree, key, &ok); if (node && ok == ZAVL_OK) return node->item; return NULL; } /* * zAVLDelete: * Deletes the node with the given key. Does not delete the item at * that key. Returns 0 on success and -1 if a node with the given key * does not exist. */ int zAVLDelete (zAVLTree *avltree, zAVLKey key) { zAVLNode *avlnode; zAVLNode *origparent; zAVLNode **superparent; int ok; avlnode = zAVLCloseSearchNode(avltree, key, &ok); if (avlnode == NULL || ok == ZAVL_NO) /* does not exist */ return -1; origparent = avlnode->parent; if (origparent) { if (zAVLKey_cmp(avltree, avlnode->key, avlnode->parent->key) < 0) superparent = &(avlnode->parent->left); else superparent = &(avlnode->parent->right); } else superparent = &(avltree->top); zAVLFillVacancy(avltree, origparent, superparent, avlnode->left, avlnode->right); free(avlnode); avltree->count--; return 0; } /* * zAVLFirst: * Initializes an zAVLCursor object and returns the item with the lowest * key in the zAVLTree. */ void *zAVLFirst (zAVLCursor *avlcursor, zAVLTree const *avltree) { const zAVLNode *avlnode; if (NULL == avltree) /* R.W. Mon Nov 19 21:15:44 CET 2001 */ return NULL; avlcursor->avltree = avltree; if (avltree->top == NULL) { avlcursor->curnode = NULL; return NULL; } for (avlnode = avltree->top; avlnode->left != NULL; avlnode = avlnode->left); avlcursor->curnode = avlnode; return avlnode->item; } /* * zAVLNext: * Called after an zAVLFirst() call, this returns the item with the least * key that is greater than the last item returned either by zAVLFirst() * or a previous invokation of this function. */ void *zAVLNext (zAVLCursor *avlcursor) { const zAVLNode *avlnode; avlnode = avlcursor->curnode; if (avlnode->right != NULL) { for (avlnode = avlnode->right; avlnode->left != NULL; avlnode = avlnode->left); avlcursor->curnode = avlnode; return avlnode->item; } while (avlnode->parent && avlnode->parent->left != avlnode) { avlnode = avlnode->parent; } if (avlnode->parent == NULL) { avlcursor->curnode = NULL; return NULL; } avlcursor->curnode = avlnode->parent; return avlnode->parent->item; } /* * zAVLCloseSearchNode: * Return a pointer to the node closest to the given key. * Returns NULL if the AVL tree is empty. */ static zAVLNode *zAVLCloseSearchNode (zAVLTree const *avltree, zAVLKey key, int * ok) { zAVLNode *node; *ok = ZAVL_NO; node = avltree->top; if (!node) return NULL; for (;;) { if (!zAVLKey_cmp(avltree, node->key, key)) { *ok = ZAVL_OK; return node; } if (zAVLKey_cmp(avltree, node->key, key) < 0) { if (node->right) node = node->right; else return node; } else { if (node->left) node = node->left; else return node; } } } /* * zAVLRebalanceNode: * Rebalances the AVL tree if one side becomes too heavy. This function * assumes that both subtrees are AVL trees with consistant data. This * function has the additional side effect of recalculating the depth of * the tree at this node. It should be noted that at the return of this * function, if a rebalance takes place, the top of this subtree is no * longer going to be the same node. */ static void zAVLRebalanceNode (zAVLTree *avltree, zAVLNode *avlnode) { long depthdiff; zAVLNode *child; zAVLNode *gchild; zAVLNode *origparent; zAVLNode **superparent; origparent = avlnode->parent; if (origparent) { if (zAVLKey_cmp(avltree, avlnode->key, avlnode->parent->key) < 0) superparent = &(avlnode->parent->left); else superparent = &(avlnode->parent->right); } else superparent = &(avltree->top); depthdiff = R_DEPTH(avlnode) - L_DEPTH(avlnode); if (depthdiff <= -2 && avlnode->left) { child = avlnode->left; if (L_DEPTH(child) >= R_DEPTH(child)) { avlnode->left = child->right; if (avlnode->left != NULL) avlnode->left->parent = avlnode; avlnode->depth = CALC_DEPTH(avlnode); child->right = avlnode; if (child->right != NULL) child->right->parent = child; child->depth = CALC_DEPTH(child); *superparent = child; child->parent = origparent; } else { gchild = child->right; if (gchild) { avlnode->left = gchild->right; if (avlnode->left != NULL) avlnode->left->parent = avlnode; avlnode->depth = CALC_DEPTH(avlnode); child->right = gchild->left; if (child->right != NULL) child->right->parent = child; child->depth = CALC_DEPTH(child); gchild->right = avlnode; if (gchild->right != NULL) gchild->right->parent = gchild; gchild->left = child; if (gchild->left != NULL) gchild->left->parent = gchild; gchild->depth = CALC_DEPTH(gchild); *superparent = gchild; gchild->parent = origparent; } } } else if (depthdiff >= 2 && avlnode->right) { child = avlnode->right; if (R_DEPTH(child) >= L_DEPTH(child)) { avlnode->right = child->left; if (avlnode->right != NULL) avlnode->right->parent = avlnode; avlnode->depth = CALC_DEPTH(avlnode); child->left = avlnode; if (child->left != NULL) child->left->parent = child; child->depth = CALC_DEPTH(child); *superparent = child; child->parent = origparent; } else { gchild = child->left; if (gchild) { avlnode->right = gchild->left; if (avlnode->right != NULL) avlnode->right->parent = avlnode; avlnode->depth = CALC_DEPTH(avlnode); child->left = gchild->right; if (child->left != NULL) child->left->parent = child; child->depth = CALC_DEPTH(child); gchild->left = avlnode; if (gchild->left != NULL) gchild->left->parent = gchild; gchild->right = child; if (gchild->right != NULL) gchild->right->parent = gchild; gchild->depth = CALC_DEPTH(gchild); *superparent = gchild; gchild->parent = origparent; } } } else { avlnode->depth = CALC_DEPTH(avlnode); } } /* * zAVLFreeBranch: * Free memory used by this node and its item. If the freeitem argument * is not NULL, then that function is called on the items to free their * memory as well. In other words, the freeitem function is a * destructor for the items in the tree. */ static void zAVLFreeBranch (zAVLNode *avlnode, void (freeitem)(void *item)) { if (avlnode->left) zAVLFreeBranch(avlnode->left, freeitem); if (avlnode->right) zAVLFreeBranch(avlnode->right, freeitem); if (freeitem) { freeitem(avlnode->item); avlnode->item = NULL; } free(avlnode); } /* * zAVLFillVacancy: * Given a vacancy in the AVL tree by it's parent, children, and parent * component pointer, fill that vacancy. */ static void zAVLFillVacancy (zAVLTree *avltree, zAVLNode *origparent, zAVLNode **superparent, zAVLNode *left, zAVLNode *right) { zAVLNode *avlnode; zAVLNode *balnode; zAVLNode *nextbalnode; if (left == NULL) { if (right) right->parent = origparent; *superparent = right; balnode = origparent; } else { for (avlnode = left; avlnode->right != NULL; avlnode = avlnode->right); if (avlnode == left) { balnode = avlnode; } else { balnode = avlnode->parent; balnode->right = avlnode->left; if (balnode->right != NULL) balnode->right->parent = balnode; avlnode->left = left; left->parent = avlnode; } avlnode->right = right; if (right != NULL) right->parent = avlnode; *superparent = avlnode; avlnode->parent = origparent; } for (; balnode; balnode = nextbalnode) { nextbalnode = balnode->parent; zAVLRebalanceNode(avltree, balnode); } } samhain-4.1.4/src/sh_extern.c0000644000175000017500000011252312615253277013031 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2000,2004 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #ifdef HAVE_MEMORY_H #include #endif /* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.' * for debugging */ #if 0 #define PDGBFILE "/pdbg." #endif #if defined(PDGBFILE) static FILE * pdbg = NULL; static FILE * pdbgc = NULL; #define PDBG_OPEN if (pdbg == NULL) pdbg = fopen(PDGBFILE"main", "a") #define PDBG_CLOSE sl_fclose (FIL__, __LINE__, pdbg); pdbg = NULL #define PDBG(arg) fprintf(pdbg, "PDBG: step %d\n", arg); fflush(pdbg) #define PDBG_D(arg) fprintf(pdbg, "PDBG: %d\n", arg); fflush(pdbg) #define PDBG_S(arg) fprintf(pdbg, "PDBG: %s\n", arg); fflush(pdbg) #define PDBGC_OPEN if (pdbgc == NULL) pdbgc = fopen(PDGBFILE"child", "a") #define PDBGC_CLOSE sl_fclose (FIL__, __LINE__, pdbgc); pdbgc = NULL #define PDBGC(arg) fprintf(pdbgc, "PDBGC: step %d\n", arg); fflush(pdbgc) #define PDBGC_D(arg) fprintf(pdbgc, "PDBGC: %d\n", arg); fflush(pdbgc) #define PDBGC_S(arg) fprintf(pdbgc, "PDBGC: %s\n", arg); fflush(pdbgc) #else #define PDBG_OPEN #define PDBG_CLOSE #define PDBG(arg) #define PDBG_D(arg) #define PDBG_S(arg) #define PDBGC_OPEN #define PDBGC_CLOSE #define PDBGC(arg) #define PDBGC_D(arg) #define PDBGC_S(arg) #endif #include #include #include #include #include #include #include #include #include #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #include "samhain.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_tiger.h" #include "sh_extern.h" #include "sh_calls.h" #include "sh_filter.h" #define SH_NEED_PWD_GRP 1 #include "sh_static.h" #undef FIL__ #define FIL__ _("sh_extern.c") extern int get_the_fd (SL_TICKET ticket); /* * -- generic safe popen */ int sh_ext_popen (sh_tas_t * task) { long status = 0; int flags; char * tmp; char * tmp2; int errnum; int pipedes[2]; FILE * outf = NULL; char * envp[1]; char * argp[2]; char * errfile; char errbuf[SH_ERRBUF_SIZE]; static int some_error = 0; #if defined (__linux__) SL_TICKET fd = -1; char pname[128]; int pfd = -1; #endif SL_ENTER(_("sh_ext_popen")); /* Linux, HP-UX and FreeBSD will happily accept envp = argp = NULL * (newer Linuxes (gcc 4.4.4) warn on argp == NULL, but accept it, * as reported by T. Luettgert) * Solaris (and probably some other Unices) * needs a valid *envp[] with envp[0] = NULL; * and similarly for argp * OpenBSD finally needs non-null argp[0] ... */ argp[0] = task->command; argp[1] = NULL; envp[0] = NULL; /* * -- check whether path is trustworthy */ status = sl_trustfile(task->command, NULL, NULL); #if 0 if ((uid_t) -1 != task->trusted_users[0]) { status = sl_trustfile(task->command, task->trusted_users, NULL); } #endif PDBG_OPEN; PDBG_D( (int) status); if ( SL_ENONE != status) { PDBG_S("SL_ENONE != status"); if (some_error == 0) { tmp = sh_util_safe_name (task->command); errfile = sl_trust_errfile(); if (errfile[0] != '\0') { tmp2 = sh_util_safe_name (sl_trust_errfile()); sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_TRUST2, sl_error_string((int)status), tmp, tmp2); SH_FREE(tmp2); } else { sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_TRUST1, sl_error_string((int)status), tmp); } SH_FREE(tmp); } some_error = 1; SL_RETURN ((-1), _("sh_ext_popen")); } PDBG(1); /* * -- check whether the checksum is correct; with linux emulate fdexec */ #if ( !defined(__linux__) || ( defined(__linux__) && defined(HAVE_PTHREAD)) ) && !defined(SL_DEBUG) if (task->checksum[0] != '\0') { char hashbuf[KEYBUF_SIZE]; PDBG_S("checksum test"); if (0 != sl_strcmp(task->checksum, sh_tiger_hash (task->command, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)) ) ) { PDBG_S("checksum mismatch"); if (some_error == 0) { tmp = sh_util_safe_name (task->command); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HASH, tmp); SH_FREE(tmp); } some_error = 1; SL_RETURN ((-1), _("sh_ext_popen")); } } #endif some_error = 0; PDBG(2); /* * -- Create the pipe */ if (aud_pipe(FIL__, __LINE__, pipedes) < 0) { PDBG_S("pipe() failure"); errnum = errno; sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN, sh_error_message(errnum, errbuf, sizeof(errbuf)), _("pipe")); SL_RETURN ((-1), _("sh_ext_popen")); } PDBG(3); /* * -- Flush streams and fork */ fflush (NULL); task->pid = aud_fork(FIL__, __LINE__); if (task->pid == (pid_t) - 1) { PDBG_S("fork() failure"); /*@-usedef@*/ (void) sl_close_fd(FIL__, __LINE__, pipedes[0]); (void) sl_close_fd(FIL__, __LINE__, pipedes[1]); /*@+usedef@*/ errnum = errno; sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN, sh_error_message(errnum, errbuf, sizeof(errbuf)), _("fork")); SL_RETURN ((-1), _("sh_ext_popen")); } PDBG(4); if (task->pid == (pid_t) 0) { /* * -- fork again, if requested */ if (S_TRUE == task->fork_twice) { task->pid = fork(); if (task->pid == (pid_t) - 1) { _exit (EXIT_FAILURE); } } if (task->pid == (pid_t) 0) { int val_return; PDBGC_OPEN; PDBGC(1); /* * -- grandchild - make write side of the pipe stdin */ if (task->rw == 'w') { do { val_return = dup2 (pipedes[STDIN_FILENO], STDIN_FILENO); } while (val_return < 0 && errno == EINTR); if (val_return < 0) _exit(EXIT_FAILURE); } else { do { val_return = dup2 (pipedes[STDOUT_FILENO], STDOUT_FILENO); } while (val_return < 0 && errno == EINTR); if (val_return < 0) _exit(EXIT_FAILURE); } PDBGC(2); /* close the pipe descriptors */ (void) sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]); (void) sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]); /* don't leak file descriptors */ #if !defined(PDGBFILE) sh_unix_closeall (3, task->com_fd, S_TRUE); /* in child process */ #endif /* drop root privileges, if possible && requested */ if (task->privileged == 0 && 0 == getuid()) { PDBGC_S("privileged"); /* zero priv info */ memset(skey, 0, sizeof(sh_key_t)); if (setgid((gid_t) task->run_user_gid) != 0) _exit(EXIT_FAILURE); if (setuid((uid_t) task->run_user_uid) != 0) _exit(EXIT_FAILURE); /* make sure we cannot get root again */ if (setuid(0) >= 0) _exit(EXIT_FAILURE); } PDBGC(3); (void) fflush(NULL); if (task->rw == 'w') { PDBGC_S("w"); (void) fcntl (STDOUT_FILENO, F_SETFD, FD_CLOEXEC); (void) fcntl (STDERR_FILENO, F_SETFD, FD_CLOEXEC); /* freopen(_("/dev/null"), "r+", stderr); freopen(_("/dev/null"), "r+", stdout); */ } else { PDBGC_S("r"); do { val_return = dup2 (STDOUT_FILENO, STDERR_FILENO); } while (val_return < 0 && errno == EINTR); (void) fcntl (STDIN_FILENO, F_SETFD, FD_CLOEXEC); /* freopen(_("/dev/null"), "r+", stdin); */ } PDBGC(4); #if defined(__linux__) /* * -- emulate an fdexec with checksum testing */ #if !defined(HAVE_PTHREAD) if (task->checksum[0] != '\0') #endif { PDBGC_S("fexecve"); if (task->com_fd != (-1)) { do { val_return = dup (task->com_fd); } while (val_return < 0 && errno == EINTR); pfd = val_return; if (pfd < 0) { PDBGC_S("fexecve: dup failed"); _exit(EXIT_FAILURE); } } #if !defined(HAVE_PTHREAD) else { char hashbuf[KEYBUF_SIZE]; fd = sl_open_read(FIL__, __LINE__, task->command, task->privileged==0 ? SL_NOPRIV : SL_YESPRIV); if (0 != sl_strcmp(task->checksum, sh_tiger_hash (task->command, fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)))) { PDBGC_S("fexecve: checksum mismatch"); sl_close(fd); _exit(EXIT_FAILURE); } pfd = get_the_fd(fd); do { val_return = dup (pfd); } while (val_return < 0 && errno == EINTR); pfd = val_return; sl_close(fd); fd = -1; if (pfd < 0) { PDBGC_S("fexecve: dup (2) failed"); _exit(EXIT_FAILURE); } } #endif PDBGC(5); /* Cannot use sprintf because of deadlock in malloc/free */ { static char digit[] = "0123456789"; char str0[128]; char str1[128]; int ival = pfd; unsigned int n = 0; unsigned int m = 0; if (ival < 0) ival = -ival; do { str0[n] = digit[ival % 10]; ++n; ival /= 10; } while (ival); if (pfd < 0) { str0[n] = '-'; ++n; } str0[n] = '\0'; str1[n] = '\0'; while (n > 0) { str1[m] = str0[n-1]; ++m; --n; } sl_strlcpy(pname, _("/proc/self/fd/"), sizeof(pname)); sl_strlcat(pname, str1, sizeof(pname)); } if (access(pname, R_OK|X_OK) == 0) /* flawfinder: ignore */ { PDBGC(6); PDBGC_CLOSE; fcntl (pfd, F_SETFD, FD_CLOEXEC); do { val_return = execve (pname, (task->argc == 0) ? argp : task->argv, (task->envc == 0) ? NULL : task->envv ); } while (val_return < 0 && errno == EINTR); errnum = errno; PDBGC_OPEN; PDBGC_S(strerror(errnum)); PDBGC_S(task->command); PDBGC_S("fexecve: failed"); PDBGC_CLOSE; /* failed */ _exit((errnum == 0) ? (EXIT_SUCCESS) : (EXIT_FAILURE)); } PDBGC_S("fexecve: not working"); /* * procfs not working, go ahead; checksum is tested already */ if (fd != -1) sl_close(fd); else if (pfd != -1) sl_close_fd(FIL__, __LINE__, pfd); } #endif PDBGC_S(" -- non fexecve --"); /* * -- execute path if executable */ if (0 == access(task->command, R_OK|X_OK)) /* flawfinder: ignore */ { PDBGC(5); PDBGC_CLOSE; do { val_return = execve (task->command, (task->argc == 0) ? argp : task->argv, (task->envc == 0) ? envp : task->envv ); } while (val_return < 0 && errno == EINTR); } errnum = errno; PDBGC_OPEN; PDBGC_S(strerror(errnum)); PDBGC_S(task->command); PDBGC_S("execve: failed"); PDBGC_CLOSE; /* failed */ _exit((errnum == 0) ? (EXIT_SUCCESS) : (EXIT_FAILURE)); } /* * if we have forked twice, this is parent::detached_subprocess */ if (S_TRUE == task->fork_twice) { _exit (0); } } /* * -- parent; task->pid is child pid; exit status is status of * grandchild if exited */ if (S_TRUE == task->fork_twice) { (void) waitpid (task->pid, NULL, 0); } PDBG(5); /* open an output stream on top of the write side of the pipe */ if (task->rw == 'w') { PDBG_S("is w"); (void) sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]); (void) retry_fcntl (FIL__, __LINE__, pipedes[STDOUT_FILENO], F_SETFD, FD_CLOEXEC); outf = fdopen (pipedes[STDOUT_FILENO], "w"); } else { PDBG_S("is r"); (void) sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]); (void) retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); outf = fdopen (pipedes[STDIN_FILENO], "r"); } if (outf == NULL) { errnum = errno; PDBG_S("outf == NULL"); tmp = sh_util_safe_name (task->command); if (task->privileged == 0 && 0 == getuid()) sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_NOEXEC, (UID_CAST) task->run_user_uid, tmp); else sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_NOEXEC, (UID_CAST) getuid(), tmp); SH_FREE(tmp); (void) aud_kill (FIL__, __LINE__, task->pid, SIGKILL); (void) sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]); (void) sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]); (void) waitpid (task->pid, NULL, 0); task->pid = 0; SL_RETURN ((-1), _("sh_ext_popen")); } if (task->rw == 'w') task->pipeFD = pipedes[STDOUT_FILENO]; else task->pipeFD = pipedes[STDIN_FILENO]; PDBG_D(task->pipeFD); task->pipeTI = sl_make_ticket(FIL__, __LINE__, task->pipeFD, _("pipe"), outf); flags = (int) retry_fcntl (FIL__, __LINE__, task->pipeFD, F_GETFL, 0); if (flags != (-1)) (void) retry_fcntl (FIL__, __LINE__, task->pipeFD, F_SETFL, flags|O_NONBLOCK); task->pipe = outf; PDBG_S("return from popen"); PDBG_CLOSE; SL_RETURN (0, _("sh_ext_popen")); } /* * -- close the pipe */ extern int flag_err_debug; int sh_ext_pclose (sh_tas_t * task) { int status = 0; int retry = 0; pid_t retval; char infomsg[256]; #ifdef WCONTINUED int wflags = WNOHANG|WUNTRACED|WCONTINUED; #else int wflags = WNOHANG|WUNTRACED; #endif SL_ENTER(_("sh_ext_pclose")); PDBG_OPEN; PDBG_S(" -> pclose"); (void) fflush(task->pipe); if (!SL_ISERROR(task->pipeTI)) (void) sl_close(task->pipeTI); task->pipe = NULL; task->pipeFD = (-1); task->pipeTI = SL_ETICKET; if (S_FALSE == task->fork_twice) { infomsg[0] = '\0'; nochmal: retval = waitpid(task->pid, &(task->exit_status), wflags); /*@-bufferoverflowhigh@*/ if (task->pid == retval) { #ifndef USE_UNO if (WIFEXITED(task->exit_status) != 0) { task->exit_status = WEXITSTATUS(task->exit_status); if ((flag_err_debug == S_TRUE) || (task->exit_status != 0)) sl_snprintf(infomsg, sizeof(infomsg), _("Subprocess exited normally with status %d"), task->exit_status); } else if (WIFSIGNALED(task->exit_status) != 0) { sl_snprintf(infomsg, sizeof(infomsg), _("Subprocess terminated by signal %d"), WTERMSIG(task->exit_status)); task->exit_status = EXIT_FAILURE; } else if (WIFSTOPPED(task->exit_status) != 0) { sl_snprintf(infomsg, sizeof(infomsg), _("Subprocess stopped by signal %d, killing"), WSTOPSIG(task->exit_status)); task->exit_status = EXIT_FAILURE; (void) aud_kill (FIL__, __LINE__, task->pid, 9); (void) retry_msleep (0, 30); (void) waitpid (task->pid, NULL, wflags); } else { sl_snprintf(infomsg, sizeof(infomsg), _("Subprocess exit status unknown")); task->exit_status = EXIT_FAILURE; } #else task->exit_status = EXIT_FAILURE; #endif } else if (0 == retval) { if (retry < 3) { ++retry; (void) retry_msleep(0, (retry * 30)); goto nochmal; } (void) aud_kill (FIL__, __LINE__, task->pid, 9); sl_snprintf(infomsg, sizeof(infomsg), _("Subprocess not yet exited, killing")); task->exit_status = EXIT_FAILURE; (void) waitpid (task->pid, NULL, 0); } else { sl_snprintf(infomsg, sizeof(infomsg), _("Waitpid returned error %d\n"), errno); task->exit_status = EXIT_FAILURE; } /*@+bufferoverflowhigh@*/ status = task->exit_status; if (flag_err_debug == S_TRUE) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task->exit_status, MSG_E_SUBGEN, infomsg, _("sh_ext_pclose")); } else if (status != 0) { sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, task->exit_status, MSG_E_SUBGEN, infomsg, _("sh_ext_pclose")); } } task->pid = 0; task->exit_status = 0; PDBG_S(" <--"); PDBG_CLOSE; SL_RETURN (status, _("sh_ext_pclose")); } void sh_ext_tas_init (sh_tas_t * tas) { int i; tas->command = NULL; tas->argc = 0; tas->envc = 0; tas->checksum[0] = '\0'; tas->pipeFD = (-1); tas->pipeTI = SL_ETICKET; tas->pid = (pid_t) -1; tas->privileged = 1; tas->pipe = NULL; tas->rw = 'w'; tas->exit_status = 0; tas->fork_twice = S_TRUE; for (i = 0; i < 32; ++i) { tas->argv[i] = NULL; tas->envv[i] = NULL; #if 0 tas->trusted_users[i] = (uid_t) -1; #endif } tas->run_user_uid = (uid_t) getuid(); tas->run_user_gid = (gid_t) getgid(); tas->com_fd = -1; tas->com_ti = -1; return; } int sh_ext_tas_add_envv(sh_tas_t * tas, const char * key, const char * val) { size_t sk = 0, sv = 0; int si; SL_ENTER(_("sh_ext_tas_add_envv")); if (tas == NULL || (key == NULL && val == NULL) || tas->envc >= 30) { SL_RETURN (-1, _("sh_ext_tas_add_envv")); } if (key != NULL) sk = strlen(key) + 1; if (val != NULL) sv = strlen(val) + 1; if (!sl_ok_adds(sk, sv)) { SL_RETURN (-1, _("sh_ext_tas_add_envv")); } si = tas->envc; tas->envv[si] = SH_ALLOC(sk + sv); if (key != NULL) { (void) sl_strlcpy(tas->envv[si], key, sk+sv); (void) sl_strlcat(tas->envv[si], "=", sk+sv); if (val != NULL) (void) sl_strlcat(tas->envv[si], val, sk+sv); } else (void) sl_strlcpy(tas->envv[si], val, sv); ++(tas->envc); SL_RETURN ((tas->envc), _("sh_ext_tas_add_envv")); } int sh_ext_tas_rm_argv(sh_tas_t * tas) { int last; SL_ENTER(_("sh_ext_tas_rm_argv")); if (tas == NULL || tas->argc == 0) { SL_RETURN (-1, _("sh_ext_tas_rm_argv")); } last = (tas->argc - 1); --(tas->argc); SH_FREE(tas->argv[last]); tas->argv[last] = NULL; SL_RETURN ((tas->argc), _("sh_ext_tas_rm_argv")); } int sh_ext_tas_add_argv(sh_tas_t * tas, const char * val) { size_t sv = 0; int si; SL_ENTER(_("sh_ext_tas_add_argv")); if (tas == NULL || val == NULL || tas->argc >= 30) { SL_RETURN (-1, _("sh_ext_tas_add_argv")); } if (val != NULL) sv = strlen(val) + 1; si = tas->argc; tas->argv[si] = SH_ALLOC(sv); (void) sl_strlcpy(tas->argv[si], val, sv); ++(tas->argc); SL_RETURN ((tas->argc), _("sh_ext_tas_add_argv")); } void sh_ext_tas_command(sh_tas_t * tas, const char * command) { size_t len = sl_strlen(command); tas->command = SH_ALLOC(len+1); (void) sl_strlcpy(tas->command, command, len+1); return; } void sh_ext_tas_free(sh_tas_t * tas) { int i; if (NULL != tas->command) SH_FREE(tas->command); for (i = 0; i < 32; ++i) { if (NULL != tas->argv[i]) SH_FREE(tas->argv[i]); if (NULL != tas->envv[i]) SH_FREE(tas->envv[i]); } if (tas->com_ti != (-1)) { (void) sl_close(tas->com_ti); tas->com_ti = -1; tas->com_fd = -1; } return; } static void task_init (sh_tas_t * task) { sh_ext_tas_init(task); (void) sh_ext_tas_add_envv (task, _("SHELL"), _("/bin/sh")); (void) sh_ext_tas_add_envv (task, _("PATH"), _("/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb")); (void) sh_ext_tas_add_envv (task, _("IFS"), " \n\t"); if (sh.timezone != NULL) { (void) sh_ext_tas_add_envv(task, "TZ", sh.timezone); } return; } int sh_ext_popen_init (sh_tas_t * task, const char * command, char * argv0, ...) { va_list vl; int status; task_init (task); if (!argv0) { sh_ext_tas_command(task, _("/bin/sh")); (void) sh_ext_tas_add_argv(task, _("/bin/sh")); (void) sh_ext_tas_add_argv(task, _("-c")); (void) sh_ext_tas_add_argv(task, command); } else { char * s; sh_ext_tas_command(task, command); (void) sh_ext_tas_add_argv(task, argv0); va_start (vl, argv0); s = va_arg (vl, char * ); while (s != NULL) { (void) sh_ext_tas_add_argv(task, s); s = va_arg (vl, char * ); } va_end (vl); } task->rw = 'r'; task->fork_twice = S_FALSE; status = sh_ext_popen(task); return status; } /* Execute a system command */ int sh_ext_system (char * command, char * argv0, ...) { sh_tas_t task; int status; va_list vl; char * s; SL_ENTER(_("sh_ext_system")); task_init (&task); sh_ext_tas_command(&task, command); (void) sh_ext_tas_add_argv(&task, argv0); va_start (vl, argv0); s = va_arg (vl, char * ); while (s != NULL) { (void) sh_ext_tas_add_argv(&task, s); s = va_arg (vl, char * ); } va_end (vl); task.rw = 'r'; task.fork_twice = S_FALSE; status = sh_ext_popen(&task); if (status != 0) { sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN, _("Could not execute command"), _("sh_ext_system")); SL_RETURN ((-1), _("sh_ext_system")); } /* close pipe and return exit status */ (void) sh_ext_pclose(&task); sh_ext_tas_free (&task); SL_RETURN ((status), _("sh_ext_system")); } /* Execute command, return first line of output * ifconfig | grep -1 lo | tail -n 1 | sed s/.*inet addr:\([0-9.]*\)\(.*\)/\1/ */ char * sh_ext_popen_str (const char * command) { sh_tas_t task; struct sigaction new_act; struct sigaction old_act; char * out = NULL; int status; SL_ENTER(_("sh_ext_popen_str")); status = sh_ext_popen_init (&task, command, NULL, NULL); if (status != 0) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, _("Could not open pipe"), _("sh_ext_popen_str")); SL_RETURN ((NULL), _("sh_ext_popen_str")); } /* ignore SIGPIPE (instead get EPIPE if connection is closed) */ new_act.sa_handler = SIG_IGN; new_act.sa_flags = 0; sigemptyset( &new_act.sa_mask ); (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act); /* read from the open pipe */ if (task.pipe != NULL) { int try = 1200; /* 1000 * 0.1 = 120 sec */ sh_string * s = sh_string_new(0); do { sh_string_read(s, task.pipe, 0); if (sh_string_len(s) == 0) { --try; retry_msleep(0, 100); } } while (sh_string_len(s) == 0 && try != 0); if (sh_string_len(s) == 0) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, _("No output from command"), _("sh_ext_popen_str")); } out = sh_util_strdup(sh_string_str(s)); sh_string_destroy(&s); } /* restore old signal handler */ (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL); /* close pipe and return exit status */ (void) sh_ext_pclose(&task); sh_ext_tas_free (&task); SL_RETURN ((out), _("sh_ext_popen_str")); } /* --------------- EXTERN STUFF ------------------- */ #if defined(WITH_EXTERNAL) typedef struct _sh_com_t { char type[4]; sh_filter_type * filter; time_t deadtime; time_t last_run; sh_tas_t tas; struct _sh_com_t * next; } sh_com_t; static void set3 (char * pos, char c1, char c2, char c3) { pos[0] = c1; pos[1] = c2; pos[2] = c3; pos[3] = '\0'; return; } /* initialize the external command structure */ static sh_com_t * command_init(void) { uid_t ff_euid; sh_com_t * ext_com = NULL; SL_ENTER(_("command_init")); ext_com = (sh_com_t *) SH_ALLOC(sizeof(sh_com_t)); if (!ext_com) { SL_RETURN( NULL, _("command_init")); } sh_ext_tas_init (&(ext_com->tas)); (void) sl_get_euid(&ff_euid); #if 0 ext_com->tas.trusted_users[0] = (uid_t) 0; ext_com->tas.trusted_users[1] = (uid_t) (ff_euid); #endif /* ------------------------------------------------- */ set3(ext_com->type, 'l', 'o', 'g'); ext_com->filter = NULL; ext_com->deadtime = 0; ext_com->last_run = 0; ext_com->next = NULL; SL_RETURN( ext_com, _("command_init")); } /* the list of external commands */ static sh_com_t * ext_coms = NULL; /* if -1, allocation of last command has failed, * thus don't fill in options */ static int ext_failed = -1; static int sh_ext_add_envv(const char * key, const char * val) { int retval; SL_ENTER(_("sh_ext_add_envv")); if (ext_coms == NULL || ext_failed == (-1) || (key == NULL && val == NULL) || ext_coms->tas.envc >= 30) { SL_RETURN (-1, _("sh_ext_add_envv")); } retval = sh_ext_tas_add_envv(&(ext_coms->tas), key, val); if (retval >= 0) retval = 0; SL_RETURN (retval, _("sh_ext_add_envv")); } static int sh_ext_init(const char * command) { sh_com_t * retval; size_t size; SL_ENTER(_("sh_ext_init")); if (command == NULL) { SL_RETURN (-1, _("sh_ext_init")); } size = strlen(command); if (command[0] != '/' || size < 2) { SL_RETURN (-1, _("sh_ext_init")); } if (NULL == (retval = command_init())) { SL_RETURN (-1, _("sh_ext_init")); } sh_ext_tas_command(&(retval->tas), command); if (sh.timezone != NULL) { (void) sh_ext_add_envv( "TZ", sh.timezone); } retval->next = ext_coms; ext_coms = retval; SL_RETURN (0, _("sh_ext_init")); } static int sh_ext_uid (const char * user, /*@out@*/uid_t * uid, /*@out@*/gid_t * gid) { struct passwd * tempres; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) struct passwd pwd; char * buffer = SH_ALLOC(SH_PWBUF_SIZE); #endif SL_ENTER(_("sh_ext_uid")); *uid = (uid_t)-1; *gid = (gid_t)-1; if (user == NULL) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) SH_FREE(buffer); #endif SL_RETURN (-1, _("sh_ext_uid")); } #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) sh_getpwnam_r(user, &pwd, buffer, SH_PWBUF_SIZE, &tempres); #else tempres = sh_getpwnam(user); #endif if (NULL != tempres) { *uid = tempres->pw_uid; *gid = tempres->pw_gid; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) SH_FREE(buffer); #endif SL_RETURN (0, _("sh_ext_uid")); } #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) SH_FREE(buffer); #endif SL_RETURN (-1, _("sh_ext_uid")); } static int sh_ext_add (const char * argstring, int * ntok, char * stok[]) { int i = 0; size_t s; char * p; char * new; size_t len; SL_ENTER(_("sh_ext_add")); if (NULL == argstring) { SL_RETURN((-1), _("sh_ext_add")); } len = strlen(argstring) + 1; new = SH_ALLOC(len); sl_strlcpy(new, argstring, len); do { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) char * saveptr; if (i == 0) p = strtok_r (new, ", \t", &saveptr); else p = strtok_r (NULL, ", \t", &saveptr); #else if (i == 0) p = strtok (new, ", \t"); else p = strtok (NULL, ", \t"); #endif if (p == NULL) break; s = strlen(p) + 1; if (stok[i] != NULL) SH_FREE(stok[i]); stok[i] = SH_ALLOC(s); (void) sl_strlcpy(stok[i], p, s); ++i; if (i == 30) break; } while (p != NULL); *ntok = i; SH_FREE(new); SL_RETURN (0, _("sh_ext_add")); } /********************************************************* * * Public functions * * *********************************************************/ /* * -- start a new external command, and add it to the list */ int sh_ext_setcommand(const char * cmd) { int i; SL_ENTER(_("sh_ext_setcommand")); if ( (i = sh_ext_init(cmd)) < 0) ext_failed = -1; else ext_failed = 0; SL_RETURN( i, _("sh_ext_setcommand")); } /* * -- clean up the command list */ int sh_ext_cleanup(void) { sh_com_t * retval; SL_ENTER(_("sh_ext_cleanup")); while (ext_coms != NULL) { retval = ext_coms; ext_coms = retval->next; sh_ext_tas_free (&(retval->tas)); if (retval->filter) sh_filter_free (retval->filter); SH_FREE(retval); } SL_RETURN (0, _("sh_ext_cleanup")); } /* * -- explicitely close a command */ int sh_ext_close_command (const char * str) { (void) str; if (ext_coms == NULL || ext_failed == (-1)) return (-1); ext_failed = (-1); return 0; } /* * -- add keywords to the OR filter */ int sh_ext_add_or (const char * str) { if (ext_coms == NULL || ext_failed == (-1)) return (-1); if (ext_coms->filter == NULL) ext_coms->filter = sh_filter_alloc(); return (sh_filter_add(str, ext_coms->filter, SH_FILT_OR)); } /* * -- add keywords to the AND filter */ int sh_ext_add_and (const char * str) { if (ext_coms == NULL || ext_failed == (-1)) return (-1); if (ext_coms->filter == NULL) ext_coms->filter = sh_filter_alloc(); return (sh_filter_add(str, ext_coms->filter, SH_FILT_AND)); } /* * -- add keywords to the NOT filter */ int sh_ext_add_not (const char * str) { if (ext_coms == NULL || ext_failed == (-1)) return (-1); if (ext_coms->filter == NULL) ext_coms->filter = sh_filter_alloc(); return (sh_filter_add(str, ext_coms->filter, SH_FILT_NOT)); } /* * -- add keywords to the CL argument list */ int sh_ext_add_argv (const char * str) { if (ext_coms == NULL || ext_failed == (-1)) return (-1); return (sh_ext_add (str, &(ext_coms->tas.argc), ext_coms->tas.argv)); } /* * -- add a path to the environment */ int sh_ext_add_default (const char * dummy) { char * p = NULL; int i; char dir[SH_PATHBUF]; SL_ENTER(_("sh_ext_add_default")); if (dummy[0] == 'n' || dummy[0] == 'N' || dummy[0] == 'f' || dummy[0] == 'F' || dummy[0] == '0') { SL_RETURN(0, _("sh_ext_add_default")); } p = sh_unix_getUIDdir (SH_ERR_ERR, (uid_t) ext_coms->tas.run_user_uid, dir, sizeof(dir)); if (p) (void) sh_ext_add_envv (_("HOME"), p); (void) sh_ext_add_envv (_("SHELL"), _("/bin/sh")); (void) sh_ext_add_envv (_("PATH"), _("/sbin:/bin:/usr/sbin:/usr/bin")); (void) sh_ext_add_envv (_("IFS"), " \n\t"); i = (p == NULL ? (-1) : 0); SL_RETURN(i, _("sh_ext_add_default")); } /* * -- add an environment variable */ int sh_ext_add_environ (const char * str) { int i; SL_ENTER(_("sh_ext_add_environ")); i = sh_ext_add_envv (NULL, str); SL_RETURN(i, _("sh_ext_add_environ")); } /* * -- set deadtime */ int sh_ext_deadtime (const char * str) { long deadtime = 0; char * tail = NULL; SL_ENTER(_("sh_ext_deadtime")); if (ext_coms == NULL || ext_failed == (-1) || str == NULL) { SL_RETURN (-1, _("sh_ext_deadtime")); } deadtime = strtol(str, &tail, 10); if (tail == str || deadtime < 0 || deadtime == LONG_MAX) { SL_RETURN (-1, _("sh_ext_deadtime")); } ext_coms->deadtime = (time_t) deadtime; SL_RETURN (0, _("sh_ext_deadtime")); } /* * -- define type */ int sh_ext_type (const char * str) { SL_ENTER(_("sh_ext_type")); if (ext_coms == NULL || ext_failed == (-1) || str == NULL) { SL_RETURN((-1), _("sh_ext_type")); } if (strlen(str) != 3) { SL_RETURN((-1), _("sh_ext_type")); } set3(ext_coms->type, str[0], str[1], str[2]); if (str[0] == 'l' && str[1] == 'o' && str[2] == 'g') ext_coms->tas.rw = 'w'; else if (str[0] == 's' && str[1] == 'r' && str[2] == 'v') ext_coms->tas.rw = 'w'; else if (str[0] == 'm' && str[1] == 'o' && str[2] == 'n') ext_coms->tas.rw = 'r'; else { SL_RETURN((-1), _("sh_ext_type")); } SL_RETURN(0, _("sh_ext_type")); } /* * -- define checksum */ int sh_ext_checksum (const char * str) { SL_ENTER(_("sh_ext_checksum")); if (ext_coms == NULL || ext_failed == (-1) || str == NULL) { SL_RETURN((-1), _("sh_ext_checksum")); } if (sl_strlen(str) != KEY_LEN) { SL_RETURN((-1), _("sh_ext_checksum")); } (void) sl_strlcpy (ext_coms->tas.checksum, str, KEY_LEN+1); SL_RETURN((0), _("sh_ext_checksum")); } /* * -- choose privileges */ int sh_ext_priv (const char * c) { uid_t me_uid; gid_t me_gid; SL_ENTER(_("sh_ext_priv")); if (0 == sh_ext_uid (c, &me_uid, &me_gid)) { ext_coms->tas.run_user_uid = me_uid; ext_coms->tas.run_user_gid = me_gid; if (me_uid != (uid_t) 0) ext_coms->tas.privileged = 0; SL_RETURN((0), _("sh_ext_priv")); } SL_RETURN (-1, _("sh_ext_priv")); } /* * -- check filters */ static int sh_ext_filter (char * message, sh_com_t * task) { time_t now_time; SL_ENTER(_("sh_ext_filter")); if (task->filter) { if (0 != sh_filter_filter (message, task->filter)) { SL_RETURN ((-1), _("sh_ext_filter")); } } /* Filter passed, check deadtime */ if (task->deadtime != (time_t) 0) { now_time = time (NULL); if (task->last_run == (time_t) 0) { task->last_run = now_time; } else if ((time_t)(now_time-task->last_run) < task->deadtime) { SL_RETURN ((-1), _("sh_ext_filter")); } else { task->last_run = now_time; } } SL_RETURN ((0), _("sh_ext_filter")); } /* * -- execute external script/program */ int sh_ext_execute (char t1, char t2, char t3, /*@null@*/char * message, size_t msg_siz) { int caperr; sh_com_t * listval = ext_coms; int status = 0; char * tmp; char errbuf[SH_ERRBUF_SIZE]; static int some_error = 0; struct sigaction new_act; struct sigaction old_act; SL_ENTER(_("sh_ext_execute")); PDBG_OPEN; if (listval == NULL || message == NULL) { SL_RETURN ((-1), _("sh_ext_execute")); } PDBG(-1); if (msg_siz == 0) msg_siz = sl_strlen(message); /* ignore SIGPIPE (instead get EPIPE if connection is closed) */ new_act.sa_handler = SIG_IGN; (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act); while (listval != NULL) { PDBG_OPEN; PDBG(-2); if (t1 == listval->type[0] && t2 == listval->type[1] && t3 == listval->type[2] && 0 == sh_ext_filter (message, listval)) { PDBG(-3); if (0 != (caperr = sl_get_cap_sub())) { sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN, sh_error_message (caperr, errbuf, sizeof(errbuf)), _("sl_get_cap_sub")); } if (0 == sh_ext_popen (&(listval->tas))) { PDBG_OPEN; PDBG(-4); if (NULL != listval->tas.pipe && listval->tas.rw == 'w') { PDBG(-5); if (message != NULL) { PDBG(-6); status = (int) write (listval->tas.pipeFD, message, msg_siz); if (status >= 0) status = (int) write (listval->tas.pipeFD, "\n", 1); } PDBG_D(status); if (status >= 0) status = (int) write (listval->tas.pipeFD, "[", 1); PDBG_D(status); if (status >= 0) status = (int) write (listval->tas.pipeFD, "E", 1); PDBG_D(status); if (status >= 0) status = (int) write (listval->tas.pipeFD, "O", 1); PDBG_D(status); if (status >= 0) status = (int) write (listval->tas.pipeFD, "F", 1); PDBG_D(status); if (status >= 0) status = (int) write (listval->tas.pipeFD, "]", 1); PDBG_D(status); if (status >= 0) status = (int) write (listval->tas.pipeFD, "\n", 1); PDBG_D(status); if (status >= 0) { some_error = 0; } if ((status < 0) && (some_error == 0)) { some_error = 1; PDBG_S("some error"); PDBG_D(status); tmp = sh_util_safe_name (listval->tas.command); if (tmp) { if (listval->tas.privileged == 0 && (0 == getuid() || 0 != sl_is_suid()) ) sh_error_handle((-1), FIL__, __LINE__, 0, MSG_NOEXEC, (UID_CAST) listval->tas.run_user_uid, tmp); else sh_error_handle((-1), FIL__, __LINE__, 0, MSG_NOEXEC, (UID_CAST) getuid(), tmp); SH_FREE(tmp); } } PDBG(-7); (void) fflush(listval->tas.pipe); } PDBG(-8); (void) sh_ext_pclose(&(listval->tas)); } else { PDBG_OPEN; PDBG_S("0 != sh_ext_popen()"); } if (0 != (caperr = sl_drop_cap_sub())) { sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN, sh_error_message (caperr, errbuf, sizeof(errbuf)), _("sl_drop_cap_sub")); } } listval = listval->next; } PDBG_OPEN; PDBG_S("no more commands"); /* restore old signal handler */ (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL); PDBG_S("return"); PDBG_CLOSE; SL_RETURN ((0), _("sh_ext_execute")); } /* #if defined(WITH_EXTERNAL) */ #endif samhain-4.1.4/src/sh_files.c0000644000175000017500000024401412723611341012615 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #if defined(HAVE_PTHREAD_MUTEX_RECURSIVE) #define _XOPEN_SOURCE 500 #endif #include #include #include #include #include #include /* Must be before on FreeBSD */ #include #include #include #include #include #if !defined(O_NOATIME) #if defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) #define O_NOATIME 01000000 #endif #endif #include #ifdef HAVE_DIRENT_H #include #define NAMLEN(dirent) sl_strlen((dirent)->d_name) #else #define dirent direct #define NAMLEN(dirent) (dirent)->d_namlen #ifdef HAVE_SYS_NDIR_H #include #endif #ifdef HAVE_SYS_DIR_H #include #endif #ifdef HAVE_NDIR_H #include #endif #endif #define NEED_ADD_DIRENT #ifdef HAVE_GLOB_H #include #endif #ifdef HAVE_FNMATCH_H #include #endif #include "samhain.h" #if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)) #include "sh_pthread.h" #include "sh_error.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_files.h" #include "sh_tiger.h" #include "sh_hash.h" #include "sh_ignore.h" #include "sh_inotify.h" #include "zAVLTree.h" #include "sh_dbIO.h" #undef FIL__ #define FIL__ _("sh_files.c") extern sh_watches sh_file_watches; static char * sh_files_C_dequote (char * s, size_t * length) { size_t i, len = *length; int flag = 0; char *p, *q, *po, *pend; /* search for backslash */ for (i = 0; i < len; ++i) { if (s[i] == '\\') { flag = 1; break; } } if (flag == 0 || *s == '\0') return s; po = SH_ALLOC(len+1); *po = '\0'; p = po; pend = &po[len]; q = s; do { if (*q == '\\') { ++q; if (*q == '\0') { *p = *q; flag = 0; break; } else if (*q == 'a') { *p = '\a'; ++p; ++q; } else if (*q == 'b') { *p = '\b'; ++p; ++q; } else if (*q == 'f') { *p = '\f'; ++p; ++q; } else if (*q == 'n') { *p = '\n'; ++p; ++q; } else if (*q == 'r') { *p = '\r'; ++p; ++q; } else if (*q == 't') { *p = '\t'; ++p; ++q; } else if (*q == 'v') { *p = '\v'; ++p; ++q; } else if (*q == '\\') { *p = '\\'; ++p; ++q; } else if (*q == '\'') { *p = '\''; ++p; ++q; } else if (*q == '"') { *p = '"'; ++p; ++q; } else if (*q == 'x') { if (isxdigit((int) q[1]) && isxdigit((int) q[2])) { /* hexadecimal value following */ unsigned char cc = (16 * sh_util_hexchar(q[1])) + sh_util_hexchar(q[2]); *p = (char) cc; ++p; q += 3; } else { *p = '\0'; flag = 0; break; } } else if (isdigit((int)*q)) { if (isdigit((int) q[1]) && q[1] < '8' && isdigit((int) q[2]) && q[2] < '8') { /* octal value following */ char tmp[4]; unsigned char cc; tmp[0] = *q; ++q; tmp[1] = *q; ++q; tmp[2] = *q; ++q; tmp[3] = '\0'; cc = strtol(tmp, NULL, 8); *p = (char) cc; ++p; } else { *p = '\0'; flag = 0; break; } } else { /* invalid escape sequence */ *p = '\0'; flag = 0; break; } } else { *p = *q; ++p; ++q; } } while (*q && p <= pend); SL_REQUIRE (p <= pend, _("p <= pend")); if (flag) { *p = '\0'; *length = strlen(po); } else { SH_FREE(po); po = NULL; *length = 0; } SL_REQUIRE (*length <= len, _("*length <= len")); SH_FREE(s); return po; } char * sh_files_parse_input(const char * str_s, size_t * len) { char * p; if (!str_s || *str_s == '\0') return NULL; *len = sl_strlen(str_s); if ( (str_s[0] == '"' && str_s[*len-1] == '"' ) || (str_s[0] == '\'' && str_s[*len-1] == '\'') ) { if (*len < 3) return NULL; --(*len); p = sh_util_strdup_l(&str_s[1], *len); p[*len-1] = '\0'; --(*len); } else { p = sh_util_strdup_l(str_s, *len); } p = sh_files_C_dequote(p, len); return p; } extern int flag_err_debug; extern int flag_err_info; int sh_files_reportonce(const char * c) { int i; SL_ENTER(_("sh_files_reportonce")); i = sh_util_flagval(c, &(sh.flag.reportonce)); SL_RETURN(i, _("sh_files_reportonce")); } int sh_files_fulldetail(const char * c) { int i; SL_ENTER(_("sh_files_fulldetail")); i = sh_util_flagval(c, &(sh.flag.fulldetail)); SL_RETURN((i), _("sh_files_fulldetail")); } typedef struct dir_struct { long NumRegular; long NumDirs; long NumSymlinks; long NumFifos; long NumSockets; long NumCDev; long NumBDev; long NumDoor; long NumPort; long NumAll; long TotalBytes; char DirPath[PATH_MAX]; } dir_type; typedef struct dirstack_entry { char * name; int class; unsigned long check_flags; int rdepth; short checked; short childs_checked; short is_reported; /* struct dirstack_entry * next; */ } dirstack_t; /* the destructor */ void free_dirstack (void * inptr) { dirstack_t * here; SL_ENTER(_("free_dirstack")); if (inptr == NULL) SL_RET0(_("free_dirstack")); else here = (dirstack_t *) inptr; if (here->name != NULL) SH_FREE(here->name); SH_FREE(here); SL_RET0(_("free_dirstack")); } /* Function to return the key for indexing * the argument */ zAVLKey zdirstack_key (void const * arg) { const dirstack_t * sa = (const dirstack_t *) arg; return (zAVLKey) sa->name; } #define SH_LIST_FILE 0 #define SH_LIST_DIR1 1 #define SH_LIST_DIR2 2 static int which_dirList = SH_LIST_DIR1; static zAVLTree * zdirListOne = NULL; static zAVLTree * zdirListTwo = NULL; static zAVLTree * zfileList = NULL; SH_MUTEX_STATIC(mutex_zfiles, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_STATIC(mutex_zglob, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_RECURSIVE(mutex_zdirs); static int sh_files_fullpath (const char * testdir, const char * d_name, char * statpath); static int sh_files_pushdir (int class, const char * str_s); static int sh_files_pushfile (int class, const char * str_s); static long MaxRecursionLevel = 0; /* set default recursion level */ int sh_files_setrecursion (const char * flag_s) { long flag = 0; static int reject = 0; SL_ENTER( _("sh_files_setrecursion")); if (reject == 1) SL_RETURN((-1), _("sh_files_setrecursion")); if (sh.flag.opts == S_TRUE) reject = 1; if (flag_s != NULL) flag = (int)(atof(flag_s)); if (flag >= 0 && flag <= 99) MaxRecursionLevel = flag; else SL_RETURN((-1), _("sh_files_setrecursion")); SL_RETURN((0), _("sh_files_setrecursion")); } static int handle_filecheck_ret(dirstack_t * ptr, char * tmp_in, int status) { int fcount = 0; char * tmp; if (!tmp_in) tmp = sh_util_safe_name (ptr->name); else tmp = tmp_in; if (status == SH_FILE_UNKNOWN && (!SH_FFLAG_REPORTED_SET(ptr->is_reported))) { TPT(( 0, FIL__, __LINE__, _("msg= status=<%d>\n"), tmp, status)); if ( sh.flag.checkSum == SH_CHECK_INIT || sh_hash_have_it (ptr->name) >= 0) { if (S_FALSE == sh_ignore_chk_del(ptr->name)) { if (0 != hashreport_missing(ptr->name, (ptr->class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_FILE])) { if (tmp == NULL) tmp = sh_util_safe_name (ptr->name); if (!sh_global_check_silent) sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0, MSG_FI_MISS, tmp); ++sh.statistics.files_report; } } } else /* not there at init, and still missing */ { if (tmp == NULL) tmp = sh_util_safe_name (ptr->name); sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_FI_FAIL, tmp); } if (sh.flag.checkSum != SH_CHECK_INIT) sh_hash_set_missing(ptr->name); if (sh.flag.reportonce == S_TRUE) SET_SH_FFLAG_REPORTED(ptr->is_reported); } else { /* exists (status >= 0), but was missing (reported == TRUE) */ if (status != SH_FILE_UNKNOWN && SH_FFLAG_REPORTED_SET(ptr->is_reported)) { CLEAR_SH_FFLAG_REPORTED(ptr->is_reported); sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT); } /* Catchall */ else if (status == SH_FILE_UNKNOWN) { /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file * is reported if ptr->reported == S_TRUE because the * file has been added. */ if (sh_hash_have_it (ptr->name) >= 0 && !SH_FFLAG_REPORTED_SET(ptr->is_reported)) { if (S_FALSE == sh_ignore_chk_del(ptr->name)) { if (0 != hashreport_missing(ptr->name, (ptr->class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_FILE])) { if (tmp == NULL) tmp = sh_util_safe_name (ptr->name); if (!sh_global_check_silent) sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0, MSG_FI_MISS, tmp); ++sh.statistics.files_report; } } /* delete from database */ if (sh.flag.checkSum != SH_CHECK_INIT) sh_hash_set_missing(ptr->name); } else { if (tmp == NULL) tmp = sh_util_safe_name (ptr->name); sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_FI_FAIL, tmp); if (sh.flag.checkSum != SH_CHECK_INIT) sh_hash_set_visited_true(ptr->name); } } ++fcount; } if (!tmp_in) SH_FREE(tmp); return fcount; } unsigned long sh_files_chk () { zAVLCursor cursor; ShFileType status; unsigned long fcount = 0; char * tmp = NULL; dirstack_t * ptr; char * dir; char * file; int tmp_reported; SL_ENTER(_("sh_files_chk")); for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr; ptr = (dirstack_t *) zAVLNext(&cursor)) { if (sig_urgent > 0) { SL_RETURN(fcount, _("sh_files_chk")); } if (ptr->checked == S_FALSE) { dir = sh_util_dirname (ptr->name); file = sh_util_basename (ptr->name); #if defined(WITH_TPT) tmp = sh_util_safe_name (ptr->name); #endif if (flag_err_info == S_TRUE) { char pstr[32]; #if !defined(WITH_TPT) tmp = sh_util_safe_name (ptr->name); #endif sl_strlcpy(pstr, sh_hash_getpolicy(ptr->class), sizeof(pstr)); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmp); } if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0) { sh_inotify_add_watch_later(ptr->name, &sh_file_watches, NULL, ptr->class, ptr->check_flags, SH_INOTIFY_FILE, 0); } BREAKEXIT(sh_files_filecheck); tmp_reported = ptr->is_reported; /* fix aliasing warning */ status = sh_files_filecheck (ptr->class, ptr->check_flags, dir, file, &tmp_reported, 0); ptr->is_reported = tmp_reported; TPT(( 0, FIL__, __LINE__, _("msg= status=<%d> reported=<%d>\n"), tmp, status, ptr->is_reported)); fcount += handle_filecheck_ret(ptr, tmp, status); if (tmp != NULL) { SH_FREE(tmp); tmp = NULL; } if (file) SH_FREE(file); if (dir) SH_FREE(dir); ptr->checked = S_TRUE; } } SL_RETURN(fcount, _("sh_files_chk")); } static zAVLTree * fileTree = NULL; static zAVLTree * dirTree = NULL; static void clear_lists() { if (fileTree) { zAVL_string_reset(fileTree); fileTree = NULL; } if (dirTree) { zAVL_string_reset(dirTree); dirTree = NULL; } return; } static void add_to_filelist(zAVLTree * tree) { dirstack_t * ptr; zAVLCursor avlcursor; SL_ENTER(_("add_to_filelist")); SH_MUTEX_LOCK(mutex_zfiles); for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor)) zAVL_string_set (&fileTree, ptr->name); SH_MUTEX_UNLOCK(mutex_zfiles); SL_RET0(_("add_to_filelist")); } static void add_to_dirlist(zAVLTree * tree) { dirstack_t * ptr; zAVLCursor avlcursor; SL_ENTER(_("add_to_dirlist")); SH_MUTEX_LOCK(mutex_zfiles); for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor)) zAVL_string_set (&dirTree, ptr->name); SH_MUTEX_UNLOCK(mutex_zfiles); SL_RET0(_("add_to_dirlist")); } char * sh_files_findfile(const char * path) { return zAVL_string_get (fileTree, path); } void * sh_dummy_621_candidate; static char * intern_find_morespecific_dir(zAVLTree * tree, const char * path, size_t * len) { dirstack_t * ptr; zAVLCursor avlcursor; size_t l_path = strlen(path); size_t l_name; char * candidate = NULL; size_t l_candidate = 0; if (NULL == tree) return NULL; sh_dummy_621_candidate = (void *) &candidate; SH_MUTEX_LOCK(mutex_zfiles); for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor)) { l_name = strlen(ptr->name); if (l_name <= l_path) { if (0 == strncmp(ptr->name, path, l_name)) { if ((l_name == l_path) || (path[l_name] == '/')) { if (!candidate || (l_candidate < l_name)) { candidate = ptr->name; l_candidate = l_name; *len = l_candidate; } } } } } SH_MUTEX_UNLOCK(mutex_zfiles); return candidate; } char * sh_files_find_mostspecific_dir(const char * path) { size_t l_one = 0; size_t l_two = 0; char * one; char * two; one = intern_find_morespecific_dir(zdirListOne, path, &l_one); two = intern_find_morespecific_dir(zdirListTwo, path, &l_two); if (l_one > l_two) return one; else return two; } int sh_files_delfilestack () { SL_ENTER(_("sh_files_delfilestack")); SH_MUTEX_LOCK(mutex_zfiles); zAVLFreeTree (zfileList, free_dirstack); zfileList = NULL; SH_MUTEX_UNLOCK(mutex_zfiles); SL_RETURN(0, _("sh_files_delfilestack")); } int sh_files_setrec_int (zAVLTree * tree) { dirstack_t * ptr; zAVLCursor avlcursor; SL_ENTER(_("sh_files_setrec")); if (tree != NULL) { for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor)) { if (ptr->rdepth < (-1) || ptr->rdepth > 99) { ptr->rdepth = MaxRecursionLevel; } if ( (ptr->rdepth == (-1)) && (ptr->class == SH_LEVEL_ALLIGNORE) && (sh.flag.checkSum != SH_CHECK_INIT)) hash_remove_tree (ptr->name); } } SL_RETURN(0, _("sh_files_setrec")); } int sh_files_setrec () { volatile int ret; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); clear_lists(); add_to_dirlist(zdirListOne); add_to_dirlist(zdirListTwo); add_to_filelist(zfileList); sh_files_setrec_int(zdirListOne); ret = sh_files_setrec_int(zdirListTwo); SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); return ret; } zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr) { SL_ENTER(_("sh_files_deldirstack")); zAVLFreeTree (ptr, free_dirstack); SL_RETURN(NULL, _("sh_files_deldirstack")); } int sh_files_deldirstack () { SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); zdirListOne = sh_files_deldirstack_int(zdirListOne); zdirListTwo = sh_files_deldirstack_int(zdirListTwo); SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); return 0; } void sh_files_reset() { dirstack_t * ptr; zAVLCursor avlcursor; SL_ENTER(_("sh_files_reset")); SH_MUTEX_LOCK(mutex_zfiles); for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor)) ptr->checked = 0; SH_MUTEX_UNLOCK(mutex_zfiles); SL_RET0(_("sh_files_reset")); } void sh_dirs_reset() { dirstack_t * ptr; zAVLCursor avlcursor1; zAVLCursor avlcursor2; SL_ENTER(_("sh_dirs_reset")); SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor1)) ptr->checked = 0; for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr; ptr = (dirstack_t *) zAVLNext(&avlcursor2)) ptr->checked = 0; SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); SL_RET0(_("sh_dirs_reset")); } int sh_files_pushfile_prelink (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s)); } int sh_files_pushfile_user0 (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_USER0, str_s)); } int sh_files_pushfile_user1 (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_USER1, str_s)); } int sh_files_pushfile_user2 (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_USER2, str_s)); } int sh_files_pushfile_user3 (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_USER3, str_s)); } int sh_files_pushfile_user4 (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_USER4, str_s)); } int sh_files_pushfile_ro (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_READONLY, str_s)); } int sh_files_pushfile_attr (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s)); } int sh_files_pushfile_log (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s)); } int sh_files_pushfile_glog (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s)); } int sh_files_pushfile_noig (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s)); } int sh_files_pushfile_allig (const char * str_s) { return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s)); } static void sh_files_set_mask (unsigned long * mask, unsigned long val, int act) { SL_ENTER(_("sh_files_set_mask")); if (act == 0) (*mask) = val; else if (act > 0) (*mask) |= val; else (*mask) &= ~val; SL_RET0(_("sh_files_set_mask")); } /* set mask(class) */ static int sh_files_parse_mask (unsigned long * mask, const char * str) { int l, i = 0, act = 0, k = 0; char myword[64]; SL_ENTER(_("sh_files_parse_mask")); myword[0] = '\0'; if (str == NULL) { SL_RETURN ( (-1), _("sh_files_parse_mask")); } else l = sl_strlen(str); while (i < l) { if (str[i] == '\0') break; if (str[i] == ' ' || str[i] == '\t' || str[i] == ',') { ++i; continue; } if (str[i] == '+') { act = +1; ++i; myword[0] = '\0'; goto getword; } else if (str[i] == '-') { act = -1; ++i; myword[0] = '\0'; goto getword; } else /* a word */ { getword: k = 0; while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ',' && str[i] != '+' && str[i] != '-' && str[i] != '\0') { myword[k] = str[i]; ++i; ++k; } myword[k] = '\0'; if (sl_strlen(myword) == 0) { SL_RETURN ( (-1), _("sh_files_parse_mask")); } /* checksum */ if (0 == strcmp(myword, _("CHK"))) sh_files_set_mask (mask, MODI_CHK, act); /* link */ else if (0 == strcmp(myword, _("LNK"))) sh_files_set_mask (mask, MODI_LNK, act); /* inode */ else if (0 == strcmp(myword, _("RDEV"))) sh_files_set_mask (mask, MODI_RDEV, act); /* inode */ else if (0 == strcmp(myword, _("INO"))) sh_files_set_mask (mask, MODI_INO, act); /* user */ else if (0 == strcmp(myword, _("USR"))) sh_files_set_mask (mask, MODI_USR, act); /* group */ else if (0 == strcmp(myword, _("GRP"))) sh_files_set_mask (mask, MODI_GRP, act); /* mtime */ else if (0 == strcmp(myword, _("MTM"))) sh_files_set_mask (mask, MODI_MTM, act); /* ctime */ else if (0 == strcmp(myword, _("CTM"))) sh_files_set_mask (mask, MODI_CTM, act); /* atime */ else if (0 == strcmp(myword, _("ATM"))) sh_files_set_mask (mask, MODI_ATM, act); /* size */ else if (0 == strcmp(myword, _("SIZ"))) sh_files_set_mask (mask, MODI_SIZ, act); /* file mode */ else if (0 == strcmp(myword, _("MOD"))) sh_files_set_mask (mask, MODI_MOD, act); /* hardlinks */ else if (0 == strcmp(myword, _("HLN"))) sh_files_set_mask (mask, MODI_HLN, act); /* size may grow */ else if (0 == strcmp(myword, _("SGROW"))) sh_files_set_mask (mask, MODI_SGROW, act); /* use prelink */ else if (0 == strcmp(myword, _("PRE"))) sh_files_set_mask (mask, MODI_PREL, act); /* get content */ else if (0 == strcmp(myword, _("TXT"))) sh_files_set_mask (mask, MODI_TXT, act); /* get audit report */ else if (0 == strcmp(myword, _("AUDIT"))) sh_files_set_mask (mask, MODI_AUDIT, act); else { SL_RETURN ( (-1), _("sh_files_parse_mask")); } act = 0; myword[0] = '\0'; } } SL_RETURN ( (0), _("sh_files_parse_mask")); } int sh_files_redef_prelink(const char * str) { return (sh_files_parse_mask(&mask_PRELINK, str)); } int sh_files_redef_user0(const char * str) { return (sh_files_parse_mask(&mask_USER0, str)); } int sh_files_redef_user1(const char * str) { return (sh_files_parse_mask(&mask_USER1, str)); } int sh_files_redef_user2(const char * str) { return (sh_files_parse_mask(&mask_USER2, str)); } int sh_files_redef_user3(const char * str) { return (sh_files_parse_mask(&mask_USER3, str)); } int sh_files_redef_user4(const char * str) { return (sh_files_parse_mask(&mask_USER4, str)); } int sh_files_redef_readonly(const char * str) { return (sh_files_parse_mask(&mask_READONLY, str)); } int sh_files_redef_loggrow(const char * str) { return (sh_files_parse_mask(&mask_LOGGROW, str)); } int sh_files_redef_logfiles(const char * str) { return (sh_files_parse_mask(&mask_LOGFILES, str)); } int sh_files_redef_attributes(const char * str) { return (sh_files_parse_mask(&mask_ATTRIBUTES, str)); } int sh_files_redef_noignore(const char * str) { return (sh_files_parse_mask(&mask_NOIGNORE, str)); } int sh_files_redef_allignore(const char * str) { return (sh_files_parse_mask(&mask_ALLIGNORE, str)); } unsigned long sh_files_maskof (int class) { switch (class) { case SH_LEVEL_READONLY: return (unsigned long) (mask_READONLY | MODI_INIT); case SH_LEVEL_ATTRIBUTES: return (unsigned long) (mask_ATTRIBUTES | MODI_INIT); case SH_LEVEL_LOGFILES: return (unsigned long) (mask_LOGFILES | MODI_INIT); case SH_LEVEL_LOGGROW: return (unsigned long) (mask_LOGGROW | MODI_INIT); case SH_LEVEL_ALLIGNORE: return (unsigned long) (mask_ALLIGNORE | MODI_INIT); case SH_LEVEL_NOIGNORE: return (unsigned long) (mask_NOIGNORE | MODI_INIT); case SH_LEVEL_USER0: return (unsigned long) (mask_USER0 | MODI_INIT); case SH_LEVEL_USER1: return (unsigned long) (mask_USER1 | MODI_INIT); case SH_LEVEL_USER2: return (unsigned long) (mask_USER2 | MODI_INIT); case SH_LEVEL_USER3: return (unsigned long) (mask_USER3 | MODI_INIT); case SH_LEVEL_USER4: return (unsigned long) (mask_USER4 | MODI_INIT); case SH_LEVEL_PRELINK: return (unsigned long) (mask_PRELINK | MODI_INIT); default: return (unsigned long) 0; } } #ifdef HAVE_GLOB_H int sh_files_has_metachar (const char * str) { SL_ENTER(_("sh_files_has_metachar")); if (NULL != strchr(str, '*')) SL_RETURN(1, _("sh_files_has_metachar")); else if (NULL != strchr(str, '?')) SL_RETURN(1, _("sh_files_has_metachar")); else if (NULL != (strchr(str, '['))) SL_RETURN(1, _("sh_files_has_metachar")); else SL_RETURN(0, _("sh_files_has_metachar")); } int sh_files_globerr (const char * epath, int errnum) { char * p; char errbuf[SH_ERRBUF_SIZE]; SL_ENTER(_("sh_files_globerr")); if (errnum == ENOTDIR || errnum == ENOENT) { SL_RETURN(0, _("sh_files_globerr")); } p = sh_util_safe_name (epath); sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB, sh_error_message (errnum, errbuf, sizeof(errbuf)), p); SH_FREE(p); SL_RETURN(0, _("sh_files_globerr")); } /* #ifdef HAVE_GLOB_H */ #endif int sh_files_push_file_int (int class, const char * str_s, size_t len, unsigned long check_flags) { dirstack_t * new_item_ptr; char * fileName; int ret; volatile int count = 0; SL_ENTER(_("sh_files_push_file_int")); fileName = SH_ALLOC(len+1); sl_strlcpy(fileName, str_s, len+1); new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t)); new_item_ptr->name = fileName; new_item_ptr->class = class; new_item_ptr->check_flags = check_flags; new_item_ptr->rdepth = 0; new_item_ptr->checked = S_FALSE; new_item_ptr->is_reported = 0; new_item_ptr->childs_checked = S_FALSE; SH_MUTEX_LOCK(mutex_zfiles); if (zfileList == NULL) { zfileList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING); if (zfileList == NULL) { (void) safe_logger (0, 0, NULL); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } } ret = zAVLInsert (zfileList, new_item_ptr); SH_MUTEX_UNLOCK(mutex_zfiles); if (-1 == ret) { (void) safe_logger (0, 0, NULL); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } else if (3 == ret) { if (sh.flag.started != S_TRUE) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE, fileName); SH_FREE(fileName); SH_FREE(new_item_ptr); new_item_ptr = NULL; } else { int reported; unsigned long check_flags = sh_files_maskof(class); if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0) { sh_files_filecheck (class, check_flags, str_s, NULL, &reported, 0); if (SH_FFLAG_REPORTED_SET(reported)) sh_files_set_file_reported(str_s); sh_inotify_add_watch_later(str_s, &sh_file_watches, NULL, class, check_flags, SH_INOTIFY_FILE, 0); } if (MODI_AUDIT_ENABLED(check_flags)) { sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Setting audit watch"), _("sh_files_push_file_int"), str_s); sh_audit_mark(str_s); } ++count; } SL_RETURN(count, _("sh_files_push_file_int")); } int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags); #ifdef HAVE_GLOB_H typedef struct globstack_entry { char * name; char * type_name; int class; unsigned long check_flags; int rdepth; short type; /* struct dirstack_entry * next; */ } sh_globstack_t; static zAVLTree * zglobList = NULL; zAVLKey zglobstack_key (void const * arg) { const sh_globstack_t * sa = (const sh_globstack_t *) arg; return (zAVLKey) sa->type_name; } static int sh_files_pushglob (int class, int type, const char * p, int rdepth, unsigned long check_flags_in, int flag) { int globstatus = -1; unsigned int gloop; glob_t pglob; volatile int count = 0; volatile unsigned long check_flags = (flag == 0) ? sh_files_maskof(class) : check_flags_in; SL_ENTER(_("sh_files_pushglob")); pglob.gl_offs = 0; globstatus = glob (p, 0, sh_files_globerr, &pglob); if (sh.flag.checkSum != SH_CHECK_INIT) { sh_globstack_t * new_item_ptr; char * fileName; char * typeName; int ret; SH_MUTEX_TRYLOCK(mutex_zfiles); fileName = sh_util_strdup (p); typeName = sh_util_strconcat ((type == SH_LIST_FILE) ? "F" : "D", p, NULL); new_item_ptr = (sh_globstack_t *) SH_ALLOC (sizeof(sh_globstack_t)); new_item_ptr->name = fileName; new_item_ptr->type_name = typeName; new_item_ptr->class = class; new_item_ptr->check_flags = check_flags; new_item_ptr->rdepth = rdepth; new_item_ptr->type = type; if (zglobList == NULL) { zglobList = zAVLAllocTree (zglobstack_key, zAVL_KEY_STRING); if (zglobList == NULL) { (void) safe_logger (0, 0, NULL); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } } ret = zAVLInsert (zglobList, new_item_ptr); if (ret != 0) /* already in list */ { SH_FREE(fileName); SH_FREE(typeName); SH_FREE(new_item_ptr); } SH_MUTEX_TRYLOCK_UNLOCK(mutex_zfiles); } if (globstatus == 0 && pglob.gl_pathc > 0) { for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop) { if (type == SH_LIST_FILE) { count += sh_files_push_file_int (class, pglob.gl_pathv[gloop], sl_strlen(pglob.gl_pathv[gloop]), check_flags); } else { which_dirList = type; count += sh_files_push_dir_int (class, pglob.gl_pathv[gloop], sl_strlen(pglob.gl_pathv[gloop]), rdepth, check_flags); } } } else { char * tmp = sh_util_safe_name (p); if (pglob.gl_pathc == 0 #ifdef GLOB_NOMATCH || globstatus == GLOB_NOMATCH #endif ) sh_error_handle ((sh.flag.started != S_TRUE) ? SH_ERR_ERR : SH_ERR_NOTICE, FIL__, __LINE__, globstatus, MSG_FI_GLOB, _("No matches found"), tmp); #ifdef GLOB_NOSPACE else if (globstatus == GLOB_NOSPACE) sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, globstatus, MSG_FI_GLOB, _("Out of memory"), tmp); #endif #ifdef GLOB_ABORTED else if (globstatus == GLOB_ABORTED) sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, globstatus, MSG_FI_GLOB, _("Read error"), tmp); #endif else sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, globstatus, MSG_FI_GLOB, _("Unknown error"), tmp); SH_FREE(tmp); } globfree(&pglob); SL_RETURN(count, _("sh_files_pushglob")); return count; } void sh_files_check_globFilePatterns() { sh_globstack_t * testPattern; zAVLCursor cursor; SL_ENTER(_("sh_files_check_globPatterns")); SH_MUTEX_LOCK(mutex_zglob); for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList); testPattern; testPattern = (sh_globstack_t *) zAVLNext (&cursor)) { if (testPattern->type == SH_LIST_FILE) { sh_files_pushglob(testPattern->class, testPattern->type, testPattern->name, testPattern->rdepth, testPattern->check_flags, 1); } } SH_MUTEX_UNLOCK(mutex_zglob); SL_RET0(_("sh_files_check_globPatterns")); } void sh_files_check_globPatterns() { sh_globstack_t * testPattern; zAVLCursor cursor; SL_ENTER(_("sh_files_check_globPatterns")); SH_MUTEX_LOCK(mutex_zglob); for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList); testPattern; testPattern = (sh_globstack_t *) zAVLNext (&cursor)) { sh_files_pushglob(testPattern->class, testPattern->type, testPattern->name, testPattern->rdepth, testPattern->check_flags, 1); } SH_MUTEX_UNLOCK(mutex_zglob); SL_RET0(_("sh_files_check_globPatterns")); } /* the destructor */ void free_globstack (void * inptr) { sh_globstack_t * here; SL_ENTER(_("free_globstack")); if (inptr == NULL) SL_RET0(_("free_globstack")); else here = (sh_globstack_t *) inptr; if (here->name != NULL) SH_FREE(here->name); if (here->type_name != NULL) SH_FREE(here->type_name); SH_FREE(here); SL_RET0(_("free_globstack")); } int sh_files_delglobstack () { SL_ENTER(_("sh_files_delglobstack")); SH_MUTEX_LOCK(mutex_zglob); zAVLFreeTree (zglobList, free_globstack); zglobList = NULL; SH_MUTEX_UNLOCK(mutex_zglob); SL_RETURN(0, _("sh_files_delglobstack")); } #else void sh_files_check_globPatterns() { return; } int sh_files_delglobstack () { return 0; } #endif static int sh_files_pushfile (int class, const char * str_s) { size_t len; char * tmp; char * p; static int reject = 0; SL_ENTER(_("sh_files_pushfile")); if (reject == 1) SL_RETURN((-1),_("sh_files_pushfile")); /* if we push a filename from the command line, make sure it * is the only one -- and will stay the only one */ if (sh.flag.opts == S_TRUE) { sh_files_delfilestack (); sh_files_deldirstack (); sh_files_delglobstack (); reject = 1; } p = sh_files_parse_input(str_s, &len); if (!p || len == 0) SL_RETURN((-1), _("sh_files_pushfile")); if (len >= PATH_MAX) { /* Name too long */ tmp = sh_util_safe_name (p); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG, tmp); SH_FREE(tmp); SL_RETURN((-1),_("sh_files_pushfile")); } else if (p[0] != '/') { /* Not an absolute path */ tmp = sh_util_safe_name (p); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH, tmp); SH_FREE(tmp); SL_RETURN((-1),_("sh_files_pushfile")); } else { /* remove a terminating '/', take care of the * special case of the root directory. */ if (p[len-1] == '/' && len > 1) { p[len-1] = '\0'; --len; } } #ifdef HAVE_GLOB_H if (0 == sh_files_has_metachar(p)) { sh_files_push_file_int (class, p, len, sh_files_maskof(class)); } else { sh_files_pushglob (class, SH_LIST_FILE, p, 0, 0, 0); } #else sh_files_push_file_int (class, p, len, sh_files_maskof(class)); #endif SH_FREE(p); SL_RETURN((0),_("sh_files_pushfile")); } /* ------ directories ----- */ int sh_files_is_allignore_int (char * str, zAVLTree * tree) { dirstack_t * ptr; SL_ENTER(_("sh_files_is_allignore")); if (tree) { ptr = zAVLSearch(tree, str); if (ptr) { if (ptr->class == SH_LEVEL_ALLIGNORE) SL_RETURN( 1, _("sh_files_is_allignore")); else SL_RETURN( 0, _("sh_files_is_allignore")); } } SL_RETURN( 0, _("sh_files_is_allignore")); } int sh_files_is_allignore (char * str) { int retval = 0; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); retval = sh_files_is_allignore_int(str, zdirListOne); if (NULL != zdirListTwo && retval == 0) { retval = sh_files_is_allignore_int(str, zdirListTwo); } SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); return retval; } void * sh_dummy_1493_ptr; unsigned long sh_dirs_chk (int which) { zAVLTree * tree; zAVLCursor cursor; dirstack_t * ptr; dirstack_t * dst_ptr; int status; int tmp_reported; volatile int filetype = SH_FILE_UNKNOWN; volatile unsigned long dcount = 0; char * tmp; SL_ENTER(_("sh_dirs_chk")); sh_dummy_1493_ptr = (void *) &ptr; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); if (which == 1) tree = zdirListOne; else tree = zdirListTwo; for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr; ptr = (dirstack_t *) zAVLNext(&cursor)) { if (sig_urgent > 0) { goto out; } if (ptr->checked == S_FALSE) { SH_MUTEX_LOCK(mutex_zfiles); /* 28 Aug 2001 check the top level directory */ status = S_FALSE; dst_ptr = zAVLSearch(zfileList, ptr->name); if (dst_ptr) { if (dst_ptr->checked == S_FALSE) { BREAKEXIT(sh_files_filecheck); tmp_reported = dst_ptr->is_reported; filetype = sh_files_filecheck (dst_ptr->class, dst_ptr->check_flags, ptr->name, NULL, &tmp_reported, 0); dst_ptr->is_reported = tmp_reported; (void) handle_filecheck_ret(dst_ptr, NULL, filetype); dst_ptr->checked = S_TRUE; status = S_TRUE; } else { status = S_TRUE; } } SH_MUTEX_UNLOCK(mutex_zfiles); if (status == S_FALSE) { tmp_reported = ptr->is_reported; filetype = sh_files_filecheck (ptr->class, ptr->check_flags, ptr->name, NULL, &tmp_reported, 0); ptr->is_reported = tmp_reported; (void) handle_filecheck_ret(ptr, NULL, filetype); } BREAKEXIT(sh_files_checkdir); status = sh_files_checkdir (ptr->class, ptr->check_flags, ptr->rdepth, ptr->name, ptr->name); if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported))) { /* directory is missing */ if (S_FALSE == sh_ignore_chk_del(ptr->name)) { if (0 != hashreport_missing(ptr->name, (ptr->class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_DIR])) { tmp = sh_util_safe_name (ptr->name); if (!sh_global_check_silent) sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_FI_MISS, tmp); ++sh.statistics.files_report; SH_FREE(tmp); } } if (sh.flag.reportonce == S_TRUE) SET_SH_FFLAG_REPORTED(ptr->is_reported); } else { /* exists (status >= 0), but was missing (reported == TRUE) */ if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported)) { CLEAR_SH_FFLAG_REPORTED(ptr->is_reported); sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT); #if 0 /* obsoleted (really?) by the mandatory sh_files_filecheck() * above, which will catch missing directories anyway */ tmp = sh_util_safe_name (ptr->name); if (!sh_global_check_silent) sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[ptr->class] : ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_FI_ADD, tmp); ++sh.statistics.files_report; SH_FREE(tmp); #endif } else if (status == SH_FILE_UNKNOWN) { /* catchall */ tmp = sh_util_safe_name (ptr->name); sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_FI_FAIL, tmp); SH_FREE(tmp); if (sh.flag.checkSum != SH_CHECK_INIT) sh_hash_set_visited_true(ptr->name); } ++dcount; } ptr->checked = S_TRUE; ptr->childs_checked = S_TRUE; } if (sig_urgent > 0) { goto out; } } out: ; /* 'label at end of compound statement' */ SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); SL_RETURN(dcount, _("sh_dirs_chk")); } int sh_files_pushdir_prelink (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s)); } int sh_files_pushdir_user0 (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_USER0, str_s)); } int sh_files_pushdir_user1 (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_USER1, str_s)); } int sh_files_pushdir_user2 (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_USER2, str_s)); } int sh_files_pushdir_user3 (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_USER3, str_s)); } int sh_files_pushdir_user4 (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_USER4, str_s)); } int sh_files_pushdir_attr (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s)); } int sh_files_pushdir_ro (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_READONLY, str_s)); } int sh_files_pushdir_log (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s)); } int sh_files_pushdir_glog (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s)); } int sh_files_pushdir_noig (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s)); } int sh_files_pushdir_allig (const char * str_s) { return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s)); } int set_dirList (int which) { if (which == 2) which_dirList = SH_LIST_DIR2; else which_dirList = SH_LIST_DIR1; return 0; } int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags) { zAVLTree * tree; dirstack_t * new_item_ptr; char * dirName; int ret; SL_ENTER(_("sh_files_push_dir_int")); dirName = SH_ALLOC(len+1); sl_strlcpy(dirName, tail, len+1); new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t)); new_item_ptr->name = dirName; new_item_ptr->class = class; new_item_ptr->check_flags = check_flags; new_item_ptr->rdepth = rdepth; new_item_ptr->checked = S_FALSE; new_item_ptr->is_reported = 0; new_item_ptr->childs_checked = S_FALSE; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); if (which_dirList == SH_LIST_DIR1) { tree = zdirListOne; } else { tree = zdirListTwo; } if (tree == NULL) { tree = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING); if (tree == NULL) { (void) safe_logger (0, 0, NULL); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } if (which_dirList == SH_LIST_DIR1) zdirListOne = tree; else zdirListTwo = tree; } ret = zAVLInsert (tree, new_item_ptr); SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); if (-1 == ret) { (void) safe_logger (0, 0, NULL); aud__exit(FIL__, __LINE__, EXIT_FAILURE); } if (3 == ret) { if (sh.flag.started != S_TRUE) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE, dirName); SH_FREE(dirName); SH_FREE(new_item_ptr); new_item_ptr = NULL; } else { if (MODI_AUDIT_ENABLED(check_flags)) { sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Setting audit watch"), _("sh_files_push_file_int"), tail); sh_audit_mark(tail); } } SL_RETURN(0, _("sh_files_push_dir_int")); } static int sh_files_pushdir (int class, const char * str_s) { char * tmp; size_t len; int rdepth = 0; char * tail = NULL; char * p; SL_ENTER(_("sh_files_pushdir")); if (sh.flag.opts == S_TRUE) { sh_files_delfilestack (); sh_files_deldirstack (); sh_files_delglobstack (); } p = sh_files_parse_input(str_s, &len); if (!p || len == 0) SL_RETURN((-1),_("sh_files_pushdir")); if (p[0] != '/') { rdepth = strtol(p, &tail, 10); if (tail == p) { SH_FREE(p); SL_RETURN((-1), _("sh_files_pushdir")); } } else tail = p; if (tail == p) { /* Setting to an invalid number will force MaxRecursionLevel, * see sh_files_setrec_int() */ rdepth = (-2); } else if ( (rdepth < (-1) || rdepth > 99) || ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) ) { SH_FREE(p); SL_RETURN((-1), _("sh_files_pushdir")); } len = sl_strlen(tail); if (len >= PATH_MAX) { tmp = sh_util_safe_name (tail); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG, tmp); SH_FREE(tmp); SH_FREE(p); SL_RETURN((-1), _("sh_files_pushdir")); } else if (len < 1) { SH_FREE(p); SL_RETURN((-1), _("sh_files_pushdir")); } else if (tail[0] != '/') { tmp = sh_util_safe_name (tail); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH, tmp); SH_FREE(tmp); SH_FREE(p); SL_RETURN((-1), _("sh_files_pushdir")); } else { if (tail[len-1] == '/' && len > 1) { tail[len-1] = '\0'; --len; } } #ifdef HAVE_GLOB_H if (0 == sh_files_has_metachar(tail)) { sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class)); } else { sh_files_pushglob (class, which_dirList, tail, rdepth, 0, 0); } #else sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class)); #endif SH_FREE(p); SL_RETURN((0), _("sh_files_pushdir")); } /** struct sh_dirent { char * sh_d_name; struct sh_dirent * next; }; **/ void kill_sh_dirlist (struct sh_dirent * dirlist) { struct sh_dirent * this; while (dirlist) { this = dirlist->next; SH_FREE(dirlist->sh_d_name); SH_FREE(dirlist); dirlist = this; } return; } /* -- add an entry to a directory listing */ struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry, struct sh_dirent * dirlist) { struct sh_dirent * this; size_t len; if (thisEntry == NULL) return dirlist; len = sl_strlen(thisEntry->d_name); if (len == 0) return dirlist; ++len; this = SH_ALLOC(sizeof(struct sh_dirent)); if (!this) return dirlist; this->sh_d_name = SH_ALLOC(len); sl_strlcpy(this->sh_d_name, thisEntry->d_name, len); this->next = dirlist; return this; } static int sh_check_hardlinks = S_TRUE; /* Simply sets our boolean as to whether this check is active */ int sh_files_check_hardlinks (const char * opt) { int i; SL_ENTER(_("sh_files_check_hardlinks")); i = sh_util_flagval(opt, &sh_check_hardlinks); SL_RETURN(i, _("sh_files_check_hardlinks")); } struct sh_hle_struct { long offset; char * path; struct sh_hle_struct * next; }; static struct sh_hle_struct * sh_hl_exc = NULL; int sh_files_hle_reg (const char * str) { long offset; size_t len; char * path; struct sh_hle_struct * tmp = sh_hl_exc; SL_ENTER(_("sh_files_hle_reg")); /* Free the linked list if called with NULL argument */ if (str == NULL) { while (tmp) { sh_hl_exc = tmp->next; SH_FREE(tmp->path); SH_FREE(tmp); tmp = sh_hl_exc; } sh_hl_exc = NULL; SL_RETURN(0, _("sh_files_hle_reg")); } /* We expect 'offset:/path' */ offset = strtol(str, &path, 0); if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/')) { SL_RETURN(-1, _("sh_files_hle_reg")); } ++path; len = 1 + sl_strlen(path); tmp = SH_ALLOC(sizeof(struct sh_hle_struct)); tmp->path = SH_ALLOC(len); sl_strlcpy (tmp->path, path, len); tmp->offset = offset; tmp->next = sh_hl_exc; sh_hl_exc = tmp; SL_RETURN(0, _("sh_files_hle_reg")); } #if !defined(HOST_IS_DARWIN) static int sh_files_hle_test (int offset, char * path) { struct sh_hle_struct * tmp = sh_hl_exc; SL_ENTER(_("sh_files_hle_reg")); while(tmp) { if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path))) { SL_RETURN(0, _("sh_files_hle_test")); } tmp = tmp->next; } #ifdef HAVE_FNMATCH_H if ( (offset == 1) && (0 == fnmatch(_("/run/user/*"), path, FNM_PATHNAME)) ) { /* gvfs directory in /run/user/username/ */ SL_RETURN(0, _("sh_files_hle_test")); } #endif SL_RETURN(-1, _("sh_files_hle_test")); } #endif static void * sh_dummy_dirlist; static void * sh_dummy_tmpcat; /* -- Check a single directory and its content. Does not * check the directory inode itself. */ int sh_files_checkdir (int iclass, unsigned long check_flags, int idepth, char * iname, char * relativeName) { struct sh_dirent * dirlist; struct sh_dirent * dirlist_orig; DIR * thisDir = NULL; struct dirent * thisEntry; int status; int dummy = S_FALSE; dir_type * theDir; ShFileType checkit; static unsigned int state = 1; file_type * theFile; char * tmpname; char * tmpcat; char errbuf[SH_ERRBUF_SIZE]; int rdepth = 0; int class = 0; volatile int rdepth_next; volatile int class_next; volatile int file_class_next; volatile unsigned long check_flags_next; volatile unsigned long file_check_flags_next; volatile int checked_flag = S_FALSE; volatile int cchecked_flag = S_FALSE; dirstack_t * dst_ptr; dirstack_t * tmp_ptr; int hardlink_num = 0; #if !defined(HOST_IS_DARWIN) size_t len; #endif SL_ENTER(_("sh_files_checkdir")); if (sig_urgent > 0) { SL_RETURN((0), _("sh_files_checkdir")); } if (iname == NULL || idepth < (-1)) SL_RETURN((-1), _("sh_files_checkdir")); if (idepth < 0) { /* hash_remove_tree (iname); */ SL_RETURN((0), _("sh_files_checkdir")); } rdepth = idepth; class = iclass; tmpname = sh_util_safe_name (iname); /* ---- check for obscure name ---- */ if (iclass != SH_LEVEL_ALLIGNORE) { sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE); } if (flag_err_info == S_TRUE) { char pstr[32]; sl_strlcpy(pstr, sh_hash_getpolicy(iclass), sizeof(pstr)); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmpname); } /* ---- check input ---- */ if ( sl_strlen(iname) >= PATH_MAX) { sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_FI_2LONG, tmpname); SH_FREE(tmpname); SL_RETURN((-1), _("sh_files_checkdir")); } /* ---- check for absolute path ---- */ if ( iname[0] != '/') { sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_FI_NOPATH, tmpname); SH_FREE(tmpname); SL_RETURN((-1), _("sh_files_checkdir")); } /* ---- stat the directory ---- */ theFile = SH_ALLOC(sizeof(file_type)); sl_strlcpy (theFile->fullpath, iname, PATH_MAX); theFile->attr_string = NULL; theFile->link_path = NULL; theFile->check_flags = check_flags; (void) relativeName; status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR], iname, theFile, NULL, iclass); if ((sig_termfast == 1) || (sig_terminate == 1)) { if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(theFile); SH_FREE(tmpname); SL_RETURN((0), _("sh_files_checkdir")); } if (status == -1) { if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(theFile); SH_FREE(tmpname); SL_RETURN((-1), _("sh_files_checkdir")); } if (theFile->c_mode[0] != 'd') { if (!sh_global_check_silent) sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_FI_NODIR, tmpname); ++sh.statistics.files_nodir; if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(theFile); SH_FREE(tmpname); SL_RETURN((-1), _("sh_files_checkdir")); } if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0) { sh_inotify_add_watch_later(iname, &sh_file_watches, &status, iclass, check_flags, SH_INOTIFY_DIR, idepth); } hardlink_num = theFile->hardlinks; if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(theFile); /* ---- open directory for reading ---- * * opendir() will fail with ENOTDIR if the path has been changed * to a non-directory in between lstat() and opendir(). */ thisDir = opendir (iname); if (thisDir == NULL) { status = errno; sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_E_OPENDIR, sh_error_message (status, errbuf, sizeof(errbuf)), tmpname); SH_FREE(tmpname); SL_RETURN((-1), _("sh_files_checkdir")); } theDir = SH_ALLOC(sizeof(dir_type)); theDir->NumRegular = 0; theDir->NumDirs = 0; theDir->NumSymlinks = 0; theDir->NumFifos = 0; theDir->NumSockets = 0; theDir->NumCDev = 0; theDir->NumBDev = 0; theDir->NumDoor = 0; theDir->NumPort = 0; theDir->NumAll = 0; theDir->TotalBytes = 0; sl_strlcpy (theDir->DirPath, iname, PATH_MAX); sh_dummy_dirlist = (void *) &dirlist; sh_dummy_tmpcat = (void *) &tmpcat; /* ---- read ---- */ SH_MUTEX_LOCK(mutex_readdir); dirlist = NULL; dirlist_orig = NULL; do { thisEntry = readdir (thisDir); if (thisEntry != NULL) { ++theDir->NumAll; if (sl_strcmp (thisEntry->d_name, ".") == 0) { ++theDir->NumDirs; continue; } if (sl_strcmp (thisEntry->d_name, "..") == 0) { ++theDir->NumDirs; continue; } dirlist = addto_sh_dirlist (thisEntry, dirlist); } } while (thisEntry != NULL); SH_MUTEX_UNLOCK(mutex_readdir); closedir (thisDir); ++sh.statistics.dirs_checked; dirlist_orig = dirlist; do { /* If the directory is empty, dirlist = NULL */ if (!dirlist) break; if (sig_termfast == 1) { SH_FREE(theDir); SH_FREE(tmpname); SL_RETURN((0), _("sh_files_checkdir")); } BREAKEXIT(sh_derr); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R) if (0 == (rand_r(&state) % 5)) (void) sh_derr(); #else if (0 == state * (rand() % 5)) (void) sh_derr(); #endif /* ---- Check the file. ---- */ tmpcat = SH_ALLOC(PATH_MAX); sl_strlcpy(tmpcat, iname, PATH_MAX); if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/') sl_strlcat(tmpcat, "/", PATH_MAX); sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX); rdepth_next = rdepth - 1; class_next = class; check_flags_next = check_flags; file_class_next = class; file_check_flags_next = check_flags; checked_flag = -1; cchecked_flag = -1; /* Wed Aug 24 2005 compare against dirListOne, dirListTwo * this fixes the problem that the directory special file * is checked with the policy of the parent directory */ SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat); if (dst_ptr) { /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next * this fixes the problem that a policy for the directory * inode erroneously becomes a policy for the directory itself. */ file_class_next = dst_ptr->class; file_check_flags_next = dst_ptr->check_flags; checked_flag = dst_ptr->checked; cchecked_flag = dst_ptr->childs_checked; } if (checked_flag == -1) { dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat); if (dst_ptr) { /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next * this fixes the problem that a policy for the directory * inode erroneously becomes a policy for the directory itself. */ file_class_next = dst_ptr->class; file_check_flags_next = dst_ptr->check_flags; checked_flag = dst_ptr->checked; cchecked_flag = dst_ptr->childs_checked; } } SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); SH_MUTEX_LOCK_UNSAFE(mutex_zfiles); dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat); if (dst_ptr) { /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next * this fixes the problem that a policy for the directory * inode erroneously becomes a policy for the directory itself. */ file_class_next = dst_ptr->class; file_check_flags_next = dst_ptr->check_flags; checked_flag = dst_ptr->checked; /* not set, hence always FALSE */ /* cchecked_flag = dst_ptr->childs_checked; */ if (checked_flag != S_TRUE) { /* -- need to check the file itself -- */ if (sh.flag.reportonce == S_TRUE) dummy = dst_ptr->is_reported; } } SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles); /* ---- Has been checked already. ---- */ if (checked_flag == S_TRUE && cchecked_flag == S_TRUE) { /* Mar 11 2004 get ftype for complete directory count */ checkit = sh_unix_get_ftype(tmpcat); if (checkit == SH_FILE_DIRECTORY) { ++theDir->NumDirs; } SH_FREE(tmpcat); dirlist = dirlist->next; continue; } /* --- May be true, false, or not found. --- */ if (checked_flag == S_TRUE) { /* -- need only the file type -- */ checkit = sh_unix_get_ftype(tmpcat); } else { /* -- need to check the file itself -- */ /* -- moved up -- * if (dst_ptr && sh.flag.reportonce == S_TRUE) * dummy = dst_ptr->is_reported; */ checkit = sh_files_filecheck (file_class_next, file_check_flags_next, iname, dirlist->sh_d_name, &dummy, 0); SH_MUTEX_LOCK_UNSAFE(mutex_zfiles); dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat); if (dst_ptr && checked_flag == S_FALSE) dst_ptr->checked = S_TRUE; /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag */ if (dst_ptr && sh.flag.reportonce == S_TRUE) dst_ptr->is_reported = dummy; if (dst_ptr) dst_ptr->childs_checked = S_TRUE; SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles); } if (checkit == SH_FILE_REGULAR) ++theDir->NumRegular; else if (checkit == SH_FILE_DIRECTORY) { ++theDir->NumDirs; if (rdepth_next >= 0 && cchecked_flag != S_TRUE) { rdepth_next = rdepth - 1; /* check whether the new directory is in the * list with a recursion depth already defined */ checked_flag = -1; cchecked_flag = -1; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat); if (tmp_ptr) { TPT((0, FIL__, __LINE__, _("msg=<%s -> recursion depth %d\n>"), tmp_ptr->name, tmp_ptr->rdepth)); rdepth_next = tmp_ptr->rdepth; class_next = tmp_ptr->class; check_flags_next = tmp_ptr->check_flags; /* 28. Aug 2001 reversed */ cchecked_flag = tmp_ptr->childs_checked; checked_flag = tmp_ptr->checked; } if (checked_flag == -1) { tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat); if (tmp_ptr) { TPT((0, FIL__, __LINE__, _("msg=<%s -> recursion depth %d\n>"), tmp_ptr->name, tmp_ptr->rdepth)); rdepth_next = tmp_ptr->rdepth; class_next = tmp_ptr->class; check_flags_next = tmp_ptr->check_flags; /* 28. Aug 2001 reversed */ cchecked_flag = tmp_ptr->childs_checked; checked_flag = tmp_ptr->checked; } } if (tmp_ptr && cchecked_flag == S_FALSE) { tmp_ptr->childs_checked = S_TRUE; /* * 04. Feb 2006 avoid double checking */ tmp_ptr->checked = S_TRUE; } SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); if (cchecked_flag == S_FALSE) { sh_files_checkdir (class_next, check_flags_next, rdepth_next, tmpcat, dirlist->sh_d_name); /* tmp_ptr->childs_checked = S_TRUE; tmp_ptr->checked = S_TRUE; */ } else if (checked_flag == -1) sh_files_checkdir (class_next, check_flags_next, rdepth_next, tmpcat, dirlist->sh_d_name); } } else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks; else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos; else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets; else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev; else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev; else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor; else if (checkit == SH_FILE_PORT) ++theDir->NumPort; SH_FREE(tmpcat); if ((sig_termfast == 1) || (sig_terminate == 1)) { SH_FREE(theDir); sh_dummy_dirlist = NULL; SH_FREE(tmpname); SL_RETURN((0), _("sh_files_checkdir")); } dirlist = dirlist->next; /* -- moved up, only affects zfileList anyway * if (dst_ptr) * dst_ptr->childs_checked = S_TRUE; */ } while (dirlist != NULL); if (flag_err_info == S_TRUE) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM, theDir->NumDirs, theDir->NumRegular, theDir->NumSymlinks, theDir->NumFifos, theDir->NumSockets, theDir->NumCDev, theDir->NumBDev); } kill_sh_dirlist (dirlist_orig); #if !defined(HOST_IS_DARWIN) /* * Hardlink check; not done on MacOS X because of resource forks */ if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs)) { if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname)) { len = strlen(tmpname); if (sl_ok_adds(len, 256)) len += 256; tmpcat = SH_ALLOC(len); sl_snprintf(tmpcat, len, _("%s: subdirectory count (%d) != hardlinks (%d)"), tmpname, theDir->NumDirs, hardlink_num); sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0, MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir")); SH_FREE(tmpcat); } } #endif SH_FREE(tmpname); SH_FREE(theDir); sh_dummy_dirlist = NULL; SL_RETURN((0), _("sh_files_checkdir")); } void sh_files_fixup_mask (int class, unsigned long * check_flags) { if (class == SH_LEVEL_ALLIGNORE) MODI_SET((*check_flags), MODI_ALLIGNORE); sh_tiger_get_mask_hashtype(check_flags); return; } int get_the_fd (SL_TICKET ticket); static int sh_use_rsrc = S_FALSE; int sh_files_use_rsrc(const char * str) { return sh_util_flagval(str, &sh_use_rsrc); } static void * sh_dummy_fileName; static void * sh_dummy_tmpname; static void * sh_dummy_tmpdir; ShFileType sh_files_filecheck (int class, unsigned long check_flags, const char * dirName, const char * infileName, int * reported, int rsrcflag) { /* 28 Aug 2001 allow NULL fileName */ char * fullpath; char fileHash[2*(KEY_LEN + 1)]; int status; file_type * theFile; char * tmpdir; char * tmpname; const char * fileName; #if !defined(O_NOATIME) struct utimbuf utime_buf; #endif static unsigned int state = 1; char sc; SL_ENTER(_("sh_files_filecheck")); fullpath = SH_ALLOC(PATH_MAX); theFile = SH_ALLOC(sizeof(file_type)); /* Take the address to keep gcc from putting it into a register. * Avoids the 'clobbered by longjmp' warning. */ sh_dummy_fileName = (void *) &fileName; sh_dummy_tmpname = (void *) &tmpname; sh_dummy_tmpdir = (void *) &tmpdir; BREAKEXIT(sh_derr); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R) if (0 == (rand_r(&state) % 2)) (void) sh_derr(); #else if (0 == state * (rand() % 2)) (void) sh_derr(); #endif if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0') && (infileName[0] == '/') && (infileName[1] == '\0')) { fileName = NULL; } else { fileName = infileName; } /* fileName may be NULL if this is a directory */ if (dirName == NULL /* || fileName == NULL */) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(fullpath); SH_FREE(theFile); SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck")); } if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) && (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], fileName, S_FALSE))) { if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0')) { tmpname = sh_util_safe_name (fileName); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0, MSG_FI_OBSC2, "", tmpname); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmpname); } else { tmpdir = sh_util_safe_name (dirName); tmpname = sh_util_safe_name (fileName); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0, MSG_FI_OBSC2, tmpdir, tmpname); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmpname); SH_FREE(tmpdir); } } /* sh_files_fullpath accepts NULL fileName */ if (0 != sh_files_fullpath (dirName, fileName, fullpath)) { tmpdir = sh_util_safe_name (dirName); tmpname = sh_util_safe_name (fileName); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0, MSG_FI_2LONG2, tmpdir, tmpname); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmpname); SH_FREE(tmpdir); SH_FREE(fullpath); SH_FREE(theFile); SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck")); } /* stat the file and determine checksum (if a regular file) */ sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX); theFile->check_flags = check_flags /* sh_files_maskof(class) */; theFile->file_reported = (*reported); theFile->attr_string = NULL; theFile->link_path = NULL; TPT(( 0, FIL__, __LINE__, _("msg=\n"), fullpath)); status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ? ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE], fileName, theFile, fileHash, class); if (status != 0) { TPT(( 0, FIL__, __LINE__, _("msg= status=<%d>\n"), fullpath, status)); if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT) sh_hash_set_visited_true (fullpath); if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(fullpath); SH_FREE(theFile); SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck")); } if (sig_termfast == 1) { goto ret_point; } /* report */ if ((flag_err_debug == S_TRUE) && (theFile->c_mode[0] == '-')) { tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */ SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM, fileHash, tmpname); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(tmpname); } ++sh.statistics.files_checked; if ( sh.flag.checkSum == SH_CHECK_INIT) { if (class == SH_LEVEL_ALLIGNORE) MODI_SET(theFile->check_flags, MODI_ALLIGNORE); if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath)) MODI_SET(theFile->check_flags, MODI_NOCHECK); sh_tiger_get_mask_hashtype(&(theFile->check_flags)); sh_dbIO_data_write (theFile, fileHash); } else if (sh.flag.checkSum == SH_CHECK_CHECK /* && theFile.c_mode[0] == '-' */ /* && class != SH_LEVEL_ALLIGNORE */ ) { if (sh.flag.update == S_TRUE) { if (class == SH_LEVEL_ALLIGNORE) MODI_SET(theFile->check_flags, MODI_ALLIGNORE); if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath)) MODI_SET(theFile->check_flags, MODI_NOCHECK); sh_tiger_get_mask_hashtype(&(theFile->check_flags)); } sh_hash_compdata (class, theFile, fileHash, NULL, -1); } (*reported) = theFile->file_reported; /* reset the access time */ #if !defined(O_NOATIME) if (class == SH_LEVEL_NOIGNORE && (theFile->check_flags & MODI_ATM) != 0) { utime_buf.actime = (time_t) theFile->atime; utime_buf.modtime = (time_t) theFile->mtime; retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf); } #endif #if defined(HOST_IS_DARWIN) /* * Check for resource fork */ if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) ) { int dummy; static int rsrc_init = 0; static char rsrc[17]; char * testpath = SH_ALLOC(PATH_MAX); if (rsrc_init == 0) { sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17); rsrc_init = 1; } sl_strlcpy (testpath, fullpath, PATH_MAX); sl_strlcat (testpath, "/", PATH_MAX); sl_strlcat (testpath, rsrc, PATH_MAX); if (sl_strlen(testpath) == (17 + sl_strlen(fullpath))) { if (S_TRUE == sh_unix_file_exists (testpath)) { sh_files_filecheck (class, check_flags, fullpath, rsrc, &dummy, 1); } } SH_FREE(testpath); } #else (void) rsrcflag; /* avoid compiler warning */ #endif ret_point: sc = theFile->c_mode[0]; if (theFile->attr_string) SH_FREE(theFile->attr_string); if (theFile->link_path) SH_FREE(theFile->link_path); SH_FREE(fullpath); SH_FREE(theFile); switch (sc) { case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck")); case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck")); case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck")); case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck")); case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck")); case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck")); case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck")); case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck")); case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck")); default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck")); } /* notreached */ } /* concatenate statpath = testdir"/"d_name */ static int sh_files_fullpath (const char * testdir, const char * d_name, char * statpath) { int llen = 0; SL_ENTER(_("sh_files_fullpath")); if (testdir != NULL) { if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) ) SL_RETURN((-1),_("sh_files_fullpath")); sl_strlcpy(statpath, testdir, PATH_MAX - 1); } if (d_name != NULL) { if (llen > 1 || statpath[0] != '/') sl_strlcat(statpath, "/", PATH_MAX); if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX) SL_RETURN((-1),_("sh_files_fullpath")); sl_strlcat(statpath, d_name, PATH_MAX); } if (statpath == NULL) SL_RETURN((-1),_("sh_files_fullpath")); SL_RETURN((0),_("sh_files_fullpath")); } /* ----------------------------------- * Routines required for inotify * ----------------------------------- */ int sh_files_search_dir(char * name, int * class, unsigned long *check_flags, int *reported, int * rdepth) { volatile int retval = 0; #if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H) sh_globstack_t * testPattern; zAVLCursor cursor; #endif dirstack_t * item; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); item = zAVLSearch(zdirListOne, name); if (item) { *check_flags = item->check_flags; *class = item->class; *reported = item->is_reported; *rdepth = item->rdepth; item->checked = S_FALSE; item->childs_checked = S_FALSE; item->is_reported = S_FALSE; retval = 1; goto out; } item = zAVLSearch(zdirListTwo, name); if (item) { *check_flags = item->check_flags; *class = item->class; *reported = item->is_reported; *rdepth = item->rdepth; item->checked = S_FALSE; item->childs_checked = S_FALSE; item->is_reported = S_FALSE; retval = 1; goto out; } #if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H) SH_MUTEX_LOCK(mutex_zglob); for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList); testPattern; testPattern = (sh_globstack_t *) zAVLNext (&cursor)) { if (testPattern->type == SH_LIST_DIR1 || testPattern->type == SH_LIST_DIR2) { if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD)) { *check_flags = testPattern->check_flags; *class = testPattern->class; *rdepth = testPattern->rdepth; retval = 1; break; } } } SH_MUTEX_UNLOCK(mutex_zglob); #endif out: ; /* 'label at end of compound statement' */ SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); return retval; } int sh_files_search_file(char * name, int * class, unsigned long *check_flags, int *reported) { volatile int retval = 0; #if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H) sh_globstack_t * testPattern; zAVLCursor cursor; #endif dirstack_t * item; SH_MUTEX_LOCK(mutex_zfiles); item = zAVLSearch(zfileList, name); if (item) { *check_flags = item->check_flags; *class = item->class; *reported = item->is_reported; retval = 1; } SH_MUTEX_UNLOCK(mutex_zfiles); #if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H) if (retval == 0) { SH_MUTEX_LOCK(mutex_zglob); for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList); testPattern; testPattern = (sh_globstack_t *) zAVLNext (&cursor)) { if (testPattern->type == SH_LIST_FILE) { if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD)) { *check_flags = testPattern->check_flags; *class = testPattern->class; retval = 1; break; } } } SH_MUTEX_UNLOCK(mutex_zglob); } #endif return retval; } void sh_files_set_file_reported(const char * name) { dirstack_t * item; SH_MUTEX_LOCK_UNSAFE(mutex_zfiles); item = zAVLSearch(zfileList, name); if (item) { if (sh.flag.reportonce == S_TRUE) SET_SH_FFLAG_REPORTED(item->is_reported); } SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles); return; } void sh_files_clear_file_reported(const char * name) { dirstack_t * item; SH_MUTEX_LOCK_UNSAFE(mutex_zfiles); item = zAVLSearch(zfileList, name); if (item) { CLEAR_SH_FFLAG_REPORTED(item->is_reported); } SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles); return; } /* ----------------------------------- * * The following two routines serve to * verify that the user has selected * a proper setup for file policies. * * ----------------------------------- */ static int check_file(char * name) { dirstack_t * pfilL; zAVLCursor cursor; volatile int retval = -1; SL_ENTER(_("check_file")); if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name)) SL_RETURN(0, _("check_file")); for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL; pfilL = (dirstack_t *) zAVLNext (&cursor)) { if (0 == strcmp(name, pfilL->name) && (pfilL->check_flags & MODI_ATM) == 0 && (pfilL->check_flags & MODI_CTM) == 0 && (pfilL->check_flags & MODI_MTM) == 0) { retval = 0; break; } } SL_RETURN(retval, _("check_file")); } static void * sh_dummy_pdirL; int sh_files_test_setup_int (zAVLTree * tree) { int dlen, flen; zAVLCursor cursor1; zAVLCursor cursor2; dirstack_t * pdirL; dirstack_t * pfilL; SL_ENTER(_("sh_files_test_setup")); sh_dummy_pdirL = (void *) &pdirL; for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL; pdirL = (dirstack_t *) zAVLNext (&cursor1)) { dlen = strlen(pdirL->name); SH_MUTEX_LOCK(mutex_zfiles); for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL; pfilL = (dirstack_t *) zAVLNext (&cursor2)) { flen = strlen(pfilL->name); /* check whether file is in tree of dir */ if ((pfilL->class == SH_LEVEL_READONLY) || (pfilL->class == SH_LEVEL_NOIGNORE)) { ; /* do nothing */ } else { if ((flen > (dlen+1)) && (pfilL->name[dlen] == '/') && (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/ (0 == strncmp(pfilL->name, pdirL->name, dlen))) { if ((pdirL->check_flags & MODI_ATM) != 0 || (pdirL->check_flags & MODI_MTM) != 0 || (pdirL->check_flags & MODI_CTM) != 0) { if (check_file (pdirL->name) != 0) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL, pdirL->name, pfilL->name); } } } } SH_MUTEX_UNLOCK(mutex_zfiles); } SL_RETURN((0), _("sh_files_test_setup")); } int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList) { int retval = 0; zAVLCursor cursor; dirstack_t * first; for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first; first = (dirstack_t *) zAVLNext (&cursor)) { if (NULL != zAVLSearch(secondList, first->name)) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE, first->name); retval = 1; } } return retval; } extern void aud_exit (const char * file, int line, int fd); int sh_files_test_setup () { int retval; SH_MUTEX_RECURSIVE_INIT(mutex_zdirs); SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs); /* Test for modifications allowed in ReadOnly directory */ sh_files_test_setup_int (zdirListOne); sh_files_test_setup_int (zdirListTwo); /* Test for files/dirz defined twice */ retval = sh_files_test_double (zdirListOne, zdirListTwo); if (retval != 0) aud_exit(FIL__, __LINE__, EXIT_FAILURE); retval = sh_files_test_double (zdirListTwo, zdirListOne); if (retval != 0) aud_exit(FIL__, __LINE__, EXIT_FAILURE); SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs); return 0; } #endif #ifdef SH_CUTEST #include "CuTest.h" void Test_file_lists (CuTest *tc) { #if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)) extern int hash_remove_tree_test(char * s, char * fullpath, size_t len_s); char * test; int ret; sh_files_pushfile_ro("/usr/test"); sh_files_pushfile_ro("/usr/bin/test"); sh_files_pushfile_ro("/usr/bin/foo/test"); sh_files_pushdir_ro("/usr"); sh_files_pushdir_attr("/usr/bin"); sh_files_pushdir_ro("/usr/bin/foo"); add_to_dirlist(zdirListOne); add_to_dirlist(zdirListTwo); add_to_filelist(zfileList); test = sh_files_findfile("/usr/tes"); CuAssertTrue(tc, test == NULL); test = sh_files_findfile("/usr/test"); CuAssertPtrNotNull(tc, test); test = sh_files_findfile("/usr/testi"); CuAssertTrue(tc, test == NULL); test = sh_files_findfile("/test"); CuAssertTrue(tc, test == NULL); test = sh_files_find_mostspecific_dir("/usr/bin/foo/test"); CuAssertStrEquals(tc, "/usr/bin/foo", test); test = sh_files_find_mostspecific_dir("/usr/bin/test"); CuAssertStrEquals(tc, "/usr/bin", test); test = sh_files_find_mostspecific_dir("/usr/test"); CuAssertStrEquals(tc, "/usr", test); test = sh_files_find_mostspecific_dir("/test"); CuAssertTrue(tc, test == NULL); test = sh_files_find_mostspecific_dir("/usr/foo/test"); CuAssertStrEquals(tc, "/usr", test); test = sh_files_find_mostspecific_dir("/usr/bin"); CuAssertStrEquals(tc, "/usr/bin", test); ret = hash_remove_tree_test("/usr", "/usr/test", strlen("/usr")); CuAssertIntEquals(tc, S_FALSE, ret); ret = hash_remove_tree_test("/usr", "/usr/testi", strlen("/usr")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/usr", "/usr/tes", strlen("/usr")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/test", strlen("/usr/bin")); CuAssertIntEquals(tc, S_FALSE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/testi", strlen("/usr/bin")); CuAssertIntEquals(tc, S_FALSE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/tes", strlen("/usr/bin")); CuAssertIntEquals(tc, S_FALSE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/bin/test", strlen("/usr/bin")); CuAssertIntEquals(tc, S_FALSE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/bin/testi", strlen("/usr/bin")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/bin/tes", strlen("/usr/bin")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/usr/bin", "/usr/bin", strlen("/usr/bin")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/usr", "/usr", strlen("/usr")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/usr", "/usrbin", strlen("/usr")); CuAssertIntEquals(tc, S_FALSE, ret); ret = hash_remove_tree_test("/", "/usrbin", strlen("/")); CuAssertIntEquals(tc, S_TRUE, ret); ret = hash_remove_tree_test("/", "/usr", strlen("/")); CuAssertIntEquals(tc, S_FALSE, ret); #else (void) tc; /* fix compiler warning */ return; #endif } void Test_file_dequote (CuTest *tc) { #if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)) char str1[] = "1234567890"; char str1a[] = "123456\\\"789\\r"; char str1b[] = "12345678\\r9"; char str1c[] = "12345678\\x0a_9"; char str1d[] = "12345678\\007_9"; char str1e[] = "123456789\\\\"; char str2[] = "1234567890\\xw"; char str3[] = "1234567890\\xw99"; char str4[] = "1234567890\\0ww"; char str5[] = "12345\\g67890"; char str6[] = "1234567890\\009a"; char *s, *p, *q; size_t lo, lr; s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertPtrNotNull(tc, q); CuAssertTrue(tc, p == q); CuAssertTrue(tc, lr == lo); s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertPtrNotNull(tc, q); CuAssertTrue(tc, p != q); CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r")); CuAssertTrue(tc, lr == (lo-2)); s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertPtrNotNull(tc, q); CuAssertTrue(tc, p != q); CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9")); CuAssertTrue(tc, lr == (lo-1)); s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertPtrNotNull(tc, q); CuAssertTrue(tc, p != q); CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9")); CuAssertTrue(tc, lr == (lo-3)); s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertPtrNotNull(tc, q); CuAssertTrue(tc, p != q); CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9")); CuAssertTrue(tc, lr == (lo-3)); s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertPtrNotNull(tc, q); CuAssertTrue(tc, p != q); CuAssertTrue(tc, 0 == strcmp(q, "123456789\\")); CuAssertTrue(tc, lr == (lo-1)); s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertTrue(tc, q == NULL); CuAssertTrue(tc, lr == 0); s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertTrue(tc, q == NULL); CuAssertTrue(tc, lr == 0); s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertTrue(tc, q == NULL); CuAssertTrue(tc, lr == 0); s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertTrue(tc, q == NULL); CuAssertTrue(tc, lr == 0); s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo; q = sh_files_C_dequote(s, &lr); CuAssertTrue(tc, q == NULL); CuAssertTrue(tc, lr == 0); return; #else (void) tc; /* fix compiler warning */ return; #endif } #endif samhain-4.1.4/src/sh_mem.c0000644000175000017500000002525112615253277012303 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #if defined(HAVE_PTHREAD_MUTEX_RECURSIVE) #define _XOPEN_SOURCE 500 #endif #include #include #include #include #include #ifdef HAVE_MEMORY_H #include #endif #define SH_REAL_SET #include "samhain.h" #include "sh_error.h" #include "sh_utils.h" #include "sh_mem.h" #include "sh_pthread.h" extern int safe_logger (int thesignal, int method, char * details); #undef FIL__ #define FIL__ _("sh_mem.c") #ifdef MEM_DEBUG #define CHECKBYTE 0x7F /* Memory alignment; should be 16 bytes on 64 bit machines. * -> 32 bytes overhead/allocation */ #define SH_MEMMULT 16 typedef struct mem_struct { struct mem_struct *next; /* link to next struct */ char * real_address; /* address assigned */ char * address; /* address returned */ unsigned long size; /* size allocated */ char file[20]; /* Allocation file name */ int line; /* Allocation line number */ } memlist_t; memlist_t * memlist = NULL; int Free_Count = 0, Alloc_Count = 0; int Now_Alloc_Count = 0, Max_Alloc_Count = 0; unsigned long Mem_Current = 0, Mem_Max = 0; #ifdef HAVE_PTHREAD SH_MUTEX_RECURSIVE(mutex_mem); #endif /* define MEM_LOG to an absolute filename to enable this */ #ifdef MEM_LOG void sh_mem_dump () { memlist_t * this = memlist; FILE * fd; SH_MUTEX_RECURSIVE_INIT(mutex_mem); SH_MUTEX_RECURSIVE_LOCK(mutex_mem); fd = fopen(MEM_LOG, "w"); if (!fd) { perror(MEM_LOG); _exit(EXIT_FAILURE); } while (this != NULL) { fprintf (fd, "## %20s %5d %ld\n", this->file, this->line, this->size); fprintf (fd, "%10p %8ld\n", (void *)this->address, this->size); this = this->next; } sl_fclose(FIL__, __LINE__, fd); SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem); _exit(EXIT_SUCCESS); } #else void sh_mem_dump () { return; } #endif memlist_t ** sh_dummy_114_merrlist; void sh_mem_stat () { memlist_t * this; memlist_t * merrlist = NULL; SL_ENTER(_("sh_mem_stat")); sh_dummy_114_merrlist = (memlist_t **) &merrlist; if (Alloc_Count == Free_Count) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP, Mem_Max, Mem_Current); SL_RET0(_("sh_mem_stat")); } sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_MSTAMP2, Alloc_Count, Free_Count, Max_Alloc_Count); sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_MSTAMP, Mem_Max, Mem_Current); SH_MUTEX_RECURSIVE_INIT(mutex_mem); SH_MUTEX_RECURSIVE_LOCK(mutex_mem); this = memlist; while (this != NULL) { memlist_t * merr = calloc(1,sizeof(memlist_t)); memcpy(merr, this, sizeof(memlist_t)); merr->next = merrlist; merrlist = merr; this = this->next; } SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem); while (merrlist != NULL) { memlist_t * tmp = merrlist; merrlist = merrlist->next; sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_NOTFREE, tmp->size, tmp->file, tmp->line); free(tmp); } SL_RET0(_("sh_mem_stat")); } memlist_t ** sh_dummy_168_merrlist; void sh_mem_check () { memlist_t * this; memlist_t * merrlist = NULL; memlist_t * merr; long nerr = 0; SL_ENTER(_("sh_mem_check")); sh_dummy_168_merrlist = (memlist_t **) &merrlist; sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP, Mem_Max, Mem_Current); SH_MUTEX_RECURSIVE_INIT(mutex_mem); SH_MUTEX_RECURSIVE_LOCK(mutex_mem); this = memlist; while (this != NULL) { if ( this->address == NULL ) { merr = calloc (1,sizeof(memlist_t)); memcpy(merr, this, sizeof(memlist_t)); merr->size = 2; merr->next = merrlist; merrlist = merr; ++nerr; } else { if ( this->address[this->size] != CHECKBYTE ) { merr = calloc(1, sizeof(memlist_t)); memcpy(merr, this, sizeof(memlist_t)); merr->size = 1; merr->next = merrlist; merrlist = merr; ++nerr; } if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE ) { merr = calloc(1, sizeof(memlist_t)); memcpy(merr, this, sizeof(memlist_t)); merr->size = 0; merr->next = merrlist; merrlist = merr; ++nerr; } } this = this->next; } SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem); while (merrlist != NULL) { memlist_t * tmp = merrlist; merrlist = merrlist->next; if (tmp->size == 2) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL, tmp->file, tmp->line, FIL__, __LINE__); if (tmp->size == 1) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MOVER, tmp->file, tmp->line, FIL__, __LINE__); else sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MUNDER, tmp->file, tmp->line, FIL__, __LINE__); free(tmp); SH_ABORT; _exit (EXIT_FAILURE); } SL_RET0(_("sh_mem_check")); } void * sh_mem_malloc (size_t size, char * file, int line) { void * the_realAddress; void * theAddress; memlist_t * this; SL_ENTER(_("sh_mem_malloc")); SH_MUTEX_RECURSIVE_INIT(mutex_mem); SH_MUTEX_RECURSIVE_LOCK(mutex_mem); the_realAddress = calloc(1,size + 2 * SH_MEMMULT); if ( the_realAddress == NULL ) { (void) safe_logger (0, 0, NULL); /* use _exit() rather than exit() - we malloc() in atexit() functions */ _exit (EXIT_FAILURE); } /* --- Set check bytes. --- */ theAddress = ((char *) the_realAddress + SH_MEMMULT); memset(the_realAddress, CHECKBYTE, SH_MEMMULT); memset(theAddress, CHECKBYTE, size + 1); memset(theAddress, 0, 1); ++Alloc_Count; ++Now_Alloc_Count; if (Max_Alloc_Count < Now_Alloc_Count) Max_Alloc_Count = Now_Alloc_Count; Mem_Current += size; Mem_Max = ( (Mem_Current > Mem_Max) ? Mem_Current : Mem_Max); this = calloc(1,sizeof(memlist_t)); if ( this == NULL) { (void) safe_logger(0, 0, NULL); _exit(EXIT_FAILURE); } else { /* make list entry */ this->real_address = the_realAddress; this->address = theAddress; this->size = size; this->line = line; sl_strlcpy(this->file, file, 20); this->next = memlist; memlist = this; } SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem); SL_RETURN( theAddress, _("sh_mem_malloc")); } static void ** sh_mem_dummy_a; static memlist_t ** sh_mem_merr_3; void sh_mem_free (void * aa, char * file, int line) { memlist_t * this; memlist_t * before; memlist_t * merr; memlist_t * merrlist = NULL; unsigned long size = 0; void * a; volatile int flag = 0; SL_ENTER(_("sh_mem_free")); a = aa; sh_mem_dummy_a = &a; sh_mem_merr_3 = (memlist_t **) &merrlist; if ( a == NULL ) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL, file, line, FIL__, __LINE__); SH_ABORT; _exit (EXIT_FAILURE); SL_RET0(_("sh_mem_free")); } SH_MUTEX_RECURSIVE_INIT(mutex_mem); SH_MUTEX_RECURSIVE_LOCK(mutex_mem); this = memlist; before = memlist; /* -- Find record. -- */ while (this != NULL) { if (this->address == a) break; before = this; this = this->next; } if (this == NULL) { flag = 1; goto out; } else { a = this->real_address; if ( this->address[this->size] != CHECKBYTE ) { merr = calloc(1, sizeof(memlist_t)); memcpy(merr, this, sizeof(memlist_t)); merr->size = 1; merr->next = merrlist; merrlist = merr; } if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE ) { merr = calloc(1,sizeof(memlist_t)); memcpy(merr, this, sizeof(memlist_t)); merr->size = 0; merr->next = merrlist; merrlist = merr; } size = this->size; if (this == memlist) memlist = this->next; else before->next = this->next; } free(a); if (this) free(this); ++Free_Count; --Now_Alloc_Count; Mem_Current -= size; out: ; /* label at end of compound statement */ SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem); while (merrlist != NULL) { memlist_t * tmp = merrlist; merrlist = merrlist->next; if (tmp->size == 1) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MOVER, tmp->file, tmp->line, file, line); else sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MUNDER, tmp->file, tmp->line, file, line); free(tmp); SH_ABORT; _exit (EXIT_FAILURE); } if (flag != 0) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MREC, file, line); SL_RET0(_("sh_mem_free")); } #else void sh_mem_free (void * a) { SL_ENTER(_("sh_mem_free")); if (a) { free(a); } else { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL); SH_ABORT; } SL_RET0(_("sh_mem_free")); } void * sh_mem_malloc (size_t size) { void * theAddress; SL_ENTER(_("sh_mem_malloc")); theAddress = calloc(1,size); if ( theAddress != NULL ) { SL_RETURN( theAddress, _("sh_mem_malloc")); } else { (void) safe_logger(0, 0, NULL); /* use _exit() rather than exit() - we malloc() in atexit() */ SH_ABORT; _exit (EXIT_FAILURE); } } #endif samhain-4.1.4/src/sh_dbIO.c0000664000175000017500000012366612615253277012355 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include "samhain.h" #include "sh_utils.h" #include "sh_dbIO_int.h" #include "sh_hash.h" #include "sh_dbIO.h" #include "sh_gpg.h" #include "sh_tiger.h" #include "sh_xfer.h" #include "sh_pthread.h" #include "sh_socket.h" #include "sh_files.h" #undef FIL__ #define FIL__ _("sh_dbIO.c") #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) /* external prototypes */ extern int get_the_fd (SL_TICKET ticket); SH_MUTEX_EXTERN(mutex_hash); /****************************************************************** * * Get a single line * ******************************************************************/ static FILE * sh_fin_fd = NULL; int sh_dbIO_getline (FILE * fd, char * line, const size_t sizeofline) { size_t n = 0; SL_REQUIRE(sizeofline >= SH_MINIBUF, _("sizeofline >= SH_MINIBUF")); if (NULL != fgets(line, sizeofline, fd)) { n = strlen(line); if (n > 0 && line[n-1] == '\n') { n--; line[n] = '\0'; } } else { line[0] = '\0'; return -1; } return n; } /****************************************************************** * * Fast forward to start of data * ******************************************************************/ static void reopen_fin_fd(SL_TICKET fd) { if (sh_fin_fd != NULL) { sl_fclose (FIL__, __LINE__, sh_fin_fd); sh_fin_fd = NULL; } sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb"); return; } static int seek_sof(FILE * fd, char * line, int size, const char * file) { long i; while (1) { i = sh_dbIO_getline (fd, line, size); if (i < 0 ) { SH_FREE(line); dlog(1, FIL__, __LINE__, _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"), (NULL == file) ? _("(null)") : file); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA, ( (NULL == file) ? _("(null)") : file) ); return -1; } #if defined(SH_STEALTH) if (0 == sl_strncmp (line, N_("[SOF]"), 5)) #else if (0 == sl_strncmp (line, _("[SOF]"), 5)) #endif break; } fflush(fd); return 0; } static int sh_dbIO_setdataent (SL_TICKET fd, char * line, int size, const char * file) { int retval; SL_ENTER(_("sh_dbIO_setdataent")); sl_rewind (fd); reopen_fin_fd(fd); if (!sh_fin_fd) { dlog(1, FIL__, __LINE__, _("The file signature database: %s is not readable.\n"), (NULL == file) ? _("(null)") : file); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA, ( (NULL == file) ? _("(null)") : file) ); SL_RETURN( -1, _("sh_dbIO_setdataent")); } retval = seek_sof(sh_fin_fd, line, size, file); SL_RETURN( retval, _("sh_dbIO_setdataent")); } static int sh_dbIO_setdataent_old (SL_TICKET fd, char * line, int size, const char * file) { FILE * fdp; SL_ENTER(_("sh_dbIO_setdataent_old")); sl_rewind (fd); fdp = sl_stream(fd, "r+"); if (0 != seek_sof(fdp, line, size, file)) SL_RETURN( SL_EREAD, _("sh_dbIO_setdataent_old")); lseek(fileno(fdp), ftello(fdp), SEEK_SET); if (0 != ftruncate(fileno(fdp), ftello(fdp))) { char ebuf[SH_ERRBUF_SIZE]; int errnum = errno; sh_error_message(errnum, ebuf, sizeof(ebuf)); sh_error_handle ((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("sh_dbIO_setdataent_old") ); SL_RETURN( SL_EWRITE, _("sh_dbIO_setdataent_old")); } SL_RETURN( 0, _("sh_dbIO_setdataent_old")); } /****************************************************************** * * IO helper functions * ******************************************************************/ static UINT32 * swap_32 (UINT32 * iptr) { #ifdef WORDS_BIGENDIAN unsigned char swap; unsigned char * ii = (unsigned char *) iptr; swap = ii[0]; ii[0] = ii[3]; ii[3] = swap; swap = ii[1]; ii[1] = ii[2]; ii[2] = swap; return iptr; #else return iptr; #endif } static UINT64 * swap_64 (UINT64 * iptr) { #ifdef WORDS_BIGENDIAN #ifdef UINT64_IS_32 swap_32 ((UINT32*) iptr); #else unsigned char swap; unsigned char * ii = (unsigned char *) iptr; swap = ii[0]; ii[0] = ii[7]; ii[7] = swap; swap = ii[1]; ii[1] = ii[6]; ii[6] = swap; swap = ii[2]; ii[2] = ii[5]; ii[5] = swap; swap = ii[3]; ii[3] = ii[4]; ii[4] = swap; #endif return iptr; #else return iptr; #endif } static unsigned short * swap_short (unsigned short * iptr) { #ifdef WORDS_BIGENDIAN if (sizeof(short) == 4) swap_32 ((UINT32*) iptr); else { /* alignment problem */ unsigned char swap; static unsigned short ooop; unsigned char * ii; ooop = *iptr; ii = (unsigned char *) &ooop; swap = ii[0]; ii[0] = ii[1]; ii[1] = swap; return &ooop; } return iptr; #else return iptr; #endif } static void swap_data(sh_filestore_t * ft) { swap_32(&(ft->mode)); swap_32(&(ft->linkmode)); swap_64(&(ft->dev)); swap_64(&(ft->rdev)); swap_32(&(ft->hardlinks)); swap_32(&(ft->ino)); swap_64(&(ft->size)); swap_64(&(ft->atime)); swap_64(&(ft->mtime)); swap_64(&(ft->ctime)); swap_32(&(ft->owner)); swap_32(&(ft->group)); swap_32(&(ft->checkflags)); #if defined(__linux__) || defined(HAVE_STAT_FLAGS) swap_32(&(ft->attributes)); #endif ft->mark = *(swap_short(&(ft->mark))); return; } #define QUOTE_CHAR '=' char * unquote_string (const char * str, size_t len) { int i = 0, t1, t2; char * tmp = NULL; size_t l2, j, k = 0; SL_ENTER(_("unquote_string")); if (str != NULL) { l2 = len - 2; tmp = SH_ALLOC(len + 1); for (j = 0; j <= len; ++j) { if (str[j] != QUOTE_CHAR) { tmp[k] = str[j]; } else if (str[j] == QUOTE_CHAR && j < l2) { t1 = sh_util_hexchar(str[j+1]); t2 = sh_util_hexchar(str[j+2]); if ((t1|t2) >= 0) { i = 16 * t1 + t2; tmp[k] = i; j += 2; } else { tmp[k] = str[j]; } } else tmp[k] = str[j]; ++k; } } SL_RETURN(tmp, _("unquote_string")); } static char * int2hex (unsigned char i, char * i2h) { static char hexchars[] = "0123456789ABCDEF"; i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */ i2h[1] = hexchars[((i) & 0x0F)]; /* low */ return i2h; } char * quote_string (const char * str, size_t len) { char * tmp; char * tmp2; size_t l2, j, i = 0, k = 0; char i2h[2]; SL_ENTER(_("quote_string")); if (str == NULL) { SL_RETURN(NULL, _("quote_string")); } for (j = 0; j < len; ++j) if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i; l2 = len + 1; if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i))) { tmp = SH_ALLOC(len + 1 + 3*i); } else { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("integer overflow"), _("quote_string")); SL_RETURN(NULL, _("quote_string")); } for (j = 0; j <= len; ++j) { if (str[j] == '\n') { tmp2 = int2hex((unsigned char) '\n', i2h); tmp[k] = QUOTE_CHAR; ++k; tmp[k] = tmp2[0]; ++k; tmp[k] = tmp2[1]; } else if (str[j] == QUOTE_CHAR) { tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h); tmp[k] = QUOTE_CHAR; ++k; tmp[k] = tmp2[0]; ++k; tmp[k] = tmp2[1]; } else { tmp[k] = str[j]; } ++k; } SL_RETURN(tmp, _("quote_string")); } static char * unquote_path(char * line, long i) { char * tmp = unquote_string (line, i); size_t len = sl_strlen(tmp)+1; char * path = SH_ALLOC(len); (void) sl_strlcpy (path, tmp, len); if (tmp) SH_FREE(tmp); if (len > 1) { if (path[len-2] == '\n') path[len-2] = '\0'; } return path; } /****************************************************************** * * Read next record and return it * ******************************************************************/ static void corrupt_record(char * file, int line, const char * filepath) { dlog(1, file, line, _("There is a corrupt record in the file signature database: %s\n"), (NULL == filepath)? _("(null)") : filepath); sh_error_handle ((-1), file, line, 0, MSG_E_SUBGPATH, _("Corrupt record in file signature database"), _("sh_dbIO_getdataent"), ( (NULL == filepath) ? _("(null)") : filepath) ); return; } static void wrong_version(char * file, int line, const char * filepath) { dlog(1, file, line, _("There is a record with a bad version number in the file signature database: %s\n"), (NULL == filepath) ? _("(null)") : filepath); sh_error_handle((-1), file, line, 0, MSG_E_SUBGPATH, _("Record with bad version number in file signature database"), _("sh_dbIO_getdataent"), (NULL == filepath) ? _("(null)") : filepath); return; } static void hexdump(unsigned char * data, size_t size) { unsigned int count =0; char ith[3]; do { int2hex(data[count], ith); ith[2] = '\0'; printf("%2s", ith); ++count; if (count % 40 == 0) putc('\n', stdout); } while (count < size); } static size_t dbIO_fread_struct (sh_filestore_t * ptr, FILE *stream, const char * path, int * errflag) { sh_filestore_old_t old_struct; fpos_t position; static int oldflag = -1; start: if (oldflag != -1) /* 'initialized' case first */ { if (oldflag == 0) return fread (ptr, sizeof(sh_filestore_t), 1, stream); else { unsigned short mark; if (1 != fread (&old_struct, sizeof(old_struct), 1, stream)) return 0; /* set mark to current version */ mark = old_struct.mark; mark = *(swap_short(&(mark))); if ((mark & ~REC_FLAGS_MASK) != OLD_REC_MAGIC) { sh_filestore_old_t try_struct; char try[5]; if (1 == 0) hexdump((unsigned char *)&old_struct, sizeof(old_struct)); memset(&try_struct, '\0', sizeof(try_struct)); if (!memcmp(&old_struct, &try_struct, sizeof(try_struct))) return 0; /* NULL read */ if (1 != fread (try, sizeof(try), 1, stream)) return 0; if (feof(stream)) return 0; wrong_version(FIL__, __LINE__, path); *errflag = -1; return 0; } if ((mark & REC_FLAGS_ATTR) != 0) mark = REC_MAGIC|REC_FLAGS_ATTR; else mark = REC_MAGIC; mark = *(swap_short(&(mark))); old_struct.mark = mark; /* copy into current struct version */ memcpy(ptr, &old_struct, sizeof(old_struct)); ptr->checkflags = 0; return 1; } } else /* not initialized yet, test DB version */ { if (0 == fgetpos(stream, &position)) { unsigned short mark; if (1 != fread (&old_struct, sizeof(old_struct), 1, stream)) return 0; mark = old_struct.mark; mark = *(swap_short(&(mark))); if ((mark & ~REC_FLAGS_MASK) == REC_MAGIC) oldflag = 0; else if ((mark & ~REC_FLAGS_MASK) == OLD_REC_MAGIC) oldflag = 1; else { wrong_version(FIL__, __LINE__, path); *errflag = -1; return 0; } /* return to previous position and read data */ if (0 != fsetpos(stream, &position)) return 0; goto start; } return 0; } } int sig_end_detected (void * ft) { char * str = (char *) ft; char cmp[SH_MINIBUF]; sl_strlcpy(cmp, _("-----BEGIN PGP SIGNATURE-----"), sizeof(cmp)); if ( 0 == memcmp(str, cmp, strlen(cmp)) ) return S_TRUE; return S_FALSE; } static sh_file_t * sh_dbIO_getdataent (char * line, int size, const char * filepath, int * errflag) { sh_file_t * p; sh_filestore_t ft; long i; char * fullpath; char * linkpath; char * attr_string = NULL; SL_ENTER(_("sh_dbIO_getdataent")); *errflag = 0; p = SH_ALLOC(sizeof(sh_file_t)); /* Read next record -- Part One */ if (1 != dbIO_fread_struct (&ft, sh_fin_fd, filepath, errflag)) { SH_FREE(p); SL_RETURN( NULL, _("sh_dbIO_getdataent")); } ft.mark = *(swap_short(&(ft.mark))); if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC) { if (sig_end_detected(&ft)) { SH_FREE(p); SL_RETURN( NULL, _("sh_dbIO_getdataent")); } SH_FREE(p); wrong_version(FIL__, __LINE__, filepath); *errflag = -1; SL_RETURN( NULL, _("sh_dbIO_getdataent")); } ft.mark = *(swap_short(&(ft.mark))); swap_data(&ft); /* Read next record -- Part Two -- Fullpath */ i = sh_dbIO_getline (sh_fin_fd, line, size); if (i <= 0 ) { SH_FREE(p); corrupt_record(FIL__, __LINE__, filepath); *errflag = -1; SL_RETURN( NULL, _("sh_dbIO_getdataent")); } fullpath = unquote_path(line, i); /* Read next record -- Part Three -- Linkpath */ i = sh_dbIO_getline (sh_fin_fd, line, size); if (i <= 0 ) { SH_FREE(fullpath); SH_FREE(p); corrupt_record(FIL__, __LINE__, filepath); *errflag = -1; SL_RETURN( NULL, _("sh_dbIO_getdataent")); } linkpath = unquote_path(line, i); /* Read next record -- Part Four -- attr_string */ if ((ft.mark & REC_FLAGS_ATTR) != 0) { i = sh_dbIO_getline (sh_fin_fd, line, size); if (i <= 0 ) { SH_FREE(fullpath); SH_FREE(linkpath); SH_FREE(p); corrupt_record(FIL__, __LINE__, filepath); *errflag = -1; SL_RETURN( NULL, _("sh_dbIO_getdataent")); } attr_string = unquote_path(line, i); } /* Read next record -- Part Four -- Decode */ #if defined(SH_STEALTH) sh_do_decode(fullpath, sl_strlen(fullpath)); #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sh_do_decode(ft.c_attributes, sl_strlen(ft.c_attributes)); #endif sh_do_decode(ft.c_mode, sl_strlen(ft.c_mode)); sh_do_decode(ft.c_owner, sl_strlen(ft.c_owner)); sh_do_decode(ft.c_group, sl_strlen(ft.c_group)); sh_do_decode(ft.checksum, sl_strlen(ft.checksum)); /* * TXT entries are c_mode[0] != 'l' and do not get decoded */ if (ft.c_mode[0] == 'l' && linkpath[0] != '-') { sh_do_decode(linkpath, sl_strlen(linkpath)); } if ((ft.mark & REC_FLAGS_ATTR) != 0) { sh_do_decode(attr_string, sl_strlen(attr_string)); } #endif memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) ); /* init fflags, such that suid files in * database are recognized as such */ { mode_t mode = (mode_t) ft.mode; if (S_ISREG(mode) && (0 !=(S_ISUID & mode) || #if defined(HOST_IS_LINUX) (0 !=(S_ISGID & mode) && 0 !=(S_IXGRP & mode)) #else 0 !=(S_ISGID & mode) #endif ) ) p->fflags = SH_FFLAG_SUIDCHK; else p->fflags = 0; } p->modi_mask = ft.checkflags; if (MODI_ISSET(ft.checkflags, MODI_ALLIGNORE)) SET_SH_FFLAG_ALLIGNORE(p->fflags); p->fullpath = fullpath; p->linkpath = linkpath; p->attr_string = attr_string; /* set to an invalid value */ ft.mark = (REC_MAGIC + 5); SL_REQUIRE((*errflag == 0), _("errflag not set correctly")); SL_RETURN( p, _("sh_dbIO_getdataent")); } /****************************************************************** * * Data loading routines * ******************************************************************/ static SL_TICKET load_data_from_server(const char * uuid) { SL_TICKET fd = -1; #if defined(SH_WITH_CLIENT) char hashbuf[KEYBUF_SIZE]; /* Data file from Server */ if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER"))) return -1; sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART); fd = sh_xfer_request_file((!uuid) ? _("DATA") : uuid); if (SL_ISERROR(fd)) { if (!uuid) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD); dlog(1, FIL__, __LINE__, _("Could not retrieve the file signature database from the server(errnum = %ld).\nPossible reasons include:\n - the server is not running,\n - session key negotiation failed (see the manual for proper setup), or\n - the server cannot access the file.\n"), fd); } else sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_TCP_FBAD); return fd; } sl_rewind (fd); if (!uuid) { sl_strlcpy (sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), KEY_LEN+1); sl_rewind (fd); } #else (void) uuid; #endif return fd; } static SL_TICKET load_data_from_disk(const char * filepath) { char hashbuf[KEYBUF_SIZE]; SL_TICKET fd = -1; /* Local data file */ if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, filepath, SL_YESPRIV)) ) { TPT(( 0, FIL__, __LINE__, _("msg=\n"), filepath)); dlog(1, FIL__, __LINE__, _("Could not open the local file signature database for reading because\nof the following error: %s (errnum = %ld)\nIf this is a permission problem, you need to change file permissions\nto make the file readable for the effective UID: %d\n"), sl_get_errmsg(), fd, (int) sl_ret_euid()); sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, sh.prg_name); return -1; } TPT(( 0, FIL__, __LINE__, _("msg=\n"), filepath)); if (sh.data.hash[0] == '\0') { char hashbuf[KEYBUF_SIZE]; sl_strlcpy(sh.data.hash, sh_tiger_hash (filepath, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } else { if (0 != sl_strncmp(sh.data.hash, sh_tiger_hash (filepath, fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), KEY_LEN) && sh.flag.checkSum != SH_CHECK_INIT) { dlog(1, FIL__, __LINE__, _("The checksum of the file signature database has changed since startup: %s -> %s\n"), sh.data.hash, sh_tiger_hash (filepath, fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf))); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH, ( (NULL == filepath) ? _("(null)") : filepath ) ); } } sl_rewind (fd); return fd; } static SL_TICKET verify_data (SL_TICKET fd) { #if defined(WITH_GPG) || defined(WITH_PGP) SL_TICKET fdTmp; /* extract the data and copy to temporary file */ fdTmp = sh_gpg_extract_signed(fd); if (sig_termfast == 1) /* SIGTERM */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); --sig_raised; --sig_urgent; return -1; } sl_close(fd); fd = fdTmp; /* Validate signature of open file. */ if (0 != sh_gpg_check_sign (fd, SIG_DATA)) { sl_close(fd); return -1; } sl_rewind (fd); #endif return fd; } static int read_data(SL_TICKET fd, sh_file_t * tab[TABSIZE], const char * filepath) { sh_file_t * p; int count = 0; int errflag = 0; char * line = SH_ALLOC(MAX_PATH_STORE+2); /* fast forward to start of data */ if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, filepath)) return -1; while (1) { if (sig_termfast == 1) /* SIGTERM */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); --sig_raised; --sig_urgent; SH_FREE(line); return -1; } p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, filepath, &errflag); if (p != NULL) { if (!sh_hash_is_null_record(&(p->theFile))) hashinsert (tab, p); else sh_hash_remove_unconditional (p->fullpath); ++count; } else break; } if (line != NULL) SH_FREE(line); /* Always keep db in memory, so we have no open file */ sl_close (fd); sl_fclose (FIL__, __LINE__, sh_fin_fd); sh_fin_fd = NULL; return errflag; } static int sh_dbIO_load_db_int(sh_file_t * tab[TABSIZE], const char * filepath, const char * uuid) { #define FGETS_BUF 16384 SL_TICKET fd = -1; if (uuid) { fd = load_data_from_server(uuid); if (SL_ISERROR(fd)) return -1; } else if (!filepath) { char * dbpath = file_path('D', 'R'); fd = load_data_from_server(NULL); if (SL_ISERROR(fd)) { if (*dbpath == '/') fd = load_data_from_disk(dbpath); } } else { fd = load_data_from_disk(filepath); } if (SL_ISERROR(fd)) return -1; if (sig_termfast == 1) /* SIGTERM */ { TPT((0, FIL__, __LINE__, _("msg=\n"))); --sig_raised; --sig_urgent; aud_exit (FIL__, __LINE__, EXIT_SUCCESS); } fd = verify_data(fd); if (SL_ISERROR(fd)) return -1; if (!uuid) { int i; for (i = 0; i < TABSIZE; ++i) tab[i] = NULL; } return read_data (fd, tab, filepath); } int sh_dbIO_load_db(sh_file_t * tab[TABSIZE]) { return sh_dbIO_load_db_int(tab, NULL, NULL); } int sh_dbIO_load_db_file(sh_file_t * tab[TABSIZE], const char * filepath) { return sh_dbIO_load_db_int(tab, filepath, NULL); } int sh_dbIO_load_delta() { int status = 0; #if defined(SH_WITH_CLIENT) sh_file_t ** mtab = get_default_data_table(); int errflag = 0; unsigned int count; time_t last; if ( sh.flag.checkSum != SH_CHECK_INIT ) { if (sh_hash_get_initialized() != 0) { char * uuid = sh_socket_get_uuid(&errflag, &count, &last); if (!uuid) return errflag; if (count > 0) sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, count, MSG_E_SUBGEN, _("Retrying download of delta DB"), _("sh_dbIO_load_delta")); status = sh_dbIO_load_db_int(mtab, NULL, uuid); if (status < 0) { /* Return status < 0 indicates that max_try is exceeded */ if (sh_socket_return_uuid(uuid, count, last) < 0) sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAFAIL, uuid); } else { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAOK, uuid); } SH_FREE(uuid); } else { /* not initialized yet */ sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, -1, MSG_E_SUBGEN, _("Download of delta DB skipped, not initialized yet"), _("sh_dbIO_load_delta")); return -1; } } #endif return status; } /****************************************************************** * * Writing out a file to the database. * ******************************************************************/ static int pushdata_isfirst = 1; static SL_TICKET pushdata_fd = -1; static int pushdata_stdout = S_FALSE; static char * sh_db_version_string = NULL; int sh_dbIO_writeout_stdout (const char * str) { if (!str) { pushdata_stdout = S_TRUE; return 0; } return -1; } int sh_dbIO_version_string(const char * str) { if (str) { if (sh_db_version_string != NULL) { SH_FREE(sh_db_version_string); } if (0 == sl_strncmp(str, _("NULL"), 4)) { sh_db_version_string = NULL; return 0; } sh_db_version_string = sh_util_strdup(str); return 0; } return -1; } void do_writeout_checks(const char * outpath) { if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE)) { dlog(1, FIL__, __LINE__, _("You cannot write the database to stdout when you use update rather than init.\n")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS, _("Writing database to stdout with update"), sh.prg_name, _("sh_dbIO_data_write_int")); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } if ((pushdata_stdout == S_TRUE) && (sl_is_suid())) { dlog(1, FIL__, __LINE__, _("You cannot write the database to stdout when running with suid privileges.\n")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS, _("Writing database to stdout when suid"), sh.prg_name, _("sh_dbIO_data_write_int")); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } if ( (pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) && ( (NULL == outpath) || (0 == sl_strcmp(outpath, _("REQ_FROM_SERVER"))) ) ) { dlog(1, FIL__, __LINE__, _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n")); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS, _("No local path for database specified"), sh.prg_name, _("sh_dbIO_data_write_int")); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE)) { /* Warn that file already exists; file_path != NULL here because * checked above */ struct stat sbuf; if (0 == retry_lstat(FIL__, __LINE__, outpath, &sbuf)) { if (sh.flag.update == S_FALSE) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX, file_path('D', 'W')); } } } return; } static SL_TICKET open_writeout_data_truncate(const char * path) { int status; SL_TICKET fd; if ( SL_ISERROR(fd = sl_open_rdwr_trunc(FIL__, __LINE__, path, SL_YESPRIV))) { sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS, geteuid(), path); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } if (SL_ISERROR(status = sl_lock (fd))) { sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH, _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"), path); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } return fd; } static SL_TICKET open_writeout_data(const char * path) { int status; SL_TICKET fd; if ( SL_ISERROR(fd = sl_open_rdwr(FIL__, __LINE__, path, SL_YESPRIV))) { sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS, geteuid(), path); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } if (SL_ISERROR(status = sl_lock (fd))) { sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH, _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"), path); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } return fd; } static void seek_writeout_data(SL_TICKET fd, const char * path) { int status; if ( SL_ISERROR(status = sl_forward(fd))) { sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH, _("Failed to seek to end of baseline database"), _("seek_writeout_data"), path); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } return; } static int seek_writeout_data_old(SL_TICKET fd, const char * path) { char * line = SH_ALLOC(MAX_PATH_STORE+1); if (SL_ISERROR(sh_dbIO_setdataent_old (fd, line, MAX_PATH_STORE, path))) { SH_FREE(line); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Failed to seek to end of baseline database"), _("seek_writeout_data_old"), path); aud_exit(FIL__, __LINE__, EXIT_FAILURE); } SH_FREE(line); return 0; } char * prep_path(char * path, int flag) { size_t old_len = sl_strlen(path); char * tmp; size_t tmp_len; size_t path_len; char * outpath = NULL; #if !defined(SH_STEALTH) (void) flag; #endif #if defined(SH_STEALTH) if (flag == S_TRUE) sh_do_encode(path, old_len); #endif tmp = quote_string(path, old_len); tmp_len = sl_strlen(tmp); #if defined(SH_STEALTH) if (flag == S_TRUE) sh_do_decode(path, old_len); #endif if (tmp && tmp_len <= MAX_PATH_STORE) { outpath = sh_util_strdup(path); } else { char hashbuf[KEYBUF_SIZE]; outpath = sh_util_strdup(sh_tiger_hash (path, TIGER_DATA, old_len, hashbuf, sizeof(hashbuf))); } if (tmp) SH_FREE(tmp); path_len = sl_strlen(outpath); #if defined(SH_STEALTH) if (flag == S_TRUE) sh_do_encode(outpath, path_len); #endif tmp = quote_string(outpath, path_len); if (tmp) { SH_FREE(outpath); outpath = tmp; } return outpath; } static char * prep_attr(char * attr_str) { char * tmp; char * outstr = NULL; size_t old_len = sl_strlen(attr_str); #if defined(SH_STEALTH) sh_do_encode(attr_str, old_len); #endif tmp = quote_string(attr_str, old_len); if (tmp) { outstr = tmp; } #if defined(SH_STEALTH) sh_do_decode(attr_str, old_len); #endif return outstr; } static void prep_encode(sh_filestore_t * p) { #if defined(SH_STEALTH) sh_do_encode(p->c_mode, sl_strlen(p->c_mode)); sh_do_encode(p->c_owner, sl_strlen(p->c_owner)); sh_do_encode(p->c_group, sl_strlen(p->c_group)); sh_do_encode(p->checksum, sl_strlen(p->checksum)); sh_do_encode(p->c_attributes, sl_strlen(p->c_attributes)); #else (void) p; #endif return; } static void prep_struct(sh_filestore_t * p, file_type * buf, char * fileHash) { #if !defined(__linux__) && !defined(HAVE_STAT_FLAGS) int i; #endif p->mark = REC_MAGIC; sl_strlcpy(p->c_mode, buf->c_mode, CMODE_SIZE); sl_strlcpy(p->c_group, buf->c_group, GROUP_MAX+1); sl_strlcpy(p->c_owner, buf->c_owner, USER_MAX+1); if (fileHash) { sl_strlcpy(p->checksum, fileHash, KEY_LEN+1); } #if defined(__linux__) || defined(HAVE_STAT_FLAGS) sl_strlcpy(p->c_attributes, buf->c_attributes, ATTRBUF_SIZE); #else for (i = 0; i < ATTRBUF_USED; ++i) p->c_attributes[i] = '-'; p->c_attributes[ATTRBUF_USED] = '\0'; #endif prep_encode(p); #if defined(__linux__) || defined(HAVE_STAT_FLAGS) p->attributes = (UINT32) buf->attributes; #else p->attributes = 0; #endif p->linkmode = (UINT32) buf->linkmode; p->hardlinks = (UINT32) buf->hardlinks; p->dev = (UINT64) buf->dev; p->rdev = (UINT64) buf->rdev; p->mode = (UINT32) buf->mode; p->ino = (UINT32) buf->ino; p->size = (UINT64) buf->size; p->mtime = (UINT64) buf->mtime; p->atime = (UINT64) buf->atime; p->ctime = (UINT64) buf->ctime; p->owner = (UINT32) buf->owner; p->group = (UINT32) buf->group; p->checkflags = (UINT32) buf->check_flags; return; } static void write_start_header(SL_TICKET fd) { char timestring[81]; if (pushdata_stdout == S_FALSE) { sl_write (fd, _("\n#Host "), 7); sl_write (fd, sh.host.name, sl_strlen(sh.host.name)); sl_write (fd, _(" Version "), 9); sl_write (fd, sh_db_version_string, sl_strlen(sh_db_version_string)); sl_write (fd, _(" Date "), 6); (void) sh_unix_time(0, timestring, sizeof(timestring)); sl_write (fd, timestring, strlen(timestring)); sl_write (fd, "\n", 1); } else { printf ("%s",_("\n#Host ")); printf ("%s", sh.host.name); printf ("%s",_(" Version ")); printf ("%s", sh_db_version_string); printf ("%s",_(" Date ")); (void) sh_unix_time(0, timestring, sizeof(timestring)); printf ("%s\n", timestring); } } static void write_start_marker(SL_TICKET fd) { if (sh_db_version_string != NULL) { write_start_header(fd); } if (pushdata_stdout == S_FALSE) { #if defined(SH_STEALTH) sl_write (fd, "\n", 1); sl_write_line (fd, N_("[SOF]"), 5); #else sl_write_line (fd, _("\n[SOF]"), 6); #endif } else { #if defined(SH_STEALTH) puts (N_("[SOF]")); #else puts (_("\n[SOF]")); #endif } } static void write_record(SL_TICKET fd, sh_filestore_t * p, char * fullpath, char * linkpath, char * attr_string) { static char ll[2] = { '-', '\0' }; char * lpath; if (!linkpath || 0 == sl_strlen(linkpath)) lpath = ll; else lpath = linkpath; if (pushdata_stdout == S_FALSE) { if (SL_ENONE != sl_write (fd, p, sizeof(sh_filestore_t))) { char * tmp = sh_util_safe_name(fullpath); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Failed to write record to baseline database"), _("write_record"), tmp); SH_FREE(tmp); aud_exit(FIL__, __LINE__, EXIT_FAILURE ); } if (SL_ENONE != sl_write_line_fast (fd, fullpath, sl_strlen(fullpath))) { char * tmp = sh_util_safe_name(fullpath); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Failed to write path to baseline database"), _("write_record"), tmp); SH_FREE(tmp); aud_exit(FIL__, __LINE__, EXIT_FAILURE ); } if (SL_ENONE != sl_write_line_fast (fd, lpath, sl_strlen(lpath))) { char * tmp = sh_util_safe_name(fullpath); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH, _("Failed to write lpath to baseline database"), _("write_record"), tmp); SH_FREE(tmp); aud_exit(FIL__, __LINE__, EXIT_FAILURE ); } if (attr_string) sl_write_line_fast (fd, attr_string, sl_strlen(attr_string)); } else { if (fwrite (p, sizeof(sh_filestore_t), 1, stdout)) { puts (fullpath); puts (lpath); if (attr_string) puts (attr_string); } else { perror(_("Error writing database")); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } } SH_FREE(fullpath); if (linkpath) SH_FREE(linkpath); if (attr_string) SH_FREE(attr_string); return; } static void sh_dbIO_data_write_int (file_type * buf, char * fileHash, const char * outpath, int truncate) { static long p_count = 0; sh_filestore_t p; char * fullpath = NULL; char * linkpath = NULL; char * attr_string = NULL; SL_ENTER(_("sh_dbIO_data_write_int")); do_writeout_checks(outpath); if (sh.flag.update == S_FALSE) { if (pushdata_stdout == S_FALSE && pushdata_fd == -1) { if (truncate == S_TRUE) pushdata_fd = open_writeout_data_truncate(outpath); else { pushdata_fd = open_writeout_data(outpath); seek_writeout_data(pushdata_fd, outpath); } } } else /* update == TRUE */ { if (pushdata_isfirst == 1) { TPT((0, FIL__, __LINE__, _("msg=\n"))); pushdata_fd = open_writeout_data(outpath); seek_writeout_data_old(pushdata_fd, outpath); } } if (!buf) { memset(&p, '\0', sizeof(sh_filestore_t)); } if (buf != NULL) { fullpath = prep_path(buf->fullpath, S_TRUE); } /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded */ if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL) { if (buf->c_mode[0] == 'l') linkpath = prep_path(buf->link_path, S_TRUE); else linkpath = prep_path(buf->link_path, S_FALSE); } if (buf != NULL && buf->attr_string != NULL) { attr_string = prep_attr(buf->attr_string); } if (buf != NULL) { prep_struct(&p, buf, fileHash); if (attr_string) p.mark |= REC_FLAGS_ATTR; swap_data(&p); } /* write the start marker */ if (pushdata_isfirst == 1) { if (sh.flag.update == S_FALSE) write_start_marker(pushdata_fd); pushdata_isfirst = 0; } if (buf && fullpath) { write_record(pushdata_fd, &p, fullpath, linkpath, attr_string); ++p_count; } if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE)) { if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL)) { sl_close (pushdata_fd); pushdata_fd = -1; } } SL_RET0(_("sh_dbIO_data_write_int")); } SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER); void sh_dbIO_data_write (file_type * buf, char * fileHash) { SH_MUTEX_LOCK(mutex_writeout); sh_dbIO_data_write_int (buf, fileHash, file_path('D', 'W'), S_FALSE); SH_MUTEX_UNLOCK(mutex_writeout); return; } static int dbIO_writeout(sh_file_t * mtab[TABSIZE], const char * outpath, int truncate) { sh_file_t * p; int i; file_type * f; char fileHash[KEY_LEN + 1]; SL_ENTER(_("dbIO_writeout")); SH_MUTEX_LOCK(mutex_writeout); if (!SL_ISERROR(pushdata_fd)) { sl_close(pushdata_fd); pushdata_fd = -1; } pushdata_isfirst = 1; SH_MUTEX_LOCK(mutex_hash); for (i = 0; i < TABSIZE; ++i) { for (p = mtab[i]; p; p = p->next) { f = sh_hash_create_ft (p, fileHash); sh_dbIO_data_write_int (f, fileHash, outpath, (i == 0) ? truncate : S_FALSE); if (f->attr_string) SH_FREE(f->attr_string); if (f->link_path) SH_FREE(f->link_path); SH_FREE(f); } } SH_MUTEX_UNLOCK(mutex_hash); if (!SL_ISERROR(pushdata_fd)) { sl_close(pushdata_fd); pushdata_fd = -1; } pushdata_isfirst = 1; SH_MUTEX_UNLOCK(mutex_writeout); SL_RETURN (0, _("dbIO_writeout")); } int sh_dbIO_writeout_update() { sh_file_t ** mtab = get_default_data_table(); if (S_TRUE == file_is_remote()) { sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN, _("Baseline database is remote"), _("sh_dbIO_writeout")); SL_RETURN (1, _("sh_dbIO_writeout_update")); } return dbIO_writeout(mtab, file_path('D', 'W'), S_FALSE); } int sh_dbIO_writeout_to_path(const char * path) { sh_file_t ** mtab = get_default_data_table(); return dbIO_writeout(mtab, path, S_TRUE); } static void dbIO_write_record(sh_file_t * record, SL_TICKET fd) { sh_filestore_t * p = &(record->theFile); char * fullpath = NULL; char * linkpath = NULL; char * attr_string = NULL; fullpath = prep_path(record->fullpath, S_TRUE); /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded */ if (record->linkpath != NULL && 0 != strcmp("-", record->linkpath)) { if (p->c_mode[0] == 'l') linkpath = prep_path(record->linkpath, S_TRUE); else linkpath = prep_path(record->linkpath, S_FALSE); } if (record->attr_string != NULL) attr_string = prep_attr(record->attr_string); prep_encode(p); swap_data(p); write_record(fd, p, fullpath, linkpath, attr_string); return; } static void dbIO_write_entry(sh_file_t * p) { static int is_first = 1; if (is_first) { pushdata_isfirst = 1; if (!sh.outpath || sh.outpath[0] == '\0') pushdata_stdout = S_TRUE; else pushdata_fd = open_writeout_data_truncate(sh.outpath); write_start_marker(pushdata_fd); pushdata_isfirst = 0; is_first = 0; } dbIO_write_record(p, pushdata_fd); } /****************************************************************** * * Listing the database. * ******************************************************************/ static int ListBinary = S_FALSE; static char * ListFilter = NULL; int sh_dbIO_list_binary (const char * c) { (void) c; ListBinary = S_TRUE; return 0; } int sh_dbIO_list_filter (const char * c) { ListFilter = sh_util_strdup(c); return 0; } #include "zAVLTree.h" static zAVLTree * filter_list = NULL; extern char * rtrim (char * str); #include static void read_filter() { int i, n = 0; size_t len; char * key; char * str; char * line = SH_ALLOC(SH_MAXBUF); FILE * fd = fopen(ListFilter, "r"); if (!fd) { perror(_("read_filter: fopen:")); _exit(EXIT_FAILURE); } do { i = sh_dbIO_getline (fd, line, SH_MAXBUF); str = rtrim(line); while (isspace((int)*str)) ++str; key = sh_files_parse_input(str, &len); if (key && *key == '/') { zAVL_string_set(&filter_list, key); ++n; } } while (i >= 0); fclose(fd); SH_FREE(line); if (n == 0) { fprintf(stderr, _("read_filter: empty file <%s>\n"), ListFilter); _exit (EXIT_FAILURE); } return; } static int check_filter(char * path) { if (NULL == zAVL_string_get(filter_list, path)) return S_FALSE; return S_TRUE; } int sh_dbIO_list_db (const char * db_file) { sh_file_t * p; SL_TICKET fd; char * line; int errflag = 0; int flag = 0; char * ListFile = get_list_file(); if (!db_file) { fputs(_("ERROR: no database file given\n"), stderr); _exit(EXIT_FAILURE); return -1; } if (sl_is_suid()) { fputs(_("ERROR: insufficient privilege\n"), stderr); _exit (EXIT_FAILURE); return -1; /* for Mac OSX compiler */ } if (0 == strcmp(db_file, _("default"))) db_file = file_path('D', 'W'); if (!db_file) { fputs(_("ERROR: no filename\n"), stderr); _exit(EXIT_FAILURE); return -1; } if (ListFilter) read_filter(); line = SH_ALLOC(MAX_PATH_STORE+2); if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV))) { fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"), db_file, fd); _exit(EXIT_FAILURE); return -1; } /* fast forward to start of data */ if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, db_file)) { fprintf(stderr, _("ERROR: can't find start marker in %s\n"), db_file); _exit(EXIT_FAILURE); return -1; } while (1) { p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, db_file, &errflag); if ((p != NULL) && (p->fullpath[0] == '/')) { if (!ListFile) { flag = 1; if (ListFilter && S_FALSE == check_filter(p->fullpath)) continue; if (ListBinary) dbIO_write_entry (p); else sh_hash_list_db_entry (p); } else { if (0 != sl_strcmp(ListFile, p->fullpath)) { continue; } flag = 1; if ('l' != p->theFile.c_mode[0]) { if (sh_hash_printcontent(p->linkpath) < 0) { fputs(_("Error listing file content\n"), stderr); _exit(EXIT_FAILURE); return -1; } } else { fputs(_("File is a link\n"), stderr); _exit(EXIT_FAILURE); return -1; } break; } } else if (p == NULL) { break; } } if (line != NULL) SH_FREE(line); sl_close (fd); fflush(NULL); if (flag == 0) { fputs(_("File not found.\n"), stderr); _exit(EXIT_FAILURE); } else if (errflag < 0) { fputs(_("Error while reading file.\n"), stderr); _exit(EXIT_FAILURE); } _exit(EXIT_SUCCESS); return 0; } /* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */ #endif samhain-4.1.4/src/sh_log_check.c0000644000175000017500000010274412615253277013446 00000000000000 #include "config_xor.h" #include #include #include #include #include #include #ifdef HAVE_DIRENT_H #include #define NAMLEN(dirent) sl_strlen((dirent)->d_name) #else #define dirent direct #define NAMLEN(dirent) (dirent)->d_namlen #ifdef HAVE_SYS_NDIR_H #include #endif #ifdef HAVE_SYS_DIR_H #include #endif #ifdef HAVE_NDIR_H #include #endif #endif #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif #ifdef USE_LOGFILE_MONITOR #undef FIL__ #define FIL__ _("sh_log_check.c") /* Debian/Ubuntu: libpcre3-dev */ #ifdef HAVE_PCRE_PCRE_H #include #else #include #endif #include "samhain.h" #include "sh_pthread.h" #include "sh_utils.h" #include "sh_unix.h" #include "sh_string.h" #include "sh_log_check.h" #include "sh_log_evalrule.h" #include "sh_log_correlate.h" #include "sh_log_mark.h" #include "sh_log_repeat.h" #include "sh_extern.h" /* List of supported logfile types, format is * { * "TYPE_CODE", * Reader_Callback_Function, * Parser_Callback_function, * Evaluate_Callback_Function * } * If Reader_Callback_Function is NULL, the default (line-oriented * text file) reader is used. */ struct sh_logfile_type sh_logtypes_def[] = { { "SYSLOG", NULL, sh_parse_syslog, NULL }, { "SAMBA", sh_read_samba, sh_parse_samba, NULL }, { "APACHE", NULL, sh_parse_apache, sh_eval_fileinfo_apache }, #if defined(HAVE_SYS_ACCT_H) { "PACCT", sh_read_pacct, sh_parse_pacct, NULL }, #endif { "SHELL", sh_read_shell, sh_parse_shell, NULL }, }; /* -------------------------- Internal Stuff -------------------------- */ struct logfile_record { dev_t device_id; ino_t inode; fpos_t offset; }; static int do_checkpoint_cleanup = S_FALSE; static char * save_dir = NULL; static const char * get_save_dir(void) { int retval; if (!save_dir) { save_dir = sh_util_strdup(DEFAULT_DATAROOT); SH_MUTEX_LOCK(mutex_thread_nolog); retval = tf_trust_check (save_dir, SL_YESPRIV); SH_MUTEX_UNLOCK(mutex_thread_nolog); if (retval != 0) { return(NULL); } } return save_dir; } static void clean_dir() { DIR * dir; struct dirent * entry; const char * dirpath; if (S_FALSE == do_checkpoint_cleanup) return; dirpath = get_save_dir(); if (dirpath) { dir = opendir(dirpath); if (dir) { unsigned long a, b; int retval; char c; size_t dlen = strlen(dirpath) + 1; time_t now = time(NULL); while (NULL != (entry = readdir(dir))) { retval = sscanf(entry->d_name, "%lu_%lu%c", &a, &b, &c); if (2 == retval) { struct stat buf; char * path; size_t plen = strlen(entry->d_name) + 1; if (S_TRUE == sl_ok_adds(plen, dlen)) { plen += dlen; path = SH_ALLOC(plen); (void) sl_snprintf(path, plen, "%s/%s", dirpath,entry->d_name); if (0 == retry_lstat(FIL__, __LINE__, path, &buf) && S_ISREG(buf.st_mode)) { if (buf.st_mtime < now && (now - buf.st_mtime) > 2592000) /* 30 days */ { if (0 == tf_trust_check (path, SL_YESPRIV)) { unlink(path); } } } } } } closedir(dir); } } } static char * build_path (struct sh_logfile * record) { size_t plen; char * path = NULL; const char * dir = get_save_dir(); if (dir) { plen = strlen(dir); if (S_TRUE == sl_ok_adds(plen, 130)) { plen += 130; /* 64 + 64 + 2 */ path = SH_ALLOC(plen); (void) sl_snprintf(path, plen, "%s/%lu_%lu", dir, (unsigned long) record->device_id, (unsigned long) record->inode); } } return path; } static void save_pos (struct sh_logfile * record) { char * path; FILE * fd; mode_t mask; struct logfile_record save_rec; path = build_path(record); if (path) { if (0 != sh_unix_check_piddir (path)) { SH_FREE(path); return; } mask = umask(S_IWGRP | S_IWOTH); fd = fopen(path, "wb"); (void) umask(mask); if (fd) { save_rec.device_id = record->device_id; save_rec.inode = record->inode; memcpy(&(save_rec.offset), &(record->offset), sizeof(fpos_t)); if (1 != fwrite(&save_rec, sizeof(struct logfile_record), 1, fd)) { (void) sl_fclose(FIL__, __LINE__, fd); (void) remove(path); } else { (void) sl_fclose(FIL__, __LINE__, fd); } } SH_FREE(path); } return; } static int read_pos (struct sh_logfile * record) { int retval = 0; char * path; FILE * fd; struct logfile_record save_rec; path = build_path(record); if (path) { fd = fopen(path, "rb"); if (fd) { if (1 == fread(&save_rec, sizeof(struct logfile_record), 1, fd)) { if (save_rec.device_id == record->device_id && save_rec.inode == record->inode) { memcpy(&(record->offset),&(save_rec.offset),sizeof(fpos_t)); retval = 1; } } (void) sl_fclose(FIL__, __LINE__, fd); } SH_FREE(path); } return retval; } /*@null@*/ static struct sh_logfile * sh_watched_logs = NULL; int sh_add_watch (const char * str) { char * filename; unsigned int i; unsigned int defsize; struct sh_logfile_type * log_type = NULL; struct sh_logfile * thisfile; struct stat buf; unsigned int nfields = 3; /* logtype:path[:regex] */ size_t lengths[3]; char * new = sh_util_strdup(str); char ** splits = split_array(new, &nfields, ':', lengths); if (nfields < 2 || (lengths[0] == 0 || lengths[0] >= SH_MAX_LCODE_SIZE || lengths[1] == 0)) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Format error: ")); sh_string_add_from_char(msg, str); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_add_watch")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(new); return -2; } defsize = (unsigned int) (sizeof(sh_logtypes_def)/sizeof(struct sh_logfile_type)); for (i = 0; i < defsize; ++i) { if (0 == strcmp(splits[0], sh_logtypes_def[i].code)) { log_type = &(sh_logtypes_def[i]); break; } } if (log_type == NULL) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Unsupported log type: ")); sh_string_add_from_char(msg, splits[0]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_add_watch")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(new); return -3; } if (splits[1][0] != '/' && 0 != strcmp(splits[0], _("SHELL"))) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Logfile path not absolute: ")); sh_string_add_from_char(msg, splits[1]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_add_watch")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(new); return -4; } filename = /*@i@*/sh_util_strdup(splits[1]); thisfile = SH_ALLOC(sizeof(struct sh_logfile)); thisfile->filename = filename; if (0 == strcmp(splits[0], _("SHELL"))) thisfile->flags = SH_LOGFILE_NOFILE; else thisfile->flags = SH_LOGFILE_REWIND; thisfile->inode = 0; thisfile->device_id = 0; thisfile->fp = NULL; if (log_type->get_record) thisfile->get_record = log_type->get_record; else thisfile->get_record = sh_default_reader; thisfile->parse_record = log_type->parse_record; /* An optional regex for parsing the file. The result * 'fileinfo' should contain info about host/time position. */ if (log_type->eval_fileinfo) { if (nfields == 3 && lengths[2] > 0) { thisfile->fileinfo = log_type->eval_fileinfo(splits[2]); if (thisfile->fileinfo == NULL) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Logfile format description not recognized: ")); sh_string_add_from_char(msg, splits[2]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_add_watch")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(filename); SH_FREE(thisfile); SH_FREE(new); return -1; } } else { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Logfile format description missing: ")); sh_string_add_from_char(msg, splits[1]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_add_watch")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(filename); SH_FREE(thisfile); SH_FREE(new); return -1; } } else { thisfile->fileinfo = NULL; } thisfile->next = sh_watched_logs; /* Try reading saved offset. On success clear rewind flag. */ if ((thisfile->flags & SH_LOGFILE_NOFILE) == 0) { if (0 == stat(thisfile->filename, &buf)) { if (S_ISREG(buf.st_mode) #ifdef S_ISLNK || S_ISLNK(buf.st_mode) #endif ) { thisfile->inode = buf.st_ino; thisfile->device_id = buf.st_dev; if (0 != read_pos(thisfile)) { thisfile->flags &= ~SH_LOGFILE_REWIND; } } else if (S_ISFIFO(buf.st_mode)) { thisfile->inode = buf.st_ino; thisfile->device_id = buf.st_dev; thisfile->flags |= SH_LOGFILE_PIPE; } } else { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Logfile is not a regular file, link, or named pipe: ")); sh_string_add_from_char(msg, splits[1]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_add_watch")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(filename); SH_FREE(thisfile); SH_FREE(new); return -1; } } sh_watched_logs = thisfile; SH_FREE(new); return 0; } void sh_dump_watches() { struct sh_logfile * thisfile; while (sh_watched_logs) { thisfile = sh_watched_logs; sh_watched_logs = thisfile->next; if ((thisfile->flags & SH_LOGFILE_NOFILE) == 0 && (thisfile->flags & SH_LOGFILE_PIPE) == 0) { save_pos(thisfile); } if ((thisfile->flags & SH_LOGFILE_NOFILE) == 0) { if (thisfile->fp) sl_fclose(FIL__, __LINE__, thisfile->fp); } if (thisfile->filename) SH_FREE(thisfile->filename); SH_FREE(thisfile); } return; } /* This variable is not used anywhere. It only exist * to assign &new to them, which keeps gcc from * putting it into a register, and avoids the 'clobbered * by longjmp' warning. And no, 'volatile' proved insufficient. */ void * sh_dummy_502_thisfile = NULL; void sh_check_watches() { struct sh_logrecord * logrecord; struct sh_logfile * thisfile = sh_watched_logs; sh_string * record = sh_string_new(0); char * tmp; /* Take the address to keep gcc from putting them into registers. * Avoids the 'clobbered by longjmp' warning. */ sh_dummy_502_thisfile = (void*) &thisfile; while (thisfile) { volatile size_t count = 0; SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (thisfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_CHKS, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); for (;;) { record = thisfile->get_record(record, thisfile); if (record) { logrecord = thisfile->parse_record(record, thisfile->fileinfo); ++count; if (logrecord) { logrecord->filename = thisfile->filename; /* Don't report if 'init', just set file pointer */ if (sh.flag.checkSum != SH_CHECK_INIT) { sh_eval_process_msg(logrecord); } if (logrecord->message) sh_string_destroy(&(logrecord->message)); if (logrecord->host) sh_string_destroy(&(logrecord->host)); if (logrecord->timestr) sh_string_destroy(&(logrecord->timestr)); SH_FREE(logrecord); } } else { record = sh_string_new(0); break; } } SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (thisfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_CHKE, tmp, (unsigned long)count); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); thisfile = thisfile->next; } sh_string_destroy(&record); return; } /******************************************************** * Search rotated logfile */ extern char * sh_rotated_log_search(const char * path, struct stat * buf); /* Open file, position at stored offset */ int sh_open_for_reader (struct sh_logfile * logfile) { struct stat buf; sh_string * filename; /* check whether file exists, get inode to check for * logfile rotation */ if (0 != retry_stat(FIL__, __LINE__, logfile->filename, &buf)) { char * tmp; SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (logfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_MISS, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); memset (&(logfile->offset), '\0', sizeof(fpos_t)); logfile->flags |= SH_LOGFILE_REWIND; return 0; } filename = sh_string_new(0); (void) sh_string_set_from_char (filename, logfile->filename); /* detect and handle logfile rotation */ if (logfile->inode != buf.st_ino && logfile->inode != 0 && !S_ISFIFO(buf.st_mode)) { /* Case 1) We have dealt with the moved file already. * Clear the moved flag, set the rewind flag, * fix logfile->inode. */ if ((logfile->flags & SH_LOGFILE_MOVED) != 0) { /* done with rotated file, start with current file */ memset (&(logfile->offset), '\0', sizeof(fpos_t)); logfile->flags |= SH_LOGFILE_REWIND; logfile->flags &= ~SH_LOGFILE_MOVED; logfile->inode = buf.st_ino; logfile->device_id = buf.st_dev; } /* Case 2) Searching for rotated file. * If found: set the moved flag, fix path for fopen. * If not found: set the rewind flag, fix logfile->inode. */ else { char *oldfile = sh_rotated_log_search(logfile->filename, &buf); if (NULL != oldfile) { (void) sh_string_set_from_char (filename, oldfile); SH_FREE(oldfile); logfile->flags |= SH_LOGFILE_MOVED; } else { memset (&(logfile->offset), '\0', sizeof(fpos_t)); logfile->flags |= SH_LOGFILE_REWIND; logfile->inode = buf.st_ino; logfile->device_id = buf.st_dev; } } } /* open file */ if (!S_ISFIFO(buf.st_mode)) { logfile->fp = fopen(filename->str, "r"); } else { int fd_temp = open (filename->str, O_RDONLY|O_NONBLOCK); if (fd_temp >= 0) { logfile->fp = fdopen(fd_temp, "r"); } } if (!logfile->fp) { char * tmp; SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (logfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_EOPEN, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&filename); return 0; } sh_string_destroy(&filename); if ((logfile->flags & SH_LOGFILE_PIPE) == 0) { if ((logfile->flags & SH_LOGFILE_REWIND) != 0) { rewind(logfile->fp); fgetpos(logfile->fp, &(logfile->offset)); logfile->flags &= ~SH_LOGFILE_REWIND; } else { /* file too short */ if (0 != fsetpos(logfile->fp, &(logfile->offset))) { rewind(logfile->fp); fgetpos(logfile->fp, &(logfile->offset)); } } } return 1; } /****************************************************** * Default reader for ascii text files */ sh_string * sh_default_reader (sh_string * s, struct sh_logfile * logfile) { volatile int status; char * tmp; start_read: if (logfile->fp) { /* Result cannot be larger than 8192, thus cast is ok */ status = (int) sh_string_read(s, logfile->fp, 8192); if (status <= 0) { fgetpos(logfile->fp, &(logfile->offset)); sl_fclose(FIL__, __LINE__, logfile->fp); logfile->fp = NULL; sh_string_destroy(&s); if (status == 0 || (logfile->flags & SH_LOGFILE_PIPE) != 0) { return NULL; } SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (logfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_EREAD, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); return NULL; } return s; } if (0 != sh_open_for_reader(logfile)) goto start_read; return NULL; } struct task_entry { sh_tas_t task; struct task_entry * next; }; static struct task_entry * tasklist = NULL; static struct task_entry * task_find(FILE * fp) { struct task_entry * entry = tasklist; while (entry) { if (entry->task.pipe == fp) return (entry); entry = entry->next; } return NULL; } static void task_remove(struct task_entry * task) { struct task_entry * entry = tasklist; struct task_entry * prev = tasklist; while (entry) { if (entry == task) { if (entry == tasklist) { tasklist = entry->next; SH_FREE(entry); return; } else { prev->next = entry->next; SH_FREE(entry); return; } } prev = entry; entry = entry->next; } return; } static void task_add(struct task_entry * entry) { entry->next = tasklist; tasklist = entry; return; } sh_string * sh_command_reader (sh_string * s, struct sh_logfile * logfile) { struct task_entry * entry; volatile int status; char * tmp; start_read: if (logfile->fp) { /* Result cannot be larger than 8192, thus cast is ok */ status = (int) sh_string_read(s, logfile->fp, 8192); if (status <= 0) { entry = task_find(logfile->fp); sh_ext_pclose (&(entry->task)); task_remove(entry); logfile->fp = NULL; sh_string_destroy(&s); if (status == 0) { return NULL; } SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (logfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_EREAD, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); return NULL; } return s; } entry = SH_ALLOC(sizeof(struct task_entry)); status = sh_ext_popen_init (&(entry->task), logfile->filename, logfile->filename, NULL); if (0 == status) { task_add(entry); logfile->fp = entry->task.pipe; goto start_read; } else { SH_FREE(entry); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, _("Could not open pipe"), _("sh_command reader")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } return NULL; } /****************************************************** * Reader for continued text files */ sh_string * sh_cont_reader (sh_string * s, struct sh_logfile * logfile, char*cont) { int status; char * tmp; sh_string * str; int remain = 8192; int count = 0; if (!sh_string_truncate(s, 0)) return NULL; start_read: if (logfile->fp) { str = sh_string_new(0); /* Result cannot be larger than 8192, thus cast is ok */ status = (int) sh_string_read(str, logfile->fp, 8192); if (status > 0) { do { s = sh_string_add (s, str); count += status; remain -= status; if (remain <= 0) { return s; } status = (int) sh_string_read_cont(str, logfile->fp, count, cont); if (status == 0) { return s; } } while (status > 0); } if (status <= 0) { fgetpos(logfile->fp, &(logfile->offset)); sl_fclose(FIL__, __LINE__, logfile->fp); logfile->fp = NULL; sh_string_destroy(&s); if (status == 0 || (logfile->flags & SH_LOGFILE_PIPE) != 0) { return NULL; } SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (logfile->filename); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_EREAD, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); return NULL; } return s; } if (0 != sh_open_for_reader(logfile)) goto start_read; return NULL; } /****************************************************** * Reader for binary files */ sh_string * sh_binary_reader (void * s, size_t size, struct sh_logfile * logfile) { size_t status; start_read: if (logfile->fp) { status = fread(s, size, 1, logfile->fp); if (status != 1) { memset(s, '\0', size); if (ferror(logfile->fp) && (logfile->flags & SH_LOGFILE_PIPE) == 0) { char * tmp; SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name (logfile->filename); sh_error_handle((-1), FIL__, __LINE__, errno, MSG_LOGMON_EREAD, tmp); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); } fgetpos(logfile->fp, &(logfile->offset)); sl_fclose(FIL__, __LINE__, logfile->fp); logfile->fp = NULL; return NULL; } return s; } if (0 != sh_open_for_reader(logfile)) goto start_read; return NULL; } /********************************************************** * * Utilities * **********************************************************/ /* Return current year, unless that would result * in a date far in the future. If that happens, * return last year. */ static int year_guess (struct tm * btime) { int year; struct tm ts; time_t now = time(NULL); time_t check; memcpy(&ts, localtime(&now), sizeof(struct tm)); year = ts.tm_year; /* Check result to detect year wrap * (logfile entry from last year). */ btime->tm_year = year; check = mktime(btime); if (check > (now + (86400*30))) --year; return year; } time_t conv_timestamp (struct tm * btime, struct tm * old_tm, time_t * old_time) { time_t timestamp; long offtime; /* timestamp - mktime is slooow, thus cache result */ if (btime->tm_isdst == old_tm->tm_isdst && btime->tm_year == old_tm->tm_year && btime->tm_mon == old_tm->tm_mon && btime->tm_mday == old_tm->tm_mday) { offtime = (btime->tm_hour - old_tm->tm_hour) * 3600 + (btime->tm_min - old_tm->tm_min) * 60 + (btime->tm_sec - old_tm->tm_sec); *old_time += offtime; memcpy(old_tm, btime, sizeof(struct tm)); timestamp = *old_time; } else { int year_btime = btime->tm_year; if (btime->tm_year == 0) btime->tm_year = year_guess(btime); timestamp = mktime(btime); btime->tm_year = year_btime; *old_time = timestamp; memcpy(old_tm, btime, sizeof(struct tm)); } return timestamp; } /********************************************************* * * MODULE STUFF * *********************************************************/ #include "sh_modules.h" SH_MUTEX_STATIC(mutex_logmon_check, PTHREAD_MUTEX_INITIALIZER); static int ShLogmonActive = S_FALSE; #define SH_LOGMON_INTERVAL 10 static time_t sh_logmon_interval = SH_LOGMON_INTERVAL; int sh_log_check_init (struct mod_type * arg) { #if !defined(HAVE_PTHREAD) (void) arg; #endif if (ShLogmonActive == S_FALSE) return SH_MOD_FAILED; #ifdef HAVE_PTHREAD if (arg != NULL && arg->initval < 0 && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg)) return SH_MOD_THREAD; else return SH_MOD_FAILED; } else if (arg != NULL && arg->initval == SH_MOD_THREAD && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { return SH_MOD_THREAD; } #endif if (sh_watched_logs != NULL) return 0; return -1; } int sh_log_check_timer(time_t tcurrent) { static time_t lastcheck = 0; SL_ENTER(_("sh_log_check_timer")); if ((time_t) (tcurrent - lastcheck) >= sh_logmon_interval) { lastcheck = tcurrent; SL_RETURN((-1), _("sh_log_check_timer")); } SL_RETURN(0, _("sh_log_check_timer")); } int sh_log_check_check(void) { int status = 0; SL_ENTER(_("sh_log_check_check")); SH_MUTEX_LOCK(mutex_logmon_check); status = 0; if( ShLogmonActive != S_FALSE ) { sh_check_watches(); sh_keep_match(); sh_log_mark_check(); clean_dir(); } SH_MUTEX_UNLOCK(mutex_logmon_check); SL_RETURN(status, _("sh_log_check_check")); } int sh_log_check_reconf(void) { int status = 0; SL_ENTER(_("sh_log_check_check")); SH_MUTEX_LOCK(mutex_logmon_check); ShLogmonActive = S_FALSE; sh_logmon_interval = SH_LOGMON_INTERVAL; sh_dump_watches(); sh_eval_cleanup(); SH_MUTEX_UNLOCK(mutex_logmon_check); SL_RETURN(status, _("sh_log_check_check")); } int sh_log_check_cleanup(void) { sh_log_mark_destroy(); return sh_log_check_reconf(); } /********************* OPTIONS **********************/ static int sh_logmon_set_active (const char *str); static int sh_logmon_set_clean (const char *str); static int sh_logmon_set_interval(const char *str); static int sh_logmon_add_watch (const char * str); static int sh_logmon_add_group (const char * str); static int sh_logmon_end_group (const char * str); static int sh_logmon_add_host (const char * str); static int sh_logmon_end_host (const char * str); static int sh_logmon_add_queue (const char * str); static int sh_logmon_add_rule (const char * str); extern int sh_set_hidepid(const char *s); static int sh_logmon_set_save_dir(const char *s); sh_rconf sh_log_check_table[] = { { N_("logmonactive"), sh_logmon_set_active, }, { N_("logmoninterval"), sh_logmon_set_interval, }, { N_("logmonclean"), sh_logmon_set_clean, }, { N_("logmonwatch"), sh_logmon_add_watch, }, { N_("logmonqueue"), sh_logmon_add_queue, }, { N_("logmongroup"), sh_logmon_add_group, }, { N_("logmonendgroup"), sh_logmon_end_group, }, { N_("logmonhost"), sh_logmon_add_host, }, { N_("logmonendhost"), sh_logmon_end_host, }, { N_("logmonrule"), sh_logmon_add_rule, }, { N_("logmonhidepid"), sh_set_hidepid, }, { N_("logmonsavedir"), sh_logmon_set_save_dir, }, { N_("logmonmarkseverity"), sh_log_set_mark_severity, }, { N_("logmonburstthreshold"), sh_repeat_set_trigger, }, { N_("logmonburstqueue"), sh_repeat_set_queue, }, { N_("logmonburstcron"), sh_repeat_set_cron, }, { N_("logmondeadtime"), sh_keep_deadtime, }, { NULL, NULL } }; /* Decide if we're active. */ static int sh_logmon_set_active(const char *str) { int value; SL_ENTER(_("sh_logmon_set_active")); value = sh_util_flagval(str, &ShLogmonActive); SL_RETURN((value), _("sh_logmon_set_active")); } /* Decide if we're active. */ static int sh_logmon_set_clean(const char *str) { int value; SL_ENTER(_("sh_logmon_set_active")); value = sh_util_flagval(str, &do_checkpoint_cleanup); SL_RETURN((value), _("sh_logmon_set_active")); } static int sh_logmon_set_save_dir(const char *str) { int retval = -1; SL_ENTER(_("sh_logmon_set_save_dir")); if (str && str[0] == '/') { if (save_dir) { SH_FREE(save_dir); save_dir = NULL; } save_dir = sh_util_strdup(str); retval = 0; } SL_RETURN((retval), _("sh_logmon_set_save_dir")); } static int sh_logmon_set_interval (const char * c) { int retval = 0; long val; SL_ENTER(_("sh_logmon_set_interval")); val = strtol (c, (char **)NULL, 10); if (val <= 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("log monitoring interval"), c); SH_MUTEX_UNLOCK(mutex_thread_nolog); retval = -1; } else { sh_logmon_interval = (time_t) val; } SL_RETURN(retval, _("sh_logmon_set_interval")); } /* Add a watch on a logfile. * Format: TYPE : Filename [: File_Format] */ static int sh_logmon_add_watch (const char * str) { return sh_add_watch(str); } /* Add a host. * Format: Name_Regex */ static int sh_logmon_add_host (const char * str) { return sh_eval_hadd(str); } /* End a host. * Format: Name */ static int sh_logmon_end_host (const char * str) { (void) str; return sh_eval_hend(NULL); } /* Add a group of rules. * Groups can be under hosts, but not vice versa. * Format: Name : Prefix_Regex */ static int sh_logmon_add_group (const char * str) { return sh_eval_gadd(str); } /* End a group of rules. * Format: Name */ static int sh_logmon_end_group (const char * str) { (void) str; return sh_eval_gend(NULL); } /* Define a reporting queue. * Format: Label : [Interval] : TYPE : Severity[:alias] * TYPE must be 'report' or 'sum' * Interval is ignored for TYPE='report' */ static int sh_logmon_add_queue (const char * str) { return sh_eval_qadd(str); } /* Define a check rule. * Format: [KEEP(seconds,label):]Queue_Label : Regex * KEEP indicates that we keep the label, to perform * correlation matching */ static int sh_logmon_add_rule (const char * str) { return sh_eval_radd(str); } #if 0 /* >>>>>>>>>>> MAIN <<<<<<<<<<<<<<<<<<< */ int main (int argc, char * argv[]) { int status, i; FILE * fp; sh_string * s = NULL; static char template[] = "/tmp/xtest.XXXXXX"; /* pacct */ status = sh_add_watch("PACCT:/var/log/account/pacct"); sh_check_watches(); sh_dump_watches(); exit(0); /* apache log */ sh_eval_gadd("four_o_four:404"); sh_eval_qadd("test:1:sum:7"); sh_eval_radd("test:^(\\d+.\\d+.\\d+.\\d+).*"); sh_eval_gend(NULL); sh_eval_radd("trash:.*"); status = sh_add_watch("APACHE:/var/log/apache2/access.log:combined"); sh_check_watches(); sh_dump_watches(); exit(0); /* logfile */ sh_set_hidepid(1); sh_eval_hadd("hslxmsrv1"); sh_eval_gadd("postfix:postfix"); sh_eval_qadd("test::report:7"); sh_eval_radd("test:postfix/smtpd: disconnect from localhost.*"); sh_eval_radd("trash:postfix/smtpd: disconnect.*"); sh_eval_hadd("hspc05"); sh_eval_gadd("cron:CRON"); sh_eval_qadd("test:1:sum:7"); sh_eval_radd("test:CRON: PAM adding faulty module: (/lib/security/.*.so)"); sh_eval_radd("trash:.*"); status = sh_add_watch("SYSLOG:/var/log/messages"); sh_check_watches(); sh_dump_watches(); exit(0); printf("%d types\n", (int) (sizeof(sh_logtypes_def)/sizeof(struct sh_logfile_type))); /* test sh_add_watch */ status = sh_add_watch(""); printf("%2d: zero length, expect -1\n", status); status = sh_add_watch(NULL); printf("%2d: NULL, expect -2\n", status); status = sh_add_watch("0123456789012345:/var/log/messages"); printf("%2d: long, expect -2\n", status); status = sh_add_watch("012345678901234:/var/log/messages"); printf("%2d: exact length, expect -3\n", status); status = sh_add_watch("01234567890123:56789"); printf("%2d: short length, expect -3\n", status); status = sh_add_watch("SYSLOG:var/log/messages"); printf("%2d: short badpath, expect -4\n", status); status = sh_add_watch("SYSLOG:/var/log/messages"); /* status = sh_add_watch("SYSLOG:/var/log/dpkg.log.1"); */ printf("%2d: short path ok, expect 0\n", status); /* test sh_string_read */ s = sh_string_new(); status = /*@i@*/mkstemp(template); if (status < 0) { fprintf(stderr, "error in mkstemp!\n"); exit(EXIT_FAILURE); } fp = fdopen(status, "r+"); if (!fp) { fprintf(stderr, "error in fdopen!\n"); exit(EXIT_FAILURE); } for (i = 0; i < 80; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 0 */ for (i = 0; i < 118; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 1 */ for (i = 0; i < 119; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 2 */ for (i = 0; i < 120; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 3 */ for (i = 0; i < 121; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 4 */ for (i = 0; i < 238; ++i) { fputc ('a', fp); } fputc ('\n', fp); for (i = 0; i < 239; ++i) { fputc ('a', fp); } fputc ('\n', fp); for (i = 0; i < 240; ++i) { fputc ('a', fp); } fputc ('\n', fp); for (i = 0; i < 241; ++i) { fputc ('a', fp); } fputc ('\n', fp); rewind(fp); for (i = 0; i < 9; ++i) { status = (int) sh_string_read(s, fp, 120); printf("%d: status = %d, len = %d, size = %d\n", i, status, (int)s->len, (int)s->siz); if (status == -2) (void) sh_string_read(s, fp, 240); else printf("%s\n", s->str); } rewind(fp); (void) sh_string_truncate(s, 0); for (i = 0; i < 9; ++i) { status = (int) sh_string_read(s, fp, 240); printf("%d: status = %d, len = %d, size = %d\n", i, status, (int)s->len, (int)s->siz); if (status == -2) (void) sh_string_read(s, fp, 240); else { for (status = 0; status < (int)s->len; ++status) { if (s->str[status] != 'a') { break; } } printf("%d %s\n", status, s->str); } } sl_fclose(FIL__, __LINE__, fp); remove(template); return 0; } #endif /* #ifdef USE_LOGFILE_MONITOR */ #endif samhain-4.1.4/src/sh_schedule.c0000644000175000017500000002347312615253277013325 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2002 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include /* gcc -Wall -O2 -o mysched sh_schedule.c -DTESTONLY */ #ifndef TESTONLY #undef FIL__ #define FIL__ _("sh_schedule.c") #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) #define SCHEDULER_YES #endif #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #include "samhain.h" #include "sh_mem.h" #include "sh_error_min.h" /* TESTONLY */ #else #define SCHEDULER_YES #include #endif #include "sh_schedule.h" #ifdef SCHEDULER_YES /************************************************ * * Scheduler class - private area * ************************************************/ static const int sh_schedule_max[5] = { 59, 23, 31, 12, 7 }; static const int sh_schedule_min[5] = { 0, 0, 0, 0, 0 }; static int test_val (int i, int min, int max, int min_step, time_t * last, time_t now, int nval, int first_flag) { /* don't miss a minute's task * IDEA: set last = now after first check (? seems to work) */ if (i == 0 && max == min && nval > max /* && ( ((now - *last) > min_step) || (*last == (time_t)-1) ) */ ) { if (*last == (time_t)-1) { /* fake execution at nval-max */ *last = now - 60 * (nval-max); return 0; } if ((int)(now - *last) > min_step) return 1; } /* out of range */ if (nval > max || nval < min) return 0; /* first call - invalid last_exec if (*last == (time_t)-1) return 1; */ if (first_flag == 0) return 1; /* before min_step - too early (e.g. same minute) */ if ((int)(now - *last) <= min_step) return 0; return 1; } static int test_sched_int (sh_schedule_t * isched) { time_t now; struct tm * tval; int count, i, nval; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) struct tm time_tm; #endif if (!isched) return 0; now = time(NULL); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) tval = localtime_r(&now, &time_tm); #else tval = localtime(&now); #endif if (!tval) { sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, _("localime() failed"), _("test_sched_int") ); return 0; } count = 0; for (i = 0; i < 5; ++i) { if (i == 0) nval = tval->tm_min; else if (i == 1) nval = tval->tm_hour; else if (i == 2) nval = tval->tm_mday; else if (i == 3) nval = tval->tm_mon; else nval = tval->tm_wday; count += test_val (i, isched->min[i], isched->max[i], isched->min_step, &(isched->last_exec), now, nval, isched->first); } if (count == 5) { isched->first = 1; isched->last_exec = now; return 1; } return 0; } /* test a linked list of schedules */ int test_sched (sh_schedule_t * isched) { sh_schedule_t * intern = isched; int retval = 0; while (intern != NULL) { if (test_sched_int(intern) == 1) retval = 1; intern = intern->next; } return retval; } static char DayNames[7][4] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" }; static char MonNames[12][4] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; static int parse_func (int i, char * p) { int j, k, l; char *tail; errno = 0; j = (int) strtol(p, &tail, 10); if (errno != 0) /* overflow */ return -1; if (j < 0) return -1; if (tail != p) /* numeric */ return j; if (i < 3) /* names not allowed */ return -1; if (i == 3) { for (j = 0; j < 12; ++j) { l = 0; /*@+charint@*//* Incompatible types for == (char, char): ??? */ for (k = 0; k < 3; ++k) if (p[k] != '\0' && tolower((int) p[k]) == MonNames[j][k]) ++l; /*@-charint@*/ if (l == 3) return j; } } if (i == 4) { for (j = 0; j < 7; ++j) { l = 0; /*@+charint@*//* Incompatible types for == (char, char): ??? */ for (k = 0; k < 3; ++k) if (p[k] != '\0' && tolower((int) p[k]) == DayNames[j][k]) ++l; /*@-charint@*/ if (l == 3) return j; } } return -1; } static int parse_token(int i, sh_schedule_t * isched, char * p) { char * q; if ( NULL != (q = strchr(p, ','))) return -1; if (*p == '*') { isched->min[i] = sh_schedule_min[i]; isched->max[i] = sh_schedule_max[i]; } else { isched->min[i] = parse_func(i, p); if (i == 4 && isched->min[i] == 7) isched->min[i] = 0; if (isched->min[i] < sh_schedule_min[i] || isched->min[i] > sh_schedule_max[i]) { return -1; } if ( NULL != (q = strchr(p, '-'))) { ++q; isched->max[i] = parse_func(i, q); if (i == 4 && isched->max[i] == 7) isched->max[i] = 0; if (isched->max[i] < sh_schedule_min[i] || isched->max[i] > sh_schedule_max[i] || isched->max[i] < isched->min[i]) { return -1; } } else isched->max[i] = isched->min[i]; } if ( NULL != (q = strchr(p, '/'))) { ++q; isched->step[i] = atoi(q); if (isched->step[i] < 1 || isched->step[i] > sh_schedule_max[i]) { return -1; } if (i == 4 && isched->step[i] == 7) isched->step[i] = 6; } else { isched->step[i] = 1; } switch (i) { case 0: if (isched->max[i] == isched->min[i]) isched->min_step = 3599; else isched->min_step = (isched->step[i] * 60) - 1; break; case 1: if (isched->max[i] == isched->min[i]) { /* fix for daylight saving time: subtract 3600 sec */ if (isched->min_step == 3599) isched->min_step = 86399 - 3600; } else { if (isched->min_step == 3599) isched->min_step = (isched->step[i] * 3600) - 1; } break; default: break; } return 0; } static int parse_sched (const char * ssched, sh_schedule_t * isched) { char * p; char * copy; int i = 0; size_t len; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) char * saveptr; #endif if (!ssched || !isched) return -1; len = strlen(ssched)+1; #ifdef TESTONLY copy = calloc(1,len); /* testonly code */ #else copy = SH_ALLOC(len); #endif sl_strlcpy(copy, ssched, len); #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) p = strtok_r(copy, " \t", &saveptr); /* parse crontab-style schedule */ #else p = strtok(copy, " \t"); /* parse crontab-style schedule */ #endif if (!p) goto err; if (parse_token(i, isched, p) == -1) goto err; for (i = 1; i < 5; ++i) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) p = strtok_r(NULL, " \t", &saveptr); /* parse crontab-style schedule */ #else p = strtok(NULL, " \t"); /* parse crontab-style schedule */ #endif if (!p) goto err; if (parse_token(i, isched, p) == -1) goto err; } isched->last_exec = (time_t)-1; isched->first = 0; isched->next = NULL; #ifdef TESTONLY free(copy); #else SH_FREE(copy); #endif return 0; err: #ifdef TESTONLY free(copy); #else SH_FREE(copy); #endif return -1; } int create_sched (const char * ssched, sh_schedule_t * isched) { int j; if (!isched || !ssched) return -1; j = parse_sched(ssched, isched); #ifdef TESTONLY if (j == 0) { int i; for (i = 0; i < 5; ++i) printf("%2d MIN %3d MAX %3d STEP %3d\n", i, isched->max[i], isched->min[i], isched->step[i]); printf("MINSTEP %7d\n", isched->min_step); printf("LASTEXEC %7ld\n", (long) isched->last_exec); } #endif return j; } /* #ifdef SCHEDULER_YES */ #endif /************************************************** * * Schedule class - Test driver * **************************************************/ #ifdef TESTONLY int main(int argc, char * argv[]) { sh_schedule_t isched; if (argc < 2) { fprintf(stderr, "Usage: %s 'schedule'\n", argv[0]); exit (1); } if (create_sched(argv[1], &isched) < 0) { fprintf(stderr, "Bad schedule <%s>\n", argv[1]); exit (1); } while (1 == 1) { if (test_sched(&isched)) printf("EXECUTE at: %s", ctime(&(isched.last_exec))); /* TESTONLY */ sleep (1); /* TESTONLY */ } return 0; } #endif samhain-4.1.4/src/sh_pthread.c0000644000175000017500000001712512622127201013136 00000000000000#include "config_xor.h" #include "sh_pthread.h" #ifdef HAVE_PTHREAD #include #include "sh_calls.h" #include "sh_modules.h" extern volatile int sh_thread_pause_flag; SH_MUTEX_INIT(mutex_skey, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_INIT(mutex_resolv, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_INIT(mutex_pwent, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_INIT(mutex_readdir, PTHREAD_MUTEX_INITIALIZER); SH_MUTEX_INIT(mutex_thread_nolog, PTHREAD_MUTEX_INITIALIZER); int sh_pthread_setsigmask(int how, const void *set, void *oldset) { return pthread_sigmask(how, (const sigset_t *)set, (sigset_t *)oldset); } void sh_pthread_mutex_unlock (void *arg) { (void) pthread_mutex_unlock ((pthread_mutex_t *)arg); return; } int sh_pthread_init_threadspecific(void) { int rc = 0; #ifdef SH_STEALTH do { extern int sh_g_thread(void); rc = sh_g_thread(); } while (0); #endif return rc; } /* * ---- Utilities for modules ---- */ /* MODULES: init() * * #ifdef HAVE_PTHREAD * if (arg != NULL) * { * if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg)) * return SH_MOD_THREAD; * else * return SH_MOD_FAILED; * } * #else * return sh_utmp_init_internal(); * #endif * * * sh_threaded_module_run(module_struct) * -- calls internal init, * -- polls timer, * -- runs module check, * -- runs sh_pthread_testcancel() * -- returns (return == exit) */ #define SH_NUM_THREADS 16 static pthread_t threads[SH_NUM_THREADS]; static int ithread[SH_NUM_THREADS]; static pthread_mutex_t create_mutex = PTHREAD_MUTEX_INITIALIZER; int sh_pthread_create(void *(*start_routine)(void*), void *arg) { int rc, nthread = 1; sigset_t signal_set; int retval = 0; pthread_mutex_lock(&create_mutex); /* block all signals */ sigfillset( &signal_set ); #if defined(SCREW_IT_UP) /* * raise(SIGTRAP) sends to same thread, like * pthread_kill(pthread_self(), sig); so we need to unblock the * signal. */ sigdelset( &signal_set, SIGTRAP ); #endif pthread_sigmask( SIG_BLOCK, &signal_set, NULL ); /* find a free slot in threads[] */ while (nthread < SH_NUM_THREADS) { if (ithread[nthread] == 0) break; ++nthread; if (nthread == SH_NUM_THREADS) { retval = -1; goto err_out; } } rc = pthread_create(&threads[nthread], NULL, start_routine, arg); if (rc != 0) { retval = -1; goto err_out; } ithread[nthread] = 1; err_out: pthread_sigmask( SIG_UNBLOCK, &signal_set, NULL ); pthread_mutex_unlock(&create_mutex); return retval; } int sh_pthread_cancel_all() { int i; int ret = 0; SH_MUTEX_LOCK(create_mutex); for (i = 1; i < SH_NUM_THREADS; ++i) { if (ithread[i] != 0) if (0 != pthread_cancel(threads[i])) ithread[i] = 0; } for (i = 1; i < SH_NUM_THREADS; ++i) { if (ithread[i] != 0) pthread_join(threads[i], NULL); ithread[i] = 0; } SH_MUTEX_UNLOCK(create_mutex); return ret; } /* ---- Utility functions for modules ---- */ #undef S_TRUE #define S_TRUE 1 #undef S_FALSE #define S_FALSE 0 void sh_threaded_module_cleanup(void *arg) { sh_mtype * this_module = (sh_mtype *) arg; this_module->mod_cleanup(); this_module->initval = -1; return; } void * sh_threaded_module_run(void *arg) { sh_mtype * this_module = (sh_mtype *) arg; /* First we lock the module. This ensures that it cannot be * run twice. */ pthread_cleanup_push(sh_pthread_mutex_unlock, (void*) &(this_module->mod_mutex)); pthread_mutex_lock(&(this_module->mod_mutex)); if (0 == sh_pthread_init_threadspecific()) { if (0 == this_module->mod_init(NULL)) { pthread_cleanup_push(sh_threaded_module_cleanup, arg); while (1) { if (sh_thread_pause_flag != S_TRUE) { this_module->flags &= ~SH_MODFL_ISPAUSED; if (0 != this_module->mod_timer(time(NULL))) { /* If module has been de-activated on reconfigure, * mod_check() must return non-zero. * The mod_cleanup() routine must then enable the * module to be re-activated eventually. */ if (0 != this_module->mod_check()) break; pthread_testcancel(); } } else { this_module->flags |= SH_MODFL_ISPAUSED; } if (0 == (SH_MODFL_NOTIMER & this_module->flags) || sh_thread_pause_flag == S_TRUE) retry_msleep(1,0); } pthread_cleanup_pop(1); /* notreached,but required */ } } pthread_cleanup_pop(1); return NULL; } /* * ---- Implementation of recursive mutexes from libxml2 ---- */ #if !defined(HAVE_PTHREAD_MUTEX_RECURSIVE) /** * libxml2 threads.c: set of generic threading related routines * * Gary Pennington * daniel@veillard.com * Except where otherwise noted in the source code (e.g. the files hash.c, * list.c and the trio files, which are covered by a similar licence but * with different Copyright notices) all the files are: * * Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is fur- * nished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Daniel Veillard shall not * be used in advertising or otherwise to promote the sale, use or other deal- * ings in this Software without prior written authorization from him. */ /* Modified NewRMutex -> InitRMutex. We use a static structure, rather than * allocating one. Also dropped code for non-POSIX OSes. */ void sh_InitRMutex(struct sh_RMutex * tok) { pthread_mutex_init(&tok->lock, NULL); tok->held = 0; tok->waiters = 0; pthread_cond_init(&tok->cv, NULL); return; } void sh_RMutexLock(struct sh_RMutex * tok) { if (tok == NULL) return; pthread_mutex_lock(&tok->lock); if (tok->held) { if (pthread_equal(tok->tid, pthread_self())) { tok->held++; pthread_mutex_unlock(&tok->lock); return; } else { tok->waiters++; while (tok->held) pthread_cond_wait(&tok->cv, &tok->lock); tok->waiters--; } } tok->tid = pthread_self(); tok->held = 1; pthread_mutex_unlock(&tok->lock); } void sh_RMutexUnlock(void * arg) { struct sh_RMutex * tok = (struct sh_RMutex *) arg; if (tok == NULL) return; pthread_mutex_lock(&tok->lock); tok->held--; if (tok->held == 0) { if (tok->waiters) pthread_cond_signal(&tok->cv); tok->tid = 0; } pthread_mutex_unlock(&tok->lock); } #endif #else #include int sh_pthread_setsigmask(int how, const void *set, void *oldset) { return sigprocmask(how, (const sigset_t *)set, (sigset_t *)oldset); } #endif samhain-4.1.4/src/minilzo.c0000644000175000017500000020016012615253277012506 00000000000000/* minilzo.c -- mini subset of the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer The LZO library 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. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html */ /* * NOTE: * the full LZO package can be found at * http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html */ #define _ANSI_C_SOURCE #define _POSIX_SOURCE #define __LZO_IN_MINILZO #ifdef MINILZO_HAVE_CONFIG_H # include #endif #undef LZO_HAVE_CONFIG_H #include "minilzo.h" #if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1060) # error "version mismatch in miniLZO source files" #endif #ifdef MINILZO_HAVE_CONFIG_H # define LZO_HAVE_CONFIG_H #endif #if !defined(LZO_NO_SYS_TYPES_H) # include #endif #include #ifndef __LZO_CONF_H #define __LZO_CONF_H #if !defined(__LZO_IN_MINILZO) # ifndef __LZOCONF_H # include # endif #endif #if !defined(LZO_HAVE_CONFIG_H) # include # include # if !defined(NO_STDLIB_H) # include # endif # define HAVE_MEMCMP # define HAVE_MEMCPY # define HAVE_MEMMOVE # define HAVE_MEMSET #else # include # if defined(STDC_HEADERS) # include # include # endif # if defined(HAVE_STDDEF_H) # include # endif # if defined(HAVE_MEMORY_H) # include # endif #endif #if defined(__LZO_DOS16) || defined(__LZO_WIN16) # define HAVE_MALLOC_H # define HAVE_HALLOC #endif #undef NDEBUG #if !defined(LZO_DEBUG) # define NDEBUG #endif #if defined(LZO_DEBUG) || !defined(NDEBUG) # if !defined(NO_STDIO_H) # include # endif #endif #include #if defined(__BOUNDS_CHECKING_ON) # include #else # define BOUNDS_CHECKING_OFF_DURING(stmt) stmt # define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) #endif #if !defined(LZO_UNUSED) # define LZO_UNUSED(parm) (parm = parm) #endif #if !defined(__inline__) && !defined(__GNUC__) # if defined(__cplusplus) # define __inline__ inline # else # define __inline__ # endif #endif #if defined(NO_MEMCMP) # undef HAVE_MEMCMP #endif #if !defined(HAVE_MEMCMP) # undef memcmp # define memcmp lzo_memcmp #endif #if !defined(HAVE_MEMCPY) # undef memcpy # define memcpy lzo_memcpy #endif #if !defined(HAVE_MEMMOVE) # undef memmove # define memmove lzo_memmove #endif #if !defined(HAVE_MEMSET) # undef memset # define memset lzo_memset #endif #if 1 # define LZO_BYTE(x) ((unsigned char) (x)) #else # define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) #endif #if 0 # define LZO_USHORT(x) ((unsigned short) (x)) #else # define LZO_USHORT(x) ((unsigned short) ((x) & 0xffff)) #endif #define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) #define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) #define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) #define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) #define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) #define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) #define LZO_SIZE(bits) (1u << (bits)) #define LZO_MASK(bits) (LZO_SIZE(bits) - 1) #define LZO_LSIZE(bits) (1ul << (bits)) #define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) #define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) #define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) #define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) #define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) #if !defined(SIZEOF_UNSIGNED) # if (UINT_MAX == 0xffff) # define SIZEOF_UNSIGNED 2 # elif (UINT_MAX == LZO_0xffffffffL) # define SIZEOF_UNSIGNED 4 # elif (UINT_MAX >= LZO_0xffffffffL) # define SIZEOF_UNSIGNED 8 # else # error SIZEOF_UNSIGNED # endif #endif #if !defined(SIZEOF_UNSIGNED_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define SIZEOF_UNSIGNED_LONG 4 # elif (ULONG_MAX >= LZO_0xffffffffL) # define SIZEOF_UNSIGNED_LONG 8 # else # error SIZEOF_UNSIGNED_LONG # endif #endif #if !defined(SIZEOF_SIZE_T) # define SIZEOF_SIZE_T SIZEOF_UNSIGNED #endif #if !defined(SIZE_T_MAX) # define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) #endif #if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) # if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) # define LZO_UNALIGNED_OK_2 # endif # if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) # define LZO_UNALIGNED_OK_4 # endif #endif #if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) # if !defined(LZO_UNALIGNED_OK) # define LZO_UNALIGNED_OK # endif #endif #if defined(__LZO_NO_UNALIGNED) # undef LZO_UNALIGNED_OK # undef LZO_UNALIGNED_OK_2 # undef LZO_UNALIGNED_OK_4 #endif #if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) # error "LZO_UNALIGNED_OK_2 must not be defined on this system" #endif #if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) # error "LZO_UNALIGNED_OK_4 must not be defined on this system" #endif #if defined(__LZO_NO_ALIGNED) # undef LZO_ALIGNED_OK_4 #endif #if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) # error "LZO_ALIGNED_OK_4 must not be defined on this system" #endif #define LZO_LITTLE_ENDIAN 1234 #define LZO_BIG_ENDIAN 4321 #define LZO_PDP_ENDIAN 3412 #if !defined(LZO_BYTE_ORDER) # if defined(MFX_BYTE_ORDER) # define LZO_BYTE_ORDER MFX_BYTE_ORDER # elif defined(__LZO_i386) # define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN # elif defined(BYTE_ORDER) # define LZO_BYTE_ORDER BYTE_ORDER # elif defined(__BYTE_ORDER) # define LZO_BYTE_ORDER __BYTE_ORDER # endif #endif #if defined(LZO_BYTE_ORDER) # if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) # error "invalid LZO_BYTE_ORDER" # endif #endif #if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) # error "LZO_BYTE_ORDER is not defined" #endif #define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY #if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__BOUNDS_CHECKING_ON) # if defined(__GNUC__) && defined(__i386__) # if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) # define LZO_OPTIMIZE_GNUC_i386 # endif # endif #endif __LZO_EXTERN_C int __lzo_init_done; __LZO_EXTERN_C const lzo_byte __lzo_copyright[]; LZO_EXTERN(const lzo_byte *) lzo_copyright(void); __LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; #define _LZO_STRINGIZE(x) #x #define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) #define _LZO_CONCAT2(a,b) a ## b #define _LZO_CONCAT3(a,b,c) a ## b ## c #define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d #define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) #define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) #define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) #define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) #if 0 #define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) #define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ (*ol = (n)*(s), LZO_E_OK) #define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) #define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ (*ol = (n)*(s), LZO_E_OK) #define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) #define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ (*ol = (n)*(s), LZO_E_OK) #endif #ifndef __LZO_PTR_H #define __LZO_PTR_H #ifdef __cplusplus extern "C" { #endif #if defined(__LZO_DOS16) || defined(__LZO_WIN16) # include # if 1 && defined(__WATCOMC__) # include __LZO_EXTERN_C unsigned char _HShift; # define __LZO_HShift _HShift # elif 1 && defined(_MSC_VER) __LZO_EXTERN_C unsigned short __near _AHSHIFT; # define __LZO_HShift ((unsigned) &_AHSHIFT) # elif defined(__LZO_WIN16) # define __LZO_HShift 3 # else # define __LZO_HShift 12 # endif # if !defined(_FP_SEG) && defined(FP_SEG) # define _FP_SEG FP_SEG # endif # if !defined(_FP_OFF) && defined(FP_OFF) # define _FP_OFF FP_OFF # endif #endif #if (UINT_MAX >= LZO_0xffffffffL) typedef ptrdiff_t lzo_ptrdiff_t; #else typedef long lzo_ptrdiff_t; #endif #if !defined(__LZO_HAVE_PTR_T) # if defined(lzo_ptr_t) # define __LZO_HAVE_PTR_T # endif #endif #if !defined(__LZO_HAVE_PTR_T) # if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) # if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) typedef unsigned long lzo_ptr_t; typedef long lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif # endif #endif #if !defined(__LZO_HAVE_PTR_T) # if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) # if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) typedef unsigned int lzo_ptr_t; typedef int lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif # endif #endif #if !defined(__LZO_HAVE_PTR_T) # if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) # if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) typedef unsigned short lzo_ptr_t; typedef short lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif # endif #endif #if !defined(__LZO_HAVE_PTR_T) # if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) # error "no suitable type for lzo_ptr_t" # else typedef unsigned long lzo_ptr_t; typedef long lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif #endif #if defined(__LZO_DOS16) || defined(__LZO_WIN16) #define PTR(a) ((lzo_bytep) (a)) #define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) #define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) #else #define PTR(a) ((lzo_ptr_t) (a)) #define PTR_LINEAR(a) PTR(a) #define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) #define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) #define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) #define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) #endif #define PTR_LT(a,b) (PTR(a) < PTR(b)) #define PTR_GE(a,b) (PTR(a) >= PTR(b)) #define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) LZO_EXTERN(lzo_ptr_t) __lzo_ptr_linear(const lzo_voidp ptr); typedef union { char a_char; unsigned char a_uchar; short a_short; unsigned short a_ushort; int a_int; unsigned int a_uint; long a_long; unsigned long a_ulong; lzo_int a_lzo_int; lzo_uint a_lzo_uint; lzo_int32 a_lzo_int32; lzo_uint32 a_lzo_uint32; ptrdiff_t a_ptrdiff_t; lzo_ptrdiff_t a_lzo_ptrdiff_t; lzo_ptr_t a_lzo_ptr_t; char * a_charp; lzo_bytep a_lzo_bytep; lzo_bytepp a_lzo_bytepp; } lzo_align_t; #ifdef __cplusplus } #endif #endif #define LZO_DETERMINISTIC #define LZO_DICT_USE_PTR #if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) # undef LZO_DICT_USE_PTR #endif #if defined(LZO_DICT_USE_PTR) # define lzo_dict_t const lzo_bytep # define lzo_dict_p lzo_dict_t __LZO_MMODEL * #else # define lzo_dict_t lzo_uint # define lzo_dict_p lzo_dict_t __LZO_MMODEL * #endif #if !defined(lzo_moff_t) #define lzo_moff_t lzo_uint #endif #endif LZO_PUBLIC(lzo_ptr_t) __lzo_ptr_linear(const lzo_voidp ptr) { lzo_ptr_t p; #if defined(__LZO_DOS16) || defined(__LZO_WIN16) p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); #else p = PTR_LINEAR(ptr); #endif return p; } LZO_PUBLIC(unsigned) __lzo_align_gap(const lzo_voidp ptr, lzo_uint size) { lzo_ptr_t p, s, n; assert(size > 0); p = __lzo_ptr_linear(ptr); s = (lzo_ptr_t) (size - 1); #if 0 assert((size & (size - 1)) == 0); n = ((p + s) & ~s) - p; #else n = (((p + s) / size) * size) - p; #endif assert((long)n >= 0); assert(n <= s); return (unsigned)n; } #ifndef __LZO_UTIL_H #define __LZO_UTIL_H #ifndef __LZO_CONF_H #endif #ifdef __cplusplus extern "C" { #endif #if 1 && defined(HAVE_MEMCPY) #if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) #define MEMCPY8_DS(dest,src,len) \ memcpy(dest,src,len); \ dest += len; \ src += len #endif #endif #if 0 && !defined(MEMCPY8_DS) #define MEMCPY8_DS(dest,src,len) \ { do { \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ len -= 8; \ } while (len > 0); } #endif #if !defined(MEMCPY8_DS) #define MEMCPY8_DS(dest,src,len) \ { register lzo_uint __l = (len) / 8; \ do { \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ *dest++ = *src++; \ } while (--__l > 0); } #endif #define MEMCPY_DS(dest,src,len) \ do *dest++ = *src++; \ while (--len > 0) #define MEMMOVE_DS(dest,src,len) \ do *dest++ = *src++; \ while (--len > 0) #if 0 && defined(LZO_OPTIMIZE_GNUC_i386) #define BZERO8_PTR(s,l,n) \ __asm__ __volatile__( \ "movl %0,%%eax \n" \ "movl %1,%%edi \n" \ "movl %2,%%ecx \n" \ "cld \n" \ "rep \n" \ "stosl %%eax,(%%edi) \n" \ : \ :"g" (0),"g" (s),"g" (n) \ :"eax","edi","ecx", "memory", "cc" \ ) #elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) #if 1 #define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) #else #define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) #endif #else #define BZERO8_PTR(s,l,n) \ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) #endif #if 0 #if defined(__GNUC__) && defined(__i386__) unsigned char lzo_rotr8(unsigned char value, int shift); extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) { unsigned char result; __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" : "=a"(result) : "g"(value), "c"(shift)); return result; } unsigned short lzo_rotr16(unsigned short value, int shift); extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) { unsigned short result; __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" : "=a"(result) : "g"(value), "c"(shift)); return result; } #endif #endif #ifdef __cplusplus } #endif #endif LZO_PUBLIC(lzo_bool) lzo_assert(int expr) { return (expr) ? 1 : 0; } /* If you use the LZO library in a product, you *must* keep this * copyright string in the executable of your product. */ const lzo_byte __lzo_copyright[] = #if !defined(__LZO_IN_MINLZO) LZO_VERSION_STRING; #else "\n\n\n" "LZO real-time data compression library.\n" "Copyright (C) 1996, 1997, 1998, 1999 Markus Franz Xaver Johannes Oberhumer\n" "\n" "http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html\n" "\n" "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" "LZO build date: " __DATE__ " " __TIME__ "\n\n" "LZO special compilation options:\n" #ifdef __cplusplus " __cplusplus\n" #endif #if defined(__PIC__) " __PIC__\n" #elif defined(__pic__) " __pic__\n" #endif #if (UINT_MAX < LZO_0xffffffffL) " 16BIT\n" #endif #if defined(__LZO_STRICT_16BIT) " __LZO_STRICT_16BIT\n" #endif #if (UINT_MAX > LZO_0xffffffffL) " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" #endif #if (ULONG_MAX > LZO_0xffffffffL) " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" #endif #if defined(LZO_BYTE_ORDER) " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" #endif #if defined(LZO_UNALIGNED_OK_2) " LZO_UNALIGNED_OK_2\n" #endif #if defined(LZO_UNALIGNED_OK_4) " LZO_UNALIGNED_OK_4\n" #endif #if defined(LZO_ALIGNED_OK_4) " LZO_ALIGNED_OK_4\n" #endif #if defined(LZO_DICT_USE_PTR) " LZO_DICT_USE_PTR\n" #endif #if defined(__LZO_QUERY_COMPRESS) " __LZO_QUERY_COMPRESS\n" #endif #if defined(__LZO_QUERY_DECOMPRESS) " __LZO_QUERY_DECOMPRESS\n" #endif #if defined(__LZO_IN_MINILZO) " __LZO_IN_MINILZO\n" #endif "\n\n" "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ #if defined(__GNUC__) && defined(__VERSION__) " by gcc " __VERSION__ #elif defined(__BORLANDC__) " by Borland C " _LZO_MEXPAND(__BORLANDC__) #elif defined(_MSC_VER) " by Microsoft C " _LZO_MEXPAND(_MSC_VER) #elif defined(__PUREC__) " by Pure C " _LZO_MEXPAND(__PUREC__) #elif defined(__SC__) " by Symantec C " _LZO_MEXPAND(__SC__) #elif defined(__TURBOC__) " by Turbo C " _LZO_MEXPAND(__TURBOC__) #elif defined(__WATCOMC__) " by Watcom C " _LZO_MEXPAND(__WATCOMC__) #endif " $\n" "$Copyright: LZO (C) 1996, 1997, 1998, 1999 Markus Franz Xaver Johannes Oberhumer $\n"; #endif LZO_PUBLIC(const lzo_byte *) lzo_copyright(void) { return __lzo_copyright; } LZO_PUBLIC(unsigned) lzo_version(void) { return LZO_VERSION; } LZO_PUBLIC(const char *) lzo_version_string(void) { return LZO_VERSION_STRING; } LZO_PUBLIC(const char *) lzo_version_date(void) { return LZO_VERSION_DATE; } LZO_PUBLIC(const lzo_charp) _lzo_version_string(void) { return LZO_VERSION_STRING; } LZO_PUBLIC(const lzo_charp) _lzo_version_date(void) { return LZO_VERSION_DATE; } #define LZO_BASE 65521u #define LZO_NMAX 5552 #define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); #define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); #define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); #define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); LZO_PUBLIC(lzo_uint32) lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) { lzo_uint32 s1 = adler & 0xffff; lzo_uint32 s2 = (adler >> 16) & 0xffff; int k; if (buf == NULL) return 1; while (len > 0) { k = len < LZO_NMAX ? (int) len : LZO_NMAX; len -= k; if (k >= 16) do { LZO_DO16(buf,0); buf += 16; k -= 16; } while (k >= 16); if (k != 0) do { s1 += *buf++; s2 += s1; } while (--k > 0); s1 %= LZO_BASE; s2 %= LZO_BASE; } return (s2 << 16) | s1; } LZO_PUBLIC(int) lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) { #if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) return memcmp(s1,s2,len); #else const lzo_byte *p1 = (const lzo_byte *) s1; const lzo_byte *p2 = (const lzo_byte *) s2; int d; if (len > 0) do { d = *p1 - *p2; if (d != 0) return d; p1++; p2++; } while (--len > 0); return 0; #endif } LZO_PUBLIC(lzo_voidp) lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) { #if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) return memcpy(dest,src,len); #else lzo_byte *p1 = (lzo_byte *) dest; const lzo_byte *p2 = (const lzo_byte *) src; if (len <= 0 || p1 == p2) return dest; do *p1++ = *p2++; while (--len > 0); return dest; #endif } LZO_PUBLIC(lzo_voidp) lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) { #if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) return memmove(dest,src,len); #else lzo_byte *p1 = (lzo_byte *) dest; const lzo_byte *p2 = (const lzo_byte *) src; if (len <= 0 || p1 == p2) return dest; if (p1 < p2) { do *p1++ = *p2++; while (--len > 0); } else { p1 += len; p2 += len; do *--p1 = *--p2; while (--len > 0); } return dest; #endif } LZO_PUBLIC(lzo_voidp) lzo_memset(lzo_voidp s, int c, lzo_uint len) { #if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) return memset(s,c,len); #else lzo_byte *p = (lzo_byte *) s; if (len > 0) do *p++ = LZO_BYTE(c); while (--len > 0); return s; #endif } #include #if 0 # define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) # define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) #else # define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) # define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) #endif static lzo_bool schedule_insns_bug(void); static lzo_bool strength_reduce_bug(int *); #if 0 || defined(LZO_DEBUG) static lzo_bool __lzo_assert_fail(const char *s, unsigned line) { #if defined(__palmos__) printf("LZO assertion failed in line %u: '%s'\n",line,s); #else fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); #endif return 0; } # define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) #else # define __lzo_assert(x) ((x) ? 1 : 0) #endif static lzo_bool basic_integral_check(void) { lzo_bool r = 1; lzo_bool sanity; r &= __lzo_assert(CHAR_BIT == 8); r &= __lzo_assert(sizeof(char) == 1); r &= __lzo_assert(sizeof(short) >= 2); r &= __lzo_assert(sizeof(long) >= 4); r &= __lzo_assert(sizeof(int) >= sizeof(short)); r &= __lzo_assert(sizeof(long) >= sizeof(int)); r &= __lzo_assert(sizeof(lzo_uint32) >= 4); r &= __lzo_assert(sizeof(lzo_uint32) >= sizeof(unsigned)); #if defined(__LZO_STRICT_16BIT) r &= __lzo_assert(sizeof(lzo_uint) == 2); #else r &= __lzo_assert(sizeof(lzo_uint) >= 4); r &= __lzo_assert(sizeof(lzo_uint) >= sizeof(unsigned)); #endif #if defined(SIZEOF_UNSIGNED) r &= __lzo_assert(SIZEOF_UNSIGNED == sizeof(unsigned)); #endif #if defined(SIZEOF_UNSIGNED_LONG) r &= __lzo_assert(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); #endif #if defined(SIZEOF_UNSIGNED_SHORT) r &= __lzo_assert(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); #endif #if !defined(__LZO_IN_MINILZO) #if defined(SIZEOF_SIZE_T) r &= __lzo_assert(SIZEOF_SIZE_T == sizeof(size_t)); #endif #endif sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) && IS_UNSIGNED(unsigned long) && IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long); if (sanity) { r &= __lzo_assert(IS_UNSIGNED(lzo_uint32)); r &= __lzo_assert(IS_UNSIGNED(lzo_uint)); r &= __lzo_assert(IS_SIGNED(lzo_int32)); r &= __lzo_assert(IS_SIGNED(lzo_int)); r &= __lzo_assert(INT_MAX == LZO_STYPE_MAX(sizeof(int))); r &= __lzo_assert(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); r &= __lzo_assert(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); r &= __lzo_assert(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); r &= __lzo_assert(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); r &= __lzo_assert(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); r &= __lzo_assert(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); r &= __lzo_assert(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); #if !defined(__LZO_IN_MINILZO) r &= __lzo_assert(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); #endif } #if 0 r &= __lzo_assert(LZO_BYTE(257) == 1); r &= __lzo_assert(LZO_USHORT(65537L) == 1); #endif return r; } static lzo_bool basic_ptr_check(void) { lzo_bool r = 1; lzo_bool sanity; r &= __lzo_assert(sizeof(char *) >= sizeof(int)); r &= __lzo_assert(sizeof(lzo_byte *) >= sizeof(char *)); r &= __lzo_assert(sizeof(lzo_voidp) == sizeof(lzo_byte *)); r &= __lzo_assert(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); r &= __lzo_assert(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); r &= __lzo_assert(sizeof(lzo_voidp) >= sizeof(lzo_uint)); r &= __lzo_assert(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); r &= __lzo_assert(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); r &= __lzo_assert(sizeof(lzo_ptrdiff_t) >= 4); r &= __lzo_assert(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); #if defined(SIZEOF_CHAR_P) r &= __lzo_assert(SIZEOF_CHAR_P == sizeof(char *)); #endif #if defined(SIZEOF_PTRDIFF_T) r &= __lzo_assert(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); #endif sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) && IS_UNSIGNED(unsigned long) && IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long); if (sanity) { r &= __lzo_assert(IS_UNSIGNED(lzo_ptr_t)); r &= __lzo_assert(IS_UNSIGNED(lzo_moff_t)); r &= __lzo_assert(IS_SIGNED(lzo_ptrdiff_t)); r &= __lzo_assert(IS_SIGNED(lzo_sptr_t)); } return r; } static lzo_bool ptr_check(void) { lzo_bool r = 1; int i; char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_align_t)]; lzo_byte *wrkmem; const lzo_bytepp dict; unsigned char x[4 * sizeof(lzo_align_t)]; long d; lzo_align_t a; for (i = 0; i < (int) sizeof(x); i++) x[i] = LZO_BYTE(i); wrkmem = (lzo_byte *) LZO_PTR_ALIGN_UP(_wrkmem,sizeof(lzo_align_t)); dict = (const lzo_bytepp) wrkmem; d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); r &= __lzo_assert(d >= 0); r &= __lzo_assert(d < (long) sizeof(lzo_align_t)); memset(&a,0xff,sizeof(a)); r &= __lzo_assert(a.a_ushort == USHRT_MAX); r &= __lzo_assert(a.a_uint == UINT_MAX); r &= __lzo_assert(a.a_ulong == ULONG_MAX); r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); if (r == 1) { for (i = 0; i < 8; i++) r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); } memset(&a,0,sizeof(a)); r &= __lzo_assert(a.a_charp == NULL); r &= __lzo_assert(a.a_lzo_bytep == NULL); r &= __lzo_assert(NULL == 0); if (r == 1) { for (i = 0; i < 10; i++) dict[i] = wrkmem; BZERO8_PTR(dict+1,sizeof(dict[0]),8); r &= __lzo_assert(dict[0] == wrkmem); for (i = 1; i < 9; i++) r &= __lzo_assert(dict[i] == NULL); r &= __lzo_assert(dict[9] == wrkmem); } if (r == 1) { unsigned k = 1; const unsigned n = (unsigned) sizeof(lzo_uint32); lzo_byte *p0; lzo_byte *p1; k += __lzo_align_gap(&x[k],n); p0 = (lzo_bytep) &x[k]; #if defined(PTR_LINEAR) r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); #else r &= __lzo_assert(n == 4); r &= __lzo_assert(PTR_ALIGNED_4(p0)); #endif r &= __lzo_assert(k >= 1); p1 = (lzo_bytep) &x[1]; r &= __lzo_assert(PTR_GE(p0,p1)); r &= __lzo_assert(k < 1+n); p1 = (lzo_bytep) &x[1+n]; r &= __lzo_assert(PTR_LT(p0,p1)); if (r == 1) { lzo_uint32 v0 = * (lzo_uint32 *) &x[k]; lzo_uint32 v1 = * (lzo_uint32 *) &x[k+n]; r &= __lzo_assert(v0 > 0); r &= __lzo_assert(v1 > 0); } } return r; } LZO_PUBLIC(int) _lzo_config_check(void) { lzo_bool r = 1; int i; union { lzo_uint32 a; unsigned short b; lzo_uint32 aa[4]; unsigned char x[4*sizeof(lzo_align_t)]; } u; #if 0 r &= __lzo_assert((const void *)&u == (const void *)&u.a); r &= __lzo_assert((const void *)&u == (const void *)&u.b); r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); #endif r &= basic_integral_check(); r &= basic_ptr_check(); if (r != 1) return LZO_E_ERROR; for (i = 0; i < (int) sizeof(u.x); i++) u.x[i] = LZO_BYTE(i); #if 0 r &= __lzo_assert( (int) (unsigned char) ((char) -1) == 255); #endif #if defined(LZO_BYTE_ORDER) if (r == 1) { # if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); unsigned short b = (unsigned short) (u.b & 0xffff); r &= __lzo_assert(a == 0x03020100L); r &= __lzo_assert(b == 0x0100); # elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); unsigned short b = u.b >> (8 * sizeof(u.b) - 16); r &= __lzo_assert(a == 0x00010203L); r &= __lzo_assert(b == 0x0001); # else # error invalid LZO_BYTE_ORDER # endif } #endif #if defined(LZO_UNALIGNED_OK_2) r &= __lzo_assert(sizeof(short) == 2); if (r == 1) { unsigned short b[4]; for (i = 0; i < 4; i++) b[i] = * (const unsigned short *) &u.x[i]; # if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) r &= __lzo_assert(b[0] == 0x0100); r &= __lzo_assert(b[1] == 0x0201); r &= __lzo_assert(b[2] == 0x0302); r &= __lzo_assert(b[3] == 0x0403); # elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) r &= __lzo_assert(b[0] == 0x0001); r &= __lzo_assert(b[1] == 0x0102); r &= __lzo_assert(b[2] == 0x0203); r &= __lzo_assert(b[3] == 0x0304); # endif } #endif #if defined(LZO_UNALIGNED_OK_4) r &= __lzo_assert(sizeof(lzo_uint32) == 4); if (r == 1) { lzo_uint32 a[4]; for (i = 0; i < 4; i++) a[i] = * (const lzo_uint32 *) &u.x[i]; # if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) r &= __lzo_assert(a[0] == 0x03020100L); r &= __lzo_assert(a[1] == 0x04030201L); r &= __lzo_assert(a[2] == 0x05040302L); r &= __lzo_assert(a[3] == 0x06050403L); # elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) r &= __lzo_assert(a[0] == 0x00010203L); r &= __lzo_assert(a[1] == 0x01020304L); r &= __lzo_assert(a[2] == 0x02030405L); r &= __lzo_assert(a[3] == 0x03040506L); # endif } #endif #if defined(LZO_ALIGNED_OK_4) r &= __lzo_assert(sizeof(lzo_uint32) == 4); #endif r &= __lzo_assert(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); #if defined(__LZO_IN_MINLZO) if (r == 1) { lzo_uint32 adler; adler = lzo_adler32(0, NULL, 0); adler = lzo_adler32(adler, lzo_copyright(), 200); r &= __lzo_assert(adler == 0x7ea34377L); } #endif if (r == 1) { r &= __lzo_assert(!schedule_insns_bug()); } if (r == 1) { static int x[3]; static unsigned xn = 3; register unsigned j; for (j = 0; j < xn; j++) x[j] = (int)j - 3; r &= __lzo_assert(!strength_reduce_bug(x)); } if (r == 1) { r &= ptr_check(); } return r == 1 ? LZO_E_OK : LZO_E_ERROR; } static lzo_bool schedule_insns_bug(void) { #if defined(__BOUNDS_CHECKING_ON) || defined(__CHECKER__) return 0; #else const int clone[] = {1, 2, 0}; const int *q; q = clone; return (*q) ? 0 : 1; #endif } static lzo_bool strength_reduce_bug(int *x) { return x[0] != -3 || x[1] != -2 || x[2] != -1; } int __lzo_init_done = 0; LZO_PUBLIC(int) __lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, int s6, int s7, int s8, int s9) { int r; __lzo_init_done = 1; if (v == 0) return LZO_E_ERROR; r = (s1 == -1 || s1 == (int) sizeof(short)) && (s2 == -1 || s2 == (int) sizeof(int)) && (s3 == -1 || s3 == (int) sizeof(long)) && (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && (s7 == -1 || s7 == (int) sizeof(char *)) && (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); if (!r) return LZO_E_ERROR; r = _lzo_config_check(); if (r != LZO_E_OK) return r; return r; } #if !defined(__LZO_IN_MINILZO) LZO_EXTERN(int) __lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); LZO_PUBLIC(int) __lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) { if (v == 0 || v > 0x1010) return LZO_E_ERROR; return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); } #endif #define do_compress _lzo1x_1_do_compress #define LZO_NEED_DICT_H #define D_BITS 14 #define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) #define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) #ifndef __LZO_CONFIG1X_H #define __LZO_CONFIG1X_H #if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) # define LZO1X #endif #if !defined(__LZO_IN_MINILZO) #include #endif #define LZO_EOF_CODE #undef LZO_DETERMINISTIC #define M1_MAX_OFFSET 0x0400 #ifndef M2_MAX_OFFSET #define M2_MAX_OFFSET 0x0800 #endif #define M3_MAX_OFFSET 0x4000 #define M4_MAX_OFFSET 0xbfff #define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) #define M1_MIN_LEN 2 #define M1_MAX_LEN 2 #define M2_MIN_LEN 3 #ifndef M2_MAX_LEN #define M2_MAX_LEN 8 #endif #define M3_MIN_LEN 3 #define M3_MAX_LEN 33 #define M4_MIN_LEN 3 #define M4_MAX_LEN 9 #define M1_MARKER 0 #define M2_MARKER 64 #define M3_MARKER 32 #define M4_MARKER 16 #ifndef MIN_LOOKAHEAD #define MIN_LOOKAHEAD (M2_MAX_LEN + 1) #endif #if defined(LZO_NEED_DICT_H) #ifndef LZO_HASH #define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B #endif #define DL_MIN_LEN M2_MIN_LEN #ifndef __LZO_DICT_H #define __LZO_DICT_H #ifdef __cplusplus extern "C" { #endif #if !defined(D_BITS) && defined(DBITS) # define D_BITS DBITS #endif #if !defined(D_BITS) # error D_BITS is not defined #endif #if (D_BITS < 16) # define D_SIZE LZO_SIZE(D_BITS) # define D_MASK LZO_MASK(D_BITS) #else # define D_SIZE LZO_USIZE(D_BITS) # define D_MASK LZO_UMASK(D_BITS) #endif #define D_HIGH ((D_MASK >> 1) + 1) #if !defined(DD_BITS) # define DD_BITS 0 #endif #define DD_SIZE LZO_SIZE(DD_BITS) #define DD_MASK LZO_MASK(DD_BITS) #if !defined(DL_BITS) # define DL_BITS (D_BITS - DD_BITS) #endif #if (DL_BITS < 16) # define DL_SIZE LZO_SIZE(DL_BITS) # define DL_MASK LZO_MASK(DL_BITS) #else # define DL_SIZE LZO_USIZE(DL_BITS) # define DL_MASK LZO_UMASK(DL_BITS) #endif #if (D_BITS != DL_BITS + DD_BITS) # error D_BITS does not match #endif #if (D_BITS < 8 || D_BITS > 18) # error invalid D_BITS #endif #if (DL_BITS < 8 || DL_BITS > 20) # error invalid DL_BITS #endif #if (DD_BITS < 0 || DD_BITS > 6) # error invalid DD_BITS #endif #if !defined(DL_MIN_LEN) # define DL_MIN_LEN 3 #endif #if !defined(DL_SHIFT) # define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) #endif #define LZO_HASH_GZIP 1 #define LZO_HASH_GZIP_INCREMENTAL 2 #define LZO_HASH_LZO_INCREMENTAL_A 3 #define LZO_HASH_LZO_INCREMENTAL_B 4 #if !defined(LZO_HASH) # error choose a hashing strategy #endif #if (DL_MIN_LEN == 3) # define _DV2_A(p,shift1,shift2) \ (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) # define _DV2_B(p,shift1,shift2) \ (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) # define _DV3_B(p,shift1,shift2,shift3) \ ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) #elif (DL_MIN_LEN == 2) # define _DV2_A(p,shift1,shift2) \ (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) # define _DV2_B(p,shift1,shift2) \ (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) #else # error invalid DL_MIN_LEN #endif #define _DV_A(p,shift) _DV2_A(p,shift,shift) #define _DV_B(p,shift) _DV2_B(p,shift,shift) #define DA2(p,s1,s2) \ (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) #define DS2(p,s1,s2) \ (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) #define DX2(p,s1,s2) \ (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) #define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) #define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) #define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) #define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) #define DM(v) DMS(v,0) #if (LZO_HASH == LZO_HASH_GZIP) # define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) #elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) # define __LZO_HASH_INCREMENTAL # define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) # define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) # define _DINDEX(dv,p) (dv) # define DVAL_LOOKAHEAD DL_MIN_LEN #elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) # define __LZO_HASH_INCREMENTAL # define DVAL_FIRST(dv,p) dv = _DV_A((p),5) # define DVAL_NEXT(dv,p) \ dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) # define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) # define DVAL_LOOKAHEAD DL_MIN_LEN #elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) # define __LZO_HASH_INCREMENTAL # define DVAL_FIRST(dv,p) dv = _DV_B((p),5) # define DVAL_NEXT(dv,p) \ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) # define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) # define DVAL_LOOKAHEAD DL_MIN_LEN #else # error choose a hashing strategy #endif #ifndef DINDEX #define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) #endif #if !defined(DINDEX1) && defined(D_INDEX1) #define DINDEX1 D_INDEX1 #endif #if !defined(DINDEX2) && defined(D_INDEX2) #define DINDEX2 D_INDEX2 #endif #if !defined(__LZO_HASH_INCREMENTAL) # define DVAL_FIRST(dv,p) ((void) 0) # define DVAL_NEXT(dv,p) ((void) 0) # define DVAL_LOOKAHEAD 0 #endif #if !defined(DVAL_ASSERT) #if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) { lzo_uint32 df; DVAL_FIRST(df,(p)); assert(DINDEX(dv,p) == DINDEX(df,p)); } #else # define DVAL_ASSERT(dv,p) ((void) 0) #endif #endif #if defined(LZO_DICT_USE_PTR) # define DENTRY(p,in) (p) # define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] #else # define DENTRY(p,in) ((lzo_uint) ((p)-(in))) # define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] #endif #if (DD_BITS == 0) # define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) # define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) # define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) #else # define UPDATE_D(dict,drun,dv,p,in) \ dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK # define UPDATE_I(dict,drun,index,p,in) \ dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK # define UPDATE_P(ptr,drun,p,in) \ (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK #endif #if defined(LZO_DICT_USE_PTR) #define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ (BOUNDS_CHECKING_OFF_IN_EXPR( \ (PTR_LT(m_pos,in) || \ (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ m_off > max_offset) )) #else #define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_off == 0 || \ ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ (m_pos = (ip) - (m_off), 0) ) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ ((lzo_moff_t) ((ip)-(in)) <= m_off || \ ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ (m_pos = (ip) - (m_off), 0) ) #endif #if defined(LZO_DETERMINISTIC) # define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET #else # define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET #endif #ifdef __cplusplus } #endif #endif #endif #endif #define DO_COMPRESS lzo1x_1_compress static lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, lzo_byte *out, lzo_uint *out_len, lzo_voidp wrkmem ) { #if 0 && defined(__GNUC__) && defined(__i386__) register const lzo_byte *ip __asm__("%esi"); #else register const lzo_byte *ip; #endif lzo_byte *op; const lzo_byte * const in_end = in + in_len; const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; const lzo_byte *ii; lzo_dict_p const dict = (lzo_dict_p) wrkmem; op = out; ip = in; ii = ip; ip += 4; for (;;) { #if 0 && defined(__GNUC__) && defined(__i386__) register const lzo_byte *m_pos __asm__("%edi"); #else register const lzo_byte *m_pos; #endif lzo_moff_t m_off; lzo_uint m_len; lzo_uint dindex; DINDEX1(dindex,ip); GINDEX(m_pos,m_off,dict,dindex,in); if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) goto literal; #if 1 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) goto try_match; DINDEX2(dindex,ip); #endif GINDEX(m_pos,m_off,dict,dindex,in); if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) goto literal; if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) goto try_match; goto literal; try_match: #if 1 && defined(LZO_UNALIGNED_OK_2) if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) #else if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) #endif { } else { if (m_pos[2] == ip[2]) { #if 0 if (m_off <= M2_MAX_OFFSET) goto match; if (lit <= 3) goto match; if (lit == 3) { assert(op - 2 > out); op[-2] |= LZO_BYTE(3); *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; goto code_match; } if (m_pos[3] == ip[3]) #endif goto match; } else { #if 0 #if 0 if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) #else if (m_off <= M1_MAX_OFFSET && lit == 3) #endif { register lzo_uint t; t = lit; assert(op - 2 > out); op[-2] |= LZO_BYTE(t); do *op++ = *ii++; while (--t > 0); assert(ii == ip); m_off -= 1; *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); *op++ = LZO_BYTE(m_off >> 2); ip += 2; goto match_done; } #endif } } literal: UPDATE_I(dict,0,dindex,ip,in); ++ip; if (ip >= ip_end) break; continue; match: UPDATE_I(dict,0,dindex,ip,in); if (ip - ii > 0) { register lzo_uint t = ip - ii; if (t <= 3) { assert(op - 2 > out); op[-2] |= LZO_BYTE(t); } else if (t <= 18) *op++ = LZO_BYTE(t - 3); else { register lzo_uint tt = t - 18; *op++ = 0; while (tt > 255) { tt -= 255; *op++ = 0; } assert(tt > 0); *op++ = LZO_BYTE(tt); } do *op++ = *ii++; while (--t > 0); } assert(ii == ip); ip += 3; if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ #ifdef LZO1Y || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ #endif ) { --ip; m_len = ip - ii; assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); if (m_off <= M2_MAX_OFFSET) { m_off -= 1; #if defined(LZO1X) *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); *op++ = LZO_BYTE(m_off >> 3); #elif defined(LZO1Y) *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); *op++ = LZO_BYTE(m_off >> 2); #endif } else if (m_off <= M3_MAX_OFFSET) { m_off -= 1; *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); goto m3_m4_offset; } else #if defined(LZO1X) { m_off -= 0x4000; assert(m_off > 0); assert(m_off <= 0x7fff); *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2)); goto m3_m4_offset; } #elif defined(LZO1Y) goto m4_match; #endif } else { { const lzo_byte *end = in_end; const lzo_byte *m = m_pos + M2_MAX_LEN + 1; while (ip < end && *m == *ip) m++, ip++; m_len = (ip - ii); } assert(m_len > M2_MAX_LEN); if (m_off <= M3_MAX_OFFSET) { m_off -= 1; if (m_len <= 33) *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); else { m_len -= 33; *op++ = M3_MARKER | 0; goto m3_m4_len; } } else { #if defined(LZO1Y) m4_match: #endif m_off -= 0x4000; assert(m_off > 0); assert(m_off <= 0x7fff); if (m_len <= M4_MAX_LEN) *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2)); else { m_len -= M4_MAX_LEN; *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); m3_m4_len: while (m_len > 255) { m_len -= 255; *op++ = 0; } assert(m_len > 0); *op++ = LZO_BYTE(m_len); } } m3_m4_offset: *op++ = LZO_BYTE((m_off & 63) << 2); *op++ = LZO_BYTE(m_off >> 6); } #if 0 match_done: #endif ii = ip; if (ip >= ip_end) break; } *out_len = op - out; return (lzo_uint) (in_end - ii); } LZO_PUBLIC(int) DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, lzo_byte *out, lzo_uint *out_len, lzo_voidp wrkmem ) { lzo_byte *op = out; lzo_uint t; #if defined(__LZO_QUERY_COMPRESS) if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); #endif if (in_len <= M2_MAX_LEN + 5) t = in_len; else { t = do_compress(in,in_len,op,out_len,wrkmem); op += *out_len; } if (t > 0) { const lzo_byte *ii = in + in_len - t; if (op == out && t <= 238) *op++ = LZO_BYTE(17 + t); else if (t <= 3) op[-2] |= LZO_BYTE(t); else if (t <= 18) *op++ = LZO_BYTE(t - 3); else { lzo_uint tt = t - 18; *op++ = 0; while (tt > 255) { tt -= 255; *op++ = 0; } assert(tt > 0); *op++ = LZO_BYTE(tt); } do *op++ = *ii++; while (--t > 0); } *op++ = M4_MARKER | 1; *op++ = 0; *op++ = 0; *out_len = op - out; return LZO_E_OK; } #undef do_compress #undef DO_COMPRESS #undef LZO_HASH #undef LZO_TEST_DECOMPRESS_OVERRUN #undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT #undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT #undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND #undef DO_DECOMPRESS #define DO_DECOMPRESS lzo1x_decompress #if defined(LZO_TEST_DECOMPRESS_OVERRUN) # if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) # define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 # endif # if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) # define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 # endif # if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) # define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND # endif #endif #undef TEST_IP #undef TEST_OP #undef TEST_LOOKBEHIND #undef NEED_IP #undef NEED_OP #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP #undef HAVE_NEED_OP #undef HAVE_ANY_IP #undef HAVE_ANY_OP #if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) # if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) # define TEST_IP (ip < ip_end) # endif # if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun # endif #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) # if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) # define TEST_OP (op <= op_end) # endif # if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun # endif #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) # define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun #else # define TEST_LOOKBEHIND(m_pos,op) ((void) 0) #endif #if !defined(LZO_EOF_CODE) && !defined(TEST_IP) # define TEST_IP (ip < ip_end) #endif #if defined(TEST_IP) # define HAVE_TEST_IP #else # define TEST_IP 1 #endif #if defined(TEST_OP) # define HAVE_TEST_OP #else # define TEST_OP 1 #endif #if defined(NEED_IP) # define HAVE_NEED_IP #else # define NEED_IP(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP #else # define NEED_OP(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) # define HAVE_ANY_IP #endif #if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) # define HAVE_ANY_OP #endif #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, lzo_byte *out, lzo_uint *out_len, lzo_voidp wrkmem ) #endif { register lzo_byte *op; register const lzo_byte *ip; register lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_byte *dict_end; #else register const lzo_byte *m_pos; #endif const lzo_byte * const ip_end = in + in_len; #if defined(HAVE_ANY_OP) lzo_byte * const op_end = out + *out_len; #endif #if defined(LZO1Z) lzo_uint last_m_off = 0; #endif LZO_UNUSED(wrkmem); #if defined(__LZO_QUERY_DECOMPRESS) if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); #endif #if defined(COPY_DICT) if (dict) { if (dict_len > M4_MAX_OFFSET) { dict += dict_len - M4_MAX_OFFSET; dict_len = M4_MAX_OFFSET; } dict_end = dict + dict_len; } else { dict_len = 0; dict_end = NULL; } #endif *out_len = 0; op = out; ip = in; if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0); NEED_OP(t); NEED_IP(t+1); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } while (TEST_IP && TEST_OP) { t = *ip++; if (t >= 16) goto match; if (t == 0) { NEED_IP(1); while (*ip == 0) { t += 255; ip++; NEED_IP(1); } t += 15 + *ip++; } assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) if (PTR_ALIGNED2_4(op,ip)) { #endif * (lzo_uint32p) op = * (const lzo_uint32p) ip; op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { * (lzo_uint32p) op = * (const lzo_uint32p) ip; op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } #if !defined(LZO_UNALIGNED_OK_4) } else #endif #endif #if !defined(LZO_UNALIGNED_OK_4) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); } #endif first_literal_run: t = *ip++; if (t >= 16) goto match; #if defined(COPY_DICT) #if defined(LZO1Z) m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif NEED_OP(3); t = 3; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; while (TEST_IP && TEST_OP) { match: if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); t = (t >> 5) - 1; #elif defined(LZO1Y) m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); t = (t >> 4) - 3; #elif defined(LZO1Z) m_off = t & 0x1f; if (m_off >= 0x1c) m_off = last_m_off; else { m_off = 1 + (m_off << 6) + (*ip++ >> 2); last_m_off = m_off; } t = (t >> 5) - 1; #endif #else #if defined(LZO1X) m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; #elif defined(LZO1Y) m_pos = op - 1; m_pos -= (t >> 2) & 3; m_pos -= *ip++ << 2; t = (t >> 4) - 3; #elif defined(LZO1Z) { lzo_uint off = t & 0x1f; m_pos = op; if (off >= 0x1c) { assert(last_m_off > 0); m_pos -= last_m_off; } else { off = 1 + (off << 6) + (*ip++ >> 2); m_pos -= off; last_m_off = off; } } t = (t >> 5) - 1; #endif TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); goto copy_match; #endif } else if (t >= 32) { t &= 31; if (t == 0) { NEED_IP(1); while (*ip == 0) { t += 255; ip++; NEED_IP(1); } t += 31 + *ip++; } #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); last_m_off = m_off; #else m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) { lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); m_pos = op - off; last_m_off = off; } #elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) m_pos = op - 1; m_pos -= (* (const lzo_ushortp) ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif ip += 2; } else if (t >= 16) { #if defined(COPY_DICT) m_off = (t & 8) << 11; #else m_pos = op; m_pos -= (t & 8) << 11; #endif t &= 7; if (t == 0) { NEED_IP(1); while (*ip == 0) { t += 255; ip++; NEED_IP(1); } t += 7 + *ip++; } #if defined(COPY_DICT) #if defined(LZO1Z) m_off += (ip[0] << 6) + (ip[1] >> 2); #else m_off += (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_off == 0) goto eof_found; m_off += 0x4000; #if defined(LZO1Z) last_m_off = m_off; #endif #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) m_pos -= (* (const lzo_ushortp) ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_pos == op) goto eof_found; m_pos -= 0x4000; #if defined(LZO1Z) last_m_off = op - m_pos; #endif #endif } else { #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = 1 + (t >> 2) + (*ip++ << 2); #endif NEED_OP(2); t = 2; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = 1 + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; } #if defined(COPY_DICT) NEED_OP(t+3-1); t += 3-1; COPY_DICT(t,m_off) #else TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); #else if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif * (lzo_uint32p) op = * (const lzo_uint32p) m_pos; op += 4; m_pos += 4; t -= 4 - (3 - 1); do { * (lzo_uint32p) op = * (const lzo_uint32p) m_pos; op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else #endif { copy_match: *op++ = *m_pos++; *op++ = *m_pos++; do *op++ = *m_pos++; while (--t > 0); } #endif match_done: #if defined(LZO1Z) t = ip[-1] & 3; #else t = ip[-2] & 3; #endif if (t == 0) break; match_next: assert(t > 0); NEED_OP(t); NEED_IP(t+1); do *op++ = *ip++; while (--t > 0); t = *ip++; } } #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) *out_len = op - out; return LZO_E_EOF_NOT_FOUND; #endif eof_found: assert(t == 1); *out_len = op - out; return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: *out_len = op - out; return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: *out_len = op - out; return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) lookbehind_overrun: *out_len = op - out; return LZO_E_LOOKBEHIND_OVERRUN; #endif } #define LZO_TEST_DECOMPRESS_OVERRUN #undef DO_DECOMPRESS #define DO_DECOMPRESS lzo1x_decompress_safe #if defined(LZO_TEST_DECOMPRESS_OVERRUN) # if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) # define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 # endif # if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) # define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 # endif # if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) # define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND # endif #endif #undef TEST_IP #undef TEST_OP #undef TEST_LOOKBEHIND #undef NEED_IP #undef NEED_OP #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP #undef HAVE_NEED_OP #undef HAVE_ANY_IP #undef HAVE_ANY_OP #if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) # if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) # define TEST_IP (ip < ip_end) # endif # if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) # define NEED_IP(x, y) \ if ( ((y > 0) && (x > (LZO_UINT_MAX - y))) || ((lzo_uint)(ip_end - ip) < (lzo_uint)((x)+(y))) ) goto input_overrun # endif #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) # if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) # define TEST_OP (op <= op_end) # endif # if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) # undef TEST_OP # define NEED_OP(x,y) \ if ( ((y > 0) && (x > (LZO_UINT_MAX - y))) || ((lzo_uint)(op_end - op) < (lzo_uint)((x)+(y))) ) goto output_overrun # endif #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) # define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun #else # define TEST_LOOKBEHIND(m_pos,op) ((void) 0) #endif #if !defined(LZO_EOF_CODE) && !defined(TEST_IP) # define TEST_IP (ip < ip_end) #endif #if defined(TEST_IP) # define HAVE_TEST_IP #else # define TEST_IP 1 #endif #if defined(TEST_OP) # define HAVE_TEST_OP #else # define TEST_OP 1 #endif #if defined(NEED_IP) # define HAVE_NEED_IP #else /* # define NEED_IP(x) ((void) 0) */ #error "no need_ip" #endif #if defined(NEED_OP) # define HAVE_NEED_OP #else /* # define NEED_OP(x) ((void) 0) */ #error "no need_op" #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) # define HAVE_ANY_IP #endif #if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) # define HAVE_ANY_OP #endif #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, lzo_byte *out, lzo_uint *out_len, lzo_voidp wrkmem ) #endif { register lzo_byte *op; register const lzo_byte *ip; register lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_byte *dict_end; #else register const lzo_byte *m_pos; #endif const lzo_byte * const ip_end = in + in_len; #if defined(HAVE_ANY_OP) lzo_byte * const op_end = out + *out_len; #endif #if defined(LZO1Z) lzo_uint last_m_off = 0; #endif LZO_UNUSED(wrkmem); #if defined(__LZO_QUERY_DECOMPRESS) if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); #endif #if defined(COPY_DICT) if (dict) { if (dict_len > M4_MAX_OFFSET) { dict += dict_len - M4_MAX_OFFSET; dict_len = M4_MAX_OFFSET; } dict_end = dict + dict_len; } else { dict_len = 0; dict_end = NULL; } #endif *out_len = 0; op = out; ip = in; if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0); NEED_OP(t, 0); NEED_IP(t, 1); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } while (TEST_IP && TEST_OP) { t = *ip++; if (t >= 16) goto match; if (t == 0) { NEED_IP(1, 0); while (*ip == 0) { t += 255; ip++; NEED_IP(1, 0); } t += 15 + *ip++; } assert(t > 0); NEED_OP(t,3); NEED_IP(t,4); #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) if (PTR_ALIGNED2_4(op,ip)) { #endif * (lzo_uint32p) op = * (const lzo_uint32p) ip; op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { * (lzo_uint32p) op = * (const lzo_uint32p) ip; op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } #if !defined(LZO_UNALIGNED_OK_4) } else #endif #endif #if !defined(LZO_UNALIGNED_OK_4) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); } #endif first_literal_run: t = *ip++; if (t >= 16) goto match; #if defined(COPY_DICT) #if defined(LZO1Z) m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif NEED_OP(3); t = 3; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LOOKBEHIND(m_pos,out); NEED_OP(3,0); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; while (TEST_IP && TEST_OP) { match: if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); t = (t >> 5) - 1; #elif defined(LZO1Y) m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); t = (t >> 4) - 3; #elif defined(LZO1Z) m_off = t & 0x1f; if (m_off >= 0x1c) m_off = last_m_off; else { m_off = 1 + (m_off << 6) + (*ip++ >> 2); last_m_off = m_off; } t = (t >> 5) - 1; #endif #else #if defined(LZO1X) m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; #elif defined(LZO1Y) m_pos = op - 1; m_pos -= (t >> 2) & 3; m_pos -= *ip++ << 2; t = (t >> 4) - 3; #elif defined(LZO1Z) { lzo_uint off = t & 0x1f; m_pos = op; if (off >= 0x1c) { assert(last_m_off > 0); m_pos -= last_m_off; } else { off = 1 + (off << 6) + (*ip++ >> 2); m_pos -= off; last_m_off = off; } } t = (t >> 5) - 1; #endif TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t,(3-1)); goto copy_match; #endif } else if (t >= 32) { t &= 31; if (t == 0) { NEED_IP(1,0); while (*ip == 0) { t += 255; ip++; NEED_IP(1,0); } t += 31 + *ip++; } #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); last_m_off = m_off; #else m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) { lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); m_pos = op - off; last_m_off = off; } #elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) m_pos = op - 1; m_pos -= (* (const lzo_ushortp) ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif ip += 2; } else if (t >= 16) { #if defined(COPY_DICT) m_off = (t & 8) << 11; #else m_pos = op; m_pos -= (t & 8) << 11; #endif t &= 7; if (t == 0) { NEED_IP(1,0); while (*ip == 0) { t += 255; ip++; NEED_IP(1,0); } t += 7 + *ip++; } #if defined(COPY_DICT) #if defined(LZO1Z) m_off += (ip[0] << 6) + (ip[1] >> 2); #else m_off += (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_off == 0) goto eof_found; m_off += 0x4000; #if defined(LZO1Z) last_m_off = m_off; #endif #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) m_pos -= (* (const lzo_ushortp) ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_pos == op) goto eof_found; m_pos -= 0x4000; #if defined(LZO1Z) last_m_off = op - m_pos; #endif #endif } else { #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = 1 + (t >> 2) + (*ip++ << 2); #endif NEED_OP(2,0); t = 2; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = 1 + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LOOKBEHIND(m_pos,out); NEED_OP(2,0); *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; } #if defined(COPY_DICT) NEED_OP(t,(3-1)); t += 3-1; COPY_DICT(t,m_off) #else TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t,(3-1)); #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); #else if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif * (lzo_uint32p) op = * (const lzo_uint32p) m_pos; op += 4; m_pos += 4; t -= 4 - (3 - 1); do { * (lzo_uint32p) op = * (const lzo_uint32p) m_pos; op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else #endif { copy_match: *op++ = *m_pos++; *op++ = *m_pos++; do *op++ = *m_pos++; while (--t > 0); } #endif match_done: #if defined(LZO1Z) t = ip[-1] & 3; #else t = ip[-2] & 3; #endif if (t == 0) break; match_next: assert(t > 0); NEED_OP(t,0); NEED_IP(t,1); do *op++ = *ip++; while (--t > 0); t = *ip++; } } #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) *out_len = op - out; return LZO_E_EOF_NOT_FOUND; #endif eof_found: assert(t == 1); *out_len = op - out; return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: *out_len = op - out; return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: *out_len = op - out; return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) lookbehind_overrun: *out_len = op - out; return LZO_E_LOOKBEHIND_OVERRUN; #endif } /***** End of minilzo.c *****/ samhain-4.1.4/src/sh_filetype.c0000644000175000017500000004376112615253277013354 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2011 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #ifndef NULL #if !defined(__cplusplus) #define NULL ((void*)0) #else #define NULL (0) #endif #endif #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) #include "samhain.h" #include "sh_mem.h" #include "sh_error_min.h" #include "sh_utils.h" #define FIL__ _("sh_filetype.c") #include #include #include /* #define SH_FILE_MAIN 1 */ #ifdef SH_FILE_MAIN #include #define _(a) a #define N_(a) a #define sl_strlcpy strncpy #endif #define SH_FTYPE_MAX 32 /* List of filetype description, in the format: * offset : type(0=text, 1=binary) : length(if binary) : G1 : G2 : G3 : Name : Teststring * * This list is mostly taken from the 'filetype' library by Paul L Daniels. * * Copyright (c) 2003, PLD * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the * following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * * 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. * * * Neither the name of the PLD 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 COPYRIGHT HOLDERS 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 * COPYRIGHT OWNER 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. */ char * sh_ftype_list[] = { N_("6:0:0:IMAGE:COMPRESSED:JPG:JFIF Jpeg:JFIF"), N_("0:0:0:IMAGE:COMPRESSED:PNG:PNG:=89PNG=0d=0a=1a=0a"), N_("0:0:0:IMAGE:COMPRESSED:JPG:JFIF Jpeg:=FF=D8=FF"), N_("0:0:0:IMAGE:COMPRESSED:GIF:GIF:GIF97a"), N_("0:0:0:IMAGE:COMPRESSED:GIF:GIF:GIF89a"), N_("0:0:0:IMAGE:COMPRESSED:GIF:GIF:GIF87a"), N_("0:1:4:IMAGE:COMPRESSED:TIFF:TIFF-LE:II=2A=00"), N_("0:1:4:IMAGE:COMPRESSED:TIFF:TIFF-BE:MM=00=2A"), N_("0:1:2:IMAGE:COMPRESSED:PCX:PCX25:=0A=00"), N_("0:1:2:IMAGE:COMPRESSED:PCX:PCX28WP:=0A=02"), N_("0:1:2:IMAGE:COMPRESSED:PCX:PCX28NP:=0A=03"), N_("0:1:2:IMAGE:COMPRESSED:PCX:PCX30:=0A=05"), N_("0:0:0:IMAGE:RAW:BMP:Bitmap:BM"), N_("0:0:0:IMAGE:RAW:XPM:XPM:/* XPM */"), N_("0:0:0:IMAGE:SPECIAL:AUTOCAD:DWT:AC=31=30=31"), N_("0:0:0:IMAGE:SPECIAL:AUTOCAD:DWF:(DWF V"), N_("0:0:0:IMAGE:SPECIAL:AUTOCAD:WMF:=D7=CD=C6=9A"), N_("0:0:0:IMAGE:SPECIAL:AUTOCAD:DWG:AC10"), N_("8:0:0:IMAGE:SPECIAL:COREL:CorelDraw:CDR"), N_("0:0:0:IMAGE:SPECIAL:FITS:Fits file:SIMPLE=20=20="), N_("1536:0:0:IMAGE:SPECIAL:VISIO:VisioDraw:Visio"), N_("128:0:0:IMAGE:SPECIAL:DICM:DICOM medical:DICM"), N_("0:0:0:IMAGE:SPECIAL:PHS:Photoshop:8BPS"), N_("0:0:0:IMAGE:SPECIAL:XCF:Gimp XCF:gimp xcf"), N_("0:0:0:MOVIE:COMPRESSED:RIFF:RIFF/AVI Movie:RIFF"), N_("0:0:0:MOVIE:RAW:MOV:SGI Movie:MOVI:.mov SGI Movie"), N_("0:1:4:MOVIE:COMPRESSED:MPG:Mpeg 2:=00=00=01=BA"), N_("0:1:4:MOVIE:COMPRESSED:MPG:Mpeg 2:=00=00=01=B3"), N_("4:0:0:MOVIE:COMPRESSED:QT:QuickTime:moov"), N_("4:0:0:MOVIE:COMPRESSED:QT:QuickTime:mdat"), N_("36:0:0:MOVIE:COMPRESSED:QT:QuickTime:moov"), N_("36:0:0:MOVIE:COMPRESSED:QT:QuickTime:mdat"), N_("68:0:0:MOVIE:COMPRESSED:QT:QuickTime:moov"), N_("68:0:0:MOVIE:COMPRESSED:QT:QuickTime:mdat"), N_("0:1:3:MOVIE:COMPRESSED:FLI:FLIC animation:=00=11=AF"), N_("0:0:0:MOVIE:COMPRESSED:FLASH:Flash data:FWS"), N_("0:0:0:MOVIE:COMPRESSED:FLASH:Flash data:CWS"), N_("0:0:0:MOVIE:COMPRESSED:FLASH:Flash video:FLV"), N_("0:0:0:MOVIE:COMPRESSED:WMV:WMV:=30=26=B2=75=8E=66=CF"), N_("0:0:0:AUDIO:RAW:SND:Sun Audio:.snd"), N_("0:0:0:AUDIO:RAW:EMOD:EMOD:Mod"), N_("1080:0:0:AUDIO:RAW:MOD:SoundTracker (.M.K):.M.K"), N_("1080:0:0:AUDIO:RAW:MOD:SoundTracker (M.K.):M.K."), N_("1080:0:0:AUDIO:RAW:MOD:NoiseTracker:N.T."), N_("1080:0:0:AUDIO:RAW:MOD:SoundTracker (M!K!):M!K!"), N_("1080:0:0:AUDIO:RAW:MOD:SoundTracker (M&K!):M&K!"), N_("8:0:0:AUDIO:RAW:WAVE:Wave:WAVE"), N_("0:1:4:AUDIO:RAW:DEC:DEC-Audio:=00=64=73=2E"), N_("0:0:0:AUDIO:STANDARD:MIDI:Midi:MThd"), N_("0:0:0:AUDIO:COMPRESSED:REAL:RealMedia:.RMF"), N_("0:0:0:AUDIO:COMPRESSED:OGG:Ogg Vorbis:OggS"), N_("0:0:0:AUDIO:COMPRESSED:FLAC:Flac:fLaC"), N_("0:1:5:AUDIO:COMPRESSED:MP3:MP3 Audio:=49=44=33=02=00"), N_("0:1:5:AUDIO:COMPRESSED:MP3:MP3 Audio:=49=44=33=03=00"), N_("0:1:5:AUDIO:COMPRESSED:MP3:MP3 Audio:=49=44=33=04=00"), N_("0:1:2:AUDIO:COMPRESSED:MP3:MP3 Audio:=ff=fb"), N_("0:1:2:AUDIO:COMPRESSED:MP3:MP3 Audio:=ff=fa"), N_("2:0:0:ARCHIVE:COMPRESSED:LHA:Lha 0:-lh0-"), N_("2:0:0:ARCHIVE:COMPRESSED:LHA:Lha 1:-lh1-"), N_("2:0:0:ARCHIVE:COMPRESSED:LHA:Lha 4:-lz4-"), N_("2:0:0:ARCHIVE:COMPRESSED:LHA:Lha z5:-lz5-"), N_("2:0:0:ARCHIVE:COMPRESSED:LHA:Lha 5:-lh5-"), N_("0:0:0:ARCHIVE:COMPRESSED:RAR:RarArchive:Rar!"), N_("0:0:0:ARCHIVE:COMPRESSED:ZIP:PkZip:PK=03=04"), N_("0:0:0:ARCHIVE:COMPRESSED:7Z:7-Zip:=37=7A=BC=AF=27=1C"), N_("0:0:0:ARCHIVE:COMPRESSED:COMPRESS:Compress:=1F=89"), N_("0:0:0:ARCHIVE:COMPRESSED:GZIP:Gzip:=1F=8B"), N_("0:0:0:ARCHIVE:COMPRESSED:BZIP2:Bzip2:BZh"), N_("0:0:0:ARCHIVE:COMPRESSED:ARJ:ARJ:=60=ea"), N_("0:0:0:ARCHIVE:COMPRESSED:ARJ:ARJ:=ea=60"), N_("0:0:0:ARCHIVE:COMPRESSED:HPAK:HPack:HPAK"), N_("0:0:0:ARCHIVE:COMPRESSED:JAM:Jam:=E9,=01JAM"), N_("0:0:0:ARCHIVE:COMPRESSED:SQUISH:Squish:SQSH"), N_("0:1:8:ARCHIVE:COMPRESSED:CAB:MS Cabinet:MSCF=00=00=00=00"), N_("20:0:0:ARCHIVE:COMPRESSED:ZOO:Zoo:=FD=C4=A7=DC"), N_("0:0:0:ARCHIVE:COMPRESSED:XPK:Amiga XPK Archive:XPKF"), N_("0:0:0:ARCHIVE:PACKAGE:RPM:RPM:=ED=AB=EE=DB"), N_("0:0:0:ARCHIVE:PACKAGE:DEB:DEB:!=0A""debian"), N_("0:0:0:ARCHIVE:UNIX:AR:AR:!"), N_("0:0:0:ARCHIVE:UNIX:AR:AR:"), N_("257:1:8:ARCHIVE:UNIX:TAR:TAR:ustar=20=20=00"), N_("257:1:6:ARCHIVE:UNIX:TAR:TAR:ustar=00"), N_("0:0:0:LIBRARY:JAVA:CLASS:Java:=CA=FE=BA=BE"), N_("2108:0:0:DOCUMENT:OFFICE:WORD:Word v5:MSWordDoc"), N_("2112:0:0:DOCUMENT:OFFICE:WORD:Word v5:MSWordDoc"), N_("2080:0:0:DOCUMENT:OFFICE:EXCEL:Excel v4:Microsoft Excel"), N_("2080:0:0:DOCUMENT:OFFICE:WORD:MS Word:Microsoft Word"), N_("0:0:0:DOCUMENT:OFFICE:WORD:Word:=94=A6=2E"), N_("512:1:19:DOCUMENT:OFFICE:WORD:Word:R=00o=00o=00t=00 =00""E=00n=00t=00r=00y"), N_("0:1:9:DOCUMENT:OFFICE:ALL:MSOffice:=D0=CF=11=E0=A1=B1=1A=E1=00"), N_("0:0:0:DOCUMENT:ADOBE:PDF:PortableDocument:%PDF-"), N_("0:0:0:DOCUMENT:ADOBE:EPS:EncapsulatedPS:%!PS-ADOBE EPS"), N_("0:0:0:DOCUMENT:STANDARD:RTF:RichText:{\\rtf"), N_("6:1:4:DOCUMENT:STANDARD:RTF:RichText Compressed:=00=00LZ"), N_("6:0:0:DOCUMENT:ID:VCARD:VCARD:vcard"), N_("0:0:0:EXECUTABLE:DOS:EXE:DosExe:MZ"), N_("0:0:0:EXECUTABLE:DOS:EXE:DosExe:LZ"), N_("0:0:0:EXECUTABLE:DOS:COM:DosCom 1:=E9"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Bourne:#!/bin/sh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Bourne:#! /bin/sh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Bourne:#!/bin/bash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Bourne:#! /bin/bash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Bourne:#!/usr/bin/bash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Bourne:#! /usr/bin/bash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Csh:#!/usr/bin/csh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Csh:#! /usr/bin/csh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Csh:#!/bin/csh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Csh:#! /bin/csh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Korn:#! /usr/bin/ksh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Korn:#!/usr/bin/ksh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Korn:#! /bin/ksh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Korn:#!/bin/ksh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Tenex:#!/usr/bin/tcsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Tenex:#! /usr/bin/tcsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Tenex:#!/bin/tcsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Tenex:#! /bin/tcsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Zsh:#!/usr/bin/zsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Zsh:#! /usr/bin/zsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Zsh:#!/bin/zsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Zsh:#! /bin/zsh"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:ash:#!/usr/bin/ash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:ash:#! /usr/bin/ash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:ash:#!/bin/ash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:ash:#! /bin/ash"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#!/usr/bin/nawk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#! /usr/bin/nawk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#!/bin/nawk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#! /bin/nawk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#!/bin/gawk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#! /bin/gawk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#!/bin/awk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:awk:#! /bin/awk"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:perl:#!/usr/bin/perl"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:perl:#! /usr/bin/perl"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:perl:#!/bin/perl"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:perl:#! /bin/perl"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Shell script:#!/"), N_("0:0:0:EXECUTABLE:UNIX:SHELL:Shell script:#! /"), N_("0:0:0:EXECUTABLE:UNIX:ELF:Linux ELF32:=7f""ELF=01"), N_("0:0:0:EXECUTABLE:UNIX:ELF:Linux ELF:=7f""ELF=02"), N_("0:0:0:EXECUTABLE:DOS:COM:DosCom 2:=8c"), N_("0:0:0:EXECUTABLE:DOS:COM:DosCom 3:=eb"), N_("0:0:0:EXECUTABLE:DOS:COM:DosCom 4:=b8"), N_("0:1:4:EXECUTABLE:AMIGAOS:EXECUTABLE:AmigaOS Executable:=00=00=03=F3"), N_("0:1:20:DATABASE:ANY:ACCESS:MSAccess:=00=01=00=00Standard=20Jet=20""DB=00"), N_("0:1:2:DATABASE:ANY:MYSQL:MySQL database:=fe=01"), N_("0:1:4:DATABASE:ANY:MYSQL:MySQL database:=fe=fe=03=00"), N_("0:1:4:DATABASE:ANY:MYSQL:MySQL database:=fe=fe=07=00"), N_("0:1:4:DATABASE:ANY:MYSQL:MySQL database:=fe=fe=05=00"), N_("0:1:4:DATABASE:ANY:MYSQL:MySQL database:=fe=fe=06=00"), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static unsigned int sh_ftype_def = 0; #define SH_FTYPE_ADD 16 struct sh_ftype_rec { size_t offset; size_t length; char pattern[SH_FTYPE_MAX]; char type[SH_FTYPE_MAX]; }; struct sh_ftype_rec ** sh_ftype_arr = NULL; static unsigned int sh_ftype_nn = 0; #if !defined(SH_FILE_MAIN) static unsigned int sh_ftype_usr = 0; extern char * unquote_string (const char * str, size_t len); int sh_restrict_add_ftype(const char * str) { size_t len; char * cond; if (sh_ftype_def == 0) { while(sh_ftype_list[sh_ftype_def] != NULL) ++sh_ftype_def; } if (!str) { if (sh_ftype_usr > 0) { unsigned int i, j = sh_ftype_def; for (i = 0; i < sh_ftype_usr; ++i) { SH_FREE(sh_ftype_list[j+i]); sh_ftype_list[j+i] = NULL; } sh_ftype_usr = 0; } if (sh_ftype_arr) { unsigned int i = 0; while(sh_ftype_arr[i] != NULL) { SH_FREE(sh_ftype_arr[i]); ++i; } SH_FREE(sh_ftype_arr); sh_ftype_arr = NULL; } } else if (sh_ftype_usr < SH_FTYPE_ADD) { len = strlen(str); cond = unquote_string(str, len); sh_ftype_list[sh_ftype_def+sh_ftype_usr] = cond; ++sh_ftype_usr; } else { return -1; } return 0; } #endif static int init_record(unsigned int n, char * define, struct sh_ftype_rec * record) { unsigned int offset, dtype, length, i = 0, xn = 0; char type[SH_FTYPE_MAX]; char pattern[SH_FTYPE_MAX]; char * end; char * start; offset = strtoul(define, &end, 0); if (*end != ':') return -1; start = end; ++start; dtype = strtoul(start, &end, 0); if (*end != ':') return -1; start = end; ++start; length = strtoul(start, &end, 0); if (*end != ':') return -1; start = end; ++start; while (*start && (i < sizeof(type))) { type[i] = *start; ++start; if (type[i] == ':') ++xn; if (xn == 3) { type[i] = '\0'; break; } ++i; } if (xn != 3) return -1; start = strchr(start, ':'); if (!start) return -1; ++start; if (dtype == 0) { sl_strlcpy(pattern, start, sizeof(pattern)); length = strlen(pattern); } else if (length <= sizeof(pattern)) { memcpy(pattern, start, length); } else { return -1; } for (i = 0; i < n; ++i) { if (sh_ftype_arr[i]->length <= length && sh_ftype_arr[i]->offset == offset) { if (0 == memcmp(sh_ftype_arr[i]->pattern, pattern, sh_ftype_arr[i]->length)) { #ifdef SH_FILE_MAIN fprintf(stderr, "Pattern %d (%s / %s) override by earlier pattern %d (%s / %s)\n", n, type, pattern, i, sh_ftype_arr[i]->type, sh_ftype_arr[i]->pattern); #else char errbuf[256]; sl_snprintf(errbuf, sizeof(errbuf), _("Pattern %d (%s) override by earlier pattern %d (%s)"), n, type, i, sh_ftype_arr[i]->type); sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, errbuf, _("init_record")); #endif } } } record->offset = offset; record->length = length; memcpy(record->pattern, pattern, length); sl_strlcpy(record->type, type, SH_FTYPE_MAX); return 0; } static void file_arr_init() { unsigned int i, nn = 0; if (sh_ftype_def == 0) { while(sh_ftype_list[sh_ftype_def] != NULL) ++sh_ftype_def; } while (sh_ftype_list[nn] != NULL) ++nn; #ifdef SH_FILE_MAIN printf("%d definitions found, defined = %d\n", nn, sh_ftype_def); #endif #ifdef SH_FILE_MAIN sh_ftype_arr = calloc((nn+1), sizeof(struct sh_ftype_rec *)); #else sh_ftype_arr = SH_ALLOC((nn+1) * sizeof(struct sh_ftype_rec *)); #endif for(i = 0; i < nn; i++) { #ifdef SH_FILE_MAIN sh_ftype_arr[i] = calloc(1, sizeof(struct sh_ftype_rec)); #else sh_ftype_arr[i] = SH_ALLOC(sizeof(struct sh_ftype_rec)); #endif memset(sh_ftype_arr[i], 0, sizeof(struct sh_ftype_rec)); if (i < sh_ftype_def) { char * p = _(sh_ftype_list[i]); size_t len = strlen(p); char * cond = unquote_string(p, len); init_record(i, cond, sh_ftype_arr[i]); } else { init_record(i, sh_ftype_list[i], sh_ftype_arr[i]); } } sh_ftype_arr[nn] = NULL; sh_ftype_nn = nn; return; } static char * check_filetype(char * filetype, const char * buffer, size_t buflen) { unsigned int i; const char * p; if (!sh_ftype_arr) { file_arr_init(); } for (i = 0; i < sh_ftype_nn; ++i) { if (sh_ftype_arr[i]->length > 0 && (sh_ftype_arr[i]->length + sh_ftype_arr[i]->offset) < buflen) { p = &buffer[sh_ftype_arr[i]->offset]; if (0 == memcmp(p, sh_ftype_arr[i]->pattern, sh_ftype_arr[i]->length)) { sl_strlcpy(filetype, sh_ftype_arr[i]->type, SH_FTYPE_MAX); return (filetype); } } } if (buflen > 0) { int flag = 0; p = buffer; for (i = 0; i < buflen; ++i) { if (*p == '\0') { sl_strlcpy(filetype, _("FILE:BINARY:UNKNOWN"), SH_FTYPE_MAX); goto out; } else if (!isgraph((int)*p) && !isspace((int)*p)) { flag = 1; } ++p; } if (flag == 0) { sl_strlcpy(filetype, _("FILE:TEXT:ASCII"), SH_FTYPE_MAX); goto out; } } sl_strlcpy(filetype, _("FILE:UNKNOWN:UNKNOWN"), SH_FTYPE_MAX); out: return filetype; } #if !defined(SH_FILE_MAIN) int matches_filetype(SL_TICKET ft, char * test_type) { char buffer[3072]; char filetype[SH_FTYPE_MAX]; long len; len = sl_read_timeout (ft, buffer, sizeof(buffer), 12, S_TRUE); sl_rewind(ft); if (len > 0) { check_filetype(filetype, buffer, len); } else { sl_strlcpy(filetype, _("FILE:UNKNOWN:UNKNOWN"), SH_FTYPE_MAX); } if (0 == strcmp(filetype, test_type)) { return 1; } return 0; } #else /* SH_FILE_MAIN */ #include int main (int argc, char * argv[]) { char buffer[3072]; char filetype[SH_FTYPE_MAX]; size_t len; FILE * fh = fopen(argv[1], "r"); if (fh) { int fd = fileno(fh); len = read(fd, buffer, 3072); check_filetype(filetype, buffer, len); fprintf(stdout, "%s: %s\n", argv[1], filetype); return 0; } return 1; } #endif #endif /* #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */ samhain-4.1.4/src/t-test0.c0000664000175000017500000002346612615253277012343 00000000000000/* * Copyright (c) 1996-1999, 2001-2004 Wolfram Gloger Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that (i) the above copyright notices and this permission notice appear in all copies of the software and related documentation, and (ii) the name of Wolfram Gloger may not be used in any advertising or publicity relating to the software. THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL WOLFRAM GLOGER BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * $Id: t-test1.c,v 1.2 2004/11/04 14:58:45 wg Exp $ * by Wolfram Gloger 1996-1999, 2001, 2004 * A multi-thread test for malloc performance, maintaining one pool of * allocated bins per thread. */ /* t-test[12] n-total = total number of threads executed (default 10) n-parallel = number of threads running in parallel (2) n-allocs = number of malloc()'s / free()'s per thread (10000) size-max = max. size requested with malloc() in bytes (10000) bins = number of bins to maintain */ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #if (defined __STDC__ && __STDC__) || defined __cplusplus # include #endif #include #include #include #include #include #include #include #include /* #if !USE_MALLOC #include #else #include "malloc.h" #endif */ #ifdef USE_SYSTEM_MALLOC extern void *memalign(size_t boundary, size_t size); /* #define memalign(a,b) malloc(b) */ #else extern void *memalign(size_t boundary, size_t size); #endif static int verbose = 1; /* dummy for the samhain safe_fatal logger */ void safe_fatal(const char * details, const char * file, int line) { (void) file; (void) line; fputs("assert failed: ", stderr); puts(details); _exit(EXIT_FAILURE); } /* lran2.h * by Wolfram Gloger 1996. * * A small, portable pseudo-random number generator. */ #ifndef _LRAN2_H #define _LRAN2_H #define LRAN2_MAX 714025l /* constants for portable */ #define IA 1366l /* random number generator */ #define IC 150889l /* (see e.g. `Numerical Recipes') */ struct lran2_st { long x, y, v[97]; }; static void lran2_init(struct lran2_st* d, long seed) { long x; int j; x = (IC - seed) % LRAN2_MAX; if(x < 0) x = -x; for(j=0; j<97; j++) { x = (IA*x + IC) % LRAN2_MAX; d->v[j] = x; } d->x = (IA*x + IC) % LRAN2_MAX; d->y = d->x; } #ifdef __GNUC__ __inline__ #endif static long lran2(struct lran2_st* d) { int j = (d->y % 97); d->y = d->v[j]; d->x = (IA*d->x + IC) % LRAN2_MAX; d->v[j] = d->x; return d->y; } #undef IA #undef IC #endif /* * $Id: t-test.h,v 1.1 2004/11/04 14:32:21 wg Exp $ * by Wolfram Gloger 1996. * Common data structures and functions for testing malloc performance. */ /* Testing level */ #ifndef TEST #define TEST 99 #endif /* For large allocation sizes, the time required by copying in realloc() can dwarf all other execution times. Avoid this with a size threshold. */ #ifndef REALLOC_MAX #define REALLOC_MAX 2000 #endif struct bin { unsigned char *ptr; unsigned long size; }; #if TEST > 0 static void mem_init(unsigned char *ptr, unsigned long size) { unsigned long i, j; if(size == 0) return; #if TEST > 3 memset(ptr, '\0', size); #endif for(i=0; i>8)) & 0xFF); } j = (unsigned long)ptr ^ (size-1); ptr[size-1] = ((j ^ (j>>8)) & 0xFF); } static int mem_check(unsigned char *ptr, unsigned long size) { unsigned long i, j; if(size == 0) return 0; for(i=0; i>8)) & 0xFF)) return 1; } j = (unsigned long)ptr ^ (size-1); if(ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 2; return 0; } static int zero_check(unsigned* ptr, unsigned long size) { unsigned char* ptr2; while(size >= sizeof(*ptr)) { if(*ptr++ != 0) return -1; size -= sizeof(*ptr); } ptr2 = (unsigned char*)ptr; while(size > 0) { if(*ptr2++ != 0) return -1; --size; } return 0; } #endif /* TEST > 0 */ /* Allocate a bin with malloc(), realloc() or memalign(). r must be a random number >= 1024. */ int n_malloc=0, n_memalign=0, n_realloc=0, n_calloc=0; static void bin_alloc(struct bin *m, unsigned long size, int r) { #if TEST > 0 if(mem_check(m->ptr, m->size)) { fprintf(stderr, "memory corrupt!\n"); exit(1); } #endif r %= 1024; /*printf("%d ", r);*/ if(r < 4) { /* memalign */ if(m->size > 0) free(m->ptr); m->ptr = (unsigned char *)memalign(sizeof(int) << r, size); ++n_memalign; } else if(r < 20) { /* calloc */ if(m->size > 0) free(m->ptr); m->ptr = (unsigned char *)calloc(size, 1); #if TEST > 0 if(zero_check((unsigned*)m->ptr, size)) { unsigned long i; for(i=0; iptr[i] != 0) break; fprintf(stderr, "calloc'ed memory non-zero (ptr=%p, i=%ld)!\n", m->ptr, i); exit(1); } #endif ++n_calloc; } else if(r < 100 && m->size < REALLOC_MAX) { /* realloc */ if(m->size == 0) m->ptr = NULL; m->ptr = realloc(m->ptr, size); ++n_realloc; } else { /* plain malloc */ if(m->size > 0) free(m->ptr); m->ptr = (unsigned char *)malloc(size); ++n_malloc; } if(!m->ptr) { fprintf(stderr, "out of memory (r=%d, size=%ld)!\n", r, (long)size); exit(1); } m->size = size; #if TEST > 0 mem_init(m->ptr, m->size); #endif } /* Free a bin. */ static void bin_free(struct bin *m) { if(m->size == 0) return; #if TEST > 0 if(mem_check(m->ptr, m->size)) { fprintf(stderr, "memory corrupt!\n"); exit(1); } #endif free(m->ptr); m->size = 0; } /* * Local variables: * tab-width: 4 * End: */ struct user_data { int bins, max; unsigned long size; long seed; }; /* * $Id: thread-st.h$ * pthread version * by Wolfram Gloger 2004 */ #include #include pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER; #ifndef USE_PTHREADS_STACKS #define USE_PTHREADS_STACKS 0 #endif #ifndef STACKSIZE #define STACKSIZE 32768 #endif /* * Local variables: * tab-width: 4 * End: */ #define N_TOTAL 10 #ifndef N_THREADS #define N_THREADS 2 #endif #ifndef N_TOTAL_PRINT #define N_TOTAL_PRINT 50 #endif #ifndef MEMORY #define MEMORY 8000000l #endif #define SIZE 10000 #define I_MAX 10000 #define ACTIONS_MAX 30 #ifndef TEST_FORK #define TEST_FORK 0 #endif #define RANDOM(d,s) (lran2(d) % (s)) struct bin_info { struct bin *m; unsigned long size, bins; }; #if TEST > 0 void bin_test(struct bin_info *p) { unsigned int b; for(b=0; bbins; b++) { if(mem_check(p->m[b].ptr, p->m[b].size)) { fprintf(stderr, "memory corrupt!\n"); abort(); } } } #endif void malloc_test(unsigned long size, int bins, int max) { unsigned int b; int i, j, actions; struct bin_info p; struct lran2_st ld; /* data for random number generator */ lran2_init(&ld, ((long)max*size + getpid()) ^ bins); p.m = (struct bin *)malloc(bins*sizeof(*p.m)); p.bins = bins; p.size = size; for(b=0; b 1 bin_test(&p); #endif actions = RANDOM(&ld, ACTIONS_MAX); #if USE_MALLOC && MALLOC_DEBUG if(actions < 2) { mallinfo(); } #endif for(j=0; j 2 bin_test(&p); #endif } i += actions; } for(b=0; b 1) && (0 == strcmp(argv[1], "-h") || 0 == strcmp(argv[1], "--help"))) { printf("%s \n\n", argv[0]); printf(" n-total = total number of threads executed (default 10)\n"); printf(" UNUSED n-parallel = number of threads running in parallel (2)\n"); printf(" n-allocs = number of malloc()'s / free()'s per thread (10000)\n"); printf(" size-max = max. size requested with malloc() in bytes (10000)\n"); printf(" bins = number of bins to maintain\n"); return 0; } if(argc > 1) n_total_max = atoi(argv[1]); if(n_total_max < 1) n_thr = 1; if(argc > 2) n_thr = atoi(argv[2]); if(n_thr < 1) n_thr = 1; if(n_thr > 100) n_thr = 100; if(argc > 3) i_max = atoi(argv[3]); if(argc > 4) size = atol(argv[4]); if(size < 2) size = 2; bins = MEMORY/(size*n_thr); if(argc > 5) bins = atoi(argv[5]); if(bins < 4) bins = 4; printf("[total=%d threads=%d] i_max=%d size=%ld bins=%d\n", n_total_max, n_thr, i_max, size, bins); do { n_total++; malloc_test(size, bins, i_max); if (verbose) if(n_total%N_TOTAL_PRINT == 0) printf("n_total = %8d - malloc %12d / memalign %12d / realloc %12d / calloc %12d\n", n_total, n_malloc, n_memalign, n_realloc, n_calloc); } while (n_total < n_total_max); #if USE_MALLOC malloc_stats(); #endif if (verbose) printf("Done.\n"); return 0; } /* * Local variables: * tab-width: 4 * End: */ samhain-4.1.4/src/sh_log_evalrule.c0000644000175000017500000007267612615253277014222 00000000000000 #include "config_xor.h" #include #include #include #include #include #include #include #ifdef USE_LOGFILE_MONITOR #undef FIL__ #define FIL__ _("sh_log_evalrule.c") /* Debian/Ubuntu: libpcre3-dev */ #ifdef HAVE_PCRE_PCRE_H #include #else #include #endif #ifndef PCRE_NO_AUTO_CAPTURE #define PCRE_NO_AUTO_CAPTURE 0 #endif #include "samhain.h" #include "sh_pthread.h" #include "sh_utils.h" #include "sh_string.h" #include "sh_log_check.h" #include "sh_log_evalrule.h" #include "sh_log_correlate.h" #include "sh_log_mark.h" #include "sh_log_repeat.h" #include "zAVLTree.h" extern int flag_err_debug; /* #define DEBUG_EVALRULES */ #ifdef DEBUG_EVALRULES static void DEBUG(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); /* flawfinder: ignore *//* we control fmt string */ va_end(ap); return; } #else static void DEBUG(const char *fmt, ...) { (void) fmt; return; } #endif struct sh_ceval /* Counter for summarizing */ { sh_string * hostname; sh_string * counted_str; sh_string * filename; unsigned long count; time_t start; time_t interval; }; void sh_ceval_free(void * item) { struct sh_ceval * counter = (struct sh_ceval *) item; if (!counter) return; sh_string_destroy(&(counter->hostname)); sh_string_destroy(&(counter->counted_str)); sh_string_destroy(&(counter->filename)); SH_FREE(counter); } enum { RFL_ISRULE = 1 << 0, RFL_ISGROUP = 1 << 1, RFL_KEEP = 1 << 2, RFL_MARK = 1 << 3 }; /*-------------------------------------------------------------- * * Adding rules/groups/hosts * *--------------------------------------------------------------*/ struct sh_geval /* Group of rules (may be a single rule) */ { sh_string * label; /* label for this group */ pcre * rule; /* compiled regex for rule */ pcre_extra * rule_extra; int * ovector; /* captured substrings */ int ovecnum; /* how many captured */ int captures; /* (captures+1)*3 required */ int flags; /* bit flags */ unsigned long delay; /* delay for keep rules */ zAVLTree * counterlist; /* counters if EVAL_SUM */ struct sh_qeval * queue; /* queue for this rule */ struct sh_geval * nextrule; /* next rule in this group */ struct sh_geval * next; /* next group of rules */ struct sh_geval * gnext; /* grouplist next */ }; struct sh_heval /* host-specific rules */ { pcre * hostname; /* compiled regex for hostname */ pcre_extra * hostname_extra; struct sh_geval * rulegroups; /* list of group of rules */ struct sh_heval * next; }; static struct sh_heval * hostlist = NULL; static struct sh_qeval * queuelist = NULL; static struct sh_geval * grouplist = NULL; /* These flags are set if we are within * the define of a host/rule group. */ static struct sh_heval * host_open = NULL; static struct sh_geval * group_open = NULL; int sh_eval_gend (const char * str) { (void) str; if (group_open) { group_open = NULL; return 0; } return -1; } int sh_eval_gadd (const char * str) { struct sh_geval * ng; struct sh_geval * tmp; pcre * group; pcre_extra * group_extra; const char * error; int erroffset; unsigned int nfields = 2; size_t lengths[2]; char * new = sh_util_strdup(str); char ** splits = split_array(new, &nfields, ':', lengths); /* group is label:regex */ if (group_open) group_open = NULL; if (nfields != 2) { SH_FREE(splits); SH_FREE(new); return -1; } group = pcre_compile(splits[1], PCRE_NO_AUTO_CAPTURE, &error, &erroffset, NULL); if (!group) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Bad regex: ")); sh_string_add_from_char(msg, splits[1]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_eval_gadd")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(splits); SH_FREE(new); return -1; } group_extra = NULL; /* pcre_study(group, 0, &error); */ ng = SH_ALLOC(sizeof(struct sh_geval)); memset(ng, '\0', sizeof(struct sh_geval)); ng->label = sh_string_new_from_lchar(splits[0], lengths[0]); ng->flags = RFL_ISGROUP; ng->rule = group; ng->rule_extra = group_extra; ng->ovector = NULL; ng->ovecnum = 0; ng->captures = 0; ng->counterlist = NULL; ng->queue = NULL; ng->nextrule = NULL; ng->next = NULL; ng->gnext = NULL; if (!host_open) { if (0 != sh_eval_hadd("^.*")) { pcre_free(group); sh_string_destroy(&(ng->label)); SH_FREE(splits); SH_FREE(new); SH_FREE(ng); return -1; } } /* * Insert at end, to keep user-defined order */ if (host_open) { if (grouplist) { tmp = grouplist; while (tmp->gnext != NULL) { tmp = tmp->gnext; } tmp->gnext = ng; } else { grouplist = ng; } /* * If there is an open host group, add it to its * rulegroups */ if (host_open->rulegroups) { tmp = host_open->rulegroups; while (tmp->next != NULL) { tmp = tmp->next; } tmp->next = ng; } else { host_open->rulegroups = ng; } } group_open = ng; SH_FREE(splits); SH_FREE(new); return 0; } int sh_eval_hend (const char * str) { (void) str; if (host_open) { host_open = NULL; return 0; } return -1; } int sh_eval_hadd (const char * str) { struct sh_heval * nh; struct sh_heval * tmp; pcre * host; pcre_extra * host_extra; const char * error; int erroffset; if (host_open) host_open = NULL; host = pcre_compile(str, PCRE_NO_AUTO_CAPTURE, &error, &erroffset, NULL); if (!host) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Bad regex: ")); sh_string_add_from_char(msg, str); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_eval_hadd")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); return -1; } host_extra = NULL; /* pcre_study(host, 0, &error); */ nh = SH_ALLOC(sizeof(struct sh_heval)); memset(nh, '\0', sizeof(struct sh_heval)); nh->hostname = host; nh->hostname_extra = host_extra; nh->rulegroups = NULL; /* * Insert at end, to keep user-defined order */ nh->next = NULL; if (hostlist) { tmp = hostlist; while (tmp->next != NULL) { tmp = tmp->next; } tmp->next = nh; } else { hostlist = nh; } host_open = nh; return 0; } int sh_eval_qadd (const char * str) { struct sh_qeval * nq; int severity; unsigned int nfields = 5; /* label:interval:(report|sum):severity[:alias] */ size_t lengths[5]; char * new = sh_util_strdup(str); char ** splits = split_array(new, &nfields, ':', lengths); if (nfields < 4) { SH_FREE(splits); SH_FREE(new); return -1; } if (strcmp(splits[2], _("sum")) && strcmp(splits[2], _("report"))) { SH_FREE(splits); SH_FREE(new); return -1; } if (!strcmp(splits[2], _("sum")) && atoi(splits[1]) < 0) { SH_FREE(splits); SH_FREE(new); return -1; } if (!strcmp(splits[1], _("trash"))) /* predefined, reserved */ { SH_FREE(splits); SH_FREE(new); return -1; } severity = sh_error_convert_level (splits[3]); if (severity < 0) { SH_FREE(splits); SH_FREE(new); return -1; } nq = SH_ALLOC(sizeof(struct sh_qeval)); memset(nq, '\0', sizeof(struct sh_qeval)); nq->label = sh_string_new_from_lchar(splits[0], lengths[0]); nq->alias = NULL; DEBUG("debug: splits[2] = %s, policy = %d\n",splits[2],nq->policy); if (0 == strcmp(splits[2], _("report"))) { nq->policy = EVAL_REPORT; nq->interval = 0; } else { nq->policy = EVAL_SUM; nq->interval = (time_t) atoi(splits[1]); } nq->severity = severity; if (nfields == 5) { nq->alias = sh_string_new_from_lchar(splits[4], lengths[4]); } nq->next = queuelist; queuelist = nq; SH_FREE(splits); SH_FREE(new); return 0; } struct sh_qeval * sh_log_find_queue(const char * str) { struct sh_qeval * retval = queuelist; if (!str) return NULL; while (retval) { if (0 == strcmp(str, sh_string_str(retval->label))) break; retval = retval->next; } return retval; } int sh_log_lookup_severity(const char * str) { struct sh_qeval * queue; if (str) { if (0 != strcmp(str, _("trash"))) { queue = sh_log_find_queue(str); if (queue) return queue->severity; } } return SH_ERR_SEVERE; } sh_string * sh_log_lookup_alias(const char * str) { struct sh_qeval * queue; if (str) { if (0 != strcmp(str, _("trash"))) { queue = sh_log_find_queue(str); if (queue) return queue->alias; } } return NULL; } static char * get_label_and_time(const char * inprefix, char * str, unsigned long * seconds) { char * res = NULL; char * endptr = NULL; unsigned int nfields = 2; /* seconds:label */ size_t lengths[2]; char * prefix = sh_util_strdup(inprefix); char * new = sh_util_strdup(str); char ** splits = split_array_braced(new, prefix, &nfields, lengths); if (splits && nfields == 2 && lengths[0] > 0 && lengths[1] > 0) { *seconds = strtoul(splits[0], &endptr, 10); if ((endptr == '\0' || endptr != splits[0]) && (*seconds != ULONG_MAX)) { res = sh_util_strdup(splits[1]); } } if (splits) SH_FREE(splits); SH_FREE(new); SH_FREE(prefix); return res; } struct sh_qeval ** sh_dummy_472_queue; char ** sh_dummy_473_dstr; int sh_eval_radd (const char * str) { struct sh_geval * nr; struct sh_geval * tmp; struct sh_qeval * queue; pcre * rule; pcre_extra * rule_extra; const char * error; int erroffset; int captures = 0; unsigned int nfields = 2; /* queue:regex */ size_t lengths[3]; char * new = sh_util_strdup(str); char ** splits; int qpos = 0; volatile int rpos = 1; unsigned long dsec = 0; char * dstr = NULL; char * s = new; volatile char pflag = '-'; while ( *s && isspace((int)*s) ) ++s; if (0 == strncmp(s, _("KEEP"), 4) || 0 == strncmp(s, _("CORRELATE"), 9) || 0 == strncmp(s, _("MARK"), 4)) { pflag = s[0]; nfields = 3; } splits = split_array(new, &nfields, ':', lengths); sh_dummy_472_queue = &queue; sh_dummy_473_dstr = &dstr; queue = NULL; if (nfields < 2 || nfields > 3) { SH_FREE(splits); SH_FREE(new); return -1; } if (nfields == 3) { if (pflag == 'K') { /* KEEP(nsec,label):queue:regex */ dstr = get_label_and_time(_("KEEP"), splits[0], &dsec); if (!dstr) { SH_FREE(splits); SH_FREE(new); return -1; } } else if (pflag == 'C') { /* CORRELATE(description):queue:regex */ int retval = sh_keep_match_add(splits[0], splits[1], splits[2]); SH_FREE(splits); SH_FREE(new); return retval; } else if (pflag == 'M') { /* MARK(description, interval):queue:regex */ int retval = -1; dstr = get_label_and_time(_("MARK"), splits[0], &dsec); if (dstr) { retval = sh_log_mark_add(dstr, dsec, splits[1]); } if (retval != 0) { SH_FREE(splits); SH_FREE(new); return retval; } } ++qpos; ++rpos; } if (0 != strcmp(splits[qpos], _("trash"))) { queue = sh_log_find_queue(splits[qpos]); if (!queue) { SH_FREE(splits); SH_FREE(new); return -1; } } rule = pcre_compile(splits[rpos], 0, &error, &erroffset, NULL); if (!rule) { sh_string * msg = sh_string_new(0); sh_string_add_from_char(msg, _("Bad regex: ")); sh_string_add_from_char(msg, splits[rpos]); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, sh_string_str(msg), _("sh_eval_radd")); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_string_destroy(&msg); SH_FREE(splits); SH_FREE(new); return -1; } rule_extra = NULL; /* pcre_study(rule, 0, &error); */ pcre_fullinfo(rule, rule_extra, PCRE_INFO_CAPTURECOUNT, &captures); if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); if (dstr) sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Adding rule: |%s| with %d captures, keep(%lu,%s)"), splits[rpos], captures, dsec, dstr); else sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Adding rule: |%s| with %d captures"), splits[rpos], captures); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("sh_eval_radd")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } DEBUG("adding rule: |%s| with %d captures\n", splits[rpos], captures); SH_FREE(splits); SH_FREE(new); nr = SH_ALLOC(sizeof(struct sh_geval)); memset(nr, '\0', sizeof(struct sh_geval)); nr->label = NULL; nr->flags = RFL_ISRULE; nr->delay = 0; nr->rule = rule; nr->rule_extra = rule_extra; nr->captures = captures; nr->ovector = SH_ALLOC(sizeof(int) * (captures+1) * 3); nr->ovecnum = 0; nr->counterlist = NULL; nr->queue = queue; nr->nextrule = NULL; nr->next = NULL; nr->gnext = NULL; if (pflag == 'K') { nr->label = sh_string_new_from_lchar(dstr, sl_strlen(dstr)); nr->flags |= RFL_KEEP; nr->delay = dsec; SH_FREE(dstr); } else if (pflag == 'M') { nr->label = sh_string_new_from_lchar(dstr, sl_strlen(dstr)); nr->flags |= RFL_MARK; nr->delay = dsec; SH_FREE(dstr); } /* * If there is an open group, add it to its * rules */ if (group_open) { if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Adding rule to group |%s|"), sh_string_str(group_open->label)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("sh_eval_radd")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } DEBUG("adding rule to group |%s|\n", sh_string_str(group_open->label)); if (group_open->nextrule) { tmp = group_open->nextrule; while (tmp->nextrule != NULL) { tmp = tmp->nextrule; } /* next -> nextrule */ tmp->nextrule = nr; /* next -> nextrule */ } else { group_open->nextrule = nr; } } /* * ..else, add it to the currently open host (open the * default host, if there is no open one) */ else { if (!host_open) { if (0 != sh_eval_hadd("^.*")) { if (nr->label) sh_string_destroy(&(nr->label)); SH_FREE(nr->ovector); SH_FREE(nr); return -1; } } if (host_open) { /* * Add rule as member to grouplist, to facilitate cleanup */ DEBUG("adding solitary rule to grouplist\n"); if (grouplist) { tmp = grouplist; while (tmp->gnext != NULL) { tmp = tmp->gnext; } tmp->gnext = nr; } else { grouplist = nr; } /* * Add rule to host rulegroups */ DEBUG("adding solitary rule to host rulegroups\n"); if (host_open->rulegroups) { /* Second, third, ... rule go to host_open->rulegroups->next, * since test_grules() iterates over nextrules */ tmp = host_open->rulegroups; while (tmp->next != NULL) { tmp = tmp->next; } tmp->next = nr; } else { /* First rule goes to host_open->rulegroups */ host_open->rulegroups = nr; } } else { if (nr->label) sh_string_destroy(&(nr->label)); SH_FREE(nr->ovector); SH_FREE(nr); return -1; } } return 0; } void sh_eval_cleanup() { struct sh_geval * gtmp; struct sh_qeval * qtmp; struct sh_heval * htmp; while (grouplist) { gtmp = grouplist; grouplist = gtmp->gnext; if (gtmp->label) sh_string_destroy(&(gtmp->label)); if (gtmp->rule_extra) (*pcre_free)(gtmp->rule_extra); if (gtmp->rule) (*pcre_free)(gtmp->rule); if (gtmp->counterlist) zAVLFreeTree(gtmp->counterlist, sh_ceval_free); if (gtmp->ovector) SH_FREE(gtmp->ovector); #if 0 while (gtmp->nextrule) { tmp = gtmp->nextrule; gtmp->nextrule = tmp->nextrule; if (tmp->rule_extra) (*pcre_free)(tmp->rule_extra); if (tmp->rule) (*pcre_free)(tmp->rule); if (tmp->counterlist) zAVLFreeTree(tmp->counterlist, sh_ceval_free); if (tmp->ovector) SH_FREE(tmp->ovector); SH_FREE(tmp); } #endif SH_FREE(gtmp); } qtmp = queuelist; while (qtmp) { if (qtmp->label) sh_string_destroy(&(qtmp->label)); queuelist = qtmp->next; SH_FREE(qtmp); qtmp = queuelist; } htmp = hostlist; while (htmp) { if (htmp->hostname_extra) (*pcre_free)(htmp->hostname_extra); if (htmp->hostname) (*pcre_free)(htmp->hostname); if (htmp->rulegroups) htmp->rulegroups = NULL; hostlist = htmp->next; htmp->next = NULL; SH_FREE(htmp); htmp = hostlist; } hostlist = NULL; queuelist = NULL; grouplist = NULL; host_open = NULL; group_open = NULL; sh_keep_destroy(); sh_keep_match_del(); return; } /********************************************************************** * * Actual rule processing * **********************************************************************/ /* Test a list of rules against msg; return matched rule, with ovector * filled in */ struct sh_geval ** sh_dummy_828_rule; static struct sh_geval * test_rule (struct sh_geval * rule, sh_string *msg, time_t tstamp) { int res; volatile int count; volatile time_t timestamp = tstamp; sh_dummy_828_rule = &rule; if (!rule) DEBUG("debug: (NULL) rule\n"); if (rule && sh_string_len(msg) < (size_t)INT_MAX) { count = 1; do { if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Check rule %d for |%s|"), count, sh_string_str(msg)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("test_rule")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } DEBUG("debug: check rule %d for <%s>\n", count, msg->str); res = pcre_exec(rule->rule, rule->rule_extra, sh_string_str(msg), (int)sh_string_len(msg), 0, 0, rule->ovector, (3*(1+rule->captures))); if (res >= 0) { rule->ovecnum = res; if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); if ( rule->flags & RFL_KEEP ) sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d matches, result = %d (keep)"), count, res); else if ( rule->flags & RFL_MARK ) sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d matches, result = %d (mark)"), count, res); else sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d matches, result = %d"), count, res); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("test_rule")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } if ( rule->flags & RFL_KEEP ) { DEBUG("debug: rule %d matches (keep), timestamp = %lu\n", count, timestamp); sh_keep_add(rule->label, rule->delay, timestamp == 0 ? time(NULL) : timestamp); } else if ( rule->flags & RFL_MARK ) { DEBUG("debug: rule %d matches (mark)\n", count); sh_log_mark_update(rule->label, timestamp == 0 ? time(NULL) : timestamp); } break; /* return the matching rule; ovector is filled in */ } if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d did not match"), count); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("test_rule")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } DEBUG("debug: rule %d did not match\n", count); rule = rule->nextrule; ++count; } while (rule); } if (!rule) DEBUG("debug: no match found\n"); /* If there was no match, this is NULL */ sh_dummy_828_rule = NULL; return rule; } /* Test a (struct sh_geval *), which may be single rule or a group of rules, * against msg */ struct sh_geval ** sh_dummy_928_result; struct sh_geval ** sh_dummy_929_group; static struct sh_geval * test_grules (struct sh_heval * host, sh_string * msg, time_t timestamp) { struct sh_geval * result = NULL; struct sh_geval * group = host->rulegroups; sh_dummy_928_result = &result; sh_dummy_929_group = &group; if (group && sh_string_len(msg) < (size_t)INT_MAX) { DEBUG("debug: if group\n"); do { if( (group->label != NULL) && (0 != (group->flags & RFL_ISGROUP))) { /* this is a rule group */ if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Checking group |%s| of rules against |%s|"), sh_string_str(group->label), sh_string_str(msg)); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("test_rule")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } DEBUG("debug: if group->label %s\n", sh_string_str(group->label)); if (pcre_exec(group->rule, group->rule_extra, sh_string_str(msg), (int) sh_string_len(msg), 0, 0, NULL, 0) >= 0) { result = test_rule(group->nextrule, msg, timestamp); if (result) break; } } else { /* If there is no group label, the 'group' is actually a solitary * rule (not within any group). */ if (flag_err_debug == S_TRUE) { char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Checking solitary rules")); SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, emsg, _("test_rule")); SH_MUTEX_UNLOCK(mutex_thread_nolog); SH_FREE(emsg); } DEBUG("debug: else (single rule)\n"); result = test_rule(group, msg, timestamp); if (result) break; } group = group->next; /* next group of rules */ } while (group); } sh_dummy_928_result = NULL; sh_dummy_929_group = NULL; return result; } /* Top-level find_rule() function */ static struct sh_geval * find_rule (sh_string *host, sh_string *msg, time_t timestamp) { struct sh_geval * result = NULL; struct sh_heval * hlist = hostlist; if (hlist && sh_string_len(host) < (size_t)INT_MAX) { do { if (pcre_exec(hlist->hostname, hlist->hostname_extra, sh_string_str(host), (int) sh_string_len(host), 0, 0, NULL, 0) >= 0) { /* matching host, check rules/groups of rules */ result = test_grules(hlist, msg, timestamp); if (result) break; } hlist = hlist->next; } while (hlist); } return result; } /* copy the message and replace captured substrings with '___' */ static sh_string * replace_captures(const sh_string * message, int * ovector, int ovecnum) { sh_string * retval = sh_string_new_from_lchar(sh_string_str(message), sh_string_len(message)); if (ovecnum > 1) { retval = sh_string_replace(retval, &(ovector[2]), (ovecnum-1), "___", 3); } return retval; } static void msg_report(int severity, const sh_string * alias, struct sh_geval * rule, struct sh_logrecord * record) { char * tmp; char * msg; sh_string * mmm = NULL; char * ttt; SH_MUTEX_LOCK(mutex_thread_nolog); if (rule) { mmm = replace_captures(record->message, rule->ovector, rule->ovecnum); rule->ovecnum = 0; msg = sh_util_safe_name_keepspace (sh_string_str(mmm)); } else { msg = sh_util_safe_name_keepspace (sh_string_str(record->message)); } tmp = sh_util_safe_name_keepspace (record->filename); ttt = sh_util_safe_name_keepspace (sh_string_str(record->timestr)); sh_error_handle (severity, FIL__, __LINE__, 0, MSG_LOGMON_REP, msg, ttt, sh_string_str(record->host), tmp); if (alias) { sh_error_mail (sh_string_str(alias), severity, FIL__, __LINE__, 0, MSG_LOGMON_REP, msg, ttt, sh_string_str(record->host), tmp); } SH_FREE(ttt); SH_FREE(msg); SH_FREE(tmp); if (mmm) sh_string_destroy(&mmm); SH_MUTEX_UNLOCK(mutex_thread_nolog); } static void sum_report(int severity, const sh_string * alias, sh_string * host, sh_string * message, sh_string * path) { char * tmp; char * msg; SH_MUTEX_LOCK(mutex_thread_nolog); tmp = sh_util_safe_name_keepspace (sh_string_str(path)); msg = sh_util_safe_name_keepspace (sh_string_str(message)); sh_error_handle (severity, FIL__, __LINE__, 0, MSG_LOGMON_SUM, msg, sh_string_str(host), tmp); if (alias) { sh_error_mail (sh_string_str(alias), severity, FIL__, __LINE__, 0, MSG_LOGMON_SUM, msg, sh_string_str(host), tmp); } SH_FREE(msg); SH_FREE(tmp); SH_MUTEX_UNLOCK(mutex_thread_nolog); } static zAVLKey sh_eval_getkey(void const *item) { return ((const struct sh_ceval *)item)->hostname->str; } /* Find the counter, or initialize one if there is none already */ static struct sh_ceval * find_counter(struct sh_geval * rule, sh_string * host, time_t interval) { struct sh_ceval * counter; if (!(rule->counterlist)) { DEBUG("debug: allocate new counterlist AVL tree\n"); rule->counterlist = zAVLAllocTree(sh_eval_getkey, zAVL_KEY_STRING); } counter = (struct sh_ceval *) zAVLSearch (rule->counterlist, sh_string_str(host)); if (!counter) { DEBUG("debug: no counter found\n"); counter = SH_ALLOC(sizeof(struct sh_ceval)); memset(counter, '\0', sizeof(struct sh_ceval)); counter->hostname = sh_string_new_from_lchar(sh_string_str(host), sh_string_len(host)); counter->counted_str = NULL; counter->filename = NULL; counter->count = 0; counter->start = time(NULL); counter->interval = interval; zAVLInsert(rule->counterlist, counter); } return counter; } /* process the counter for a SUM rule */ static int process_counter(struct sh_ceval * counter, struct sh_geval * rule, struct sh_logrecord * record) { int retval = -1; time_t now; if (!(counter->counted_str)) { counter->counted_str = replace_captures(record->message, rule->ovector, rule->ovecnum); rule->ovecnum = 0; counter->filename = sh_string_new_from_lchar(record->filename, strlen(record->filename)); DEBUG("debug: counted_str after replace: %s\n", sh_string_str(counter->counted_str)); } ++(counter->count); now = time(NULL); now -= counter->start; DEBUG("debug: count %lu, interval %lu, time %lu\n", counter->count, counter->interval, now); if (now >= counter->interval) { DEBUG("debug: report count\n"); sum_report(rule->queue->severity, rule->queue->alias, counter->hostname, counter->counted_str, counter->filename); counter->start = time(NULL); counter->count = 0; } return retval; } /* Process a rule */ static int process_rule(struct sh_geval * rule, struct sh_logrecord * record) { int retval = -1; struct sh_qeval * queue = rule->queue; if (queue) { DEBUG("debug: queue policy = %d found\n", queue->policy); if (queue->policy == EVAL_REPORT) { DEBUG("debug: EVAL_REPORT host: %s, message: %s\n", sh_string_str(record->host), sh_string_str(record->message)); msg_report(queue->severity, queue->alias, rule, record); retval = 0; } else if (queue->policy == EVAL_SUM) { struct sh_ceval * counter = find_counter(rule, record->host, queue->interval); DEBUG("debug: EVAL_SUM host: %s, message: %s\n", sh_string_str(record->host), sh_string_str(record->message)); if (counter) { DEBUG("debug: counter found\n"); retval = process_counter(counter, rule, record); } } } else { DEBUG("debug: no queue found -- trash\n"); /* No queue means 'trash' */ retval = 0; } return retval; } #define DEFAULT_SEVERITY (-1) int sh_eval_process_msg(struct sh_logrecord * record) { static unsigned long i = 0; if (record) { struct sh_geval * rule = find_rule (record->host, record->message, record->timestamp); if (rule) { DEBUG("debug: (%lu) rule found\n", i); ++i; return process_rule(rule, record); } else { DEBUG("debug: (%lu) no rule found\n", i); ++i; msg_report(DEFAULT_SEVERITY, NULL, NULL, record); } sh_repeat_message_check(record->host, record->message, record->timestamp); return 0; } return -1; } #endif samhain-4.1.4/src/sh_utmp.c0000644000175000017500000006770112615253277012520 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include #ifdef HAVE_UTADDR #include #include #ifndef S_SPLINT_S #include #else #define AF_INET 2 #endif #endif #ifdef SH_USE_UTMP #ifdef HAVE_UTMPX_H #ifdef S_SPLINT_S typedef pid_t __pid_t; #endif #include #define SH_UTMP_S utmpx #undef ut_name #define ut_name ut_user #ifdef HAVE_UTXTIME #undef ut_time #define ut_time ut_xtime #else #undef ut_time #define ut_time ut_tv.tv_sec #endif #else #include #define SH_UTMP_S utmp #endif #ifdef HAVE_PATHS_H #include #endif #undef FIL__ #define FIL__ _("sh_utmp.c") #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) #include "samhain.h" #include "sh_utils.h" #include "sh_error.h" #include "sh_modules.h" #include "sh_utmp.h" #include "sh_pthread.h" #include "sh_inotify.h" SH_MUTEX_EXTERN(mutex_thread_nolog); #ifdef TM_IN_SYS_TIME #include #else #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_DIRENT_H #include #define NAMLEN(dirent) sl_strlen((dirent)->d_name) #else #define dirent direct #define NAMLEN(dirent) (dirent)->d_namlen #ifdef HAVE_SYS_NDIR_H #include #endif #ifdef HAVE_SYS_DIR_H #include #endif #ifdef HAVE_NDIR_H #include #endif #endif #ifndef HAVE_LSTAT #define lstat stat #endif #ifndef UT_LINESIZE #ifndef __UT_LINESIZE #define UT_LINESIZE 12 #else #define UT_LINESIZE __UT_LINESIZE #endif #endif #ifndef UT_NAMESIZE #ifndef __UT_NAMESIZE #define UT_NAMESIZE 8 #else #define UT_NAMESIZE __UT_NAMESIZE #endif #endif #ifndef UT_HOSTSIZE #ifndef __UT_HOSTSIZE #define UT_HOSTSIZE 16 #else #define UT_HOSTSIZE __UT_HOSTSIZE #endif #endif #ifdef HAVE_UTMPX_H #ifndef _PATH_UTMP #ifdef UTMPX_FILE #define _PATH_UTMP UTMPX_FILE #else #error You must define UTMPX_FILE in the file config.h #endif #endif #ifndef _PATH_WTMP #ifdef WTMPX_FILE #define _PATH_WTMP WTMPX_FILE #else #error You must define WTMPX_FILE in the file config.h #endif #endif #else #ifndef _PATH_UTMP #ifdef UTMP_FILE #define _PATH_UTMP UTMP_FILE #else #error You must define UTMP_FILE in the file config.h #endif #endif #ifndef _PATH_WTMP #ifdef WTMP_FILE #define _PATH_WTMP WTMP_FILE #else #error You must define WTMP_FILE in the file config.h #endif #endif #endif typedef struct log_user { char ut_tty[UT_LINESIZE+1]; char name[UT_NAMESIZE+1]; char ut_host[UT_HOSTSIZE+1]; char ut_ship[SH_IP_BUF]; /* IP address */ time_t time; struct log_user * next; } blah_utmp; #ifdef HAVE_UTTYPE static char terminated_line[UT_HOSTSIZE]; #endif static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP }; static struct SH_UTMP_S save_utmp; static void sh_utmp_logout_morechecks(struct log_user * user); static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut); static void sh_utmp_addlogin (struct SH_UTMP_S * ut); static void sh_utmp_check_internal(int mode); static int ShUtmpLoginSolo = SH_ERR_INFO; static int ShUtmpLoginMulti = SH_ERR_WARN; static int ShUtmpLogout = SH_ERR_INFO; static int ShUtmpActive = S_TRUE; static time_t ShUtmpInterval = 300; sh_rconf sh_utmp_table[] = { { N_("severityloginmulti"), sh_utmp_set_login_multi }, { N_("severitylogin"), sh_utmp_set_login_solo }, { N_("severitylogout"), sh_utmp_set_logout_good }, { N_("logincheckactive"), sh_utmp_set_login_activate }, { N_("logincheckinterval"), sh_utmp_set_login_timer }, { N_("logincheckfirst"), sh_login_set_checklevel }, { N_("logincheckoutlier"), sh_login_set_siglevel }, { N_("logincheckdate"), sh_login_set_def_allow }, { N_("logincheckuserdate"), sh_login_set_user_allow }, { NULL, NULL }, }; static void set_defaults(void) { ShUtmpLoginSolo = SH_ERR_INFO; ShUtmpLoginMulti = SH_ERR_WARN; ShUtmpLogout = SH_ERR_INFO; ShUtmpActive = S_TRUE; ShUtmpInterval = 300; sh_login_reset(); return; } #if defined (HAVE_SETUTENT) && defined (USE_SETUTENT) #ifdef HAVE_UTMPX_H #define sh_utmp_utmpname utmpxname #define sh_utmp_setutent setutxent #define sh_utmp_endutent endutxent #define sh_utmp_getutent getutxent #define sh_utmp_getutid getutxid #define sh_utmp_getutline getutxline #else #define sh_utmp_utmpname utmpname #define sh_utmp_setutent setutent #define sh_utmp_endutent endutent #define sh_utmp_getutent getutent #define sh_utmp_getutid getutid #define sh_utmp_getutline getutline #endif #else /* BSD lacks getutent() etc. * utmpname(), setutent(), and endutent() return void, * so we do not perform much error handling. * Errors must be recognized by getutent() returning NULL. * Apparently, the application cannot check whether wtmp is empty, * or whether there was an fopen() error. */ static FILE * sh_utmpfile = NULL; static char sh_utmppath[80] = _PATH_UTMP; /* sh_utmp_feed_forward is for optimizing * (fseek instead of getutent loop) */ static long sh_utmp_feed_forward = 0; static void sh_utmp_utmpname(const char * str) { SL_ENTER(_("sh_utmp_utmpname")); if (sh_utmpfile != NULL) { (void) sl_fclose (FIL__, __LINE__, sh_utmpfile); sh_utmpfile = NULL; } (void) sl_strlcpy (sh_utmppath, str, 80); SL_RET0(_("sh_utmp_utmpname")); } static void sh_utmp_setutent(void) { int error; int fd; SL_ENTER(_("sh_utmp_setutent")); if (sh_utmpfile == NULL) { SH_MUTEX_LOCK(mutex_thread_nolog); fd = (int) aud_open (FIL__, __LINE__, SL_NOPRIV, sh_utmppath, O_RDONLY, 0); SH_MUTEX_UNLOCK(mutex_thread_nolog); if (fd >= 0) { sh_utmpfile = fdopen(fd, "r"); } /* -- If (sh_utmpfile == NULL) then either the open() or the fdopen() * has failed. */ if (sh_utmpfile == NULL) { error = errno; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_ACCESS, (long) sh.real.uid, sh_utmppath); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RET0(_("sh_utmp_setutent")); } } (void) fseek (sh_utmpfile, 0L, SEEK_SET); if (-1 == fseek (sh_utmpfile, sh_utmp_feed_forward, SEEK_CUR)) { sh_utmp_feed_forward = 0; /* modified Apr 4, 2004 */ (void) fseek (sh_utmpfile, 0L, SEEK_SET); } clearerr (sh_utmpfile); SL_RET0(_("sh_utmp_setutent")); } static void sh_utmp_endutent(void) { SL_ENTER(_("sh_utmp_endutent")); if (NULL != sh_utmpfile) (void) sl_fclose(FIL__, __LINE__, sh_utmpfile); sh_utmpfile = NULL; SL_RET0(_("sh_utmp_endutent")); } static struct SH_UTMP_S * sh_utmp_getutent(void) { size_t in; static struct SH_UTMP_S out; SL_ENTER(_("sh_utmp_getutent")); ASSERT_RET((sh_utmpfile != NULL), _("sh_utmpfile != NULL"), (NULL)) in = fread (&out, sizeof(struct SH_UTMP_S), 1, sh_utmpfile); if (in != 1) { if (ferror (sh_utmpfile) != 0) { clearerr (sh_utmpfile); SL_RETURN(NULL, _("sh_utmp_getutent")); } else { SL_RETURN(NULL, _("sh_utmp_getutent")); } } SL_RETURN(&out, _("sh_utmp_getutent")); } #ifdef USE_UNUSED static struct SH_UTMP_S * sh_utmp_getutline(struct SH_UTMP_S * ut) { struct SH_UTMP_S * out; while (1) { if ((out = sh_utmp_getutent()) == NULL) { return NULL; } #ifdef HAVE_UTTYPE if (out->ut_type == USER_PROCESS || out->ut_type == LOGIN_PROCESS) if (sl_strcmp(ut->ut_line, out->ut_line) == 0) return out; #else if ( 0 != sl_strncmp (out->ut_name, "reboot", 6) && 0 != sl_strncmp (out->ut_name, "shutdown", 8) && 0 != sl_strncmp (out->ut_name, "date", 4) ) return out; #endif } return NULL; } static struct SH_UTMP_S * sh_utmp_getutid(struct SH_UTMP_S * ut) { #ifdef HAVE_UTTYPE struct SH_UTMP_S * out; if (ut->ut_type == RUN_LVL || ut->ut_type == BOOT_TIME || ut->ut_type == NEW_TIME || ut->ut_type == OLD_TIME) { while (1) { if ((out = sh_utmp_getutent()) == NULL) { return NULL; } if (out->ut_type == ut->ut_type) return out; } } else if (ut->ut_type == INIT_PROCESS || ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS || ut->ut_type == DEAD_PROCESS ) { while (1) { if ((out = sh_utmp_getutent()) == NULL) { return NULL; } if (sl_strcmp(ut->ut_id, out->ut_id) == 0) return out; } } #endif return NULL; } /* #ifdef USE_UNUSED */ #endif /* #ifdef HAVE_SETUTENT */ #endif #ifdef HAVE_UTADDR #ifdef HAVE_UTADDR_V6 static char * my_inet_ntoa(SINT32 * ut_addr_v6, char * buf, size_t buflen) { struct in_addr in; buf[0] = '\0'; if (0 == (ut_addr_v6[1] + ut_addr_v6[2] + ut_addr_v6[3])) { memcpy(&in, ut_addr_v6, sizeof(struct in_addr)); sl_strlcpy(buf, inet_ntoa(in), buflen); } else { inet_ntop(AF_INET6, ut_addr_v6, buf, buflen); } return buf; } #else static char * my_inet_ntoa(SINT32 ut_addr, char * buf, size_t buflen) { struct in_addr in; buf[0] = '\0'; memcpy(&in, ut_addr, sizeof(struct in_addr)); sl_strlcpy(buf, inet_ntoa(in), buflen); return buf; } #endif /* #ifdef HAVE_UTADDR */ #endif #if defined(__linux__) && !defined(ut_addr) #define ut_addr ut_addr_v6[0] #endif static struct log_user * userlist = NULL; static time_t lastcheck; static int init_done = 0; /************* * * module init * *************/ static int sh_utmp_init_internal (void) { SL_ENTER(_("sh_utmp_init")); if (ShUtmpActive == BAD) SL_RETURN( (-1), _("sh_utmp_init")); /* do not re-initialize after a re-configuration */ if (init_done == 1) { SL_RETURN( (0), _("sh_utmp_init")); } lastcheck = time (NULL); userlist = NULL; memset (&save_utmp, 0, sizeof(struct SH_UTMP_S)); sh_utmp_check_internal (2); /* current logins */ sh_utmp_check_internal (0); init_done = 1; SL_RETURN( (0), _("sh_utmp_init")); } int sh_utmp_init (struct mod_type * arg) { #if !defined(HAVE_PTHREAD) (void) arg; #endif if (ShUtmpActive == BAD) return SH_MOD_FAILED; #ifdef HAVE_PTHREAD if (arg != NULL && arg->initval < 0 && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg)) return SH_MOD_THREAD; else return SH_MOD_FAILED; } else if (arg != NULL && arg->initval == SH_MOD_THREAD && (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)) { return SH_MOD_THREAD; } #endif return sh_utmp_init_internal(); } /************* * * module cleanup * *************/ #ifdef HAVE_UTTYPE static int sh_utmp_login_clean(void); #endif #if defined(HAVE_PTHREAD) static sh_watches inotify_watch = SH_INOTIFY_INITIALIZER; #endif int sh_utmp_end () { struct log_user * user = userlist; struct log_user * userold; SL_ENTER(_("sh_utmp_end")); while (user) { userold = user; user = user->next; SH_FREE(userold); } userlist = NULL; #ifdef HAVE_UTTYPE (void) sh_utmp_login_clean(); #endif /* Reset the flag, such that the module * can be re-enabled. */ set_defaults(); init_done = 0; #if defined(HAVE_PTHREAD) sh_inotify_remove(&inotify_watch); #endif SL_RETURN( (0), _("sh_utmp_end")); } int sh_utmp_reconf() { set_defaults(); #if defined(HAVE_PTHREAD) sh_inotify_remove(&inotify_watch); #endif return 0; } /************* * * module timer * *************/ int sh_utmp_timer (time_t tcurrent) { #if !defined(HAVE_PTHREAD) retry_msleep(1, 0); if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval) { lastcheck = tcurrent; return (-1); } return 0; #else int errnum = 0; if ( (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE) && sh.flag.checkSum != SH_CHECK_INIT ) { sh_inotify_wait_for_change(mode_path[1], &inotify_watch, &errnum, ShUtmpInterval); } lastcheck = tcurrent; if (SH_INOTIFY_ERROR(errnum)) { char ebuf[SH_ERRBUF_SIZE]; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_message(errnum, ebuf, sizeof(ebuf)); sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("sh_utmp_timer") ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } return -1; #endif } /************* * * module check * *************/ int sh_utmp_check () { SL_ENTER(_("sh_utmp_check")); if (ShUtmpActive == BAD) { #if defined(HAVE_PTHREAD) sh_inotify_remove(&inotify_watch); #endif SL_RETURN( (-1), _("sh_utmp_check")); } SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_utmp_check_internal (1); SL_RETURN(0, _("sh_utmp_check")); } /************* * * module setup * *************/ int sh_utmp_set_login_solo (const char * c) { int retval; char tmp[32]; SL_ENTER(_("sh_utmp_set_login_solo")); tmp[0] = '='; tmp[1] = '\0'; (void) sl_strlcat (tmp, c, 32); SH_MUTEX_LOCK(mutex_thread_nolog); retval = sh_error_set_level (tmp, &ShUtmpLoginSolo); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RETURN(retval, _("sh_utmp_set_login_solo")); } int sh_utmp_set_login_multi (const char * c) { int retval; char tmp[32]; SL_ENTER(_("sh_utmp_set_login_multi")); tmp[0] = '='; tmp[1] = '\0'; (void) sl_strlcat (tmp, c, 32); SH_MUTEX_LOCK(mutex_thread_nolog); retval = sh_error_set_level (tmp, &ShUtmpLoginMulti); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RETURN(retval, _("sh_utmp_set_login_multi")); } int sh_utmp_set_logout_good (const char * c) { int retval; char tmp[32]; SL_ENTER(_("sh_utmp_set_logout_good")); tmp[0] = '='; tmp[1] = '\0'; (void) sl_strlcat (tmp, c, 32); SH_MUTEX_LOCK(mutex_thread_nolog); retval = sh_error_set_level (tmp, &ShUtmpLogout); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RETURN(retval, _("sh_utmp_set_logout_good")); } int sh_utmp_set_login_timer (const char * c) { long val; SL_ENTER(_("sh_utmp_set_login_timer")); val = strtol (c, (char **)NULL, 10); if (val <= 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("utmp timer"), c); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RETURN((-1), _("sh_utmp_set_login_timer")); } ShUtmpInterval = (time_t) val; SL_RETURN(0, _("sh_utmp_set_login_timer")); } int sh_utmp_set_login_activate (const char * c) { int i; SL_ENTER(_("sh_utmp_set_login_activate")); i = sh_util_flagval(c, &ShUtmpActive); SL_RETURN(i, _("sh_utmp_set_login_activate")); } #ifdef HAVE_UTTYPE struct login_ct { char name[UT_NAMESIZE+1]; int nlogin; struct login_ct * next; }; static struct login_ct * login_ct_list = NULL; static int sh_utmp_login_clean(void) { struct login_ct * list = login_ct_list; struct login_ct * old; login_ct_list = NULL; while (list) { old = list; list = list->next; SH_FREE(old); } return 0; } /* add a username to the list of logged-in users */ static int sh_utmp_login_a(char * str) { struct login_ct * list = login_ct_list; while (list) { if (0 == sl_strcmp(list->name, str)) { ++(list->nlogin); return list->nlogin; } list = list->next; } list = SH_ALLOC(sizeof(struct login_ct)); (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1); list->nlogin = 1; list->next = login_ct_list; login_ct_list = list; return 1; } static int sh_utmp_login_r(char * str) { struct login_ct * list = login_ct_list; struct login_ct * old = login_ct_list; while (list) { if (0 == sl_strcmp(list->name, str)) { list->nlogin -= 1; if (list->nlogin > 0) { return list->nlogin; } if (login_ct_list == list) /* modified Apr 4, 2004 */ { login_ct_list = list->next; SH_FREE(list); } else { old->next = list->next; SH_FREE(list); } return 0; } old = list; list = list->next; } return 0; } #endif /* for each login: * - allocate a log record * - link device.ut_record -> log_record * - link user.ut_record -> log_record */ #ifdef HAVE_UTTYPE static int sh_utmp_is_virtual (char * in_utline, char * in_uthost) { if (in_uthost != NULL && in_utline != NULL && in_uthost[0] == ':' && in_uthost[1] == '0' && 0 == sl_strncmp(in_utline, _("pts/"), 4)) { return 1; } return 0; } #endif /* These variables are not used anywhere. They only exist * to assign &userold, &user to them, which keeps gcc from * putting them into a register, and avoids the 'clobbered * by longjmp' warning. And no, 'volatile' proved insufficient. */ void * sh_dummy_850_userold = NULL; void * sh_dummy_851_user = NULL; static void sh_utmp_addlogin (struct SH_UTMP_S * ut) { struct log_user * user = userlist; struct log_user * userold = userlist; #ifdef HAVE_UTTYPE struct log_user * username = userlist; #endif char ttt[TIM_MAX]; #ifdef HAVE_UTTYPE volatile int status; #endif SL_ENTER(_("sh_utmp_addlogin")); if (ut->ut_line[0] == '\0') SL_RET0(_("sh_utmp_addlogin")); /* for some stupid reason, AIX repeats the wtmp entry for logouts * with ssh */ if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0) { memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S)); SL_RET0(_("sh_utmp_addlogin")); } memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S)); /* Take the address to keep gcc from putting them into registers. * Avoids the 'clobbered by longjmp' warning. */ sh_dummy_850_userold = (void*) &userold; sh_dummy_851_user = (void*) &user; /* ------- find user -------- */ while (user != NULL) { if (0 == sl_strncmp((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE) ) break; userold = user; user = user->next; } #ifdef HAVE_UTTYPE while (username != NULL) { if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) ) break; username = username->next; } #endif #ifdef HAVE_UTTYPE /* ---------- LOGIN -------------- */ if (ut->ut_type == USER_PROCESS) { if (user == NULL) { user = SH_ALLOC(sizeof(struct log_user)); user->next = userlist; userlist = (struct log_user *) user; } (void) sl_strlcpy((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE+1); (void) sl_strlcpy((char*)(user->name), ut->ut_name, UT_NAMESIZE+1); #ifdef HAVE_UTHOST (void) sl_strlcpy((char*)(user->ut_host), ut->ut_host, UT_HOSTSIZE+1); #else user->ut_host[0] = '\0'; #endif #ifdef HAVE_UTADDR #ifdef HAVE_UTADDR_V6 my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF); #else my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF); #endif #endif user->time = ut->ut_time; if (username == NULL /* not yet logged in */ || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */ || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */ ) { status = sh_utmp_login_a((char*)user->name); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (user->time, ttt, TIM_MAX); sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG1X, #elif defined(HAVE_UTHOST) MSG_UT_LG1A, #else MSG_UT_LG1B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, status ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } else if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) { status = sh_utmp_login_a((char*)user->name); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (user->time, ttt, TIM_MAX); sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG2X, #elif defined(HAVE_UTHOST) MSG_UT_LG2A, #else MSG_UT_LG2B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, status ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } sh_utmp_login_morechecks(ut); goto out; } /* --------- LOGOUT ---------------- */ else if (ut->ut_name[0] == '\0' || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */ ) { if (user != NULL) { #if defined(__linux__) if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) { #endif status = sh_utmp_login_r((char*)user->name); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX); sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG3X, #elif defined(HAVE_UTHOST) MSG_UT_LG3A, #else MSG_UT_LG3B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, status ); SH_MUTEX_UNLOCK(mutex_thread_nolog); userold->next = user->next; if (user == userlist) userlist = user->next; sh_utmp_logout_morechecks((struct log_user *)user); SH_FREE((struct log_user *)user); user = NULL; #if defined(__linux__) } #endif } else { (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX); sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0, MSG_UT_LG3C, terminated_line, ttt, 0 ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } goto out; } /* default */ goto out; /* #ifdef HAVE_UTTYPE */ #else if (user == NULL) /* probably a login */ { user = SH_ALLOC(sizeof(struct log_user)); sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1); sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1); #ifdef HAVE_UTHOST sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1); #endif #ifdef HAVE_UTADDR #ifdef HAVE_UTADDR_V6 my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF); #else my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF); #endif #endif user->time = ut->ut_time; user->next = userlist; userlist = user; SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (user->time, ttt, TIM_MAX); sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG1X, #elif defined(HAVE_UTHOST) MSG_UT_LG1A, #else MSG_UT_LG1B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, 1 ); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_utmp_login_morechecks(ut); } else /* probably a logout */ { SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX); sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG2X, #elif defined(HAVE_UTHOST) MSG_UT_LG2A, #else MSG_UT_LG2B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, 1 ); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_utmp_logout_morechecks(user); userold->next = user->next; if (user == userlist) /* inserted Apr 4, 2004 */ userlist = user->next; SH_FREE(user); user = NULL; } #endif out: sh_dummy_851_user = NULL; sh_dummy_850_userold = NULL; SL_RET0(_("sh_utmp_addlogin")); } static time_t lastmod = 0; static off_t lastsize = 0; static unsigned long lastread = 0; static void sh_utmp_check_internal (int mode) { struct stat buf; int error; struct SH_UTMP_S * ut; unsigned long this_read; int val_retry; SL_ENTER(_("sh_utmp_check_internal")); /* error if no access */ do { val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/; } while (val_retry < 0 && errno == EINTR); if (0 != val_retry) { error = errno; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS, (long) sh.real.uid, mode_path[mode]); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RET0(_("sh_utmp_check_internal")); } /* modification time */ if (mode < 2) { if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/) { SL_RET0(_("sh_utmp_check_internal")); } else lastmod = buf.st_mtime; } /* file size */ if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT, mode_path[mode]); SH_MUTEX_UNLOCK(mutex_thread_nolog); lastread = 0; #ifndef USE_SETUTENT sh_utmp_feed_forward = 0L; #endif } if (mode < 2) lastsize = buf.st_size; if (buf.st_size == 0) SL_RET0(_("sh_utmp_check_internal")); sh_utmp_utmpname(mode_path[mode]); sh_utmp_setutent(); /* * feed forward if initializing * we need to do this here */ this_read = 0; if (mode < 2) { while (this_read < lastread) { (void) sh_utmp_getutent(); ++this_read; } } /* start reading */ this_read = 0; while (1 == 1) { ut = sh_utmp_getutent(); if (ut == NULL) break; /* modified: ut_user --> ut_name */ if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0' #ifdef HAVE_UTTYPE && ut->ut_type != DEAD_PROCESS #endif )) sh_utmp_addlogin (ut); ++this_read; } sh_utmp_endutent(); if (mode < 2) { lastread += this_read; #ifndef USE_SETUTENT sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S)); lastread = 0; #endif } SL_RET0(_("sh_utmp_check_internal")); } extern void sh_ltrack_check(struct SH_UTMP_S * ut); static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut) { sh_ltrack_check(ut); return; } static void sh_utmp_logout_morechecks(struct log_user * user) { (void) user; return; } #endif /* #ifdef SH_USE_UTMP */ #endif samhain-4.1.4/src/sh_tiger2_64.c0000644000175000017500000011725212615253277013235 00000000000000/* Tiger: A Fast New Hash Function * * Ross Anderson and Eli Biham * * From the homepage (http://www.cs.technion.ac.il/~biham/Reports/Tiger/): * * Tiger has no usage restrictions nor patents. It can be used freely, * with the reference implementation, with other implementations or with * a modification to the reference implementation (as long as it still * implements Tiger). We only ask you to let us know about your * implementation and to cite the origin of Tiger and of the reference * implementation. * * * The authors' home pages can be found both in * http://www.cs.technion.ac.il/~biham/ and in * http://www.cl.cam.ac.uk/users/rja14/. * The authors' email addresses are biham@cs.technion.ac.il * and rja14@cl.cam.ac.uk. */ #include "config_xor.h" #if defined(TIGER_64_BIT) /* #if defined(HAVE_LONG_64) || defined(HAVE_LONG_LONG_64) */ /*@-type@*/ /* sboxes.c: Tiger S boxes */ #if defined(HAVE_LONG_64) typedef unsigned long int word64; #elif defined(HAVE_LONG_LONG_64) typedef unsigned long long int word64; #else #error No 64 bit type found ! #endif word64 tiger_table[4*256] = { 0x02AAB17CF7E90C5ELL /* 0 */, 0xAC424B03E243A8ECLL /* 1 */, 0x72CD5BE30DD5FCD3LL /* 2 */, 0x6D019B93F6F97F3ALL /* 3 */, 0xCD9978FFD21F9193LL /* 4 */, 0x7573A1C9708029E2LL /* 5 */, 0xB164326B922A83C3LL /* 6 */, 0x46883EEE04915870LL /* 7 */, 0xEAACE3057103ECE6LL /* 8 */, 0xC54169B808A3535CLL /* 9 */, 0x4CE754918DDEC47CLL /* 10 */, 0x0AA2F4DFDC0DF40CLL /* 11 */, 0x10B76F18A74DBEFALL /* 12 */, 0xC6CCB6235AD1AB6ALL /* 13 */, 0x13726121572FE2FFLL /* 14 */, 0x1A488C6F199D921ELL /* 15 */, 0x4BC9F9F4DA0007CALL /* 16 */, 0x26F5E6F6E85241C7LL /* 17 */, 0x859079DBEA5947B6LL /* 18 */, 0x4F1885C5C99E8C92LL /* 19 */, 0xD78E761EA96F864BLL /* 20 */, 0x8E36428C52B5C17DLL /* 21 */, 0x69CF6827373063C1LL /* 22 */, 0xB607C93D9BB4C56ELL /* 23 */, 0x7D820E760E76B5EALL /* 24 */, 0x645C9CC6F07FDC42LL /* 25 */, 0xBF38A078243342E0LL /* 26 */, 0x5F6B343C9D2E7D04LL /* 27 */, 0xF2C28AEB600B0EC6LL /* 28 */, 0x6C0ED85F7254BCACLL /* 29 */, 0x71592281A4DB4FE5LL /* 30 */, 0x1967FA69CE0FED9FLL /* 31 */, 0xFD5293F8B96545DBLL /* 32 */, 0xC879E9D7F2A7600BLL /* 33 */, 0x860248920193194ELL /* 34 */, 0xA4F9533B2D9CC0B3LL /* 35 */, 0x9053836C15957613LL /* 36 */, 0xDB6DCF8AFC357BF1LL /* 37 */, 0x18BEEA7A7A370F57LL /* 38 */, 0x037117CA50B99066LL /* 39 */, 0x6AB30A9774424A35LL /* 40 */, 0xF4E92F02E325249BLL /* 41 */, 0x7739DB07061CCAE1LL /* 42 */, 0xD8F3B49CECA42A05LL /* 43 */, 0xBD56BE3F51382F73LL /* 44 */, 0x45FAED5843B0BB28LL /* 45 */, 0x1C813D5C11BF1F83LL /* 46 */, 0x8AF0E4B6D75FA169LL /* 47 */, 0x33EE18A487AD9999LL /* 48 */, 0x3C26E8EAB1C94410LL /* 49 */, 0xB510102BC0A822F9LL /* 50 */, 0x141EEF310CE6123BLL /* 51 */, 0xFC65B90059DDB154LL /* 52 */, 0xE0158640C5E0E607LL /* 53 */, 0x884E079826C3A3CFLL /* 54 */, 0x930D0D9523C535FDLL /* 55 */, 0x35638D754E9A2B00LL /* 56 */, 0x4085FCCF40469DD5LL /* 57 */, 0xC4B17AD28BE23A4CLL /* 58 */, 0xCAB2F0FC6A3E6A2ELL /* 59 */, 0x2860971A6B943FCDLL /* 60 */, 0x3DDE6EE212E30446LL /* 61 */, 0x6222F32AE01765AELL /* 62 */, 0x5D550BB5478308FELL /* 63 */, 0xA9EFA98DA0EDA22ALL /* 64 */, 0xC351A71686C40DA7LL /* 65 */, 0x1105586D9C867C84LL /* 66 */, 0xDCFFEE85FDA22853LL /* 67 */, 0xCCFBD0262C5EEF76LL /* 68 */, 0xBAF294CB8990D201LL /* 69 */, 0xE69464F52AFAD975LL /* 70 */, 0x94B013AFDF133E14LL /* 71 */, 0x06A7D1A32823C958LL /* 72 */, 0x6F95FE5130F61119LL /* 73 */, 0xD92AB34E462C06C0LL /* 74 */, 0xED7BDE33887C71D2LL /* 75 */, 0x79746D6E6518393ELL /* 76 */, 0x5BA419385D713329LL /* 77 */, 0x7C1BA6B948A97564LL /* 78 */, 0x31987C197BFDAC67LL /* 79 */, 0xDE6C23C44B053D02LL /* 80 */, 0x581C49FED002D64DLL /* 81 */, 0xDD474D6338261571LL /* 82 */, 0xAA4546C3E473D062LL /* 83 */, 0x928FCE349455F860LL /* 84 */, 0x48161BBACAAB94D9LL /* 85 */, 0x63912430770E6F68LL /* 86 */, 0x6EC8A5E602C6641CLL /* 87 */, 0x87282515337DDD2BLL /* 88 */, 0x2CDA6B42034B701BLL /* 89 */, 0xB03D37C181CB096DLL /* 90 */, 0xE108438266C71C6FLL /* 91 */, 0x2B3180C7EB51B255LL /* 92 */, 0xDF92B82F96C08BBCLL /* 93 */, 0x5C68C8C0A632F3BALL /* 94 */, 0x5504CC861C3D0556LL /* 95 */, 0xABBFA4E55FB26B8FLL /* 96 */, 0x41848B0AB3BACEB4LL /* 97 */, 0xB334A273AA445D32LL /* 98 */, 0xBCA696F0A85AD881LL /* 99 */, 0x24F6EC65B528D56CLL /* 100 */, 0x0CE1512E90F4524ALL /* 101 */, 0x4E9DD79D5506D35ALL /* 102 */, 0x258905FAC6CE9779LL /* 103 */, 0x2019295B3E109B33LL /* 104 */, 0xF8A9478B73A054CCLL /* 105 */, 0x2924F2F934417EB0LL /* 106 */, 0x3993357D536D1BC4LL /* 107 */, 0x38A81AC21DB6FF8BLL /* 108 */, 0x47C4FBF17D6016BFLL /* 109 */, 0x1E0FAADD7667E3F5LL /* 110 */, 0x7ABCFF62938BEB96LL /* 111 */, 0xA78DAD948FC179C9LL /* 112 */, 0x8F1F98B72911E50DLL /* 113 */, 0x61E48EAE27121A91LL /* 114 */, 0x4D62F7AD31859808LL /* 115 */, 0xECEBA345EF5CEAEBLL /* 116 */, 0xF5CEB25EBC9684CELL /* 117 */, 0xF633E20CB7F76221LL /* 118 */, 0xA32CDF06AB8293E4LL /* 119 */, 0x985A202CA5EE2CA4LL /* 120 */, 0xCF0B8447CC8A8FB1LL /* 121 */, 0x9F765244979859A3LL /* 122 */, 0xA8D516B1A1240017LL /* 123 */, 0x0BD7BA3EBB5DC726LL /* 124 */, 0xE54BCA55B86ADB39LL /* 125 */, 0x1D7A3AFD6C478063LL /* 126 */, 0x519EC608E7669EDDLL /* 127 */, 0x0E5715A2D149AA23LL /* 128 */, 0x177D4571848FF194LL /* 129 */, 0xEEB55F3241014C22LL /* 130 */, 0x0F5E5CA13A6E2EC2LL /* 131 */, 0x8029927B75F5C361LL /* 132 */, 0xAD139FABC3D6E436LL /* 133 */, 0x0D5DF1A94CCF402FLL /* 134 */, 0x3E8BD948BEA5DFC8LL /* 135 */, 0xA5A0D357BD3FF77ELL /* 136 */, 0xA2D12E251F74F645LL /* 137 */, 0x66FD9E525E81A082LL /* 138 */, 0x2E0C90CE7F687A49LL /* 139 */, 0xC2E8BCBEBA973BC5LL /* 140 */, 0x000001BCE509745FLL /* 141 */, 0x423777BBE6DAB3D6LL /* 142 */, 0xD1661C7EAEF06EB5LL /* 143 */, 0xA1781F354DAACFD8LL /* 144 */, 0x2D11284A2B16AFFCLL /* 145 */, 0xF1FC4F67FA891D1FLL /* 146 */, 0x73ECC25DCB920ADALL /* 147 */, 0xAE610C22C2A12651LL /* 148 */, 0x96E0A810D356B78ALL /* 149 */, 0x5A9A381F2FE7870FLL /* 150 */, 0xD5AD62EDE94E5530LL /* 151 */, 0xD225E5E8368D1427LL /* 152 */, 0x65977B70C7AF4631LL /* 153 */, 0x99F889B2DE39D74FLL /* 154 */, 0x233F30BF54E1D143LL /* 155 */, 0x9A9675D3D9A63C97LL /* 156 */, 0x5470554FF334F9A8LL /* 157 */, 0x166ACB744A4F5688LL /* 158 */, 0x70C74CAAB2E4AEADLL /* 159 */, 0xF0D091646F294D12LL /* 160 */, 0x57B82A89684031D1LL /* 161 */, 0xEFD95A5A61BE0B6BLL /* 162 */, 0x2FBD12E969F2F29ALL /* 163 */, 0x9BD37013FEFF9FE8LL /* 164 */, 0x3F9B0404D6085A06LL /* 165 */, 0x4940C1F3166CFE15LL /* 166 */, 0x09542C4DCDF3DEFBLL /* 167 */, 0xB4C5218385CD5CE3LL /* 168 */, 0xC935B7DC4462A641LL /* 169 */, 0x3417F8A68ED3B63FLL /* 170 */, 0xB80959295B215B40LL /* 171 */, 0xF99CDAEF3B8C8572LL /* 172 */, 0x018C0614F8FCB95DLL /* 173 */, 0x1B14ACCD1A3ACDF3LL /* 174 */, 0x84D471F200BB732DLL /* 175 */, 0xC1A3110E95E8DA16LL /* 176 */, 0x430A7220BF1A82B8LL /* 177 */, 0xB77E090D39DF210ELL /* 178 */, 0x5EF4BD9F3CD05E9DLL /* 179 */, 0x9D4FF6DA7E57A444LL /* 180 */, 0xDA1D60E183D4A5F8LL /* 181 */, 0xB287C38417998E47LL /* 182 */, 0xFE3EDC121BB31886LL /* 183 */, 0xC7FE3CCC980CCBEFLL /* 184 */, 0xE46FB590189BFD03LL /* 185 */, 0x3732FD469A4C57DCLL /* 186 */, 0x7EF700A07CF1AD65LL /* 187 */, 0x59C64468A31D8859LL /* 188 */, 0x762FB0B4D45B61F6LL /* 189 */, 0x155BAED099047718LL /* 190 */, 0x68755E4C3D50BAA6LL /* 191 */, 0xE9214E7F22D8B4DFLL /* 192 */, 0x2ADDBF532EAC95F4LL /* 193 */, 0x32AE3909B4BD0109LL /* 194 */, 0x834DF537B08E3450LL /* 195 */, 0xFA209DA84220728DLL /* 196 */, 0x9E691D9B9EFE23F7LL /* 197 */, 0x0446D288C4AE8D7FLL /* 198 */, 0x7B4CC524E169785BLL /* 199 */, 0x21D87F0135CA1385LL /* 200 */, 0xCEBB400F137B8AA5LL /* 201 */, 0x272E2B66580796BELL /* 202 */, 0x3612264125C2B0DELL /* 203 */, 0x057702BDAD1EFBB2LL /* 204 */, 0xD4BABB8EACF84BE9LL /* 205 */, 0x91583139641BC67BLL /* 206 */, 0x8BDC2DE08036E024LL /* 207 */, 0x603C8156F49F68EDLL /* 208 */, 0xF7D236F7DBEF5111LL /* 209 */, 0x9727C4598AD21E80LL /* 210 */, 0xA08A0896670A5FD7LL /* 211 */, 0xCB4A8F4309EBA9CBLL /* 212 */, 0x81AF564B0F7036A1LL /* 213 */, 0xC0B99AA778199ABDLL /* 214 */, 0x959F1EC83FC8E952LL /* 215 */, 0x8C505077794A81B9LL /* 216 */, 0x3ACAAF8F056338F0LL /* 217 */, 0x07B43F50627A6778LL /* 218 */, 0x4A44AB49F5ECCC77LL /* 219 */, 0x3BC3D6E4B679EE98LL /* 220 */, 0x9CC0D4D1CF14108CLL /* 221 */, 0x4406C00B206BC8A0LL /* 222 */, 0x82A18854C8D72D89LL /* 223 */, 0x67E366B35C3C432CLL /* 224 */, 0xB923DD61102B37F2LL /* 225 */, 0x56AB2779D884271DLL /* 226 */, 0xBE83E1B0FF1525AFLL /* 227 */, 0xFB7C65D4217E49A9LL /* 228 */, 0x6BDBE0E76D48E7D4LL /* 229 */, 0x08DF828745D9179ELL /* 230 */, 0x22EA6A9ADD53BD34LL /* 231 */, 0xE36E141C5622200ALL /* 232 */, 0x7F805D1B8CB750EELL /* 233 */, 0xAFE5C7A59F58E837LL /* 234 */, 0xE27F996A4FB1C23CLL /* 235 */, 0xD3867DFB0775F0D0LL /* 236 */, 0xD0E673DE6E88891ALL /* 237 */, 0x123AEB9EAFB86C25LL /* 238 */, 0x30F1D5D5C145B895LL /* 239 */, 0xBB434A2DEE7269E7LL /* 240 */, 0x78CB67ECF931FA38LL /* 241 */, 0xF33B0372323BBF9CLL /* 242 */, 0x52D66336FB279C74LL /* 243 */, 0x505F33AC0AFB4EAALL /* 244 */, 0xE8A5CD99A2CCE187LL /* 245 */, 0x534974801E2D30BBLL /* 246 */, 0x8D2D5711D5876D90LL /* 247 */, 0x1F1A412891BC038ELL /* 248 */, 0xD6E2E71D82E56648LL /* 249 */, 0x74036C3A497732B7LL /* 250 */, 0x89B67ED96361F5ABLL /* 251 */, 0xFFED95D8F1EA02A2LL /* 252 */, 0xE72B3BD61464D43DLL /* 253 */, 0xA6300F170BDC4820LL /* 254 */, 0xEBC18760ED78A77ALL /* 255 */, 0xE6A6BE5A05A12138LL /* 256 */, 0xB5A122A5B4F87C98LL /* 257 */, 0x563C6089140B6990LL /* 258 */, 0x4C46CB2E391F5DD5LL /* 259 */, 0xD932ADDBC9B79434LL /* 260 */, 0x08EA70E42015AFF5LL /* 261 */, 0xD765A6673E478CF1LL /* 262 */, 0xC4FB757EAB278D99LL /* 263 */, 0xDF11C6862D6E0692LL /* 264 */, 0xDDEB84F10D7F3B16LL /* 265 */, 0x6F2EF604A665EA04LL /* 266 */, 0x4A8E0F0FF0E0DFB3LL /* 267 */, 0xA5EDEEF83DBCBA51LL /* 268 */, 0xFC4F0A2A0EA4371ELL /* 269 */, 0xE83E1DA85CB38429LL /* 270 */, 0xDC8FF882BA1B1CE2LL /* 271 */, 0xCD45505E8353E80DLL /* 272 */, 0x18D19A00D4DB0717LL /* 273 */, 0x34A0CFEDA5F38101LL /* 274 */, 0x0BE77E518887CAF2LL /* 275 */, 0x1E341438B3C45136LL /* 276 */, 0xE05797F49089CCF9LL /* 277 */, 0xFFD23F9DF2591D14LL /* 278 */, 0x543DDA228595C5CDLL /* 279 */, 0x661F81FD99052A33LL /* 280 */, 0x8736E641DB0F7B76LL /* 281 */, 0x15227725418E5307LL /* 282 */, 0xE25F7F46162EB2FALL /* 283 */, 0x48A8B2126C13D9FELL /* 284 */, 0xAFDC541792E76EEALL /* 285 */, 0x03D912BFC6D1898FLL /* 286 */, 0x31B1AAFA1B83F51BLL /* 287 */, 0xF1AC2796E42AB7D9LL /* 288 */, 0x40A3A7D7FCD2EBACLL /* 289 */, 0x1056136D0AFBBCC5LL /* 290 */, 0x7889E1DD9A6D0C85LL /* 291 */, 0xD33525782A7974AALL /* 292 */, 0xA7E25D09078AC09BLL /* 293 */, 0xBD4138B3EAC6EDD0LL /* 294 */, 0x920ABFBE71EB9E70LL /* 295 */, 0xA2A5D0F54FC2625CLL /* 296 */, 0xC054E36B0B1290A3LL /* 297 */, 0xF6DD59FF62FE932BLL /* 298 */, 0x3537354511A8AC7DLL /* 299 */, 0xCA845E9172FADCD4LL /* 300 */, 0x84F82B60329D20DCLL /* 301 */, 0x79C62CE1CD672F18LL /* 302 */, 0x8B09A2ADD124642CLL /* 303 */, 0xD0C1E96A19D9E726LL /* 304 */, 0x5A786A9B4BA9500CLL /* 305 */, 0x0E020336634C43F3LL /* 306 */, 0xC17B474AEB66D822LL /* 307 */, 0x6A731AE3EC9BAAC2LL /* 308 */, 0x8226667AE0840258LL /* 309 */, 0x67D4567691CAECA5LL /* 310 */, 0x1D94155C4875ADB5LL /* 311 */, 0x6D00FD985B813FDFLL /* 312 */, 0x51286EFCB774CD06LL /* 313 */, 0x5E8834471FA744AFLL /* 314 */, 0xF72CA0AEE761AE2ELL /* 315 */, 0xBE40E4CDAEE8E09ALL /* 316 */, 0xE9970BBB5118F665LL /* 317 */, 0x726E4BEB33DF1964LL /* 318 */, 0x703B000729199762LL /* 319 */, 0x4631D816F5EF30A7LL /* 320 */, 0xB880B5B51504A6BELL /* 321 */, 0x641793C37ED84B6CLL /* 322 */, 0x7B21ED77F6E97D96LL /* 323 */, 0x776306312EF96B73LL /* 324 */, 0xAE528948E86FF3F4LL /* 325 */, 0x53DBD7F286A3F8F8LL /* 326 */, 0x16CADCE74CFC1063LL /* 327 */, 0x005C19BDFA52C6DDLL /* 328 */, 0x68868F5D64D46AD3LL /* 329 */, 0x3A9D512CCF1E186ALL /* 330 */, 0x367E62C2385660AELL /* 331 */, 0xE359E7EA77DCB1D7LL /* 332 */, 0x526C0773749ABE6ELL /* 333 */, 0x735AE5F9D09F734BLL /* 334 */, 0x493FC7CC8A558BA8LL /* 335 */, 0xB0B9C1533041AB45LL /* 336 */, 0x321958BA470A59BDLL /* 337 */, 0x852DB00B5F46C393LL /* 338 */, 0x91209B2BD336B0E5LL /* 339 */, 0x6E604F7D659EF19FLL /* 340 */, 0xB99A8AE2782CCB24LL /* 341 */, 0xCCF52AB6C814C4C7LL /* 342 */, 0x4727D9AFBE11727BLL /* 343 */, 0x7E950D0C0121B34DLL /* 344 */, 0x756F435670AD471FLL /* 345 */, 0xF5ADD442615A6849LL /* 346 */, 0x4E87E09980B9957ALL /* 347 */, 0x2ACFA1DF50AEE355LL /* 348 */, 0xD898263AFD2FD556LL /* 349 */, 0xC8F4924DD80C8FD6LL /* 350 */, 0xCF99CA3D754A173ALL /* 351 */, 0xFE477BACAF91BF3CLL /* 352 */, 0xED5371F6D690C12DLL /* 353 */, 0x831A5C285E687094LL /* 354 */, 0xC5D3C90A3708A0A4LL /* 355 */, 0x0F7F903717D06580LL /* 356 */, 0x19F9BB13B8FDF27FLL /* 357 */, 0xB1BD6F1B4D502843LL /* 358 */, 0x1C761BA38FFF4012LL /* 359 */, 0x0D1530C4E2E21F3BLL /* 360 */, 0x8943CE69A7372C8ALL /* 361 */, 0xE5184E11FEB5CE66LL /* 362 */, 0x618BDB80BD736621LL /* 363 */, 0x7D29BAD68B574D0BLL /* 364 */, 0x81BB613E25E6FE5BLL /* 365 */, 0x071C9C10BC07913FLL /* 366 */, 0xC7BEEB7909AC2D97LL /* 367 */, 0xC3E58D353BC5D757LL /* 368 */, 0xEB017892F38F61E8LL /* 369 */, 0xD4EFFB9C9B1CC21ALL /* 370 */, 0x99727D26F494F7ABLL /* 371 */, 0xA3E063A2956B3E03LL /* 372 */, 0x9D4A8B9A4AA09C30LL /* 373 */, 0x3F6AB7D500090FB4LL /* 374 */, 0x9CC0F2A057268AC0LL /* 375 */, 0x3DEE9D2DEDBF42D1LL /* 376 */, 0x330F49C87960A972LL /* 377 */, 0xC6B2720287421B41LL /* 378 */, 0x0AC59EC07C00369CLL /* 379 */, 0xEF4EAC49CB353425LL /* 380 */, 0xF450244EEF0129D8LL /* 381 */, 0x8ACC46E5CAF4DEB6LL /* 382 */, 0x2FFEAB63989263F7LL /* 383 */, 0x8F7CB9FE5D7A4578LL /* 384 */, 0x5BD8F7644E634635LL /* 385 */, 0x427A7315BF2DC900LL /* 386 */, 0x17D0C4AA2125261CLL /* 387 */, 0x3992486C93518E50LL /* 388 */, 0xB4CBFEE0A2D7D4C3LL /* 389 */, 0x7C75D6202C5DDD8DLL /* 390 */, 0xDBC295D8E35B6C61LL /* 391 */, 0x60B369D302032B19LL /* 392 */, 0xCE42685FDCE44132LL /* 393 */, 0x06F3DDB9DDF65610LL /* 394 */, 0x8EA4D21DB5E148F0LL /* 395 */, 0x20B0FCE62FCD496FLL /* 396 */, 0x2C1B912358B0EE31LL /* 397 */, 0xB28317B818F5A308LL /* 398 */, 0xA89C1E189CA6D2CFLL /* 399 */, 0x0C6B18576AAADBC8LL /* 400 */, 0xB65DEAA91299FAE3LL /* 401 */, 0xFB2B794B7F1027E7LL /* 402 */, 0x04E4317F443B5BEBLL /* 403 */, 0x4B852D325939D0A6LL /* 404 */, 0xD5AE6BEEFB207FFCLL /* 405 */, 0x309682B281C7D374LL /* 406 */, 0xBAE309A194C3B475LL /* 407 */, 0x8CC3F97B13B49F05LL /* 408 */, 0x98A9422FF8293967LL /* 409 */, 0x244B16B01076FF7CLL /* 410 */, 0xF8BF571C663D67EELL /* 411 */, 0x1F0D6758EEE30DA1LL /* 412 */, 0xC9B611D97ADEB9B7LL /* 413 */, 0xB7AFD5887B6C57A2LL /* 414 */, 0x6290AE846B984FE1LL /* 415 */, 0x94DF4CDEACC1A5FDLL /* 416 */, 0x058A5BD1C5483AFFLL /* 417 */, 0x63166CC142BA3C37LL /* 418 */, 0x8DB8526EB2F76F40LL /* 419 */, 0xE10880036F0D6D4ELL /* 420 */, 0x9E0523C9971D311DLL /* 421 */, 0x45EC2824CC7CD691LL /* 422 */, 0x575B8359E62382C9LL /* 423 */, 0xFA9E400DC4889995LL /* 424 */, 0xD1823ECB45721568LL /* 425 */, 0xDAFD983B8206082FLL /* 426 */, 0xAA7D29082386A8CBLL /* 427 */, 0x269FCD4403B87588LL /* 428 */, 0x1B91F5F728BDD1E0LL /* 429 */, 0xE4669F39040201F6LL /* 430 */, 0x7A1D7C218CF04ADELL /* 431 */, 0x65623C29D79CE5CELL /* 432 */, 0x2368449096C00BB1LL /* 433 */, 0xAB9BF1879DA503BALL /* 434 */, 0xBC23ECB1A458058ELL /* 435 */, 0x9A58DF01BB401ECCLL /* 436 */, 0xA070E868A85F143DLL /* 437 */, 0x4FF188307DF2239ELL /* 438 */, 0x14D565B41A641183LL /* 439 */, 0xEE13337452701602LL /* 440 */, 0x950E3DCF3F285E09LL /* 441 */, 0x59930254B9C80953LL /* 442 */, 0x3BF299408930DA6DLL /* 443 */, 0xA955943F53691387LL /* 444 */, 0xA15EDECAA9CB8784LL /* 445 */, 0x29142127352BE9A0LL /* 446 */, 0x76F0371FFF4E7AFBLL /* 447 */, 0x0239F450274F2228LL /* 448 */, 0xBB073AF01D5E868BLL /* 449 */, 0xBFC80571C10E96C1LL /* 450 */, 0xD267088568222E23LL /* 451 */, 0x9671A3D48E80B5B0LL /* 452 */, 0x55B5D38AE193BB81LL /* 453 */, 0x693AE2D0A18B04B8LL /* 454 */, 0x5C48B4ECADD5335FLL /* 455 */, 0xFD743B194916A1CALL /* 456 */, 0x2577018134BE98C4LL /* 457 */, 0xE77987E83C54A4ADLL /* 458 */, 0x28E11014DA33E1B9LL /* 459 */, 0x270CC59E226AA213LL /* 460 */, 0x71495F756D1A5F60LL /* 461 */, 0x9BE853FB60AFEF77LL /* 462 */, 0xADC786A7F7443DBFLL /* 463 */, 0x0904456173B29A82LL /* 464 */, 0x58BC7A66C232BD5ELL /* 465 */, 0xF306558C673AC8B2LL /* 466 */, 0x41F639C6B6C9772ALL /* 467 */, 0x216DEFE99FDA35DALL /* 468 */, 0x11640CC71C7BE615LL /* 469 */, 0x93C43694565C5527LL /* 470 */, 0xEA038E6246777839LL /* 471 */, 0xF9ABF3CE5A3E2469LL /* 472 */, 0x741E768D0FD312D2LL /* 473 */, 0x0144B883CED652C6LL /* 474 */, 0xC20B5A5BA33F8552LL /* 475 */, 0x1AE69633C3435A9DLL /* 476 */, 0x97A28CA4088CFDECLL /* 477 */, 0x8824A43C1E96F420LL /* 478 */, 0x37612FA66EEEA746LL /* 479 */, 0x6B4CB165F9CF0E5ALL /* 480 */, 0x43AA1C06A0ABFB4ALL /* 481 */, 0x7F4DC26FF162796BLL /* 482 */, 0x6CBACC8E54ED9B0FLL /* 483 */, 0xA6B7FFEFD2BB253ELL /* 484 */, 0x2E25BC95B0A29D4FLL /* 485 */, 0x86D6A58BDEF1388CLL /* 486 */, 0xDED74AC576B6F054LL /* 487 */, 0x8030BDBC2B45805DLL /* 488 */, 0x3C81AF70E94D9289LL /* 489 */, 0x3EFF6DDA9E3100DBLL /* 490 */, 0xB38DC39FDFCC8847LL /* 491 */, 0x123885528D17B87ELL /* 492 */, 0xF2DA0ED240B1B642LL /* 493 */, 0x44CEFADCD54BF9A9LL /* 494 */, 0x1312200E433C7EE6LL /* 495 */, 0x9FFCC84F3A78C748LL /* 496 */, 0xF0CD1F72248576BBLL /* 497 */, 0xEC6974053638CFE4LL /* 498 */, 0x2BA7B67C0CEC4E4CLL /* 499 */, 0xAC2F4DF3E5CE32EDLL /* 500 */, 0xCB33D14326EA4C11LL /* 501 */, 0xA4E9044CC77E58BCLL /* 502 */, 0x5F513293D934FCEFLL /* 503 */, 0x5DC9645506E55444LL /* 504 */, 0x50DE418F317DE40ALL /* 505 */, 0x388CB31A69DDE259LL /* 506 */, 0x2DB4A83455820A86LL /* 507 */, 0x9010A91E84711AE9LL /* 508 */, 0x4DF7F0B7B1498371LL /* 509 */, 0xD62A2EABC0977179LL /* 510 */, 0x22FAC097AA8D5C0ELL /* 511 */, 0xF49FCC2FF1DAF39BLL /* 512 */, 0x487FD5C66FF29281LL /* 513 */, 0xE8A30667FCDCA83FLL /* 514 */, 0x2C9B4BE3D2FCCE63LL /* 515 */, 0xDA3FF74B93FBBBC2LL /* 516 */, 0x2FA165D2FE70BA66LL /* 517 */, 0xA103E279970E93D4LL /* 518 */, 0xBECDEC77B0E45E71LL /* 519 */, 0xCFB41E723985E497LL /* 520 */, 0xB70AAA025EF75017LL /* 521 */, 0xD42309F03840B8E0LL /* 522 */, 0x8EFC1AD035898579LL /* 523 */, 0x96C6920BE2B2ABC5LL /* 524 */, 0x66AF4163375A9172LL /* 525 */, 0x2174ABDCCA7127FBLL /* 526 */, 0xB33CCEA64A72FF41LL /* 527 */, 0xF04A4933083066A5LL /* 528 */, 0x8D970ACDD7289AF5LL /* 529 */, 0x8F96E8E031C8C25ELL /* 530 */, 0xF3FEC02276875D47LL /* 531 */, 0xEC7BF310056190DDLL /* 532 */, 0xF5ADB0AEBB0F1491LL /* 533 */, 0x9B50F8850FD58892LL /* 534 */, 0x4975488358B74DE8LL /* 535 */, 0xA3354FF691531C61LL /* 536 */, 0x0702BBE481D2C6EELL /* 537 */, 0x89FB24057DEDED98LL /* 538 */, 0xAC3075138596E902LL /* 539 */, 0x1D2D3580172772EDLL /* 540 */, 0xEB738FC28E6BC30DLL /* 541 */, 0x5854EF8F63044326LL /* 542 */, 0x9E5C52325ADD3BBELL /* 543 */, 0x90AA53CF325C4623LL /* 544 */, 0xC1D24D51349DD067LL /* 545 */, 0x2051CFEEA69EA624LL /* 546 */, 0x13220F0A862E7E4FLL /* 547 */, 0xCE39399404E04864LL /* 548 */, 0xD9C42CA47086FCB7LL /* 549 */, 0x685AD2238A03E7CCLL /* 550 */, 0x066484B2AB2FF1DBLL /* 551 */, 0xFE9D5D70EFBF79ECLL /* 552 */, 0x5B13B9DD9C481854LL /* 553 */, 0x15F0D475ED1509ADLL /* 554 */, 0x0BEBCD060EC79851LL /* 555 */, 0xD58C6791183AB7F8LL /* 556 */, 0xD1187C5052F3EEE4LL /* 557 */, 0xC95D1192E54E82FFLL /* 558 */, 0x86EEA14CB9AC6CA2LL /* 559 */, 0x3485BEB153677D5DLL /* 560 */, 0xDD191D781F8C492ALL /* 561 */, 0xF60866BAA784EBF9LL /* 562 */, 0x518F643BA2D08C74LL /* 563 */, 0x8852E956E1087C22LL /* 564 */, 0xA768CB8DC410AE8DLL /* 565 */, 0x38047726BFEC8E1ALL /* 566 */, 0xA67738B4CD3B45AALL /* 567 */, 0xAD16691CEC0DDE19LL /* 568 */, 0xC6D4319380462E07LL /* 569 */, 0xC5A5876D0BA61938LL /* 570 */, 0x16B9FA1FA58FD840LL /* 571 */, 0x188AB1173CA74F18LL /* 572 */, 0xABDA2F98C99C021FLL /* 573 */, 0x3E0580AB134AE816LL /* 574 */, 0x5F3B05B773645ABBLL /* 575 */, 0x2501A2BE5575F2F6LL /* 576 */, 0x1B2F74004E7E8BA9LL /* 577 */, 0x1CD7580371E8D953LL /* 578 */, 0x7F6ED89562764E30LL /* 579 */, 0xB15926FF596F003DLL /* 580 */, 0x9F65293DA8C5D6B9LL /* 581 */, 0x6ECEF04DD690F84CLL /* 582 */, 0x4782275FFF33AF88LL /* 583 */, 0xE41433083F820801LL /* 584 */, 0xFD0DFE409A1AF9B5LL /* 585 */, 0x4325A3342CDB396BLL /* 586 */, 0x8AE77E62B301B252LL /* 587 */, 0xC36F9E9F6655615ALL /* 588 */, 0x85455A2D92D32C09LL /* 589 */, 0xF2C7DEA949477485LL /* 590 */, 0x63CFB4C133A39EBALL /* 591 */, 0x83B040CC6EBC5462LL /* 592 */, 0x3B9454C8FDB326B0LL /* 593 */, 0x56F56A9E87FFD78CLL /* 594 */, 0x2DC2940D99F42BC6LL /* 595 */, 0x98F7DF096B096E2DLL /* 596 */, 0x19A6E01E3AD852BFLL /* 597 */, 0x42A99CCBDBD4B40BLL /* 598 */, 0xA59998AF45E9C559LL /* 599 */, 0x366295E807D93186LL /* 600 */, 0x6B48181BFAA1F773LL /* 601 */, 0x1FEC57E2157A0A1DLL /* 602 */, 0x4667446AF6201AD5LL /* 603 */, 0xE615EBCACFB0F075LL /* 604 */, 0xB8F31F4F68290778LL /* 605 */, 0x22713ED6CE22D11ELL /* 606 */, 0x3057C1A72EC3C93BLL /* 607 */, 0xCB46ACC37C3F1F2FLL /* 608 */, 0xDBB893FD02AAF50ELL /* 609 */, 0x331FD92E600B9FCFLL /* 610 */, 0xA498F96148EA3AD6LL /* 611 */, 0xA8D8426E8B6A83EALL /* 612 */, 0xA089B274B7735CDCLL /* 613 */, 0x87F6B3731E524A11LL /* 614 */, 0x118808E5CBC96749LL /* 615 */, 0x9906E4C7B19BD394LL /* 616 */, 0xAFED7F7E9B24A20CLL /* 617 */, 0x6509EADEEB3644A7LL /* 618 */, 0x6C1EF1D3E8EF0EDELL /* 619 */, 0xB9C97D43E9798FB4LL /* 620 */, 0xA2F2D784740C28A3LL /* 621 */, 0x7B8496476197566FLL /* 622 */, 0x7A5BE3E6B65F069DLL /* 623 */, 0xF96330ED78BE6F10LL /* 624 */, 0xEEE60DE77A076A15LL /* 625 */, 0x2B4BEE4AA08B9BD0LL /* 626 */, 0x6A56A63EC7B8894ELL /* 627 */, 0x02121359BA34FEF4LL /* 628 */, 0x4CBF99F8283703FCLL /* 629 */, 0x398071350CAF30C8LL /* 630 */, 0xD0A77A89F017687ALL /* 631 */, 0xF1C1A9EB9E423569LL /* 632 */, 0x8C7976282DEE8199LL /* 633 */, 0x5D1737A5DD1F7ABDLL /* 634 */, 0x4F53433C09A9FA80LL /* 635 */, 0xFA8B0C53DF7CA1D9LL /* 636 */, 0x3FD9DCBC886CCB77LL /* 637 */, 0xC040917CA91B4720LL /* 638 */, 0x7DD00142F9D1DCDFLL /* 639 */, 0x8476FC1D4F387B58LL /* 640 */, 0x23F8E7C5F3316503LL /* 641 */, 0x032A2244E7E37339LL /* 642 */, 0x5C87A5D750F5A74BLL /* 643 */, 0x082B4CC43698992ELL /* 644 */, 0xDF917BECB858F63CLL /* 645 */, 0x3270B8FC5BF86DDALL /* 646 */, 0x10AE72BB29B5DD76LL /* 647 */, 0x576AC94E7700362BLL /* 648 */, 0x1AD112DAC61EFB8FLL /* 649 */, 0x691BC30EC5FAA427LL /* 650 */, 0xFF246311CC327143LL /* 651 */, 0x3142368E30E53206LL /* 652 */, 0x71380E31E02CA396LL /* 653 */, 0x958D5C960AAD76F1LL /* 654 */, 0xF8D6F430C16DA536LL /* 655 */, 0xC8FFD13F1BE7E1D2LL /* 656 */, 0x7578AE66004DDBE1LL /* 657 */, 0x05833F01067BE646LL /* 658 */, 0xBB34B5AD3BFE586DLL /* 659 */, 0x095F34C9A12B97F0LL /* 660 */, 0x247AB64525D60CA8LL /* 661 */, 0xDCDBC6F3017477D1LL /* 662 */, 0x4A2E14D4DECAD24DLL /* 663 */, 0xBDB5E6D9BE0A1EEBLL /* 664 */, 0x2A7E70F7794301ABLL /* 665 */, 0xDEF42D8A270540FDLL /* 666 */, 0x01078EC0A34C22C1LL /* 667 */, 0xE5DE511AF4C16387LL /* 668 */, 0x7EBB3A52BD9A330ALL /* 669 */, 0x77697857AA7D6435LL /* 670 */, 0x004E831603AE4C32LL /* 671 */, 0xE7A21020AD78E312LL /* 672 */, 0x9D41A70C6AB420F2LL /* 673 */, 0x28E06C18EA1141E6LL /* 674 */, 0xD2B28CBD984F6B28LL /* 675 */, 0x26B75F6C446E9D83LL /* 676 */, 0xBA47568C4D418D7FLL /* 677 */, 0xD80BADBFE6183D8ELL /* 678 */, 0x0E206D7F5F166044LL /* 679 */, 0xE258A43911CBCA3ELL /* 680 */, 0x723A1746B21DC0BCLL /* 681 */, 0xC7CAA854F5D7CDD3LL /* 682 */, 0x7CAC32883D261D9CLL /* 683 */, 0x7690C26423BA942CLL /* 684 */, 0x17E55524478042B8LL /* 685 */, 0xE0BE477656A2389FLL /* 686 */, 0x4D289B5E67AB2DA0LL /* 687 */, 0x44862B9C8FBBFD31LL /* 688 */, 0xB47CC8049D141365LL /* 689 */, 0x822C1B362B91C793LL /* 690 */, 0x4EB14655FB13DFD8LL /* 691 */, 0x1ECBBA0714E2A97BLL /* 692 */, 0x6143459D5CDE5F14LL /* 693 */, 0x53A8FBF1D5F0AC89LL /* 694 */, 0x97EA04D81C5E5B00LL /* 695 */, 0x622181A8D4FDB3F3LL /* 696 */, 0xE9BCD341572A1208LL /* 697 */, 0x1411258643CCE58ALL /* 698 */, 0x9144C5FEA4C6E0A4LL /* 699 */, 0x0D33D06565CF620FLL /* 700 */, 0x54A48D489F219CA1LL /* 701 */, 0xC43E5EAC6D63C821LL /* 702 */, 0xA9728B3A72770DAFLL /* 703 */, 0xD7934E7B20DF87EFLL /* 704 */, 0xE35503B61A3E86E5LL /* 705 */, 0xCAE321FBC819D504LL /* 706 */, 0x129A50B3AC60BFA6LL /* 707 */, 0xCD5E68EA7E9FB6C3LL /* 708 */, 0xB01C90199483B1C7LL /* 709 */, 0x3DE93CD5C295376CLL /* 710 */, 0xAED52EDF2AB9AD13LL /* 711 */, 0x2E60F512C0A07884LL /* 712 */, 0xBC3D86A3E36210C9LL /* 713 */, 0x35269D9B163951CELL /* 714 */, 0x0C7D6E2AD0CDB5FALL /* 715 */, 0x59E86297D87F5733LL /* 716 */, 0x298EF221898DB0E7LL /* 717 */, 0x55000029D1A5AA7ELL /* 718 */, 0x8BC08AE1B5061B45LL /* 719 */, 0xC2C31C2B6C92703ALL /* 720 */, 0x94CC596BAF25EF42LL /* 721 */, 0x0A1D73DB22540456LL /* 722 */, 0x04B6A0F9D9C4179ALL /* 723 */, 0xEFFDAFA2AE3D3C60LL /* 724 */, 0xF7C8075BB49496C4LL /* 725 */, 0x9CC5C7141D1CD4E3LL /* 726 */, 0x78BD1638218E5534LL /* 727 */, 0xB2F11568F850246ALL /* 728 */, 0xEDFABCFA9502BC29LL /* 729 */, 0x796CE5F2DA23051BLL /* 730 */, 0xAAE128B0DC93537CLL /* 731 */, 0x3A493DA0EE4B29AELL /* 732 */, 0xB5DF6B2C416895D7LL /* 733 */, 0xFCABBD25122D7F37LL /* 734 */, 0x70810B58105DC4B1LL /* 735 */, 0xE10FDD37F7882A90LL /* 736 */, 0x524DCAB5518A3F5CLL /* 737 */, 0x3C9E85878451255BLL /* 738 */, 0x4029828119BD34E2LL /* 739 */, 0x74A05B6F5D3CECCBLL /* 740 */, 0xB610021542E13ECALL /* 741 */, 0x0FF979D12F59E2ACLL /* 742 */, 0x6037DA27E4F9CC50LL /* 743 */, 0x5E92975A0DF1847DLL /* 744 */, 0xD66DE190D3E623FELL /* 745 */, 0x5032D6B87B568048LL /* 746 */, 0x9A36B7CE8235216ELL /* 747 */, 0x80272A7A24F64B4ALL /* 748 */, 0x93EFED8B8C6916F7LL /* 749 */, 0x37DDBFF44CCE1555LL /* 750 */, 0x4B95DB5D4B99BD25LL /* 751 */, 0x92D3FDA169812FC0LL /* 752 */, 0xFB1A4A9A90660BB6LL /* 753 */, 0x730C196946A4B9B2LL /* 754 */, 0x81E289AA7F49DA68LL /* 755 */, 0x64669A0F83B1A05FLL /* 756 */, 0x27B3FF7D9644F48BLL /* 757 */, 0xCC6B615C8DB675B3LL /* 758 */, 0x674F20B9BCEBBE95LL /* 759 */, 0x6F31238275655982LL /* 760 */, 0x5AE488713E45CF05LL /* 761 */, 0xBF619F9954C21157LL /* 762 */, 0xEABAC46040A8EAE9LL /* 763 */, 0x454C6FE9F2C0C1CDLL /* 764 */, 0x419CF6496412691CLL /* 765 */, 0xD3DC3BEF265B0F70LL /* 766 */, 0x6D0E60F5C3578A9ELL /* 767 */, 0x5B0E608526323C55LL /* 768 */, 0x1A46C1A9FA1B59F5LL /* 769 */, 0xA9E245A17C4C8FFALL /* 770 */, 0x65CA5159DB2955D7LL /* 771 */, 0x05DB0A76CE35AFC2LL /* 772 */, 0x81EAC77EA9113D45LL /* 773 */, 0x528EF88AB6AC0A0DLL /* 774 */, 0xA09EA253597BE3FFLL /* 775 */, 0x430DDFB3AC48CD56LL /* 776 */, 0xC4B3A67AF45CE46FLL /* 777 */, 0x4ECECFD8FBE2D05ELL /* 778 */, 0x3EF56F10B39935F0LL /* 779 */, 0x0B22D6829CD619C6LL /* 780 */, 0x17FD460A74DF2069LL /* 781 */, 0x6CF8CC8E8510ED40LL /* 782 */, 0xD6C824BF3A6ECAA7LL /* 783 */, 0x61243D581A817049LL /* 784 */, 0x048BACB6BBC163A2LL /* 785 */, 0xD9A38AC27D44CC32LL /* 786 */, 0x7FDDFF5BAAF410ABLL /* 787 */, 0xAD6D495AA804824BLL /* 788 */, 0xE1A6A74F2D8C9F94LL /* 789 */, 0xD4F7851235DEE8E3LL /* 790 */, 0xFD4B7F886540D893LL /* 791 */, 0x247C20042AA4BFDALL /* 792 */, 0x096EA1C517D1327CLL /* 793 */, 0xD56966B4361A6685LL /* 794 */, 0x277DA5C31221057DLL /* 795 */, 0x94D59893A43ACFF7LL /* 796 */, 0x64F0C51CCDC02281LL /* 797 */, 0x3D33BCC4FF6189DBLL /* 798 */, 0xE005CB184CE66AF1LL /* 799 */, 0xFF5CCD1D1DB99BEALL /* 800 */, 0xB0B854A7FE42980FLL /* 801 */, 0x7BD46A6A718D4B9FLL /* 802 */, 0xD10FA8CC22A5FD8CLL /* 803 */, 0xD31484952BE4BD31LL /* 804 */, 0xC7FA975FCB243847LL /* 805 */, 0x4886ED1E5846C407LL /* 806 */, 0x28CDDB791EB70B04LL /* 807 */, 0xC2B00BE2F573417FLL /* 808 */, 0x5C9590452180F877LL /* 809 */, 0x7A6BDDFFF370EB00LL /* 810 */, 0xCE509E38D6D9D6A4LL /* 811 */, 0xEBEB0F00647FA702LL /* 812 */, 0x1DCC06CF76606F06LL /* 813 */, 0xE4D9F28BA286FF0ALL /* 814 */, 0xD85A305DC918C262LL /* 815 */, 0x475B1D8732225F54LL /* 816 */, 0x2D4FB51668CCB5FELL /* 817 */, 0xA679B9D9D72BBA20LL /* 818 */, 0x53841C0D912D43A5LL /* 819 */, 0x3B7EAA48BF12A4E8LL /* 820 */, 0x781E0E47F22F1DDFLL /* 821 */, 0xEFF20CE60AB50973LL /* 822 */, 0x20D261D19DFFB742LL /* 823 */, 0x16A12B03062A2E39LL /* 824 */, 0x1960EB2239650495LL /* 825 */, 0x251C16FED50EB8B8LL /* 826 */, 0x9AC0C330F826016ELL /* 827 */, 0xED152665953E7671LL /* 828 */, 0x02D63194A6369570LL /* 829 */, 0x5074F08394B1C987LL /* 830 */, 0x70BA598C90B25CE1LL /* 831 */, 0x794A15810B9742F6LL /* 832 */, 0x0D5925E9FCAF8C6CLL /* 833 */, 0x3067716CD868744ELL /* 834 */, 0x910AB077E8D7731BLL /* 835 */, 0x6A61BBDB5AC42F61LL /* 836 */, 0x93513EFBF0851567LL /* 837 */, 0xF494724B9E83E9D5LL /* 838 */, 0xE887E1985C09648DLL /* 839 */, 0x34B1D3C675370CFDLL /* 840 */, 0xDC35E433BC0D255DLL /* 841 */, 0xD0AAB84234131BE0LL /* 842 */, 0x08042A50B48B7EAFLL /* 843 */, 0x9997C4EE44A3AB35LL /* 844 */, 0x829A7B49201799D0LL /* 845 */, 0x263B8307B7C54441LL /* 846 */, 0x752F95F4FD6A6CA6LL /* 847 */, 0x927217402C08C6E5LL /* 848 */, 0x2A8AB754A795D9EELL /* 849 */, 0xA442F7552F72943DLL /* 850 */, 0x2C31334E19781208LL /* 851 */, 0x4FA98D7CEAEE6291LL /* 852 */, 0x55C3862F665DB309LL /* 853 */, 0xBD0610175D53B1F3LL /* 854 */, 0x46FE6CB840413F27LL /* 855 */, 0x3FE03792DF0CFA59LL /* 856 */, 0xCFE700372EB85E8FLL /* 857 */, 0xA7BE29E7ADBCE118LL /* 858 */, 0xE544EE5CDE8431DDLL /* 859 */, 0x8A781B1B41F1873ELL /* 860 */, 0xA5C94C78A0D2F0E7LL /* 861 */, 0x39412E2877B60728LL /* 862 */, 0xA1265EF3AFC9A62CLL /* 863 */, 0xBCC2770C6A2506C5LL /* 864 */, 0x3AB66DD5DCE1CE12LL /* 865 */, 0xE65499D04A675B37LL /* 866 */, 0x7D8F523481BFD216LL /* 867 */, 0x0F6F64FCEC15F389LL /* 868 */, 0x74EFBE618B5B13C8LL /* 869 */, 0xACDC82B714273E1DLL /* 870 */, 0xDD40BFE003199D17LL /* 871 */, 0x37E99257E7E061F8LL /* 872 */, 0xFA52626904775AAALL /* 873 */, 0x8BBBF63A463D56F9LL /* 874 */, 0xF0013F1543A26E64LL /* 875 */, 0xA8307E9F879EC898LL /* 876 */, 0xCC4C27A4150177CCLL /* 877 */, 0x1B432F2CCA1D3348LL /* 878 */, 0xDE1D1F8F9F6FA013LL /* 879 */, 0x606602A047A7DDD6LL /* 880 */, 0xD237AB64CC1CB2C7LL /* 881 */, 0x9B938E7225FCD1D3LL /* 882 */, 0xEC4E03708E0FF476LL /* 883 */, 0xFEB2FBDA3D03C12DLL /* 884 */, 0xAE0BCED2EE43889ALL /* 885 */, 0x22CB8923EBFB4F43LL /* 886 */, 0x69360D013CF7396DLL /* 887 */, 0x855E3602D2D4E022LL /* 888 */, 0x073805BAD01F784CLL /* 889 */, 0x33E17A133852F546LL /* 890 */, 0xDF4874058AC7B638LL /* 891 */, 0xBA92B29C678AA14ALL /* 892 */, 0x0CE89FC76CFAADCDLL /* 893 */, 0x5F9D4E0908339E34LL /* 894 */, 0xF1AFE9291F5923B9LL /* 895 */, 0x6E3480F60F4A265FLL /* 896 */, 0xEEBF3A2AB29B841CLL /* 897 */, 0xE21938A88F91B4ADLL /* 898 */, 0x57DFEFF845C6D3C3LL /* 899 */, 0x2F006B0BF62CAAF2LL /* 900 */, 0x62F479EF6F75EE78LL /* 901 */, 0x11A55AD41C8916A9LL /* 902 */, 0xF229D29084FED453LL /* 903 */, 0x42F1C27B16B000E6LL /* 904 */, 0x2B1F76749823C074LL /* 905 */, 0x4B76ECA3C2745360LL /* 906 */, 0x8C98F463B91691BDLL /* 907 */, 0x14BCC93CF1ADE66ALL /* 908 */, 0x8885213E6D458397LL /* 909 */, 0x8E177DF0274D4711LL /* 910 */, 0xB49B73B5503F2951LL /* 911 */, 0x10168168C3F96B6BLL /* 912 */, 0x0E3D963B63CAB0AELL /* 913 */, 0x8DFC4B5655A1DB14LL /* 914 */, 0xF789F1356E14DE5CLL /* 915 */, 0x683E68AF4E51DAC1LL /* 916 */, 0xC9A84F9D8D4B0FD9LL /* 917 */, 0x3691E03F52A0F9D1LL /* 918 */, 0x5ED86E46E1878E80LL /* 919 */, 0x3C711A0E99D07150LL /* 920 */, 0x5A0865B20C4E9310LL /* 921 */, 0x56FBFC1FE4F0682ELL /* 922 */, 0xEA8D5DE3105EDF9BLL /* 923 */, 0x71ABFDB12379187ALL /* 924 */, 0x2EB99DE1BEE77B9CLL /* 925 */, 0x21ECC0EA33CF4523LL /* 926 */, 0x59A4D7521805C7A1LL /* 927 */, 0x3896F5EB56AE7C72LL /* 928 */, 0xAA638F3DB18F75DCLL /* 929 */, 0x9F39358DABE9808ELL /* 930 */, 0xB7DEFA91C00B72ACLL /* 931 */, 0x6B5541FD62492D92LL /* 932 */, 0x6DC6DEE8F92E4D5BLL /* 933 */, 0x353F57ABC4BEEA7ELL /* 934 */, 0x735769D6DA5690CELL /* 935 */, 0x0A234AA642391484LL /* 936 */, 0xF6F9508028F80D9DLL /* 937 */, 0xB8E319A27AB3F215LL /* 938 */, 0x31AD9C1151341A4DLL /* 939 */, 0x773C22A57BEF5805LL /* 940 */, 0x45C7561A07968633LL /* 941 */, 0xF913DA9E249DBE36LL /* 942 */, 0xDA652D9B78A64C68LL /* 943 */, 0x4C27A97F3BC334EFLL /* 944 */, 0x76621220E66B17F4LL /* 945 */, 0x967743899ACD7D0BLL /* 946 */, 0xF3EE5BCAE0ED6782LL /* 947 */, 0x409F753600C879FCLL /* 948 */, 0x06D09A39B5926DB6LL /* 949 */, 0x6F83AEB0317AC588LL /* 950 */, 0x01E6CA4A86381F21LL /* 951 */, 0x66FF3462D19F3025LL /* 952 */, 0x72207C24DDFD3BFBLL /* 953 */, 0x4AF6B6D3E2ECE2EBLL /* 954 */, 0x9C994DBEC7EA08DELL /* 955 */, 0x49ACE597B09A8BC4LL /* 956 */, 0xB38C4766CF0797BALL /* 957 */, 0x131B9373C57C2A75LL /* 958 */, 0xB1822CCE61931E58LL /* 959 */, 0x9D7555B909BA1C0CLL /* 960 */, 0x127FAFDD937D11D2LL /* 961 */, 0x29DA3BADC66D92E4LL /* 962 */, 0xA2C1D57154C2ECBCLL /* 963 */, 0x58C5134D82F6FE24LL /* 964 */, 0x1C3AE3515B62274FLL /* 965 */, 0xE907C82E01CB8126LL /* 966 */, 0xF8ED091913E37FCBLL /* 967 */, 0x3249D8F9C80046C9LL /* 968 */, 0x80CF9BEDE388FB63LL /* 969 */, 0x1881539A116CF19ELL /* 970 */, 0x5103F3F76BD52457LL /* 971 */, 0x15B7E6F5AE47F7A8LL /* 972 */, 0xDBD7C6DED47E9CCFLL /* 973 */, 0x44E55C410228BB1ALL /* 974 */, 0xB647D4255EDB4E99LL /* 975 */, 0x5D11882BB8AAFC30LL /* 976 */, 0xF5098BBB29D3212ALL /* 977 */, 0x8FB5EA14E90296B3LL /* 978 */, 0x677B942157DD025ALL /* 979 */, 0xFB58E7C0A390ACB5LL /* 980 */, 0x89D3674C83BD4A01LL /* 981 */, 0x9E2DA4DF4BF3B93BLL /* 982 */, 0xFCC41E328CAB4829LL /* 983 */, 0x03F38C96BA582C52LL /* 984 */, 0xCAD1BDBD7FD85DB2LL /* 985 */, 0xBBB442C16082AE83LL /* 986 */, 0xB95FE86BA5DA9AB0LL /* 987 */, 0xB22E04673771A93FLL /* 988 */, 0x845358C9493152D8LL /* 989 */, 0xBE2A488697B4541ELL /* 990 */, 0x95A2DC2DD38E6966LL /* 991 */, 0xC02C11AC923C852BLL /* 992 */, 0x2388B1990DF2A87BLL /* 993 */, 0x7C8008FA1B4F37BELL /* 994 */, 0x1F70D0C84D54E503LL /* 995 */, 0x5490ADEC7ECE57D4LL /* 996 */, 0x002B3C27D9063A3ALL /* 997 */, 0x7EAEA3848030A2BFLL /* 998 */, 0xC602326DED2003C0LL /* 999 */, 0x83A7287D69A94086LL /* 1000 */, 0xC57A5FCB30F57A8ALL /* 1001 */, 0xB56844E479EBE779LL /* 1002 */, 0xA373B40F05DCBCE9LL /* 1003 */, 0xD71A786E88570EE2LL /* 1004 */, 0x879CBACDBDE8F6A0LL /* 1005 */, 0x976AD1BCC164A32FLL /* 1006 */, 0xAB21E25E9666D78BLL /* 1007 */, 0x901063AAE5E5C33CLL /* 1008 */, 0x9818B34448698D90LL /* 1009 */, 0xE36487AE3E1E8ABBLL /* 1010 */, 0xAFBDF931893BDCB4LL /* 1011 */, 0x6345A0DC5FBBD519LL /* 1012 */, 0x8628FE269B9465CALL /* 1013 */, 0x1E5D01603F9C51ECLL /* 1014 */, 0x4DE44006A15049B7LL /* 1015 */, 0xBF6C70E5F776CBB1LL /* 1016 */, 0x411218F2EF552BEDLL /* 1017 */, 0xCB0C0708705A36A3LL /* 1018 */, 0xE74D14754F986044LL /* 1019 */, 0xCD56D9430EA8280ELL /* 1020 */, 0xC12591D7535F5065LL /* 1021 */, 0xC83223F1720AEF96LL /* 1022 */, 0xC3A0396F7363A51FLL /* 1023 */}; #else void dummy_2_64 (int a) { (void) a; return; } #endif samhain-4.1.4/src/make-tests.sh0000755000175000017500000000337612615253277013307 00000000000000#!/bin/sh # Auto generate single AllTests file for CuTest. # Searches through all *.c files in the current directory. # Prints to stdout. # Author: Asim Jalis # Date: 01/08/2003 # Modified to return non-zero if any test has failed # Rainer Wichmann, 29. Jan 2006 # ...and to print to stderr if any test has failed # Rainer Wichmann, 31. Jan 2006 if test $# -eq 0 ; then FILES=*.c ; else FILES=$* ; fi echo ' /* This is auto-generated code. Edit at your own peril. */ #include "config.h" #include #include "CuTest.h" ' cat $FILES | grep '^void Test' | sed -e 's/(.*$//' \ -e 's/$/(CuTest*);/' \ -e 's/^/extern /' echo \ ' int RunAllTests(void) { CuString *output = CuStringNew(); CuSuite* suite = CuSuiteNew(); ' cat $FILES | grep '^void Test' | sed -e 's/^void //' \ -e 's/(.*$//' \ -e 's/^/ SUITE_ADD_TEST(suite, /' \ -e 's/$/);/' echo \ ' CuSuiteRun(suite); CuSuiteSummary(suite, output); CuSuiteDetails(suite, output); if (suite->failCount > 0) fprintf(stderr, "%s%c", output->buffer, 0x0A); else fprintf(stdout, "%s%c", output->buffer, 0x0A); return suite->failCount; } int main(void) { #if !defined(USE_SYSTEM_MALLOC) typedef void assert_handler_tp(const char * error, const char *file, int line); extern assert_handler_tp *dnmalloc_set_handler(assert_handler_tp *new); extern void safe_fatal (const char * details, const char *f, int l); #endif #if !defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK) extern int dnmalloc_pthread_init(void); dnmalloc_pthread_init(); #endif #if !defined(USE_SYSTEM_MALLOC) (void) dnmalloc_set_handler(safe_fatal); #endif int retval; retval = RunAllTests(); return (retval == 0) ? 0 : 1; } ' samhain-4.1.4/src/sh_filter.c0000644000175000017500000001472312615253277013014 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2009 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #ifdef HAVE_REGEX_H #include #endif #include "samhain.h" #include "sh_utils.h" #include "sh_mem.h" #include "sh_filter.h" #undef FIL__ #define FIL__ _("sh_filter.c") void sh_filter_free (sh_filter_type * filter) { int i; if (filter) { for (i = 0; i < filter->for_c; ++i) { #ifdef HAVE_REGEX_H if (filter->for_v[i]) regfree(filter->for_v[i]); #else if (filter->for_v[i]) SH_FREE(filter->for_v[i]); #endif filter->for_v[i] = NULL; } filter->for_c = 0; for (i = 0; i < filter->fand_c; ++i) { #ifdef HAVE_REGEX_H if (filter->fand_v[i]) regfree(filter->fand_v[i]); #else if (filter->fand_v[i]) SH_FREE(filter->fand_v[i]); #endif filter->fand_v[i] = NULL; } filter->fand_c = 0; for (i = 0; i < filter->fnot_c; ++i) { #ifdef HAVE_REGEX_H if (filter->fnot_v[i]) regfree(filter->fnot_v[i]); #else if (filter->fnot_v[i]) SH_FREE(filter->fnot_v[i]); #endif filter->fnot_v[i] = NULL; } filter->fnot_c = 0; } } int sh_filter_add (const char * str, sh_filter_type * filter, int type) { int i = 0; int flag = 0; size_t s; char * dupp; char * p; char * end; int * ntok; void ** stok; SL_ENTER(_("sh_filter_filteradd")); if (NULL == str || NULL == filter) { SL_RETURN((-1), _("sh_filter_filteradd")); } if (type == SH_FILT_OR) { ntok = &(filter->for_c); stok = filter->for_v; } else if (type == SH_FILT_AND) { ntok = &(filter->fand_c); stok = filter->fand_v; } else if (type == SH_FILT_NOT) { ntok = &(filter->fnot_c); stok = filter->fnot_v; } else { SL_RETURN((-1), _("sh_filter_filteradd")); } i = *ntok; if (i == SH_FILT_NUM) { SL_RETURN((-1), _("sh_filter_filteradd")); } dupp = sh_util_strdup(str); p = dupp; do { while (*p == ',' || *p == ' ' || *p == '\t') ++p; if (*p == '\0') break; end = p; ++end; if (*end == '\0') break; if (*p == '\'') { ++p; end = p; if (*end != '\'') ++end; if (*p == '\0' || *end == '\0') break; while (*end != '\0' && *end != '\'') ++end; } else if (*p == '"') { ++p; end = p; if (*end != '"') ++end; if (*p == '\0' || *end == '\0') break; while (*end != '\0' && *end != '"') ++end; } else { while (*end != '\0' && *end != ',' && *end != ' ' && *end != '\t') ++end; } if (*end == '\0') flag = 1; else *end = '\0'; s = strlen(p); if (s > 0) { ++s; #ifdef HAVE_REGEX_H if (stok[i] != NULL) regfree((regex_t *) stok[i]); { int status; stok[i] = SH_ALLOC(sizeof(regex_t)); status = regcomp((regex_t *) stok[i], p, REG_NOSUB|REG_EXTENDED); if (status != 0) { char * errbuf = SH_ALLOC(BUFSIZ); (void) regerror(status, (regex_t *) stok[i], errbuf, BUFSIZ); errbuf[BUFSIZ-1] = '\0'; sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX, errbuf, p); SH_FREE(errbuf); } } #else if (stok[i] != NULL) SH_FREE(stok[i]); stok[i] = SH_ALLOC(s); (void) sl_strlcpy((char *) stok[i], p, s); #endif ++i; } p = end; ++p; if (i == SH_FILT_NUM) break; } while (p != NULL && *p != '\0' && flag == 0); *ntok = i; SH_FREE(dupp); SL_RETURN (0, _("sh_filter_filteradd")); } #ifdef HAVE_REGEX_H static int sh_filter_cmp(const char * message, void * pattern) { int result; result = regexec((regex_t *)pattern, message, 0, NULL, 0); if (result != 0) return -1; /* Successful match. */ return 0; } #else static int sh_filter_cmp(const char * message, void * pattern) { if (NULL == sl_strstr(message, (char *)pattern)) return -1; /* Successful match. */ return 0; } #endif /* * -- Check filters. Returns 0 if message passes. */ int sh_filter_filter (const char * message, sh_filter_type * filter) { int i; SL_ENTER(_("sh_filter_filter")); if (filter) { /* Presence of any of these keywords prevents execution. */ if (filter->fnot_c > 0) { for (i = 0; i < filter->fnot_c; ++i) { if (0 == sh_filter_cmp(message, filter->fnot_v[i])) { SL_RETURN ((-1), _("sh_filter_filter")); } } } /* Presence of all of these keywords is required for execution. */ if (filter->fand_c > 0) { for (i = 0; i < filter->fand_c; ++i) { if (0 != sh_filter_cmp(message, filter->fand_v[i])) { SL_RETURN ((-1), _("sh_filter_filter")); } } } /* Presence of at least one of these keywords is required for execution. */ if (filter->for_c > 0) { for (i = 0; i < filter->for_c; ++i) { if (0 == sh_filter_cmp(message, filter->for_v[i])) { goto isok; } } SL_RETURN ((-1), _("sh_filter_filter")); } } isok: SL_RETURN ((0), _("sh_filter_filter")); } sh_filter_type * sh_filter_alloc(void) { sh_filter_type * filter = SH_ALLOC(sizeof(sh_filter_type)); memset(filter, '\0', sizeof(sh_filter_type)); filter->for_c = 0; filter->fand_c = 0; filter->fnot_c = 0; return filter; } samhain-4.1.4/src/samhain_stealth.c0000644000175000017500000002466512615253277014207 00000000000000#include "config_xor.h" #ifdef HAVE_BROKEN_INCLUDES #define _ANSI_C_SOURCE #define _POSIX_SOURCE #endif #include #include #include #include #include #include #include #include #include #ifndef SH_BUFSIZE #define SH_BUFSIZE 1024 #endif #ifdef SH_STEALTH char * globber(const char * string); #define _(string) globber(string) #define N_(string) string #else #define _(string) string #define N_(string) string #endif #ifdef SH_STEALTH #ifndef SH_MAX_GLOBS #define SH_MAX_GLOBS 32 #endif #ifndef GLOB_LEN #define GLOB_LEN 511 #endif char * globber(const char * str) { register int i, j; static int count = -1; static char glob[SH_MAX_GLOBS][GLOB_LEN+1]; ++count; if (count > (SH_MAX_GLOBS-1) ) count = 0; j = strlen(str); if (j > GLOB_LEN) j = GLOB_LEN; for (i = 0; i < j; ++i) { if (str[i] != '\n' && str[i] != '\t') glob[count][i] = str[i] ^ XOR_CODE; else glob[count][i] = str[i]; } glob[count][j] = '\0'; return glob[count]; } #endif static unsigned long off_data; char sh_util_charhex( int c ) { if ( c >= 0 && c <= 9 ) return '0' + c; else if ( c >= 10 && c <= 15 ) return 'a' + (c - 10); else { fprintf(stderr, _("Out of range: %d\n"), c); return 'X'; } } int sh_util_hexchar( char c ) { if ( c >= '0' && c <= '9' ) return c - '0'; else if ( c >= 'a' && c <= 'f' ) return c - 'a' + 10; else if ( c >= 'A' && c <= 'F' ) return c - 'A' + 10; else return -1; } /* --------- third step ----------- * * get data from a block of hex data */ int hideout_hex_block(int fd, unsigned char * str, int len) { register int i, j, k; unsigned char c, e; register int num; unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; unsigned long here = 0; unsigned long retval = 0; i = 0; while (i < len) { for (j = 0; j < 8; ++j) { /* get a low byte, modify, read back */ for (k = 0; k < 2; ++k) { c = ' '; do { do { num = read (fd, &c, 1); } while (num == 0 && errno == EINTR); if (num == 0) return -1; ++here; } while (c == '\n' || c == '\t' || c == '\r' || c == ' '); } /* e is the value of the low byte */ e = (unsigned char) sh_util_hexchar( c ); if ((e & mask[7]) != 0) /* bit is set */ str[i] |= mask[j]; else /* bit is not set */ str[i] &= ~mask[j]; } if (str[i] == '\n') break; ++i; } str[i+1] = '\0'; retval += here; return retval; } /* --------- second step ----------- * * hide data in a block of hex data */ int hidein_hex_block(int fd, char * str, int len) { register int i, j, k; unsigned char c, d, e; register int num; unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; unsigned long here = 0; unsigned long retval = 0; for (i = 0; i < len; ++i) { d = str[i]; for (j = 0; j < 8; ++j) { /* get a low byte, modify, read back */ for (k = 0; k < 2; ++k) { c = ' '; do { do { num = read (fd, &c, 1); } while (num == 0 && errno == EINTR); if (num == 0) return -1; ++here; } while (c == '\n' || c == '\t' || c == '\r' || c == ' '); } /* e is the value of the low byte */ e = (unsigned char) sh_util_hexchar( c ); if ((d & mask[j]) != 0) /* bit is set */ e |= mask[7]; else /* bit is not set */ e &= ~mask[7]; e = sh_util_charhex ( e ); lseek(fd, -1, SEEK_CUR); do { num = write(fd, &e, 1); } while (num == 0 && errno == EINTR); } } retval += here; return retval; } /* --------- first step ----------- * * find first block of hex data */ unsigned long first_hex_block(int fd, unsigned long * max) { int i; register int num = 1; char c; int nothex = 0; unsigned long retval = 0; int this_line = 0; char theline[SH_BUFSIZE]; *max = 0; while (1) { theline[0] = '\0'; this_line = 0; c = '\0'; while (c != '\n' && num > 0) { do { num = read (fd, &c, 1); } while (num == 0 && errno == EINTR); if (num > 0) theline[this_line] = c; else return 0; this_line += num; } theline[this_line] = '\0'; /* not only 'newline' */ if (this_line > 60) { nothex = 0; i = 0; while (nothex == 0 && i < (this_line-1)) { if (! isxdigit((int)theline[i])) nothex = 1; ++i; } if (nothex == 1) retval += this_line; } else { nothex = 1; retval += this_line; } if (nothex == 0) { *max = 0; do { do { num = read (fd, theline, SH_BUFSIZE); } while (num == 0 && errno == EINTR); for (i = 0; i < num; ++i) { c = theline[i]; if (c == '\n' || c == '\t' || c == '\r' || c == ' ') ; else if (!isxdigit((int)c)) break; else *max += 1; } } while (num > 0); *max /= 16; return retval; } } /* return 0; *//* unreachable */ } static void usage () { fprintf(stdout, "%s", _("\nUsage: samhain_stealth -i|s|g|o "\ "[what]\n\n")); fprintf(stdout, "%s", _(" -i info on PS image 'where'\n")); fprintf(stdout, "%s", _(" (how much bytes can be hidden in it).\n")); fprintf(stdout, "%s", _(" -s hide file 'what' in PS image 'where'\n")); fprintf(stdout, "%s", _(" -g get hidden data from PS image 'where'\n")); fprintf(stdout, "%s", _(" (output to stdout)\n")); fprintf(stdout, "%s", _(" -o size of file 'where' = offset to "\ "end-of-file\n")); fprintf(stdout, "%s", _(" (same as wc -c).\n\n")); fprintf(stdout, "%s", _(" Example: let bar.ps be the ps file, and"\ "foo the config file\n")); fprintf(stdout, "%s", _(" 1) extract with: samhain_stealth "\ "-g bar.ps >foo\n")); fprintf(stdout, "%s", _(" 2) hide with: samhain_stealth "\ "-s bar.ps foo\n\n")); fprintf(stdout, "%s", _(" This program hides a file in an UNCOMPRESSED "\ "postscript\n")); fprintf(stdout, "%s", _(" image. To generate such an image, you may " \ "use e.g.:\n")); fprintf(stdout, "%s", _(" 'convert +compress foo.jpg bar.ps'.\n")); fprintf(stdout, "%s", _(" 'gimp' apparently saves postscript "\ "uncompressed by default\n")); fprintf(stdout, "%s", _(" (V 1.06 of the postscript plugin).\n")); fprintf(stdout, "%s", _(" 'xv' seems to save with run-length "\ "compression, which is unsuitable.\n")); fprintf(stdout, "%s", _(" The program does not check the "\ "compression type of the PS file.\n")); fprintf(stdout, "%s", _(" Just have a look at the result to check.\n")); return; } int main (int argc, char * argv[]) { int fd; int add_off; unsigned long max; char buf[1024]; FILE * infil; int pgp_flag = 0; if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') { usage(); return (0); } if (argc == 2 && 0 == strcmp(argv[1], _("--help"))) { usage(); return (0); } if (argc < 3 || argv[1][0] != '-' || (argv[1][1] != 'o' && argv[1][1] != 'i' && argv[1][1] != 's' && argv[1][1] != 'g')) { usage (); return (1); } /* offset to end */ if (argv[1][1] == 'o') { fd = open(argv[2], O_RDONLY); if (fd == -1) { fprintf(stderr, _("Error: could not open() %s for reading\n"), argv[2]); return (1); } off_data = lseek (fd, 0, SEEK_END); fprintf(stdout, _("%ld %s\n"), off_data, argv[2]); close (fd); return (0); } fd = open(argv[2], O_RDWR); if (fd == -1) { fprintf(stderr, _("Error: could not open() %s for read/write\n"), argv[2]); return (1); } /* find the first block of hex data */ if (argv[1][1] == 'i') { off_data = first_hex_block(fd, &max); fprintf(stdout, _("IMA START AT: %ld MAX. CAPACITY: %ld Bytes\n"), off_data, max); if (max > 0) return (0); else { fprintf(stderr, _("Error: %s is probably not an uncompressed postscript image\n"), argv[2]); return (1); } } /* seek to the first block of fresh hex data and hide data */ if (argv[1][1] == 's') { infil = fopen(argv[3], "r"); if (infil == NULL) { fprintf(stderr, _("Error: could not open() %s\n"), argv[3]); return (8); } off_data = first_hex_block(fd, &max); fprintf(stdout, _("IMA START AT: %ld MAX. CAPACITY: %ld Bytes\n"), off_data, max); if (max == 0) { fprintf(stderr, _("Error: %s is probably not an uncompressed postscript image\n"), argv[2]); return (1); } fprintf(stdout, _(" .. hide %s in %s .. \n"), argv[3], argv[2]); while (fgets(buf, sizeof(buf), infil)) { lseek(fd, off_data, SEEK_SET); add_off = hidein_hex_block(fd, buf, strlen(buf)); if (add_off == -1) { fprintf(stderr, _("Error: %s has insufficient capacity\n"), argv[2]); return (1); } off_data += add_off; } fclose(infil); /* * make sure there is a terminator */ lseek(fd, off_data, SEEK_SET); add_off = hidein_hex_block(fd, _("\n[EOF]\n"), 7); if (add_off == -1) { fprintf(stderr, _("Error: %s has insufficient capacity\n"), argv[2]); return (1); } fprintf(stdout, "%s", _(" .. finished\n")); return (0); } if (argv[1][1] == 'g') { off_data = first_hex_block(fd, &max); if (max == 0) { fprintf(stderr, _("Error: %s is probably not an uncompressed postscript image\n"), argv[2]); return (1); } lseek(fd, off_data, SEEK_SET); while (1 == 1) { add_off = hideout_hex_block(fd, (unsigned char *) buf, 1023); if (add_off == -1) { fprintf(stderr, _("Error: premature end of data in %s\n"), argv[2]); return (1); } if (0 == strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))) pgp_flag = 1; fprintf(stdout, "%s", buf); if (0 == strncmp(buf, _("[EOF]"), 5) && pgp_flag == 0) break; if (0 == strcmp(buf, _("-----END PGP SIGNATURE-----\n")) && pgp_flag == 1) break; off_data += add_off; lseek(fd, off_data, SEEK_SET); } return (0); } fprintf(stderr, _("Invalid mode of operation: %s"), argv[1]); return (1); } samhain-4.1.4/src/trustfile.c0000644000175000017500000007322212615253277013055 00000000000000/* debug problems */ /* #define TRUST_DEBUG */ /* switch off full check */ /* #define TEST_ONLY */ /* standalone */ /* #define TRUST_MAIN */ /* $(CC) -DTRUST_MAIN -DSL_ALWAYS_TRUSTED=... */ /* 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. * * Compilation notes: * * this does NOT use malloc(3), but fixed storage. this means we * do lots of bounds checking, but it still is faster, and smaller, * than forcing inclusion of malloc. All buffers etc. are of size * MAXFILENAME (defined in trustfile.h); to get more room, recompile * with this set larger. * * if you support the following directory semantics, define STICKY; * otherwise, undefine it * "if a directory is both world-writeable AND has the sticky bit * set, then ONLY the owner of an existing file may delete it" * On some systems (eg, IRIX), you can delete the file under these * conditions if the file is world writeable. Foor our purposes, * this is irrelevant since if the file is world-writeable it is * untrustworthy; either it can be replaced with another file (the * IRIX version) or it can be altered (all versions). * if this is true and STICKY is not set, the sticky bit is ignored * and the directory will be flagged as untrustworthy, even when only * a trusted user could delete the file * * this uses a library call to get the name of the current working * directory. Define the following to get the various versions: * GETCWD for Solaris 2.x, SunOS 4.1.x, IRIX 5.x * char *getcwd(char *buf, int bufsz); * where buf is a buffer for the path name, and bufsz is * the size of the buffer; if the size if too small, you * get an error return (NULL) * GETWD for Ultrix 4.4 * char *getwd(char *buf) * where buf is a buffer for the path name, and it is * assumed to be at lease as big as MAXPATHLEN. * *** IMPORTANT NOTE *** * Ultrix supports getcwd as well, but it uses popen to * run the command "pwd" (according to the manual). This * means it's vulnerable to a number of attacks if used * in a privileged program. YOU DON'T WANT THIS. * * the debugging flag DEBUG prints out each step of the file name * checking, as well as info on symbolic links (if S_IFLNK defined), * file name canonicalization, and user, group, and permission for * each file or directory; this is useful if you want to be sure * you're checking the right file * * Version information: * 1.0 December 28, 1995 Matt Bishop * * 2.0 March 26, 2000 Rainer Wichmann -- adapted for slib. */ /* --- Why strcpy is safe here: ---- */ /* The input path is checked once, and then either shortened [in dirz()], * or safely expanded (symlinks) with bound checking. * I.e., the path length can never exceed (MAXFILENAME-1), while the path * is always copied between buffers of length MAXFILENAME. */ #ifndef TRUST_MAIN #include "config_xor.h" #include "sh_calls.h" #else #define UID_CAST long #define HAVE_GETPWENT #define SH_MUTEX_LOCK(a) ((void)0) #define SH_MUTEX_UNLOCK(a) ((void)0) #endif #include #include #include #include #include #include #include #include #include #if !defined(TRUST_MAIN) #include "slib.h" #define SH_NEED_PWD_GRP 1 #include "sh_static.h" #include "sh_pthread.h" #else #define sh_getgrgid getgrgid #define sh_getgrgid_r getgrgid_r #define sh_getpwnam getpwnam #define sh_getpwnam_r getpwnam_r #define sh_getpwuid getpwuid #define sh_getpwuid_r getpwuid_r #define sh_getpwent getpwent #define sh_endpwent endpwent #define TRUST_DEBUG #define S_FALSE 0 #define S_TRUE 1 #define SL_ENTER(string) #define SL_IRETURN(a, b) return a #define retry_lstat(a,b,c,d) lstat(c,d) #define _(string) string #define N_(string) string #define MAXFILENAME 4096 static int sl_errno = 0; #define SL_ENONE 0 #define SL_ENULL -1024 /* Invalid use of NULL pointer. */ #define SL_ERANGE -1025 /* Argument out of range. */ #define SL_ETRUNC -1026 /* Result truncated. */ #define SL_EINTERNAL -1028 /* Internal error. */ #define SL_EBADFILE -1030 /* File access error. Check errno. */ #define SL_EMEM -1032 /* Out of memory. */ #define SL_EBADNAME -1040 /* Invalid name. */ #define SL_ESTAT -1041 /* stat of file failed. Check errno. */ #define SL_EBADUID -1050 /* Owner not trustworthy. */ #define SL_EBADGID -1051 /* Group writeable and not trustworthy.*/ #define SL_EBADOTH -1052 /* World writeable. */ #endif #if defined(__linux__) || defined(__FreeBSD__) #define STICKY #endif #undef FIL__ #define FIL__ _("trustfile.c") /* * the get current working directory function * every version of UNIX seems to have its own * idea of how to do this, so we group them by * arguments ... * all must return a pointer to the right name */ #ifndef TRUST_MAIN #if defined(HAVE_GETCWD) && !defined(HAVE_BROKEN_GETCWD) #define CURDIR(buf,nbuf) getcwd((buf), (nbuf)) #elif defined(HAVE_GETWD) #define CURDIR(buf,nbuf) getwd((buf)) #endif #else #define CURDIR(buf,nbuf) getcwd((buf), (nbuf)) #endif /* * this checks to see if there are symbolic links * assumes the link bit in the protection mask is called S_IFLNK * (seems to be true on all UNIXes with them) */ #ifndef S_IFLNK #define lstat stat #endif /* * these are useful global variables * * first set: who you gonna trust, by default? * if the user does not specify a trusted or untrusted set of users, * all users are considered untrusted EXCEPT: * UID 0 -- root as root can do anything on most UNIX systems, this * seems reasonable * tf_euid -- programmer-selectable UID * if the caller specifies a specific UID by putting * it in this variable, it will be trusted; this is * typically used to trust the effective UID of the * process (note: NOT the real UID, which will cause all * sorts of problems!) By default, this is set to -1, * so if it's not set, root is the only trusted user */ /* modified Tue Feb 22 10:36:44 NFT 2000 Rainer Wichmann */ #ifndef SL_ALWAYS_TRUSTED #define SL_ALWAYS_TRUSTED 0 #endif uid_t test_rootonly[] = { SL_ALWAYS_TRUSTED }; #define tf_uid_neg ((uid_t)-1) uid_t rootonly[] = { SL_ALWAYS_TRUSTED, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg, tf_uid_neg }; uid_t tf_euid = tf_uid_neg; unsigned int EUIDSLOT = sizeof(test_rootonly)/sizeof(uid_t); unsigned int ORIG_EUIDSLOT = sizeof(test_rootonly)/sizeof(uid_t); char tf_path[MAXFILENAME]; /* error path for trust function */ uid_t tf_baduid; gid_t tf_badgid; static int dirz(char *path) { register char *p = path;/* points to rest of path to clean up */ register char *q; /* temp pointer for skipping over stuff */ static char swp[MAXFILENAME]; SL_ENTER(_("dirz")); /* * standard error checking */ if (path == NULL) SL_IRETURN(SL_ENULL, _("dirz")); if (path[0] == '.') SL_IRETURN(SL_EINTERNAL, _("dirz")); /* * loop over the path name until everything is checked */ while(*p) { /* skip */ if (*p != '/') { p++; continue; } /* "/./" or "/." */ if (p[1] == '.' && (p[2] == '/' || p[2] == '\0')) { /* yes -- delete "/." */ (void) strcpy(swp, &p[2]); /* known to fit */ (void) strcpy(p, swp); /* known to fit */ /* special case "/." as full path name */ if (p == path && *p == '\0') { *p++ = '/'; *p = '\0'; } } /* "//" */ else if (p[1] == '/') { /* yes -- skip */ for(q = &p[2]; *q == '/'; q++) ; (void) strcpy(swp, q); /* known to fit */ (void) strcpy(&p[1], swp); /* known to fit */ } /* "/../" or "/.." */ else if (p[1] == '.' && p[2] == '.' && (p[3] == '/' || p[3] == '\0')) { /* yes -- if it's root, delete .. only */ if (p == path) { (void) strcpy(swp, &p[3]); /* known to fit */ (void) strcpy(p, swp); /* known to fit */ } else { /* back up over previous component */ q = p - 1; while(q != path && *q != '/') q--; /* now wipe it out */ (void) strcpy(swp, &p[3]); /* known to fit */ (void) strcpy(q, swp); /* known to fit */ p = q; } } else p++; } SL_IRETURN(SL_ENONE, _("dirz")); } /* not static to circumvent stupid gcc 4 bug */ int getfname(const char *fname, char *rbuf, int rsz) { #ifndef TRUST_MAIN register int status; #endif SL_ENTER(_("getfname")); /* * do the initial checking * NULL pointer */ if (fname == NULL || rbuf == NULL) SL_IRETURN(SL_ENULL, _("getfname")); if (rsz <= 0) SL_IRETURN(SL_ERANGE, _("getfname")); /* already a full path name */ if (*fname == '/') rbuf[0] = '\0'; else { if (CURDIR(rbuf, rsz) == NULL) { #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: getcwd failed\n"); #endif SL_IRETURN(SL_EBADNAME, _("getfname")); } } /* * append the file name and reduce */ if (fname != NULL && *fname != '\0') { #ifndef TRUST_MAIN status = sl_strlcat(rbuf, "/", rsz); if (status == SL_ENONE) status = sl_strlcat(rbuf, fname, rsz); if (status != SL_ENONE) SL_IRETURN(status, _("getfname")); #else strncat(rbuf, "/", rsz-strlen(rbuf)-1); rbuf[rsz-1] = '\0'; strncat(rbuf, fname, rsz-strlen(rbuf)-1); rbuf[rsz-1] = '\0'; #endif } SL_IRETURN(dirz(rbuf), _("getfname")); } static int isin(uid_t n, uid_t *list) { SL_ENTER(_("isin")); if (list == NULL) SL_IRETURN(S_FALSE, _("isin")); while(*list != tf_uid_neg && *list != n) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: owner_uid=%ld, trusted uid=%ld, no match\n", (UID_CAST) n, (UID_CAST) *list); #endif list++; } if (*list == tf_uid_neg) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: owner_uid=%ld, no match with any trusted user --> ERROR\n", (UID_CAST) n); #endif SL_IRETURN(S_FALSE, _("isin")); } #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: owner_uid=%ld, trusted_uid=%ld, match found --> OK\n", (UID_CAST)n, (UID_CAST)*list); #endif SL_IRETURN(S_TRUE, _("isin")); } /* comment added by R. Wichmann * RETURN TRUE if ANYONE in ulist is group member */ /* not static to circumvent stupid gcc 4 bug */ int isingrp(gid_t grp, uid_t *ulist, int * errval) { struct passwd *w; /* info about group member */ register uid_t *u; /* points to current ulist member */ register char **p; /* points to current group member */ struct group *g; /* pointer to group information */ int status; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) struct group gr; char * buffer = NULL; struct passwd pwd; char * pbuffer = NULL; #endif SL_ENTER(_("isingrp")); *errval = 0; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) buffer = calloc(1,SH_GRBUF_SIZE); status = sh_getgrgid_r(grp, &gr, buffer, SH_GRBUF_SIZE, &g); #else errno = 0; g = sh_getgrgid(grp); status = errno; #endif if (g == NULL) { if (status == ERANGE) *errval = status; goto end_false; } /* this will return at the first match */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) pbuffer = calloc(1,SH_PWBUF_SIZE); #endif for(p = g->gr_mem; *p != NULL; p++) { for(u = ulist; *u != tf_uid_neg; u++) { /* map user name to UID and compare */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) sh_getpwnam_r(*p, &pwd, pbuffer, SH_PWBUF_SIZE, &w); #else w = sh_getpwnam(*p); #endif #ifdef TRUST_MAIN if (w != NULL && *u == (uid_t)(w->pw_uid) ) goto end_true; #else if (w != NULL && *u == (uid_t)(w->pw_uid) ) { goto end_true; } #endif } } /* added by R. Wichmann Fri Mar 30 08:16:14 CEST 2001: * a user can have a GID but no entry in /etc/group */ for(u = ulist; *u != tf_uid_neg; u++) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) sh_getpwuid_r(*u, &pwd, pbuffer, SH_PWBUF_SIZE, &w); #else w = sh_getpwuid(*u); #endif #ifdef TRUST_MAIN if (w != NULL && grp == (gid_t)(w->pw_gid) ) goto end_true; #else if (w != NULL && grp == (gid_t)(w->pw_gid) ) { goto end_true; } #endif } end_false: #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (buffer) free(buffer); if (pbuffer) free(pbuffer); #endif SL_IRETURN(S_FALSE, _("isingrp")); end_true: #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (buffer) free(buffer); if (pbuffer) free(pbuffer); #endif SL_IRETURN(S_TRUE, _("isingrp")); } /* added by R. Wichmann Fri Mar 30 08:16:14 CEST 2001 * RETURN TRUE only if ALL group members are trusted */ /* not static to circumvent stupid gcc 4 bug */ int onlytrustedingrp(gid_t grp, uid_t *ulist, int * errval) { struct passwd *w; /* info about group member */ register uid_t *u; /* points to current ulist member */ register char **p; /* points to current group member */ struct group *g; /* pointer to group information */ register int flag = -1; /* group member found */ int status; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) struct group gr; char * buffer = NULL; struct passwd pw; char * pbuffer = NULL; #endif int retval = S_FALSE; SL_ENTER(_("onlytrustedingrp")); *errval = 0; #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: group writeable, group_gid: %ld\n", (UID_CAST)grp); #endif #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) buffer = calloc(1,SH_GRBUF_SIZE); status = sh_getgrgid_r(grp, &gr, buffer, SH_GRBUF_SIZE, &g); #else errno = 0; g = sh_getgrgid(grp); status = errno; #endif if (g == NULL) { if (status == ERANGE) *errval = status; #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: group_gid: %ld, no such group --> ERROR\n", (UID_CAST)grp); #endif retval = S_FALSE; goto end_retval; } /* empty group -> no problem if(g->gr_mem == NULL || g->gr_mem[0] == NULL ) SL_IRETURN(S_TRUE, _("onlytrustedingrp") ); */ /* check for untrusted members of the group */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) pbuffer = calloc(1,SH_PWBUF_SIZE); #endif for(p = g->gr_mem; *p != NULL; p++) { flag = -1; #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: group_member: %s\n", *p); #endif /* map user name to UID and compare */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) sh_getpwnam_r(*p, &pw, pbuffer, SH_PWBUF_SIZE, &w); #else w = sh_getpwnam(*p); #endif if (w == NULL) /* not a valid user, ignore */ { flag = 0; } else /* check list of trusted users */ { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, checking whether it is trusted\n", (UID_CAST)(w->pw_uid)); #endif for(u = ulist; *u != tf_uid_neg; u++) { if (*u == (w->pw_uid) ) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, match found --> OK\n", (UID_CAST)(w->pw_uid), (UID_CAST)*u); #endif flag = 0; break; } else { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, no match\n", (UID_CAST)(w->pw_uid), (UID_CAST)*u); #endif ; } } } /* not found */ if (flag == -1) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: user=%s (gid %ld), not a trusted user --> ERROR\n", *p, (UID_CAST)grp); #endif tf_baduid = w->pw_uid; retval = S_FALSE; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (pbuffer) free(pbuffer); #endif goto end_retval; } } #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (pbuffer) free(pbuffer); #endif #ifndef TEST_ONLY #ifdef HAVE_GETPWENT /* now check ALL users for their GID !!! */ SH_MUTEX_LOCK(mutex_pwent); while (NULL != (w = sh_getpwent())) { if (grp == (gid_t)(w->pw_gid)) { #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: checking group member %s, uid %ld\n", w->pw_name, (UID_CAST)w->pw_uid); #endif /* is it a trusted user ? */ flag = -1; for(u = ulist; *u != tf_uid_neg; u++) { if (*u == (uid_t)(w->pw_uid)) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, match found --> OK\n", (UID_CAST)(w->pw_uid), (UID_CAST)(*u)); #endif flag = 0; break; } else { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, no match\n", (UID_CAST)(w->pw_uid), (UID_CAST)*u); #endif ; } } /* not found */ if (flag == -1) { #ifdef TRUST_DEBUG fprintf(stderr,"trustfile: group member %s not found in trusted users --> ERROR\n", w->pw_name); #endif tf_baduid = w->pw_uid; retval = S_FALSE; goto out; /* SL_IRETURN(S_FALSE, _("onlytrustedingrp")); */ } } } retval = S_TRUE; out: #ifdef HAVE_ENDPWENT sh_endpwent(); #endif SH_MUTEX_UNLOCK(mutex_pwent); /* TEST_ONLY */ #endif /* #ifdef HAVE_GETPWENT */ #endif #ifdef TRUST_DEBUG if (retval == S_TRUE) fprintf(stderr, "trustfile: group %ld: all members are trusted users --> OK\n", (UID_CAST)grp); #endif /* all found */ end_retval: #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (buffer) free(buffer); #endif SL_IRETURN(retval, _("onlytrustedingrp")); } int sl_trustfile(const char *fname, uid_t *okusers, uid_t *badusers) { char * fexp = NULL; /* file name fully expanded */ register char *p; /* used to hold name to be checked */ struct stat stbuf; /* used to check file permissions */ char c; /* used to hold temp char */ int errgrp = 0; SL_ENTER(_("sl_trustfile")); if (fname == NULL) SL_IRETURN(SL_EBADFILE, _("sl_trustfile")); fexp = calloc(1, MAXFILENAME ); if (!fexp) SL_IRETURN(SL_EMEM, _("sl_trustfile")); p = fexp; /* * next expand to the full file name * getfname sets sl_errno as appropriate */ #ifdef TRUST_MAIN sl_errno = getfname(fname, fexp, MAXFILENAME); if (sl_errno != 0) { free(fexp); return sl_errno; } #else if (SL_ISERROR(getfname(fname, fexp, MAXFILENAME))) { free(fexp); SL_IRETURN(sl_errno, _("sl_trustfile")); } #endif if (okusers == NULL && badusers == NULL) { okusers = rootonly; rootonly[EUIDSLOT] = tf_euid; } /* * now loop through the path a component at a time * note we have to special-case root */ while(*p) { /* * get next component */ while(*p && *p != '/') p++; /* save where you are */ if (p == fexp) { /* keep the / if it's the root dir */ c = p[1]; p[1] = '\0'; } else { /* clobber the / if it isn't the root dir */ c = *p; *p = '\0'; } /* * now get the information */ if (retry_lstat(FIL__, __LINE__, fexp, &stbuf) < 0) { (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: ESTAT: stat(%s) failed,\n", fexp); fprintf(stderr, "maybe the file does not exist\n"); fprintf(stderr, "---------------------------------------------\n"); #endif free(fexp); SL_IRETURN(SL_ESTAT, _("sl_trustfile")); } #ifdef S_IFLNK /* * if it's a symbolic link, recurse */ if ((stbuf.st_mode & S_IFLNK) == S_IFLNK) { /* * this is tricky * if the symlink is to an absolute path * name, just call trustfile on it; but * if it's a relative path name, it's * interpreted WRT the current working * directory AND NOT THE FILE NAME!!!!! * so, we simply put /../ at the end of * the file name, then append the symlink * contents; trustfile will canonicalize * this, and the /../ we added "undoes" * the name of the symlink to put us in * the current working directory, at * which point the symlink contents (appended * to the CWD) are interpreted correctly. * got it? */ char * csym; /* contents of symlink file */ char * full; /* "full" name of symlink */ char *b; /* used to copy stuff around */ const char *t; /* used to copy stuff around */ int lsym; /* num chars in symlink ref */ int i; /* trustworthy or not? */ const char * t_const; char *end; /* * get what the symbolic link points to * * The original code does not check the return code of readlink(), * and has an off-by-one error * (MAXFILENAME instead of MAXFILENAME-1) * R.W. Tue May 29 22:05:16 CEST 2001 */ csym = calloc(1, MAXFILENAME ); if (!csym) { free(fexp); SL_IRETURN(SL_EMEM, _("sl_trustfile")); } lsym = readlink(fexp, csym, MAXFILENAME-1); if (lsym >= 0) csym[lsym] = '\0'; else { #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADNAME: readlink(%s) failed\n", fexp); fprintf(stderr, "---------------------------------------------\n"); #endif free(csym); free(fexp); SL_IRETURN(SL_EBADNAME, _("sl_trustfile")); } full = calloc(1, MAXFILENAME ); if (!full) { free(csym); free(fexp); SL_IRETURN(SL_EMEM, _("sl_trustfile")); } /* * relative or absolute referent? */ if (csym[0] != '/') { /* pointer to one above last element */ end = &full[MAXFILENAME-1]; ++end; /* initialize pointers */ b = full; /* copy in base path */ t = fexp; while(*t && b < end) *b++ = *t++; /* smack on the /../ */ t_const = "/../"; t = (const char *)t_const; while(*t && b < end) *b++ = *t++; /* append the symlink referent */ t = csym; while(*t && b < end) *b++ = *t++; /* see if we're too big */ if (*t || b == end) { /* yes -- error */ (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: ETRUNC: normalized path too long (%s)\n", fexp); fprintf(stderr, "---------------------------------------------\n"); #endif free(full); free(csym); free(fexp); SL_IRETURN(SL_ETRUNC, _("sl_trustfile")); } *b = '\0'; } else { /* absolute -- just copy */ /* overflow can't occur as the arrays */ /* are the same size */ (void) strcpy(full, csym); /* known to fit */ } /* * now check out this file and its ancestors */ if ((i = sl_trustfile(full, okusers, badusers)) != SL_ENONE) { free(full); free(csym); free(fexp); SL_IRETURN(i, _("sl_trustfile")); } /* * okay, this part is valid ... let's check the rest * put the / back */ if (p == fexp) { /* special case for root */ p[1] = c; p++; } else { /* ordinary case for everything else */ *p = c; if (*p) p++; } free(full); free(csym); continue; } #endif #ifdef TRUST_DEBUG fprintf(stderr, "\ntrustfile: checking path=%s\n", fexp); #endif /* * if the owner is not trusted then -- as the owner can * change protection modes -- he/she can write to the * file regardless of permissions, so bomb */ if (((okusers != NULL && S_FALSE == isin((uid_t)stbuf.st_uid,okusers))|| (badusers != NULL && S_TRUE == isin((uid_t)stbuf.st_uid,badusers)))) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADUID %s (owner not trusted)\n", fexp); fprintf(stderr, "The owner of this file/directory is not in samhains\n"); fprintf(stderr, "list of trusted users.\n"); fprintf(stderr, "Please run ./configure again with the option\n"); fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; tf_baduid = (uid_t) stbuf.st_uid; free(fexp); SL_IRETURN(SL_EBADUID, _("sl_trustfile")); } /* * if a group member can write but the * member is not trusted, bomb; but if * sticky bit semantics are honored, it's * okay */ /* Thu Mar 29 21:10:28 CEST 2001 Rainer Wichmann * replace !isingrp() with onlytrustedingrp(), as isingrp() * will return at the first trusted user, even if there are additional * (untrusted) users in the group */ if (((stbuf.st_mode & S_IWGRP) == S_IWGRP) && ((okusers != NULL && !onlytrustedingrp((gid_t)stbuf.st_gid,okusers,&errgrp))|| (badusers != NULL && isingrp((gid_t)stbuf.st_gid, badusers,&errgrp))) #ifdef STICKY && ((stbuf.st_mode&S_IFDIR) != S_IFDIR || (stbuf.st_mode&S_ISVTX) != S_ISVTX) #endif ) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADGID %ld %s (group member not trusted)\n", (UID_CAST)stbuf.st_gid, fexp); fprintf(stderr, "This file/directory is group writeable, and one of the group members\n"); fprintf(stderr, "is not in samhains list of trusted users.\n"); fprintf(stderr, "Please run ./configure again with the option\n"); fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; tf_badgid = (gid_t) stbuf.st_gid; free(fexp); SL_IRETURN((errgrp == ERANGE) ? SL_ERANGE : SL_EBADGID, _("sl_trustfile")); } /* * if other can write, bomb; but if the sticky * bit semantics are honored, it's okay */ if (((stbuf.st_mode & S_IWOTH) == S_IWOTH) #ifdef STICKY && ((stbuf.st_mode&S_IFDIR) != S_IFDIR || (stbuf.st_mode&S_ISVTX) != S_ISVTX) #endif ) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADOTH (world writeable): %s\n", fexp); fprintf(stderr, "This file/directory is world writeable.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; free(fexp); SL_IRETURN(SL_EBADOTH, _("sl_trustfile")); } /* * put the / back */ if (p == fexp) { /* special case for root */ p[1] = c; p++; } else { /* ordinary case for everything else */ *p = c; if (*p) p++; } } /* * yes, it can be trusted */ (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; free(fexp); SL_IRETURN(SL_ENONE, _("sl_trustfile")); } #ifdef TRUST_MAIN #if defined(HOST_IS_CYGWIN) || defined(__cygwin__) || defined(__CYGWIN32__) || defined(__CYGWIN__) int main() { return 0; } #else int main (int argc, char * argv[]) { int status; #if defined(SH_WITH_SERVER) struct passwd * pass; #endif if (argc < 2) { fprintf(stderr, "%s: Usage: %s \n", argv[0], argv[0]); return 1; } tf_path[0] = '\0'; #if defined(SH_WITH_SERVER) pass = sh_getpwnam(SH_IDENT); /* TESTONLY */ if (pass != NULL) tf_euid = pass->pw_uid; else { fprintf(stderr, "trustfile: ERROR: getpwnam(%s) failed\n", SH_IDENT); return 1; } #else tf_euid = geteuid(); #endif status = sl_trustfile(argv[1], NULL, NULL); if (status != SL_ENONE) { fprintf(stderr, "trustfile: ERROR: not a trusted path: %s\n", argv[1]); return 1; } return 0; } #endif #endif samhain-4.1.4/src/sstrip.c0000644000175000017500000003345212615253277012361 00000000000000/* sstrip, version 2.0: Copyright (C) 1999-2001 by Brian Raiter, under the * GNU General Public License. No warranty. See LICENSE for details. */ /* Modified for portability and 64bit/32bit elf executables, Rainer Wichmann */ #include "config.h" #include #include #include #include #include #include #if !defined(__ia64) && !defined(__ia64__) && !defined(__itanium__) && \ !defined(__alpha) && !defined(__alpha__) && \ (defined(HAVE_ELF_H) || defined(HAVE_LINUX_ELF_H)) && \ (defined(__linux__) || defined(__FreeBSD__)) && \ (defined(__i386__) || defined(__i386) || defined(i386)) /* || defined(__sun) || defined(__sun__) || defined(sun) */ #if defined(HAVE_ELF_H) #include #else #include #endif #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef ELFCLASS32 #define ELFCLASS32 1 /* 32-bit objects */ #endif #ifndef ELFCLASS64 #define ELFCLASS64 2 /* 64-bit objects */ #endif /* The name of the program. */ static char const *progname; /* The name of the current file. */ static char const *filename; /* A simple error-handling function. FALSE is always returned for the * convenience of the caller. */ static int err(char const *errmsg) { fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg); return FALSE; } /* A macro for I/O errors: The given error message is used only when * errno is not set. */ #define ferr(msg) (err(errno ? strerror(errno) : (msg))) /* readelfheader() reads the ELF header into our global variable, and * checks to make sure that this is in fact a file that we should be * munging. */ static int readelfheader_32(int fd, Elf32_Ehdr *ehdr) { errno = 0; if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) return ferr("missing or incomplete ELF header."); /* Check the ELF signature. */ if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 && ehdr->e_ident[EI_MAG1] == ELFMAG1 && ehdr->e_ident[EI_MAG2] == ELFMAG2 && ehdr->e_ident[EI_MAG3] == ELFMAG3)) return err("missing ELF signature."); /* Compare the file's class and endianness with the program's. */ #ifdef ELF_DATA if (ehdr->e_ident[EI_DATA] != ELF_DATA) return err("ELF file has different endianness."); #endif if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) return FALSE; /* Check the target architecture. */ #ifdef ELF_ARCH if (ehdr->e_machine != ELF_ARCH) return err("ELF file created for different architecture."); #endif /* Verify the sizes of the ELF header and the program segment * header table entries. */ if (ehdr->e_ehsize != sizeof(Elf32_Ehdr)) return err("unrecognized ELF header size."); if (ehdr->e_phentsize != sizeof(Elf32_Phdr)) return err("unrecognized program segment header size."); /* Finally, check the file type. */ if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) return err("not an executable or shared-object library."); return TRUE; } static int readelfheader_64(int fd, Elf64_Ehdr *ehdr) { errno = 0; if (lseek(fd, 0, SEEK_SET)) return ferr("could not rewind file"); if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) return ferr("missing or incomplete ELF header."); /* Check the ELF signature. */ if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 && ehdr->e_ident[EI_MAG1] == ELFMAG1 && ehdr->e_ident[EI_MAG2] == ELFMAG2 && ehdr->e_ident[EI_MAG3] == ELFMAG3)) return err("missing ELF signature."); /* Compare the file's class and endianness with the program's. */ #ifdef ELF_DATA if (ehdr->e_ident[EI_DATA] != ELF_DATA) return err("ELF file has different endianness."); #endif if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) return err("ELF file has different word size."); /* Check the target architecture. */ #ifdef ELF_ARCH if (ehdr->e_machine != ELF_ARCH) return err("ELF file created for different architecture."); #endif /* Verify the sizes of the ELF header and the program segment * header table entries. */ if (ehdr->e_ehsize != sizeof(Elf64_Ehdr)) return err("unrecognized ELF header size."); if (ehdr->e_phentsize != sizeof(Elf64_Phdr)) return err("unrecognized program segment header size."); /* Finally, check the file type. */ if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) return err("not an executable or shared-object library."); return TRUE; } /* readphdrtable() loads the program segment header table into memory. */ static int readphdrtable_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr **phdrs) { size_t size; if (!ehdr->e_phoff || !ehdr->e_phnum) return err("ELF file has no program header table."); size = ehdr->e_phnum * sizeof **phdrs; if (!(*phdrs = calloc(1,size))) return err("Out of memory!"); errno = 0; if (read(fd, *phdrs, size) != (ssize_t)size) return ferr("missing or incomplete program segment header table."); return TRUE; } static int readphdrtable_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr **phdrs) { size_t size; if (!ehdr->e_phoff || !ehdr->e_phnum) return err("ELF file has no program header table."); size = ehdr->e_phnum * sizeof **phdrs; if (!(*phdrs = calloc(1,size))) return err("Out of memory!"); errno = 0; if (read(fd, *phdrs, size) != (ssize_t)size) return ferr("missing or incomplete program segment header table."); return TRUE; } /* getmemorysize() determines the offset of the last byte of the file * that is referenced by an entry in the program segment header table. * (Anything in the file after that point is not used when the program * is executing, and thus can be safely discarded.) */ static int getmemorysize_32(Elf32_Ehdr const *ehdr, Elf32_Phdr const *phdrs, unsigned long *newsize) { Elf32_Phdr const *phdr; unsigned long size, n; unsigned int i; /* Start by setting the size to include the ELF header and the * complete program segment header table. */ size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs; if (size < sizeof *ehdr) size = sizeof *ehdr; /* Then keep extending the size to include whatever data the * program segment header table references. */ for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { if (phdr->p_type != PT_NULL) { n = phdr->p_offset + phdr->p_filesz; if (n > size) size = n; } } *newsize = size; return TRUE; } static int getmemorysize_64(Elf64_Ehdr const *ehdr, Elf64_Phdr const *phdrs, unsigned long *newsize) { Elf64_Phdr const *phdr; unsigned long size, n; unsigned int i; /* Start by setting the size to include the ELF header and the * complete program segment header table. */ size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs; if (size < sizeof *ehdr) size = sizeof *ehdr; /* Then keep extending the size to include whatever data the * program segment header table references. */ for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { if (phdr->p_type != PT_NULL) { n = phdr->p_offset + phdr->p_filesz; if (n > size) size = n; } } *newsize = size; return TRUE; } /* truncatezeros() examines the bytes at the end of the file's * size-to-be, and reduces the size to exclude any trailing zero * bytes. */ static int truncatezeros(int fd, unsigned long *newsize) { unsigned char contents[1024]; unsigned long size, n; size = *newsize; do { n = sizeof contents; if (n > size) n = size; if (lseek(fd, size - n, SEEK_SET) == (off_t)-1) return ferr("cannot seek in file."); if (read(fd, contents, n) != (ssize_t)n) return ferr("cannot read file contents"); while (n && !contents[--n]) --size; } while (size && !n); /* Sanity check. */ if (!size) return err("ELF file is completely blank!"); *newsize = size; return TRUE; } /* modifyheaders() removes references to the section header table if * it was stripped, and reduces program header table entries that * included truncated bytes at the end of the file. */ static int modifyheaders_32(Elf32_Ehdr *ehdr, Elf32_Phdr *phdrs, unsigned long newsize) { Elf32_Phdr *phdr; unsigned int i; /* If the section header table is gone, then remove all references * to it in the ELF header. */ if (ehdr->e_shoff >= newsize) { ehdr->e_shoff = 0; ehdr->e_shnum = 0; ehdr->e_shentsize = 0; ehdr->e_shstrndx = 0; } /* The program adjusts the file size of any segment that was * truncated. The case of a segment being completely stripped out * is handled separately. */ for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { if (phdr->p_offset >= newsize) { phdr->p_offset = newsize; phdr->p_filesz = 0; } else if (phdr->p_offset + phdr->p_filesz > newsize) { phdr->p_filesz = newsize - phdr->p_offset; } } return TRUE; } static int modifyheaders_64(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, unsigned long newsize) { Elf64_Phdr *phdr; unsigned int i; /* If the section header table is gone, then remove all references * to it in the ELF header. */ if (ehdr->e_shoff >= newsize) { ehdr->e_shoff = 0; ehdr->e_shnum = 0; ehdr->e_shentsize = 0; ehdr->e_shstrndx = 0; } /* The program adjusts the file size of any segment that was * truncated. The case of a segment being completely stripped out * is handled separately. */ for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { if (phdr->p_offset >= newsize) { phdr->p_offset = newsize; phdr->p_filesz = 0; } else if (phdr->p_offset + phdr->p_filesz > newsize) { phdr->p_filesz = newsize - phdr->p_offset; } } return TRUE; } /* commitchanges() writes the new headers back to the original file * and sets the file to its new size. */ static int commitchanges_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr *phdrs, unsigned long newsize) { size_t n; /* Save the changes to the ELF header, if any. */ if (lseek(fd, 0, SEEK_SET)) return ferr("could not rewind file"); errno = 0; if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) return err("could not modify file"); /* Save the changes to the program segment header table, if any. */ if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) { err("could not seek in file."); goto warning; } n = ehdr->e_phnum * sizeof *phdrs; if (write(fd, phdrs, n) != (ssize_t)n) { err("could not write to file"); goto warning; } /* Eleventh-hour sanity check: don't truncate before the end of * the program segment header table. */ if (newsize < ehdr->e_phoff + n) newsize = ehdr->e_phoff + n; /* Chop off the end of the file. */ if (ftruncate(fd, newsize)) { err("could not resize file"); goto warning; } return TRUE; warning: return err("ELF file may have been corrupted!"); } static int commitchanges_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr *phdrs, unsigned long newsize) { size_t n; /* Save the changes to the ELF header, if any. */ if (lseek(fd, 0, SEEK_SET)) return ferr("could not rewind file"); errno = 0; if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) return err("could not modify file"); /* Save the changes to the program segment header table, if any. */ if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) { err("could not seek in file."); goto warning; } n = ehdr->e_phnum * sizeof *phdrs; if (write(fd, phdrs, n) != (ssize_t)n) { err("could not write to file"); goto warning; } /* Eleventh-hour sanity check: don't truncate before the end of * the program segment header table. */ if (newsize < ehdr->e_phoff + n) newsize = ehdr->e_phoff + n; /* Chop off the end of the file. */ if (ftruncate(fd, newsize)) { err("could not resize file"); goto warning; } return TRUE; warning: return err("ELF file may have been corrupted!"); } /* main() loops over the cmdline arguments, leaving all the real work * to the other functions. */ int main(int argc, char *argv[]) { int fd; int is_32bit_elf; Elf32_Ehdr ehdr32; Elf32_Phdr *phdrs32 = NULL; Elf64_Ehdr ehdr64; Elf64_Phdr *phdrs64 = NULL; unsigned long newsize; char **arg; int failures = 0; if (argc < 2 || argv[1][0] == '-') { printf("Usage: sstrip FILE...\n" "sstrip discards all nonessential bytes from an executable.\n\n" "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n" "This program is free software, licensed under the GNU\n" "General Public License. There is absolutely no warranty.\n"); return EXIT_SUCCESS; } progname = argv[0]; for (arg = argv + 1 ; *arg != NULL ; ++arg) { filename = *arg; fd = open(*arg, O_RDWR); if (fd < 0) { ferr("can't open"); ++failures; continue; } if (readelfheader_32(fd, &ehdr32)) { is_32bit_elf = TRUE; } else if (readelfheader_64(fd, &ehdr64)) { is_32bit_elf = FALSE; } else { close(fd); return EXIT_FAILURE; } if (is_32bit_elf) { if (!(readphdrtable_32(fd, &ehdr32, &phdrs32) && getmemorysize_32(&ehdr32, phdrs32, &newsize) && truncatezeros(fd, &newsize) && modifyheaders_32(&ehdr32, phdrs32, newsize) && commitchanges_32(fd, &ehdr32, phdrs32, newsize))) ++failures; } else { if (!(readphdrtable_64(fd, &ehdr64, &phdrs64) && getmemorysize_64(&ehdr64, phdrs64, &newsize) && truncatezeros(fd, &newsize) && modifyheaders_64(&ehdr64, phdrs64, newsize) && commitchanges_64(fd, &ehdr64, phdrs64, newsize))) ++failures; } close(fd); } return failures ? EXIT_FAILURE : EXIT_SUCCESS; } #else int main() { return (EXIT_SUCCESS); } #endif samhain-4.1.4/src/cutest_sh_hash.c0000644000175000017500000000544312615253277014040 00000000000000 #include "config_xor.h" #include #include "CuTest.h" extern char * quote_string (const char * str, size_t len); extern char * unquote_string (const char * str, size_t len); void Test_quote_string_ok (CuTest *tc) { #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) char * ret = 0; char inp1[] = "foo\nba=r\ntest"; char out1[] = "foo=0Aba=3Dr=0Atest"; char inp2[] = "\n=foo\nba=r\ntest=\n"; char out2[] = "=0A=3Dfoo=0Aba=3Dr=0Atest=3D=0A"; ret = quote_string(inp1, strlen(inp1)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, out1, ret); ret = quote_string(inp2,strlen(inp2)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, out2, ret); #else (void) tc; /* fix compiler warning */ #endif return; } void Test_unquote_string_ok (CuTest *tc) { #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) char * ret = 0; char out1[] = "foo\nba=r\ntes[t"; char inp1[] = "foo=0Aba=3Dr=0Ates=5Bt"; char out2[] = "\n=foo\nba=r\ntest=\n"; char inp2[] = "=0A=3Dfoo=0Aba=3Dr=0Atest=3D=0A"; char out3[] = ""; /* encoded '\0' at start */ char inp3[] = "=00=3Dfoo=0Aba=3Dr=0Atest=3D=0A"; ret = unquote_string(inp1, strlen(inp1)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, out1, ret); ret = unquote_string(inp2, strlen(inp2)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, out2, ret); ret = unquote_string(inp3, strlen(inp3)); CuAssertPtrNotNull(tc, ret); CuAssertStrEquals(tc, out3, ret); #else (void) tc; /* fix compiler warning */ #endif return; } void Test_csv_escape_ok (CuTest *tc) { #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) extern char * csv_escape(const char * str); char test0[80]; char expec[80]; char *ret; strcpy(test0, "foobar"); strcpy(expec, "\"foobar\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, "\"foobar\""); strcpy(expec, "\"\"\"foobar\"\"\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, "foo,bar"); strcpy(expec, "\"foo,bar\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, "foob,\"a\"r"); strcpy(expec, "\"foob,\"\"a\"\"r\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, "\",\"foobar\",\""); strcpy(expec, "\"\"\",\"\"foobar\"\",\"\"\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, ""); strcpy(expec, ""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, "a"); strcpy(expec, "\"a\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); strcpy(test0, "foo\"bar"); strcpy(expec, "\"foo\"\"bar\""); ret = csv_escape(test0); CuAssertStrEquals(tc, expec, ret); #else (void) tc; /* fix compiler warning */ #endif return; } samhain-4.1.4/src/sh_ipvx.c0000644000175000017500000003150412615253277012511 00000000000000/* SAMHAIN file system integrity testing */ /* Copyright (C) 2010 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #include #include #include #include #include #undef FIL__ #define FIL__ _("sh_ipvx.c") #include "samhain.h" #define SH_NEED_GETHOSTBYXXX #include "sh_static.h" #include "sh_pthread.h" #include "sh_utils.h" #include "sh_ipvx.h" static int sh_ipvx_is_ipv4 (const char * addr) { int j; int count = 0; int len = sl_strlen(addr); unsigned int a, b, c, d; if (len > 15) /* 3*4 + 3 dots */ return (1 == 0); for (j = 0; j < len; ++j) { if ( (addr[j] < '0' || addr[j] > '9') && addr[j] != '.') return (1 == 0); if (addr[j] == '.') ++count; } if (count != 3) return (1 == 0); if (sscanf(addr, "%3u.%3u.%3u.%3u", &a, &b, &c, &d) != 4) return( 1 == 0 ); if ((a|b|c|d) > 255) return( 1 == 0 ); return (1 == 1); } #if defined(USE_IPVX) static int sh_ipvx_is_ipv6 (const char * addr) { int j, k = 0; char c; int len = sl_strlen(addr); for (j = 0; j < len; ++j) { c = addr[j]; if (( c < '0' || c > '9' ) && ( c < 'a' || c > 'f' ) && ( c < 'A' || c > 'F' ) && ( c != ':') && ( c != '.')) return (1 == 0); else if (c == ':') ++k; else if (c == '.' && k < 2) return (1 == 0); /* ::ffff:ipv4 */ } if (k < 2 || k > 7) return (1 == 0); return (1 == 1); } #endif int sh_ipvx_is_numeric (const char * addr) { #if defined(USE_IPVX) if (!sh_ipvx_is_ipv4(addr)) return sh_ipvx_is_ipv6(addr); else return (1 == 1); #else return sh_ipvx_is_ipv4(addr); #endif } int sh_ipvx_isany (struct sh_sockaddr * a) { #if defined(HOST_IS_CYGWIN) /* * Cygwin implementation gives 'missing braces around initializer' * warning, thus replace it with correct version. */ #undef IN6ADDR_ANY_INIT #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } #endif #if defined(USE_IPVX) struct in6_addr anyaddr = IN6ADDR_ANY_INIT; #endif switch (a->ss_family) { case AF_INET: if ((a->sin).sin_addr.s_addr == INADDR_ANY) return 1; break; #if defined(USE_IPVX) case AF_INET6: if (0 == memcmp(&((a->sin6).sin6_addr.s6_addr), &anyaddr, 16)) return 1; break; #endif } return 0; } int sh_ipvx_cmp (struct sh_sockaddr * a, struct sh_sockaddr * b) { if (a->ss_family != b->ss_family) return 1; switch (a->ss_family) { case AF_INET: return memcmp(&((a->sin).sin_addr.s_addr), &((b->sin).sin_addr.s_addr), 4); break; #if defined(USE_IPVX) case AF_INET6: return memcmp(&((a->sin6).sin6_addr.s6_addr), &((b->sin6).sin6_addr.s6_addr), 16); break; #endif } return 1; } int sh_ipvx_ntoa (char * name, size_t name_size, struct sh_sockaddr * ss) { #if defined(USE_IPVX) int len = (ss->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); int ret = getnameinfo(sh_ipvx_sockaddr_cast(ss), len, name, name_size, NULL, 0, NI_NUMERICHOST); if (ret != 0 && name_size > 0) { name[name_size-1] = '\0'; if (!sh_ipvx_is_numeric(name)) { if (name_size > 7) { name[0] = '0'; name[1] = '.'; name[2] = '0'; name[3] = '.'; name[4] = '0'; name[5] = '.'; name[6] = '0'; name[7] = '\0'; } else { name[0] = '\0'; } } } return ret; #else char * p = inet_ntoa((ss->sin).sin_addr); sl_strlcpy(name, p, name_size); return 0; #endif } struct sockaddr * sh_ipvx_sockaddr_cast (struct sh_sockaddr * ss) { #if defined(USE_IPVX) if (ss->ss_family == AF_INET6) return (struct sockaddr *) &(ss->sin6); #endif return (struct sockaddr *) &(ss->sin); } char * sh_ipvx_print_sockaddr (struct sockaddr * sa, int sa_family) { struct sh_sockaddr ss; static char ipbuf[SH_IP_BUF]; sh_ipvx_save(&ss, sa_family, sa); sh_ipvx_ntoa (ipbuf, sizeof(ipbuf), &ss); return ipbuf; } void sh_ipvx_save(struct sh_sockaddr * ss, int sa_family, struct sockaddr * sa) { /* memset(ss, '\0', sizeof(struct sh_sockaddr)); */ switch (sa_family) { case AF_INET: ss->ss_family = AF_INET; memcpy(&(ss->sin), (struct sockaddr_in*) sa, sizeof(struct sockaddr_in)); break; #if defined(USE_IPVX) case AF_INET6: ss->ss_family = AF_INET6; memcpy(&(ss->sin6), (struct sockaddr_in6*) sa, sizeof(struct sockaddr_in6)); break; #endif default: break; } return; } int sh_ipvx_set_port(struct sh_sockaddr * ss, int port) { #if defined(USE_IPVX) switch (ss->ss_family) { case AF_INET: (ss->sin).sin_family = AF_INET; (ss->sin).sin_port = htons (port); break; case AF_INET6: (ss->sin6).sin6_family = AF_INET6; (ss->sin6).sin6_port = htons (port); break; } return 0; #else (ss->sin).sin_family = AF_INET; (ss->sin).sin_port = htons (port); return 0; #endif } int sh_ipvx_get_port(struct sockaddr * sa, int sa_family) { int port = 0; #if defined(USE_IPVX) switch (sa_family) { case AF_INET: port = ntohs(((struct sockaddr_in *)sa)->sin_port); break; case AF_INET6: port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); break; } #else (void) sa_family; port = ntohs(((struct sockaddr_in *)sa)->sin_port); #endif return port; } int sh_ipvx_aton (const char * name, struct sh_sockaddr * ss) { #if defined(USE_IPVX) int ret; struct addrinfo hints; struct addrinfo *res; memset(&hints, '\0', sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; ret = getaddrinfo(name, NULL, &hints, &res); if (ret) return 0; memset(ss, '\0', sizeof(struct sh_sockaddr)); switch(res->ai_family) { case AF_INET: memcpy(&(ss->sin), res->ai_addr, sizeof(struct sockaddr_in)); ss->ss_family = AF_INET; break; case AF_INET6: memcpy(&(ss->sin6), res->ai_addr, sizeof(struct sockaddr_in6)); ss->ss_family = AF_INET6; break; default: return 0; break; } return 1; #else int ret = inet_aton(name, &((ss->sin).sin_addr)); ss->ss_family = AF_INET; return ret; #endif } #if !defined(USE_IPVX) static const char * sh_ipvx_h_name (struct hostent * host_entry) { char ** p; if (strchr(host_entry->h_name, '.')) { return host_entry->h_name; } else { for (p = host_entry->h_aliases; *p; ++p) { if (strchr(*p, '.')) return *p; } } return host_entry->h_name; } #endif static char * sh_tolower (char * s) { char * ret = s; if (s) { for (; *s; ++s) { *s = tolower((unsigned char) *s); } } return ret; } void * sh_dummy_341_out; char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen) { volatile int flag = 0; char *out = NULL; #if defined(USE_IPVX) struct addrinfo hints; struct addrinfo *res; struct sockaddr *sa; int salen; int err; struct sh_sockaddr ss; const char * host; char hostbuf[SH_BUFSIZE]; numeric[0] = '\0'; sh_dummy_341_out = (void *) &out; if (sh_ipvx_is_numeric(hostname)) { sh_ipvx_aton (hostname, &ss); if (0 == getnameinfo(sh_ipvx_sockaddr_cast(&ss), SH_SS_LEN(ss), hostbuf, sizeof(hostbuf), NULL, 0, NI_NAMEREQD)) host = hostbuf; else host = hostname; } else { host = hostname; } memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; #if defined(AI_CANONNAME) hints.ai_flags = AI_CANONNAME; #endif err = getaddrinfo(host, NULL, &hints, &res); if (err == 0) { #if defined(AI_CANONNAME) if (res->ai_canonname && strlen(res->ai_canonname) > 0) { out = sh_util_strdup(res->ai_canonname); sh_tolower (out); if (strchr(out, '.')) flag = 1; } #endif sa = res->ai_addr; salen = res->ai_addrlen; getnameinfo(sa, salen, numeric, nlen, NULL, 0, NI_NUMERICHOST); if (!flag) out = SH_ALLOC(SH_PATHBUF); while (res && !flag) { sa = res->ai_addr; salen = res->ai_addrlen; getnameinfo(sa, salen, out, SH_PATHBUF, NULL, 0, 0); sh_tolower (out); if (strchr(out, '.')) flag = 1; res = res->ai_next; } } #else struct hostent *he; struct sh_sockaddr ss; volatile int isNum = 0; struct sockaddr_in *sin; numeric[0] = '\0'; sh_dummy_341_out = (void *) &out; if (sh_ipvx_is_numeric(hostname)) { sh_ipvx_aton (hostname, &ss); isNum = 1; } SH_MUTEX_LOCK(mutex_resolv); if (isNum == 0) { he = sh_gethostbyname(hostname); } else { sin = (struct sockaddr_in *) sh_ipvx_sockaddr_cast(&ss); he = sh_gethostbyaddr(&(sin->sin_addr), sizeof(sin->sin_addr), AF_INET); } if (he != NULL) { out = sh_util_strdup(sh_ipvx_h_name(he)); sh_tolower (out); sl_strlcpy (numeric, inet_ntoa (*(struct in_addr *) he->h_addr), nlen); flag = 1; } SH_MUTEX_UNLOCK(mutex_resolv); #endif if (flag) return out; if (out) SH_FREE(out); if (numeric[0] == '\0') sl_strlcpy (numeric, _("0.0.0.0"), nlen); return NULL; } char * sh_ipvx_addrtoname(struct sh_sockaddr * ss) { #if defined(USE_IPVX) char namebuf[SH_BUFSIZE]; if (getnameinfo(sh_ipvx_sockaddr_cast(ss), SH_SSP_LEN(ss), namebuf, sizeof(namebuf), NULL, 0, NI_NAMEREQD) != 0) { return NULL; } return sh_util_strdup(namebuf); #else struct sockaddr_in *sin; struct hostent *he; sin = (struct sockaddr_in *) sh_ipvx_sockaddr_cast(ss); he = sh_gethostbyaddr(&(sin->sin_addr), sizeof(sin->sin_addr), AF_INET); if (he && he->h_name) { return sh_util_strdup(he->h_name); } return NULL; #endif } int sh_ipvx_reverse_check_ok (char * peer, int port, struct sh_sockaddr * ss) { #if defined(USE_IPVX) struct addrinfo *res; struct addrinfo hints; char sport[32]; struct addrinfo *p; sl_snprintf(sport, sizeof(sport), "%d", port); memset(&hints, '\0', sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; if (getaddrinfo(peer, sport, &hints, &res) != 0) { return 0; } p = res; while (p != NULL) { if (ss->ss_family == p->ai_family) { struct sh_sockaddr pp; char dst1[SH_IP_BUF]; char dst2[SH_IP_BUF]; sh_ipvx_save(&pp, p->ai_family, p->ai_addr); sh_ipvx_ntoa (dst1, sizeof(dst1), &pp); sh_ipvx_ntoa (dst2, sizeof(dst2), ss); if (0 == sl_strcmp(dst1, dst2)) { return 1; } } p = p->ai_next; } freeaddrinfo(res); #else struct hostent * he; char ** p; struct sockaddr_in * sin = (struct sockaddr_in *) sh_ipvx_sockaddr_cast(ss); (void) port; he = sh_gethostbyname(peer); if (he != NULL) { for (p = he->h_addr_list; *p; ++p) { if (0 == memcmp (*p, &(sin->sin_addr), sizeof(in_addr_t)) ) return 1; } } #endif return 0; } #ifdef SH_CUTEST #include #include "CuTest.h" void Test_ipvx (CuTest *tc) { int result; result = sh_ipvx_is_ipv4("123456789"); CuAssertTrue(tc, result == FALSE); result = sh_ipvx_is_ipv4("123456789123..."); CuAssertTrue(tc, result == FALSE); result = sh_ipvx_is_ipv4("123.456.789.123"); CuAssertTrue(tc, result == FALSE); result = sh_ipvx_is_ipv4("123.156.189.254"); CuAssertTrue(tc, result == TRUE); result = sh_ipvx_is_ipv4("255.255.255.255"); CuAssertTrue(tc, result == TRUE); result = sh_ipvx_is_ipv4("0.0.0.0"); CuAssertTrue(tc, result == TRUE); result = sh_ipvx_is_ipv4("0022.156.189.254"); CuAssertTrue(tc, result == FALSE); result = sh_ipvx_is_ipv4("999999999.1.1.2"); CuAssertTrue(tc, result == FALSE); } #endif samhain-4.1.4/src/sh_cat.c0000644000175000017500000014460312615253277012277 00000000000000#include "config_xor.h" #include "samhain.h" #include "sh_error.h" #include "sh_cat.h" /*@-nullassign@*/ const char * class_cat[] = { N_("AUD"), /* 0 */ N_("PANIC"), /* 1 */ N_("RUN_OLD"), /* 2 */ N_("FIL_OLD"), /* 3 */ N_("TCP"), /* 4 */ N_("ERR"), /* 5 */ N_("STAMP"), /* 6 */ N_("ENET"), /* 7 */ N_("EINPUT"), /* 8 */ /* new simplified classes */ N_("EVENT"), /* 9 */ N_("START"), /* 10 */ N_("LOGKEY"), /* 11 */ N_("OTHER"), /* 12 */ /* end simplified classes */ N_("RUN"), /* 13 */ N_("FIL"), /* 14 */ N_("ERROR"), /* 15 */ NULL }; #ifdef SH_USE_XML cat_entry msg_cat[] = { #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) { MSG_FI_CSUM, SH_ERR_ALL, FIL, N_("msg=\"Checksum\" chk=\"%s\" path=\"%s\"")}, { MSG_FI_DSUM, SH_ERR_INFO, FIL, N_("msg=\"d: %3ld, -: %3ld, l: %3ld, |: %3ld, s: %3ld, c: %3ld, b: %3ld\"")}, { MSG_FI_CHK, SH_ERR_INFO, FIL, N_("msg=\"Checking %16s\" path=\"%s\"")}, #endif { MSG_EXIT_ABORTS, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC %s\" program=\"%s\" subroutine=\"%s\"")}, { MSG_START_SRV, SH_ERR_STAMP, START, N_("msg=\"Server up, simultaneous connections: %d\" socket_id=\"%d\"")}, { MSG_EXIT_ABORT1, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC Error initializing the application\" program=\"%s\"")}, { MSG_EXIT_NORMAL, SH_ERR_FATAL, START, N_("msg=\"EXIT\" program=\"%s\" status=\"%s\"")}, { MSG_START_KEY_MAIL, SH_ERR_FATAL, LOGKEY, N_("msg=\"LOGKEY\" program=\"%s\" hash=\"%s\"\r\n-----BEGIN LOGKEY-----\r\n%s%s")}, { MSG_START_KEY, SH_ERR_FATAL, LOGKEY, N_("msg=\"LOGKEY\" program=\"%s\" hash=\"%s\"")}, { MSG_START_0H, SH_ERR_FATAL, START, N_("msg=\"START\" program=\"%s\" userid=\"%ld\"")}, { MSG_START_1H, SH_ERR_FATAL, START, N_("msg=\"START\" program=\"%s\" userid=\"%ld\" path=\"%s\" hash=\"%s\"")}, { MSG_START_2H, SH_ERR_FATAL, START, N_("msg=\"START\" program=\"%s\" userid=\"%ld\" path=\"%s\" hash=\"%s\" path_data=\"%s\" hash_data=\"%s\"")}, { MSG_START_GH, SH_ERR_FATAL, START, N_("msg=\"START\" program=\"%s\" userid=\"%ld\" path=\"%s\" key_uid=\"%s\" key_id=\"%s\"")}, { MSG_START_GH2, SH_ERR_FATAL, START, N_("msg=\"EXIT\" program=\"%s\" userid=\"%ld\" path=\"%s\" key_uid=\"%s\" key_id=\"%s\" path_data=\"%s\" key_uid_data=\"%s\" key_id_data=\"%s\"")}, { MSG_SUSPEND, SH_ERR_STAMP, START, N_("msg=\"SUSPEND\" program=\"%s\"")}, { MSG_MLOCK, SH_ERR_WARN, RUN, N_("msg=\"Using insecure memory\"")}, { MSG_W_SIG, SH_ERR_WARN, RUN, N_("interface=\"sigaction\" msg=\"%s\" sig=\"%ld\"")}, { MSG_W_CHDIR, SH_ERR_ERR, RUN, N_("interface=\"chdir\" msg=\"%s\" path=\"%s\"")}, { MSG_MOD_FAIL, SH_ERR_WARN, RUN, N_("msg=\"Module not initialized\" module=\"%s\" return_code=\"%ld\"")}, { MSG_MOD_OK, SH_ERR_INFO, RUN, N_("msg=\"Module initialized\" module=\"%s\"")}, { MSG_MOD_EXEC, SH_ERR_ERR, RUN, N_("msg=\"Module execution error\" module=\"%s\" return_code=\"%ld\"")}, { MSG_RECONF, SH_ERR_SEVERE, START, N_("msg=\"Runtime configuration reloaded\"")}, { MSG_CHECK_0, SH_ERR_WARN, RUN, N_("msg=\"No files or directories defined for checking\"")}, { MSG_CHECK_1, SH_ERR_STAMP, STAMP, N_("msg=\"File check completed.\" time=\"%ld\" kBps=\"%f\"")}, { MSG_CHECK_2, SH_ERR_STAMP, STAMP, N_("msg=\"File check starting.\"")}, { MSG_STAMP, SH_ERR_STAMP, STAMP, N_("msg=\"---- TIMESTAMP ----\"")}, { MSG_D_START, SH_ERR_INFO, RUN, N_("msg=\"Downloading configuration file\"")}, { MSG_D_DSTART, SH_ERR_INFO, RUN, N_("msg=\"Downloading database file\"")}, { MSG_D_FAIL, SH_ERR_INFO, RUN, N_("msg=\"No file from server, trying local file\"")}, { MSG_D_DELTAOK, SH_ERR_SEVERE, RUN, N_("msg=\"Delta database downloaded\", path=\"%s\"")}, { MSG_D_DELTAFAIL, SH_ERR_SEVERE, RUN, N_("msg=\"Delta database download failed\", path=\"%s\"")}, #ifndef HAVE_URANDOM { MSG_ENSTART, SH_ERR_ALL, RUN, N_("msg=\"Found entropy source\" path=\"%s\"")}, { MSG_ENEXEC, SH_ERR_ALL, RUN, N_("msg=\"Execute entropy source\" path=\"%s\" rd_file_id=\"%ld\"")}, { MSG_ENFAIL, SH_ERR_ALL, RUN, N_("msg=\"Could not execute entropy source\" path=\"%s\"")}, { MSG_ENTOUT, SH_ERR_ALL, RUN, N_("msg=\"Timeout in entropy collector\" time=\"%ld\"")}, { MSG_ENCLOS, SH_ERR_ALL, RUN, N_("msg=\"End of data, closing entropy source\" rd_file_id=\"%ld\"")}, { MSG_ENCLOS1, SH_ERR_ALL, RUN, N_("msg=\"Close entropy source\" rd_file_id=\"%ld\"")}, { MSG_ENREAD, SH_ERR_ALL, RUN, N_("msg=\"Data from entropy source\" rd_file_id=\"%ld\" bytes=\"%ld\"")}, #endif #ifdef SH_USE_SUIDCHK { MSG_SUID_POLICY, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [SuidCheck] %s\" path=\"%s\" %s") }, { MSG_SUID_FOUND, SH_ERR_INFO, RUN, N_("msg=\"Found suid/sgid file\" path=\"%s\"") }, { MSG_SUID_SUMMARY,SH_ERR_INFO, RUN, N_("msg=\"Checked for SUID programs: %ld files, %ld seconds\"") }, { MSG_SUID_QREPORT,SH_ERR_SEVERE, EVENT, N_("msg=\"Quarantine report: %s\" path=\"%s\"") }, { MSG_SUID_ERROR, SH_ERR_SEVERE, EVENT, N_("msg=\"Quarantine error: %s\"") }, #endif #ifdef SH_USE_UTMP { MSG_UT_CHECK, SH_ERR_INFO, RUN, N_("msg=\"Checking logins\"")}, { MSG_UT_LG1X, SH_ERR_INFO, EVENT, N_("msg=\"Login\" userid=\"%s\" tty=\"%s\" host=\"%s\" ip=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG1A, SH_ERR_INFO, EVENT, N_("msg=\"Login\" userid=\"%s\" tty=\"%s\" host=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG1B, SH_ERR_INFO, EVENT, N_("msg=\"Login\" userid=\"%s\" tty=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG2X, SH_ERR_INFO, EVENT, N_("msg=\"Multiple login\" userid=\"%s\" tty=\"%s\" host=\"%s\" ip=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG2A, SH_ERR_INFO, EVENT, N_("msg=\"Multiple login\" userid=\"%s\" tty=\"%s\" host=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG2B, SH_ERR_INFO, EVENT, N_("msg=\"Multiple login\" userid=\"%s\" tty=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG3X, SH_ERR_INFO, EVENT, N_("msg=\"Logout\" userid=\"%s\" tty=\"%s\" host=\"%s\" ip=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG3A, SH_ERR_INFO, EVENT, N_("msg=\"Logout\" userid=\"%s\" tty=\"%s\" host=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG3B, SH_ERR_INFO, EVENT, N_("msg=\"Logout\" userid=\"%s\" tty=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_LG3C, SH_ERR_INFO, EVENT, N_("msg=\"Logout\" tty=\"%s\" time=\"%s\" status=\"%d\"")}, { MSG_UT_ROT, SH_ERR_WARN, RUN, N_("msg=\"Logfile size decreased\" path=\"%s\"")}, { MSG_UT_BAD, SH_ERR_SEVERE, EVENT, N_("msg=\"Login at disallowed time\" userid=\"%s\" host=\"%s\" time=\"%s\"")}, { MSG_UT_FIRST, SH_ERR_SEVERE, EVENT, N_("msg=\"First login from this host\" userid=\"%s\" host=\"%s\" time=\"%s\"")}, { MSG_UT_OUTLIER, SH_ERR_SEVERE, EVENT, N_("msg=\"Login time outlier\" userid=\"%s\" host=\"%s\" time=\"%s\"")}, #endif #ifdef SH_USE_PROCESSCHECK { MSG_PCK_CHECK, SH_ERR_INFO, RUN, N_("msg=\"Checking processes in pid interval [%ld,%ld]\"")}, { MSG_PCK_OK, SH_ERR_ALL, RUN, N_("msg=\"PID %ld found with tests %s\"")}, { MSG_PCK_P_HIDDEN,SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Process] Hidden pid: %ld tests: %s\" path=\"%s\" userid=\"%s\"")}, { MSG_PCK_HIDDEN, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Process] Hidden pid: %ld tests: %s\"")}, { MSG_PCK_FAKE, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Process] Fake pid: %ld tests: %s\"")}, { MSG_PCK_MISS, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Process] Missing: %s\"")}, #endif #ifdef SH_USE_PORTCHECK { MSG_PORT_MISS, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [ServiceMissing] %s\"")}, { MSG_PORT_NEW, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [ServiceNew] %s\" path=\"%s\" pid=\"%lu\" userid=\"%s\"")}, { MSG_PORT_RESTART,SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [ServiceRestarted] %s\" path=\"%s\" pid=\"%lu\" userid=\"%s\"")}, { MSG_PORT_NEWPORT,SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [ServicePortSwitch] %s\" path=\"%s\" pid=\"%lu\" userid=\"%s\"")}, #endif #ifdef SH_USE_MOUNTS { MSG_MNT_CHECK, SH_ERR_INFO, RUN, N_("msg=\"Checking mounts\"")}, { MSG_MNT_MEMLIST, SH_ERR_ERR, RUN, N_("msg=\"Cannot read mount list from memory\"")}, { MSG_MNT_MNTMISS, SH_ERR_WARN, EVENT, N_("msg=\"POLICY [Mounts] Mount missing\" path=\"%s\"")}, { MSG_MNT_OPTMISS, SH_ERR_WARN, EVENT, N_("msg=\"POLICY [Mounts] Mount option missing\" path=\"%s\" option=\"%s\"")}, #endif #ifdef SH_USE_USERFILES { MSG_USERFILES_SUMMARY,SH_ERR_INFO, RUN, N_("msg=\"Checked for users files\"") }, #endif #ifdef USE_LOGFILE_MONITOR { MSG_LOGMON_CHKS, SH_ERR_INFO, RUN, N_("msg=\"Checking logfile %s\"") }, { MSG_LOGMON_CHKE, SH_ERR_INFO, RUN, N_("msg=\"Finished logfile %s, %lu new records processed\"") }, { MSG_LOGMON_MISS, SH_ERR_ERR, RUN, N_("msg=\"Missing logfile %s\"") }, { MSG_LOGMON_EOPEN,SH_ERR_ERR, RUN, N_("msg=\"Cannot open logfile %s\"") }, { MSG_LOGMON_EREAD,SH_ERR_ERR, RUN, N_("msg=\"Error while reading logfile %s\"") }, { MSG_LOGMON_REP, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] %s\" time=\"%s\" host=\"%s\" path=\"%s\"") }, { MSG_LOGMON_SUM, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] %s\" host=\"%s\" path=\"%s\"") }, { MSG_LOGMON_COR, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] Correlation event %s occured %d time(s)\"") }, { MSG_LOGMON_MARK, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] Event %s missing for %lu seconds\"") }, { MSG_LOGMON_BURST, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] Repeated %d times: %s\" host=\"%s\"") }, #endif #ifdef USE_REGISTRY_CHECK { MSG_REG_MISS, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [RegistryKeyMissing] %s\" path=\"%s\" %s")}, { MSG_REG_NEW, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [RegistryKeyNew] %s\" path=\"%s\" %s")}, { MSG_REG_CHANGE, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [RegistryKeyChanged] %s\" path=\"%s\" %s")}, #endif #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) { MSG_FI_TOOLATE, SH_ERR_ERR, FIL, N_("msg=\"Large lstat/open overhead: %ld sec\" path=\"%s\"")}, #if 0 { MSG_FI_CSUM, SH_ERR_ALL, FIL, N_("msg=\"Checksum\" chk=\"%s\" path=\"%s\"")}, { MSG_FI_DSUM, SH_ERR_INFO, FIL, N_("msg=\"d: %3ld, -: %3ld, l: %3ld, |: %3ld, s: %3ld, c: %3ld, b: %3ld\"")}, { MSG_FI_CHK, SH_ERR_INFO, FIL, N_("msg=\"Checking %16s\" path=\"%s\"")}, #endif { MSG_FI_NULL, SH_ERR_ERR, FIL, N_("msg=\"Path is NULL\"")}, { MSG_FI_FAIL, SH_ERR_ERR, FIL, N_("msg=\"Check failed\" path=\"%s\"")}, { MSG_FI_GLOB, SH_ERR_ERR, FIL, N_("interface=\"glob\" msg=\"%s\" path=\"%s\"")}, { MSG_FI_COLL, SH_ERR_WARN, FIL, N_("msg=\"Writeable file with timestamps of parent directory fixed\" dir=\"%s\" path=\"%s\"")}, { MSG_FI_DOUBLE, SH_ERR_WARN, FIL, N_("msg=\"File or directory appears twice in configuration\" path=\"%s\"")}, { MSG_FI_2LONG, SH_ERR_ERR, FIL, N_("msg=\"Filename too long\" path=\"%s\"")}, { MSG_FI_2LONG2, SH_ERR_ERR, FIL, N_("msg=\"Filename too long\" path=\"%s/%s\"")}, { MSG_FI_NOPATH, SH_ERR_ERR, FIL, N_("msg=\"Filename not an absolute path\" path=\"%s\"")}, { MSG_FI_DLNK, SH_ERR_INFO, FIL, N_("msg=\"Dangling link\" path=\"%s\" linked_path=\"%s\"")}, { MSG_FI_RDLNK, SH_ERR_ERR, FIL, N_("interface=\"readlink\" msg=\"%s\" path=\"%s\"")}, { MSG_FI_NOGRP, SH_ERR_ERR, FIL, N_("interface=\"getgrgid\" msg=\"No such group\" group=\"%ld\" path=\"%s\"")}, { MSG_FI_NOUSR, SH_ERR_ERR, FIL, N_("interface=\"getpwuid\" msg=\"No such user\" userid=\"%ld\" path=\"%s\"")}, { MSG_FI_STAT, SH_ERR_ERR, FIL, N_("interface=\"%s\" msg=\"%s\" userid=\"%ld\" path=\"%s\"")}, { MSG_FI_OBSC, SH_ERR_ERR, FIL, N_("msg=\"Weird filename\" path=\"%s\"")}, { MSG_FI_OBSC2, SH_ERR_ERR, FIL, N_("msg=\"Weird filename\" path=\"%s/%s\"")}, { MSG_FI_LIST, SH_ERR_ALL, FIL, N_("msg=\"%10s %2d %8s %8s %14ld %21s %s\"")}, { MSG_FI_LLNK, SH_ERR_ALL, FIL, N_("msg=\" >>> %10s %s\"")}, { MSG_FI_MISS, SH_ERR_ERR, EVENT, N_("msg=\"POLICY MISSING\" path=\"%s\"")}, { MSG_FI_MISS2, SH_ERR_ERR, EVENT, N_("msg=\"POLICY MISSING\" path=\"%s\" %s")}, { MSG_FI_ADD, SH_ERR_ERR, EVENT, N_("msg=\"POLICY ADDED\" path=\"%s\"")}, { MSG_FI_ADD2, SH_ERR_ERR, EVENT, N_("msg=\"POLICY ADDED\" path=\"%s\" %s")}, { MSG_FI_CHAN, SH_ERR_ERR, EVENT, N_("msg=\"POLICY %s %s\" path=\"%s\" %s")}, { MSG_FI_NODIR, SH_ERR_ERR, EVENT, N_("msg=\"POLICY NODIRECTORY\" path=\"%s\"")}, { MSG_FI_DBEX, SH_ERR_WARN, FIL, N_("msg=\"Signature database exists\" path=\"%s\"")}, #endif { MSG_TCP_NETRP, SH_ERR_ERR, TCP, N_("msg=\"Connection error: %s\" port=\"%ld\" subroutine=\"%s\"")}, #ifndef SH_STANDALONE #ifdef INET_SYSLOG { MSG_INET_SYSLOG, SH_ERR_INET, TCP, N_("ip=\"%s\" facility=\"%s\" priority=\"%s\" syslog_msg=\"%s\"")}, { MSG_ERR_SYSLOG, SH_ERR_ERR, TCP, N_("msg=\"syslog socket: %s\" ip=\"%s\"")}, #endif { MSG_TCP_MISMATCH,SH_ERR_ERR, TCP, N_("msg=\"Protocol mismatch\"")}, { MSG_TCP_MISENC, SH_ERR_ERR, TCP, N_("msg=\"Encryption mismatch in %s: server: %s client: %s\"")}, { MSG_TCP_NONAME, SH_ERR_ERR, TCP, N_("msg=\"No server name known\"")}, { MSG_TCP_UNEXP, SH_ERR_ERR, TCP, N_("msg=\"Unexpected reply\"")}, { MSG_TCP_EFIL, SH_ERR_ERR, TCP, N_("msg=\"Could not open temporary file\"")}, { MSG_TCP_NOCONF, SH_ERR_ERR, TCP, N_("msg=\"Message delivery not confirmed\"")}, { MSG_TCP_NOAUTH, SH_ERR_ERR, TCP, N_("msg=\"Session key negotiation failed\"")}, { MSG_TCP_CONF, SH_ERR_ALL, TCP, N_("msg=\"Message delivery confirmed\"")}, { MSG_TCP_AUTH, SH_ERR_INFO, TCP, N_("msg=\"Session key negotiated\"")}, { MSG_TCP_FOK, SH_ERR_INFO, TCP, N_("msg=\"File download completed\"")}, { MSG_TCP_FBAD, SH_ERR_ERR, TCP, N_("msg=\"File download failed\"")}, { MSG_TCP_ECONN, SH_ERR_ERR, TCP, N_("msg=\"Connection error: %s\"")}, { MSG_TCP_EZERO, SH_ERR_ERR, TCP, N_("msg=\"Illegal zero reply\"")}, { MSG_TCP_EBGN, SH_ERR_ERR, TCP, N_("msg=\"Error in big integer library\"")}, { MSG_TCP_CREG, SH_ERR_ALL, TCP, N_("msg=\"Registered %s, salt %s, verifier %s\"")}, { MSG_TCP_FAUTH, SH_ERR_INFO, TCP, N_("msg=\"Force authentication\" host=\"%s\"")}, { MSG_TCP_RESCLT, SH_ERR_SEVERE, TCP, N_("msg=\"Cannot resolve client name\" host=\"%s\"")}, { MSG_TCP_RESPEER, SH_ERR_SEVERE, TCP, N_("msg=\"Cannot resolve socket peer IP for client\" host=\"%s\" peer=\"%s\"")}, { MSG_TCP_LOOKERS, SH_ERR_SEVERE, TCP, N_("msg=\"Reverse lookup of socket peer failed\" host=\"%s\" peer=\"%s\" obj=\"%s\"")}, { MSG_TCP_LOOKUP, SH_ERR_SEVERE, TCP, N_("msg=\"No socket peer alias matches client name\" host=\"%s\" peer=\"%s\"")}, { MSG_TCP_TIMOUT, SH_ERR_SEVERE, TCP, N_("msg=\"Connection timeout\" host=\"%s\"")}, { MSG_TCP_TIMEXC, SH_ERR_SEVERE, TCP, N_("msg=\"Time limit exceeded\" host=\"%s\"")}, { MSG_TCP_NOCLT, SH_ERR_SEVERE, TCP, N_("msg=\"Hostname is NULL\"")}, { MSG_TCP_BADCONN, SH_ERR_SEVERE, TCP, N_("msg=\"Invalid connection attempt: %s\" host=\"%s\"")}, { MSG_TCP_FFILE , SH_ERR_SEVERE, TCP, N_("msg=\"Unknown file request\" host=\"%s\" path=\"%s\"")}, { MSG_TCP_NFILE , SH_ERR_SEVERE, TCP, N_("msg=\"Requested file not found\" host=\"%s\" path=\"%s\"")}, { MSG_TCP_FINV , SH_ERR_SEVERE, TCP, N_("msg=\"Invalid request (%d) in pass %d\" host=\"%s\" request=\"%c%03o%c%03o%c%03o%c%03o\"")}, { MSG_TCP_OKFILE, SH_ERR_INFO, TCP, N_("msg=\"File transfer completed\" host=\"%s\"")}, { MSG_TCP_OKMSG, SH_ERR_ALL, TCP, N_("msg=\"Message transfer completed\" host=\"%s\"")}, { MSG_TCP_MSG, SH_ERR_INET, TCP, N_("remote_host=\"%s\" > %s ")}, { MSG_TCP_NEW, SH_ERR_NOTICE, TCP, N_("msg=\"NEW CLIENT\" host=\"%s\"")}, { MSG_TCP_ILL, SH_ERR_SEVERE, TCP, N_("msg=\"Restart without prior exit\" host=\"%s\"")}, { MSG_TCP_SYNC, SH_ERR_SEVERE, TCP, N_("msg=\"Out of sync\" host=\"%s\"")}, { MSG_TCP_RESET, SH_ERR_NOTICE, TCP, N_("msg=\"Connection reset by peer\" host=\"%s\"")}, { MSG_TCP_CNEW, SH_ERR_INFO, TCP, N_("msg=\"New connection\" socket_id=\"%d\"")}, { MSG_E_HTML, SH_ERR_ERR, ERR, N_("msg=\"Error writing HTML status\"")}, #endif { MSG_E_AUTH, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC - File modified\" path=\"%s\"")}, { MSG_ACCESS, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC - Access violation\" userid=\"%ld\" path=\"%s\"")}, { MSG_TRUST, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC - Untrusted path\" userid=\"%ld\" path=\"%s\"")}, { MSG_NOACCESS, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC - File not accessible\" userid=\"%ld\" path=\"%s\"")}, { MSG_P_NODATA, SH_ERR_FATAL, PANIC, N_("msg=\"PANIC - No data in file\" path=\"%s\"")}, #ifndef MEM_DEBUG { MSG_E_MNULL, SH_ERR_ERR, ERR, N_("msg=\"Dereferenced NULL pointer\"")}, { MSG_E_MMEM, SH_ERR_ERR, ERR, N_("msg=\"Out of memory\"")}, #else { MSG_MSTAMP, SH_ERR_STAMP, STAMP, N_("msg=\"Memory used: max.=%lu, current=%lu\"")}, { MSG_MSTAMP2, SH_ERR_STAMP, STAMP, N_("msg=\"Blocks: %d allocated, %d freed, %d maximum\"")}, { MSG_E_MNULL, SH_ERR_ERR, ERR, N_("msg=\"Dereferenced NULL pointer allocated in %s, line %d\" source_file=\"%s\" source_line=\"%d\"")}, { MSG_E_MMEM, SH_ERR_ERR, ERR, N_("msg=\"Out of memory\" source_file=\"%s\" source_line=\"%d\"")}, { MSG_E_MREC, SH_ERR_ERR, ERR, N_("msg=\"Free() on unrecorded block\" source_file=\"%s\" source_line=\"%d\"")}, { MSG_E_MOVER, SH_ERR_ERR, ERR, N_("msg=\"Memory overrun on block allocated in %s, line %d\" source_file=\"%s\" source_line=\"%d\"")}, { MSG_E_MUNDER, SH_ERR_ERR, ERR, N_("msg=\"Memory underrun on block allocated in %s, line %d\" source_file=\"%s\" source_line=\"%d\"")}, { MSG_E_NOTFREE, SH_ERR_ERR, ERR, N_("msg=\"Block not deallocated\" size=\"%14ld\" source_file=\"%19s\" source_line=\"%d\"")}, #endif { MSG_E_TRUST, SH_ERR_ERR, ERR, N_("msg=\"Untrusted path\" userid=\"%ld\" path=\"%s\"")}, { MSG_E_HASH, SH_ERR_ERR, ERR, N_("msg=\"Incorrect checksum\" path=\"%s\"")}, { MSG_E_ACCESS, SH_ERR_ERR, ERR, N_("msg=\"File not accessible\" userid=\"%ld\" path=\"%s\"")}, { MSG_E_READ, SH_ERR_ERR, ERR, N_("msg=\"Not accessible or not a regular file (%s / %s)\" path=\"%s\"")}, { MSG_E_NOTREG, SH_ERR_ERR, ERR, N_("msg=\"Not a regular file\" path=\"%s\"")}, { MSG_E_TIMEOUT, SH_ERR_ERR, ERR, N_("msg=\"Timeout (%d sec) while checksumming file\" path=\"%s\"")}, { MSG_NODEV, SH_ERR_ERR, ERR, N_("msg=\"Device not available or timeout during read attempt\" userid=\"%ld\" path=\"%s\"")}, { MSG_LOCKED, SH_ERR_ERR, ERR, N_("msg=\"File lock error\" userid=\"%ld\" path=\"%s\" obj=\"%s\"")}, { MSG_PIDFILE, SH_ERR_ERR, ERR, N_("msg=\"Could not write PID file\" userid=\"%ld\" path=\"%s\"")}, { MSG_NOEXEC, SH_ERR_ERR, ERR, N_("msg=\"Could not execute file\" userid=\"%ld\" path=\"%s\"")}, { MSG_ES_ENT, SH_ERR_ERR, ERR, N_("msg=\"No entropy collected\" subroutine=\"%s\"")}, { MSG_ES_KEY1, SH_ERR_ERR, ERR, N_("msg=\"Insecure key generation\" subroutine=\"%s\"")}, { MSG_ES_KEY2, SH_ERR_ERR, ERR, N_("msg=\"Error copying key\" subroutine=\"%s\"")}, { MSG_E_GPG, SH_ERR_ERR, ERR, N_("msg=\"Compiled-in gpg checksum does not match: need %s got %s\"")}, { MSG_E_GPG_FP, SH_ERR_ERR, ERR, N_("msg=\"Compiled-in fingerprint modified: one %s two %s\"")}, { MSG_E_GPG_CHK, SH_ERR_ERR, ERR, N_("msg=\"Compiled-in checksum modified: one %s two %s\"")}, { MSG_E_SUBGEN, SH_ERR_ERR, ERR, N_("msg=\"%s\" subroutine=\"%s\"")}, { MSG_E_SUBGPATH, SH_ERR_ERR, ERR, N_("msg=\"%s\" subroutine=\"%s\" path=\"%s\"")}, { MSG_E_UNLNK, SH_ERR_ERR, FIL, N_("interface=\"unlink\" msg=\"%s\" path=\"%s\"")}, { MSG_E_REGEX, SH_ERR_ERR, ERR, N_("interface=\"regcomp\" msg=\"%s\" obj=\"%s\"")}, { MSG_E_OPENDIR, SH_ERR_ERR, FIL, N_("interface=\"opendir\" msg=\"%s\" path=\"%s\"")}, { MSG_E_TRUST1, SH_ERR_ERR, ERR, N_("msg=\"%s\" subroutine=\"trustfile\" path=\"%s\"")}, { MSG_E_TRUST2, SH_ERR_ERR, ERR, N_("msg=\"%s\" subroutine=\"trustfile\" path=\"%s\" obj=\"%s\"")}, { MSG_E_PWNULL, SH_ERR_ERR, ERR, N_("msg=\"Empty password file entry: %s\" subroutine=\"%s\" userid=\"%ld\" obj=\"%s\"")}, { MSG_E_PWLONG, SH_ERR_ERR, ERR, N_("msg=\"Password file entry too long\" subroutine=\"%s\" userid=\"%ld\" obj=\"%s\"")}, { MSG_E_GRNULL, SH_ERR_ERR, ERR, N_("msg=\"Empty groups file entry: %s\" subroutine=\"%s\" group=\"%ld\" obj=\"%s\"")}, { MSG_E_NET, SH_ERR_ERR, ENET, N_("msg=\"%s\" subroutine=\"%s\" service=\"%s\" host=\"%s\"")}, { MSG_E_NETST, SH_ERR_ERR, ENET, N_("msg=\"Invalid connection state\" expect=\"%4s\" received=\"%4s\"")}, { MSG_E_NETST1, SH_ERR_ERR, ENET, N_("msg=\"Invalid connection state\" expect=\"%4s\" received=\"%4s\" host=\"%s\"")}, { MSG_E_NLOST, SH_ERR_ERR, ENET, N_("msg=\"Connection failure\" service=\"%s\" host=\"%s\"")}, { MSG_E_NEST, SH_ERR_ERR, ENET, N_("msg=\"Connection reestablished\" service=\"%s\" host=\"%s\"")}, { MSG_EINVALHEAD, SH_ERR_WARN, EINPUT,N_("msg=\"Unrecognized section heading in line %ld of configuration file\"")}, { MSG_EINVALCONF, SH_ERR_WARN, EINPUT,N_("msg=\"Invalid line %ld in configuration file: incorrect format, unrecognized option, or missing section header\"")}, { MSG_EINVALS, SH_ERR_WARN, EINPUT,N_("msg=\"Invalid input\" option=\"%s\" obj=\"%s\"")}, { MSG_EINVALL, SH_ERR_WARN, EINPUT,N_("msg=\"Invalid input\" option=\"%s\" obj=\"%ld\"")}, { MSG_EINVALD, SH_ERR_WARN, EINPUT,N_("msg=\"Configuration file: unmatched @end\" option=\"%s\" obj=\"%ld\"")}, { MSG_EINVALDD, SH_ERR_WARN, EINPUT,N_("msg=\"Configuration file: missing @end\" option=\"%s\" obj=\"%ld\"")}, { MSG_SRV_FAIL, SH_ERR_ERR, ERR, N_("msg=\"Service failure\" service=\"%s\" obj=\"%s\"")}, { MSG_QUEUE_FULL, SH_ERR_ERR, ERR, N_("msg=\"Queue full, messages may get lost\" service=\"%s\"")}, { MSG_AUD_OPEN, SH_ERR_NOTICE, AUD, N_("interface=\"open\" path=\"%s\" oflag=\"%ld\" mode=\"%ld\" return_id=\"%ld\"")}, { MSG_AUD_DUP, SH_ERR_NOTICE, AUD, N_("interface=\"dup\" file_id=\"%ld\" return_id=\"%ld\"")}, { MSG_AUD_PIPE, SH_ERR_NOTICE, AUD, N_("interface=\"pipe\" rd_file_id=\"%ld\" wr_file_id=\"%ld\"")}, { MSG_AUD_FORK, SH_ERR_NOTICE, AUD, N_("interface=\"fork\" return_id=\"%ld\"")}, { MSG_AUD_EXIT, SH_ERR_NOTICE, AUD, N_("interface=\"exit\" exit_code=\"%ld\"")}, { MSG_AUD_SETUID, SH_ERR_NOTICE, AUD, N_("interface=\"setuid\" uid=\"%ld\"")}, { MSG_AUD_SETGID, SH_ERR_NOTICE, AUD, N_("interface=\"setgid\" gid=\"%ld\"")}, { MSG_AUD_UTIME, SH_ERR_NOTICE, AUD, N_("interface=\"utime\" path=\"%s\" atime=\"%ld\" mtime=\"%ld\"")}, { MSG_AUD_EXEC, SH_ERR_NOTICE, AUD, N_("interface=\"exec\" path=\"%s\" uid=\"%ld\" gid=\"%ld\"")}, { MSG_AUD_CHDIR, SH_ERR_NOTICE, AUD, N_("interface=\"chdir\" path=\"%s\"")}, { MSG_AUD_UNLINK, SH_ERR_NOTICE, AUD, N_("interface=\"unlink\" path=\"%s\"")}, { MSG_AUD_KILL, SH_ERR_NOTICE, AUD, N_("interface=\"kill\" pid=\"%ld\" sig=\"%ld\"")}, { MSG_ERR_OPEN, SH_ERR_ALL, ERR, N_("interface=\"open\" msg=\"%s\" path=\"%s\" oflag=\"%ld\" mode=\"%ld\" return_id=\"%ld\"")}, { MSG_ERR_DUP, SH_ERR_ALL, ERR, N_("interface=\"dup\" msg=\"%s\" file_id=\"%ld\" return_id=\"%ld\"")}, { MSG_ERR_PIPE, SH_ERR_ALL, ERR, N_("interface=\"pipe\" msg=\"%s\" rd_file_id=\"%ld\" wr_file_id=\"%ld\"")}, { MSG_ERR_FORK, SH_ERR_ALL, ERR, N_("interface=\"fork\" msg=\"%s\" return_id=\"%ld\"")}, { MSG_ERR_SETUID, SH_ERR_ALL, ERR, N_("interface=\"setuid\" msg=\"%s\" uid=\"%ld\"")}, { MSG_ERR_SETGID, SH_ERR_ALL, ERR, N_("interface=\"setgid\" msg=\"%s\" gid=\"%ld\"")}, { MSG_ERR_UTIME, SH_ERR_ALL, ERR, N_("interface=\"utime\" msg=\"%s\" path=\"%s\" atime=\"%ld\" mtime=\"%ld\"")}, { MSG_ERR_EXEC, SH_ERR_ALL, ERR, N_("interface=\"exec\" msg=\"%s\" path=\"%s\" uid=\"%ld\" gid=\"%ld\"")}, { MSG_ERR_CHDIR, SH_ERR_ALL, ERR, N_("interface=\"chdir\" msg=\"%s\" path=\"%s\"")}, { MSG_ERR_UNLINK, SH_ERR_ALL, ERR, N_("interface=\"unlink\" msg=\"%s\" path=\"%s\"")}, { MSG_ERR_KILL, SH_ERR_ALL, ERR, N_("interface=\"kill\" msg=\"%s\" pid=\"%ld\" sig=\"%ld\"")}, { MSG_ERR_SIGACT, SH_ERR_ALL, ERR, N_("interface=\"sigaction\" msg=\"%s\" sig=\"%ld\"")}, { MSG_ERR_CONNECT, SH_ERR_ALL, ERR, N_("interface=\"connect\" msg=\"%s\" socket_id=\"%ld\" port=\"%ld\" host=\"%s\"")}, { MSG_ERR_ACCEPT, SH_ERR_ALL, ERR, N_("interface=\"accept\" msg=\"%s\" socket_id=\"%ld\"")}, { MSG_ERR_LSTAT, SH_ERR_ALL, ERR, N_("interface=\"lstat\" msg=\"%s\" path=\"%s\"")}, { MSG_ERR_STAT, SH_ERR_ALL, ERR, N_("interface=\"stat\" msg=\"%s\" path=\"%s\"")}, { MSG_ERR_FSTAT, SH_ERR_ALL, ERR, N_("interface=\"fstat\" msg=\"%s\" file_id=\"%ld\"")}, { MSG_ERR_FCNTL, SH_ERR_ALL, ERR, N_("interface=\"fcntl\" msg=\"%s\" file_id=\"%ld\" cmd=\"%ld\" arg=\"%ld\"")}, { 0, 0, 0, NULL} }; /******************************************************************** * * * NO XML * * ********************************************************************/ /* #ifdef (SH_USE_XML) */ #else cat_entry msg_cat[] = { #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) { MSG_FI_CSUM, SH_ERR_ALL, FIL, N_("msg=, chk=<%s>, path=<%s>")}, { MSG_FI_DSUM, SH_ERR_INFO, FIL, N_("msg=")}, { MSG_FI_CHK, SH_ERR_INFO, FIL, N_("msg=, path=<%s>")}, #endif { MSG_EXIT_ABORTS, SH_ERR_FATAL, PANIC, N_("msg=, program=<%s>, subroutine=<%s>")}, { MSG_START_SRV, SH_ERR_STAMP, START, N_("msg=, socket_id=<%d>")}, { MSG_EXIT_ABORT1, SH_ERR_FATAL, PANIC, N_("msg=, program=<%s>")}, { MSG_EXIT_NORMAL, SH_ERR_FATAL, START, N_("msg=, program=<%s>, status=<%s>")}, { MSG_START_KEY_MAIL, SH_ERR_FATAL, LOGKEY, N_("msg=, program=<%s>, hash=<%s>\r\n-----BEGIN LOGKEY-----\r\n%s%s")}, { MSG_START_KEY, SH_ERR_FATAL, LOGKEY, N_("msg=, program=<%s>, hash=<%s>")}, { MSG_START_0H, SH_ERR_FATAL, START, N_("msg=, program=<%s>, userid=<%ld>")}, { MSG_START_1H, SH_ERR_FATAL, START, N_("msg=, program=<%s>, userid=<%ld>, path=<%s>, hash=<%s>")}, { MSG_START_2H, SH_ERR_FATAL, START, N_("msg=, program=<%s>, userid=<%ld>, path=<%s>, hash=<%s>, path=<%s>, hash=<%s>")}, { MSG_START_GH, SH_ERR_FATAL, START, N_("msg=, program=<%s>, userid=<%ld>, path=<%s>, key_uid=<%s>, key_id=<%s>")}, { MSG_START_GH2, SH_ERR_FATAL, START, N_("msg=, program=<%s>, userid=<%ld>, path=<%s>, key_uid=<%s>, key_id=<%s>, path=<%s>, key_uid=<%s>, key_id=<%s>")}, { MSG_SUSPEND, SH_ERR_STAMP, START, N_("msg= program=<%s>")}, { MSG_MLOCK, SH_ERR_WARN, RUN, N_("msg=")}, { MSG_W_SIG, SH_ERR_WARN, RUN, N_("msg=<%s>, interface=, signal=<%ld>")}, { MSG_W_CHDIR, SH_ERR_ERR, RUN, N_("msg=<%s>, interface=, path=<%s>")}, { MSG_MOD_FAIL, SH_ERR_WARN, RUN, N_("msg=, module=<%s>, return_code=<%ld>")}, { MSG_MOD_OK, SH_ERR_INFO, RUN, N_("msg=, module=<%s>")}, { MSG_MOD_EXEC, SH_ERR_ERR, RUN, N_("msg=, module=<%s>, return_code=<%ld>")}, { MSG_RECONF, SH_ERR_SEVERE, START, N_("msg=")}, { MSG_CHECK_0, SH_ERR_WARN, RUN, N_("msg=")}, { MSG_CHECK_1, SH_ERR_STAMP, STAMP, N_("msg=, time=<%ld>, kBps=<%f>")}, { MSG_CHECK_2, SH_ERR_STAMP, STAMP, N_("msg=")}, { MSG_STAMP, SH_ERR_STAMP, STAMP, N_("msg=<---- TIMESTAMP ---->")}, { MSG_D_START, SH_ERR_INFO, RUN, N_("msg=")}, { MSG_D_DSTART, SH_ERR_INFO, RUN, N_("msg=")}, { MSG_D_FAIL, SH_ERR_INFO, RUN, N_("msg=")}, { MSG_D_DELTAOK, SH_ERR_SEVERE, RUN, N_("msg=, path=<%s>")}, { MSG_D_DELTAFAIL, SH_ERR_SEVERE, RUN, N_("msg=, path=<%s>")}, #ifndef HAVE_URANDOM { MSG_ENSTART, SH_ERR_ALL, RUN, N_("msg=, path=<%s>")}, { MSG_ENEXEC, SH_ERR_ALL, RUN, N_("msg=, path=<%s>, rd_file_id=<%ld>")}, { MSG_ENFAIL, SH_ERR_ALL, RUN, N_("msg=, path=<%s>")}, { MSG_ENTOUT, SH_ERR_ALL, RUN, N_("msg=, time=<%ld>")}, { MSG_ENCLOS, SH_ERR_ALL, RUN, N_("msg=, rd_file_id=<%ld>")}, { MSG_ENCLOS1, SH_ERR_ALL, RUN, N_("msg=, rd_file_id=<%ld>")}, { MSG_ENREAD, SH_ERR_ALL, RUN, N_("msg=, rd_file_id=<%ld>, bytes=<%ld>")}, #endif #ifdef SH_USE_SUIDCHK { MSG_SUID_POLICY, SH_ERR_SEVERE, EVENT, N_("msg=, path=<%s>, %s") }, { MSG_SUID_FOUND, SH_ERR_INFO, RUN, N_("msg= path=<%s>") }, { MSG_SUID_SUMMARY,SH_ERR_INFO, RUN, N_("msg=") }, { MSG_SUID_QREPORT,SH_ERR_SEVERE, EVENT, N_("msg=, path=<%s>") }, { MSG_SUID_ERROR, SH_ERR_SEVERE, EVENT, N_("msg=") }, #endif #ifdef SH_USE_KERN { MSG_KERN_POLICY, SH_ERR_SEVERE, EVENT, N_("msg=, syscall=<%03d %s>") }, { MSG_KERN_POL_CO, SH_ERR_SEVERE, EVENT, N_("msg=, syscall=<%03d %s>") }, { MSG_KERN_SYSCALL,SH_ERR_SEVERE, EVENT, N_("msg= syscall=<%03d %s>, %s") }, { MSG_KERN_PROC, SH_ERR_SEVERE, EVENT, N_("msg=") }, { MSG_KERN_IDT, SH_ERR_SEVERE, EVENT, N_("msg=, %s") }, { MSG_KERN_GATE, SH_ERR_SEVERE, EVENT, N_("msg= syscall=<%03d %s>, %s") }, #endif #ifdef SH_USE_UTMP { MSG_UT_CHECK, SH_ERR_INFO, RUN, N_("msg=")}, { MSG_UT_LG1X, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, host=<%s>, ip=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG1A, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, host=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG1B, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG2X, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, host=<%s>, ip=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG2A, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, host=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG2B, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG3X, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, host=<%s>, ip=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG3A, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, host=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG3B, SH_ERR_INFO, EVENT, N_("msg=, name=<%s>, tty=<%s>, time=<%s>, status=<%d>")}, { MSG_UT_LG3C, SH_ERR_INFO, EVENT, N_("msg=, tty=<%s>, time=<%s>")}, { MSG_UT_ROT, SH_ERR_WARN, RUN, N_("msg=, path=<%s>")}, { MSG_UT_BAD, SH_ERR_SEVERE, EVENT, N_("msg= userid=<%s> host=<%s> time=<%s>")}, { MSG_UT_FIRST, SH_ERR_SEVERE, EVENT, N_("msg= userid=<%s> host=<%s> time=<%s>")}, { MSG_UT_OUTLIER, SH_ERR_SEVERE, EVENT, N_("msg= userid=<%s> host=<%s> time=<%s>")}, #endif #ifdef SH_USE_PROCESSCHECK { MSG_PCK_CHECK, SH_ERR_INFO, RUN, N_("msg=")}, { MSG_PCK_OK, SH_ERR_ALL, RUN, N_("msg=")}, { MSG_PCK_P_HIDDEN,SH_ERR_SEVERE, EVENT, N_("msg=

samhain file integrity scanner | online documentation


Samhain client/server: What can go wrong, and how can you fix it ?



  • Almost all problems can only be diagnosed correctly by checking the server logs.
  • If the server does not write logs, fix this first. For debugging, stop the server, then run it in the foreground with yule -p info --foreground
    • By default, the server logs to the file /var/log/yule/yule_log, and since the server drops root privileges on startup, the directory /var/log/yule must be writable for the nonprivileged user the server runs as (the first existing out of: yule, daemon, nobody).
    • Logging to the logfile must be enabled in the /etc/yulerc config file (e.g. LogSeverity=mark, or LogSeverity=info for enhanced verbosity).

This document aims to explain how to diagnose and fix common problems that may result from misunderstanding or misconfiguration when setting up a client/server samhain system. This document is divided in several sections more or less corresponding to the different stages when a client connects to a server. Each section starts with a brief explanation that should provide a basic understanding of what is going on.

This document does not discuss how to setup a client/server (for this, look into the manual and/or the HOWTO-client+server).

Table of Contents

Connecting to the server
Authentication
Downloading config/database files
Other connection problems

Connecting to the server

Client/server connections are always initiated from the client. The port is compiled in (there is a configure option to change the default). The default port is 49777.

Problem #1

The client reports: Connection refused. The server reports nothing.

The server is down, listens on the wrong port, or network failure.

Problem #2

The client reports: Connection error: Connection reset by peer, and later also Session key negotiation failed. The server reports: msg="Refused connection from ..." subroutine="libwrap".

The server is compiled with libwrap (TCP Wrapper) support, and the client is either in /etc/hosts.deny, or you have set yule: ALL in /etc/hosts.deny, and forgot to put the client in /etc/hosts.allow.

To fix: make proper entries in /etc/hosts.allow and/or /etc/hosts.deny. There is no need to restart/reload the server.

Authentication

The client has a password that is used to authenticate to the server. This password is located within the binary, and is set with the samhain_setpwd helper application, as explained e.g. in the manual or in the Client+Server HOWTO.

The server has a list of clients that are allowed to connect, and the verifiers corresponding to the passwords of these clients.

Upon successful authentication, client and server will negotiate a session key that is used for signing further messages from the client.

Problem #1

If the password is wrong, the client will report Session key negotiation failed. The server will report: Invalid connection attempt: Session key mismatch

To fix: make sure that the password has in fact been set, that you are using the correct executable for the client (the one where the password is set), and that the entry in the server config file is the one generated for this password (also look out for double entries for this client).

Problem #2

If the client name (as resolved on the server) is wrong, the client will report Session key negotiation failed. The server will report: Invalid connection attempt: Not in client list, and it will tell you in the same error message what name it has inferred for the connecting client (example): client="client.mydomain.com".

The fix depends on the nature of the problem. In principle, it should be sufficient to change the name of the client in the config file entry, which isn't really a solution if e.g. the server thinks the client is 'localhost'.

There are two different ways to determine the client name. Unfortunately, judging from customer feedback as well from common sense, both do not work very well with a messed up local DNS (including /etc/hosts files) and/or überparanoid or misconfigured firewalls (in case of connections across one).

  • First method: Determine client name on client, and try to cross-check on server

    This does not work for a number of people because

    1. the /etc/hosts file on the client machine has errors (yes, there are plenty machines with a completely messed up /etc/hosts file),
    2. the server cannot resolve the client address because the local DNS is misconfigured, or
    3. the client machine has multiple network interfaces, and the interface used is not the one the client name resolves to.

    If the client uses the wrong interface on a multi-interface machine, there is a config file option SetBindAddress=IP address that allows to choose the interface the client will use for outgoing connections.

    If you want to download the config file from the server, you should instead use the corresponding command line option --bind-address=IP address to select the interface.

    If you encounter problems, you may (1) fix your /etc/hosts file(s), (2) fix your local DNS, or (3) switch to the second method.

    Error messages related to name resolving/cross-checking can be suppressed by setting a very low severity (lower than the logging threshold), e.g.

    SeverityLookup=debug

    in the Misc section of the server configuration, if you prefer running unsafe at any speed instead of fixing the problem (you have been warned). Doing so will allow an attacker to pose as the client.

  • Second method: Use address of connecting entity as known to the communication layer

    This has been dropped as default long ago because it may not always be the address of the client machine. To enable this method, use

    SetClientFromAccept=true

    in the Misc section of the server configuration file. If the address cannot be resolved, or reverse lookup of the resolved name fails, no error message will be issued, but the numerical address will be used.

Downloading config/database files

The client does not tell the server the path to the requested file - it just tells the type of the file, i.e. either a configuration file or a database file. It is entirely the responsibility of the server to locate the correct file and send it.

The server has a data directory, which by default would be /var/lib/yule. Here the config/database files should be placed.

Configuration files: rc.client.mydomain.tld or simply rc (this can be used as a catchall file).

Database files: file.client.mydomain.tld or simply file (this can be used as a catchall file).

Problem #1

If the server cannot access the configuration (or database) file, either because it does not exist or the server has no read permission, the client will report File download failed. The server will report: File not accessible, and it will tell you in the same report the path where it would have expected the file (example): path="/var/lib/yule/rc.client.mydomain.com"

To fix: put the file in the correct location, make sure the permissions are ok.

  • Note that the server drops root privileges at startup and runs as an unprivileged user (the first existing out of: yule, daemon, nobody).
  • Also remember that to access a file, at least execute permission is required for every directory in the path.

Other connection problems

The server has a table with client names and their session keys. If another client process accesses the server from the same host, it will negotiate a fresh session key for that host. As a consequence, the session key of the first client process will become invalid.

Also, the server keeps track of the status of a client. If a client process does not announce its termination to the server, the server will not expect a startup message, and issue a warning for any such message.

Problem #1

The client reports: Invalid connection state. The server reports: Invalid connection attempt: Signature mismatch. This is a sign that a client has tried to connect using an invalid session key. Most probably, another instance of the client is/was started on the respective host.

To fix: if you need to have concurrent access to the server, suspend the first process with SIGUSR2 before starting the second. Use SIGUSR2 again to wake up the first process. Give the process a second or two to return into the main event loop and go into suspend mode. Do not just use SIGSTOP/SIGCONT: it is important that the client tells the server that it will go into suspend.

Problem #2

The server reports: Restart without prior exit for a client. This is a sign that a client has re-started without informing the server about a previous termination.

This would happen if the client was killed with SIGKILL, or if it terminated within the routine to send a message to the server (the routine is not re-entrant). You may want to investigate messages logged via another logging facility (e.g. the client's local logfile). Of course it may also be a segfault, which would be reported via syslog.