From: Dinko Korunic Date: Tue, 23 Feb 2010 14:39:43 +0000 (+0100) Subject: Imported Upstream version 2.3 X-Git-Tag: v2.5.1~1 X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=commitdiff_plain;h=914feba5d54f979cd5d7e69c349c3d01f630042a Imported Upstream version 2.3 --- 914feba5d54f979cd5d7e69c349c3d01f630042a diff --git a/BUGS b/BUGS new file mode 100755 index 0000000..e56b3cc --- /dev/null +++ b/BUGS @@ -0,0 +1,20 @@ +OSSEC v2.3 +Copyright (C) 2009 Trend Micro Inc. + + +** Reporting bugs ** + +Bugs should be sent to the OSSEC mailling list +(ossec-list@ossec.net). Please, make sure to include +the following information: + +-OSSEC version number. +-Content of /etc/ossec-init.conf +-Content of /var/ossec/etc/ossec.conf +-Content of /var/ossec/logs/ossec.log +-Operating system name/version (uname -a if Unix) +-Any other relevant information. + + +If you prefer to contact us privately or if it is a security +issue, send an e-mail to contact@ossec.net. diff --git a/CONFIG b/CONFIG new file mode 100755 index 0000000..ada35a5 --- /dev/null +++ b/CONFIG @@ -0,0 +1,19 @@ +OSSEC v2.3 +Copyright (C) 2009 Trend Micro Inc. + + += Information about OSSEC = + +Visit http://www.ossec.net + + += Recommended Installation = + +See INSTALL + + +== Configuring OSSEC == + +Just follow the steps from the install.sh script. +More information at +http://www.ossec.net/en/manual.html diff --git a/CONTRIB b/CONTRIB new file mode 100755 index 0000000..a4fdee5 --- /dev/null +++ b/CONTRIB @@ -0,0 +1,79 @@ +# @(#) $Id: CONTRIB,v 1.26 2009/11/23 18:52:44 dcid Exp $ +# + +Many thanks to everyone who contributed and helped with +the ossec project. Below is the list of all the people +who helped us since our first release (0.1). +(if you feel you should be here, but it is not, let us know). + +-Development + - Daniel B. Cid + - Meir Michanie + - Slava Semushin + - Jeremy Rossi + - Ahmet Ozturk + + +-Testing/Patches and other contributions. + - Cédric Bleimling + - Sebastien Tricaud + - Jeff Schroeder + - Giannis Vrentzos + - Peter Ahlert + - Rafael Capovilla + - Andre Alexandre Gaio + - Liliane A. Cid + - Marcus Maciel - + - Kayvan A. Sylvan + - Dianzhi Wang + - Meir Michanie + - Stephen Bunn + - Jonathan Scheidell + - |SaMaN| + - ChuckD + - Jorge Augusto Senger - ossec2mysql (contrib) + - David J. Bianco + - Ivan Lotina + - Michael Starks + - Robert Millan [ackstorm] + - Martin West + - Rafael Capovilla + + +-Translations + + -Portuguese: + - Daniel Barcellos + - Allan Soares + - Willian Itiho Amano + - Liliane Cid - + + -German: + - Peter Ahlert + + -Turkish + - Ahmet Ozturk - + + -Polish + - Dziankowski Krzysztof - + + -Italian + - Alberto Furia - + + -French + - Yves Bigliazzi - + + -Japanese + - Kuzuno Hiroki - + + -Russian + - Yuri Slobodyanyuk - + + -Spanish + - Meir Michanie + + -Chinese + - Brian Wang - + +#EOF diff --git a/INSTALL b/INSTALL new file mode 100755 index 0000000..0752e89 --- /dev/null +++ b/INSTALL @@ -0,0 +1,66 @@ +OSSEC v2.3 +Copyright (C) 2009 Trend Micro Inc. + + += Information about OSSEC = + +Visit http://www.ossec.net + + += Recommended Installation = + +OSSEC installation is very simple. It can be done in the +fast way (using the script install.sh with the default values) +or in the customized way (by hand or by changing the default values +in the install.sh script). I REALLY recommend EVERYONE to use the +FAST WAY! Only developers or experienced people should use the +other methods. + +Fast way steps: + +1- Run the script ./install.sh. It will guide you through the + installation process. + +2- The script will create everything in /var/ossec and try to + create the initialization script in your system (/etc/rc.local + or /etc/rc.d/init.d/ossec). If the init script is not created, + make sure to follow the instructions from the install.sh to make + OSSEC HIDS start during the boot. To start it by hand, just run + /var/ossec/bin/ossec-control start + +3- If you are running it on multiple clients, make sure to install + the server first. Use the manage_agents tool + to create the right encryption keys. + +4- Enjoy. + + += Installation and Running (99,99% should read ABOVE) = + + +By Hand Installation steps: + +1- Create the necessary directories (by default /var/ossec). +2- Move the necessary files to the ossec directory. +3- Compile everything. +4- Move the binaries to the default directory. +5- Create the necessary users. +6- Set the right permissions to the files. + + +This 5 steps are done in the Makefile (see make server). + +The Makefile read the options from the LOCATION file. Change +whatever you need from there. + +To compile everything by yourself: + + % make clean + % make all (step 3) + % su + # make server (will do steps 1,2,4 and 6 above) + +*Before running make server, make sure to have the necessary users created. +The Makefile will not do that. + +#EOF diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..179b7ad --- /dev/null +++ b/LICENSE @@ -0,0 +1,712 @@ + + Copyright (C) 2009 Trend Micro Inc. All rights reserved. + + OSSEC HIDS is a free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License (version 3) as + published by the FSF - Free Software Foundation. + + Note that this license applies to the source code, as well as + decoders, rules and any other data file included with OSSEC (unless + otherwise specified). + + For the purpose of this license, we consider an application to constitute a + "derivative work" or a work based on this program if it does any of the + following (list not exclusive): + + * Integrates source code/data files from OSSEC. + * Includes OSSEC copyrighted material. + * Includes/integrates OSSEC into a proprietary executable installer. + * Links to a library or executes a program that does any of the above. + + This list is not exclusive, but just a clarification of our interpretation + of derived works. These restrictions only apply if you actually redistribute + OSSEC (or parts of it). + + We don't consider these to be added restrictions on top of the GPL, + but just a clarification of how we interpret "derived works" as it + applies to OSSEC. This is similar to the way Linus Torvalds has + announced his interpretation of how "derived works" applies to Linux kernel + modules. Our interpretation refers only to OSSEC - we don't speak + for any other GPL products. + + OSSEC HIDS 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 Version 3 below for more details. + +----------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + 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 +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +. diff --git a/README b/README new file mode 100755 index 0000000..039389a --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +OSSEC v2.3 +Copyright (C) 2009 Trend Micro Inc. + + += Information about OSSEC = + +** Visit our website for the latest information. +http://www.ossec.net + + += OSSEC comes with a modified version of zlib and a small part + of openssl (sha1 and blowfish libraries) = + +This product includes software developed by the OpenSSL Project +for use in the OpenSSL Toolkit (http://www.openssl.org/). + +This product includes cryptographic software written by +Eric Young (eay@cryptsoft.com) + +This product include software developed by the zlib project +(Jean-loup Gailly and Mark Adler). diff --git a/active-response/disable-account.sh b/active-response/disable-account.sh new file mode 100755 index 0000000..989f927 --- /dev/null +++ b/active-response/disable-account.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# Disable an account by setting "passwd -l" or chuser +# Requirements: System with a passwd that supports -l and -u +# or a system with chuser (AIX) +# Expect: username (can't be "root") +# Authors: Ahmet Ozturk and Daniel B. Cid +# Last modified: Jan 19, 2005 + + +UNAME=`uname` +PASSWD="/usr/bin/passwd" +CHUSER="/usr/bin/chuser" +ACTION=$1 +USER=$2 +IP=$3 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../log/active-responses.log + + +if [ "x${USER}" = "x" ]; then + echo "$0: [ add | delete ] " + exit 1; +elif [ "x${USER}" = "xroot" ]; then + echo "$0: Invalid username." + exit 1; +fi + + +# We should run on linux and on SunOS the passwd -u/-l +if [ "X${UNAME}" = "XLinux" -o "X${UNAME}" = "XSunOS" ]; then + # Checking if passwd is present + ls ${PASSWD} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + CMD=${PASSWD} + if [ "x${ACTION}" = "xadd" ]; then + ARGS="-l" + elif [ "x${ACTION}" = "xdelete" ]; then + ARGS="-u" + else + echo "$0: invalid action: ${ACTION}" + exit 1; + fi + + +# On AIX, we run CHUSER +elif [ "X${UNAME}" = "XAIX" ]; then + # Checking if chuser is present + ls ${CHUSER} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + CMD=${CHUSER} + + # Disabling an account + if [ "x${ACTION}" = "xadd" ]; then + ARGS="account_locked=true" + # Unblock the account + elif [ "x${ACTION}" = "xdelete" ]; then + ARGS="account_locked=false" + # Invalid action + else + echo "$0: invalid action: ${ACTION}" + exit 1; + fi + + +# We only support Linux, SunOS and AIX +else + exit 0; +fi + + +# Execute the command +${CMD} ${ARGS} ${USER} + +exit 1; + diff --git a/active-response/firewall-drop.sh b/active-response/firewall-drop.sh new file mode 100755 index 0000000..6d726a2 --- /dev/null +++ b/active-response/firewall-drop.sh @@ -0,0 +1,189 @@ +#!/bin/sh +# Adds an IP to the iptables drop list (if linux) +# Adds an IP to the ipfilter drop list (if solaris, freebsd or netbsd) +# Adds an IP to the ipsec drop list (if aix) +# Requirements: Linux with iptables, Solaris/FreeBSD/NetBSD with ipfilter or AIX with IPSec +# Expect: srcip +# Author: Ahmet Ozturk (ipfilter and IPSec) +# Author: Daniel B. Cid (iptables) +# Last modified: Feb 14, 2006 + +UNAME=`uname` +ECHO="/bin/echo" +GREP="/bin/grep" +IPTABLES="/sbin/iptables" +IPFILTER="/sbin/ipf" +GENFILT="/usr/sbin/genfilt" +LSFILT="/usr/sbin/lsfilt" +MKFILT="/usr/sbin/mkfilt" +RMFILT="/usr/sbin/rmfilt" +ARG1="" +ARG2="" +RULEID="" +ACTION=$1 +USER=$2 +IP=$3 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + +# Checking for an IP +if [ "x${IP}" = "x" ]; then + echo "$0: " + exit 1; +fi + + + +# Blocking IP +if [ "x${ACTION}" != "xadd" -a "x${ACTION}" != "xdelete" ]; then + echo "$0: invalid action: ${ACTION}" + exit 1; +fi + + + +# We should run on linux +if [ "X${UNAME}" = "XLinux" ]; then + if [ "x${ACTION}" = "xadd" ]; then + ARG1="-I INPUT -s ${IP} -j DROP" + ARG2="-I FORWARD -s ${IP} -j DROP" + else + ARG1="-D INPUT -s ${IP} -j DROP" + ARG2="-D FORWARD -s ${IP} -j DROP" + fi + + # Checking if iptables is present + ls ${IPTABLES} >> /dev/null 2>&1 + if [ $? != 0 ]; then + IPTABLES="/usr"${IPTABLES} + ls ${IPTABLES} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + fi + + # Executing and exiting + COUNT=0; + while [ 1 ]; do + echo ".." + ${IPTABLES} ${ARG1} + RES=$? + if [ $RES = 0 ]; then + break; + else + COUNT=`expr $COUNT + 1`; + echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + sleep $COUNT; + + if [ $COUNT -gt 4 ]; then + break; + fi + fi + done + + while [ 1 ]; do + ${IPTABLES} ${ARG2} + RES=$? + if [ $RES = 0 ]; then + break; + else + COUNT=`expr $COUNT + 1`; + echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + sleep $COUNT; + + if [ $COUNT -gt 4 ]; then + break; + fi + fi + done + + exit 0; + +# FreeBSD, SunOS or NetBSD with ipfilter +elif [ "X${UNAME}" = "XFreeBSD" -o "X${UNAME}" = "XSunOS" -o "X${UNAME}" = "XNetBSD" ]; then + + # Checking if ipfilter is present + ls ${IPFILTER} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + # Checking if echo is present + ls ${ECHO} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + if [ "x${ACTION}" = "xadd" ]; then + ARG1="\"@1 block out quick from any to ${IP}\"" + ARG2="\"@1 block in quick from ${IP} to any\"" + IPFARG="${IPFILTER} -f -" + else + ARG1="\"@1 block out quick from any to ${IP}\"" + ARG2="\"@1 block in quick from ${IP} to any\"" + IPFARG="${IPFILTER} -rf -" + fi + + # Executing it + eval ${ECHO} ${ARG1}| ${IPFARG} + eval ${ECHO} ${ARG2}| ${IPFARG} + + exit 0; + +# AIX with ipsec +elif [ "X${UNAME}" = "XAIX" ]; then + + # Checking if genfilt is present + ls ${GENFILT} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + # Checking if lsfilt is present + ls ${LSFILT} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + # Checking if mkfilt is present + ls ${MKFILT} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + # Checking if rmfilt is present + ls ${RMFILT} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + if [ "x${ACTION}" = "xadd" ]; then + ARG1=" -v 4 -a D -s ${IP} -m 255.255.255.255 -d 0.0.0.0 -M 0.0.0.0 -w B -D \"Access Denied by OSSEC-HIDS\"" + #Add filter to rule table + eval ${GENFILT} ${ARG1} + + #Deactivate and activate the filter rules. + eval ${MKFILT} -v 4 -d + eval ${MKFILT} -v 4 -u + else + # removing a specific rule is not so easy :( + eval ${LSFILT} -v 4 -O | ${GREP} ${IP} | + while read -r LINE + do + RULEID=`${ECHO} ${LINE} | cut -f 1 -d "|"` + let RULEID=${RULEID}+1 + ARG1=" -v 4 -n ${RULEID}" + eval ${RMFILT} ${ARG1} + done + #Deactivate and activate the filter rules. + eval ${MKFILT} -v 4 -d + eval ${MKFILT} -v 4 -u + fi + +else + exit 0; +fi diff --git a/active-response/firewalls/ipfw.sh b/active-response/firewalls/ipfw.sh new file mode 100755 index 0000000..fb424cb --- /dev/null +++ b/active-response/firewalls/ipfw.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Adds an IP to the IPFW drop list. +# Only works with IPFW. +# We use TABLE 00001. If you use this table for anything else, +# please change it here. +# Expect: srcip +# Author: Rafael Capovilla - under @ ( at ) underlinux.com.br +# Author: Daniel B. Cid - dcid @ ( at ) ossec.net +# Last modified: May 07, 2006 + +UNAME=`uname` +IPFW="/sbin/ipfw" +ARG1="" +ARG2="" +ACTION=$1 +USER=$2 +IP=$3 +TABLE_ID=00001 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + +# Checking for an IP +if [ "x${IP}" = "x" ]; then + echo "$0: " + exit 1; +fi + + + +# Blocking IP +if [ "x${ACTION}" != "xadd" -a "x${ACTION}" != "xdelete" ]; then + echo "$0: Invalid action: ${ACTION}" + exit 1; +fi + + +# We should run on FreeBSD +# We always use table 00001 and rule id 00001. +if [ "X${UNAME}" = "XFreeBSD" ]; then + ls ${IPFW} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + # Check if our table is set + ${IPFW} show | grep "^00001" | grep "table(1)" >/dev/null 2>&1 + if [ ! $? = 0 ]; then + # We need to add the table + ${IPFW} -q 00001 add deny ip from table\(${TABLE_ID}\) to any + ${IPFW} -q 00001 add deny ip from any to table\(${TABLE_ID}\) + fi + + + # Executing and exiting + ${IPFW} -q table ${TABLE_ID} ${ACTION} ${IP} + + exit 0; +fi + + +# Not FreeBSD +exit 1; diff --git a/active-response/firewalls/ipfw_mac.sh b/active-response/firewalls/ipfw_mac.sh new file mode 100755 index 0000000..1adcd31 --- /dev/null +++ b/active-response/firewalls/ipfw_mac.sh @@ -0,0 +1,78 @@ +#!/bin/sh +# Adds an IP to the IPFW drop list. +# Only works with IPFW. +# Expect: srcip +# Author: Rafael Capovilla - under @ ( at ) underlinux.com.br +# Author: Daniel B. Cid - dcid @ ( at ) ossec.net +# Author: Charles W. Kefauver ckefauver @ ( at ) ibacom.es +# changed for Mac OS X compatability +# Last modified: August 14, 2006 + +UNAME=`uname` +IPFW="/sbin/ipfw" +ARG1="" +ARG2="" +ACTION=$1 +USER=$2 +IP=$3 + +# warning do NOT add leading 0 in SET_ID +SET_ID=2 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + +# Checking for an IP +if [ "x${IP}" = "x" ]; then + echo "$0: " + exit 1; +fi + +# Blocking IP +if [ "x${ACTION}" != "xadd" -a "x${ACTION}" != "xdelete" ]; then + echo "$0: Invalid action: ${ACTION}" + exit 1; +fi + + +# We should run on Darwin +if [ "X${UNAME}" = "XDarwin" ]; then + ls ${IPFW} >> /dev/null 2>&1 + if [ $? != 0 ]; then + exit 0; + fi + + + # Executing and exiting + if [ "x${ACTION}" = "xadd" ]; then + #${IPFW} set disable ${SET_ID} + ${IPFW} -q add set ${SET_ID} deny ip from ${IP} to any + ${IPFW} -q add set ${SET_ID} deny ip from any to ${IP} + ${IPFW} -q set enable ${SET_ID} + exit 0; + fi + + if [ "x${ACTION}" = "xdelete" ]; then + #${IPFW} -S show | grep "set ${SET_ID}" | grep "${IP}" >/dev/null 2>&1 + #get list of ipfw rules ID to delete + RULES_TO_DELETE=`${IPFW} -S show | grep "set ${SET_ID}" | grep "${IP}" | awk '{print $1}'` + + for RULE_ID in ${RULES_TO_DELETE} + do + ${IPFW} -q delete ${RULE_ID} + done + + exit 0; + fi + + exit 0; +fi + + +# Not Darwin +exit 1; + diff --git a/active-response/firewalls/pf.sh b/active-response/firewalls/pf.sh new file mode 100755 index 0000000..1958f3e --- /dev/null +++ b/active-response/firewalls/pf.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# Author: Rafael M. Capovilla +# Last modified: Daniel B. Cid + +UNAME=`uname` +GREP=`which grep` +PFCTL="/sbin/pfctl" + +# Getting pf rules file. +PFCTL_RULES=`${GREP} pf_rules /etc/rc.conf | awk -F"=" '{print $2}' | awk '{print $1}' | awk -F"\"" '{print $1 $2}'` +if [ "X${PFCTL_RULES}" = "X" ]; then + PFCTL_RULES="/etc/pf.conf" +fi + +# Checking if ossec table is configured +PFCTL_TABLE=`cat ${PFCTL_RULES} | egrep -v "(^#|^$)" | grep ossec_fwtable | head -1 | awk '{print $2}' | sed "s///"` +ARG1="" +ACTION=$1 +USER=$2 +IP=$3 + + +# Finding path +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + +# Checking for an IP +if [ "x${IP}" = "x" ]; then + echo "$0: " + exit 1; +fi + + + +# Blocking IP +if [ "x${ACTION}" != "xadd" -a "x${ACTION}" != "xdelete" ]; then + echo "$0: invalid action: ${ACTION}" + echo "$0: invalid action: ${ACTION}" >> ${PWD}/ossec-hids-responses.log + exit 1; +fi + + + +# OpenBSD and FreeBSD pf +if [ "X${UNAME}" = "XOpenBSD" -o "X${UNAME}" = "XFreeBSD" ]; then + + # Checking if pfctl is present + ls ${PFCTL} > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "$0: PF not configured." + echo "$0: PF not configured." >> ${PWD}/ossec-hids-responses.log + exit 0; + fi + + # Checking if we have pf config file + if [ -e ${PFCTL_RULES} ]; then + + #Checking if we got the table to add the bad guys + if [ "x${PFCTL_TABLE}" = "x" ]; then + echo "$0: PF not configured." + echo "$0: PF not configured." >> ${PWD}/ossec-hids-responses.log + exit 0; + else + if [ "x${ACTION}" = "xadd" ]; then + ARG1="-t $PFCTL_TABLE -T add ${IP}" + else + ARG1="-t $PFCTL_TABLE -T delete ${IP}" + fi + fi + else + exit 0; + fi + + #Executing it + ${PFCTL} ${ARG1} > /dev/null 2>&1 + + exit 0; + +else + exit 0; +fi diff --git a/active-response/host-deny.sh b/active-response/host-deny.sh new file mode 100755 index 0000000..9a68700 --- /dev/null +++ b/active-response/host-deny.sh @@ -0,0 +1,131 @@ +#!/bin/sh +# Adds an IP to the /etc/hosts.deny file +# Requirements: sshd and other binaries with tcp wrappers support +# Expect: srcip +# Author: Daniel B. Cid +# Last modified: Nov 09, 2005 + +ACTION=$1 +USER=$2 +IP=$3 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +LOCK="${PWD}/host-deny-lock" +LOCK_PID="${PWD}/host-deny-lock/pid" +UNAME=`uname` + + +# This number should be more than enough (even if a hundred +# instances of this script is ran together). If you have +# a really loaded env, you can increase it to 75 or 100. +MAX_ITERATION="50" + + +# Lock function +lock() +{ + i=0; + # Providing a lock. + while [ 1 ]; do + mkdir ${LOCK} > /dev/null 2>&1 + MSL=$? + if [ "${MSL}" = "0" ]; then + # Lock aquired (setting the pid) + echo "$$" > ${LOCK_PID} + return; + fi + + # Getting currently/saved PID locking the file + C_PID=`cat ${LOCK_PID} 2>/dev/null` + if [ "x" = "x${S_PID}" ]; then + S_PID=${C_PID} + fi + + # Breaking out of the loop after X attempts + if [ "x${C_PID}" = "x${S_PID}" ]; then + i=`expr $i + 1`; + fi + + # Sleep 1 after 10/25 interactions + if [ "$i" = "10" -o "$i" = "25" ]; then + sleep 1; + fi + + i=`expr $i + 1`; + + # So i increments 2 by 2 if the pid does not change. + # If the pid keeps changing, we will increments one + # by one and fail after MAX_ITERACTION + if [ "$i" = "${MAX_ITERATION}" ]; then + echo "`date` Unable to execute. Locked: $0" \ + >> ${PWD}/ossec-hids-responses.log + + # Unlocking and exiting + unlock; + exit 1; + fi + done +} + +# Unlock function +unlock() +{ + rm -rf ${LOCK} +} + + +# Logging the call +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + +# IP Address must be provided +if [ "x${IP}" = "x" ]; then + echo "$0: Missing argument (ip)" + exit 1; +fi + + +# Checking for invalid entries (lacking ".", etc) +echo "${IP}" | grep "\." > /dev/null 2>&1 +if [ ! $? = 0 ]; then + echo "`date` Invalid ip/hostname entry: ${IP}" >> ${PWD}/../logs/active-responses.log + exit 1; +fi + + +# Adding the ip to hosts.deny +if [ "x${ACTION}" = "xadd" ]; then + lock; + if [ "X$UNAME" = "XFreeBSD" ]; then + echo "ALL : ${IP} : deny" >> /etc/hosts.allow + else + echo "ALL:${IP}" >> /etc/hosts.deny + fi + unlock; + exit 0; + + +# Deleting from hosts.deny +elif [ "x${ACTION}" = "xdelete" ]; then + lock; + if [ "X$UNAME" = "XFreeBSD" ]; then + cat /etc/hosts.allow | grep -v "ALL : ${IP} : deny$"> /tmp/hosts.deny.$$ + mv /tmp/hosts.deny.$$ /etc/hosts.allow + else + cat /etc/hosts.deny | grep -v "ALL:${IP}$"> /tmp/hosts.deny.$$ + cat /tmp/hosts.deny.$$ > /etc/hosts.deny + rm /tmp/hosts.deny.$$ + fi + unlock; + exit 0; + + +# Invalid action +else + echo "$0: invalid action: ${ACTION}" +fi + +exit 1; diff --git a/active-response/ossec-tweeter.sh b/active-response/ossec-tweeter.sh new file mode 100755 index 0000000..7affe2a --- /dev/null +++ b/active-response/ossec-tweeter.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# Tweeter an alert - copy at /var/ossec/active-response/bin/ossec-tweeter.sh +# Author: Daniel Cid + + +# Change these values! +TWITTERUSER="" +TWITTERPASS='' +DIRECTMSGUSER="" +SOURCE="ossec2tweeter" + + + +# Checking user arguments +if [ "x$1" = "xdelete" ]; then + exit 0; +fi +ALERTID=$4 +RULEID=$5 +LOCAL=`dirname $0`; +ALERTTIME=`echo "$ALERTID" | cut -d "." -f 1` +ALERTLAST=`echo "$ALERTID" | cut -d "." -f 2` + + + +# Logging +cd $LOCAL +cd ../ +PWD=`pwd` +echo "`date` $0 $1 $2 $3 $4 $5 $6 $7 $8" >> ${PWD}/../logs/active-responses.log +ALERTFULL=`grep -A 10 "$ALERTTIME" ${PWD}/../logs/alerts/alerts.log | grep -v ".$ALERTLAST: " -A 10 | grep -v "Src IP: " | grep -v "User: " |grep "Rule: " -A 4 | cut -c -139` + + + +# Checking if we are sending direct message or not. +if [ "x" = "x$DIRECTMSGUSER" ]; then + SITE="http://twitter.com/statuses/update.xml" + REQUESTUSER="" + REQUESTMSG="status=$ALERTFULL" +else + SITE="http://twitter.com/direct_messages/new.xml" + REQUESTUSER="user=$DIRECTMSGUSER&" + REQUESTMSG="text=$ALERTFULL" +fi + + +ls "`which curl`" > /dev/null 2>&1 +if [ ! $? = 0 ]; then + ls "`which wget`" > /dev/null 2>&1 + if [ $? = 0 ]; then + wget --keep-session-cookies --http-user=$TWITTERUSER --http-password=$TWITTERPASS --post-data="source=$SOURCE&$REQUESTUSER$REQUESTMSG" $SITE 2>>${PWD}/../logs/active-responses.log + exit 0; + fi +else + curl -u "$TWITTERUSER:$TWITTERPASS" -d "source=$SOURCE&$REQUESTUSER$REQUESTMSG" $SITE 2>>${PWD}/../logs/active-responses.log + exit 0; +fi + +echo "`date` $0: Unable to find curl or wget." >> ${PWD}/../logs/active-responses.log +exit 1; diff --git a/active-response/restart-ossec.sh b/active-response/restart-ossec.sh new file mode 100755 index 0000000..25d5f77 --- /dev/null +++ b/active-response/restart-ossec.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# Restarts ossec. +# Requirements: none +# Author: Daniel B. Cid + +ACTION=$1 +USER=$2 +IP=$3 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +UNAME=`uname` + + +# Logging the call +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + + +# Adding the ip to hosts.deny +if [ "x${ACTION}" = "xadd" ]; then + ${PWD}/../bin/ossec-control restart + exit 0; + + +# Deleting from hosts.deny +elif [ "x${ACTION}" = "xdelete" ]; then + exit 0; + + +# Invalid action +else + echo "$0: invalid action: ${ACTION}" +fi + +exit 1; diff --git a/active-response/route-null.sh b/active-response/route-null.sh new file mode 100755 index 0000000..5bc3e40 --- /dev/null +++ b/active-response/route-null.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# Adds an IP to null route +# Requirements: ip route +# Expect: srcip +# Author: Ivan Lotina +# Modifyed script host-deny from Daniel B. Cid +# Last modified: Feb 16, 2007 + +ACTION=$1 +USER=$2 +IP=$3 + +LOCAL=`dirname $0`; +cd $LOCAL +cd ../ +PWD=`pwd` +LOCK="${PWD}/host-deny-lock" +LOCK_PID="${PWD}/host-deny-lock/pid" + +UNAME=`uname` + +# Logging the call +echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log + + +# IP Address must be provided +if [ "x${IP}" = "x" ]; then + echo "$0: Missing argument (ip)" + exit 1; +fi + + +# Adding the ip to null route +if [ "x${ACTION}" = "xadd" ]; then + if [ "X${UNAME}" = "XLinux" ]; then + route add ${IP} reject + exit 0; + fi + + if [ "X${UNAME}" = "XFreeBSD" ]; then + route -q add ${IP} 127.0.0.1 -blackhole + exit 0; + fi + +# Deleting from null route +# be carefull not to remove your default route +elif [ "x${ACTION}" = "xdelete" ]; then + if [ "X${UNAME}" = "XLinux" ]; then + route del ${IP} reject + exit 0; + fi + + if [ "X${UNAME}" = "XFreeBSD" ]; then + route -q delete ${IP} 127.0.0.1 -blackhole + exit 0; + fi + +# Invalid action +else + echo "$0: invalid action: ${ACTION}" +fi + +exit 1; diff --git a/active-response/win/restart-ossec.cmd b/active-response/win/restart-ossec.cmd new file mode 100644 index 0000000..ca2d3e8 --- /dev/null +++ b/active-response/win/restart-ossec.cmd @@ -0,0 +1,28 @@ +:: Simple script to restart ossec agent. +@ECHO OFF +ECHO. + + +:: Logging it all +FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET DATE=%%B +FOR /F "TOKENS=1* DELIMS= " %%A IN ('TIME/T') DO SET TIME=%%A +ECHO %DATE% %TIME% %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 >> active-response/active-responses.log + + +IF "%1"=="add" GOTO ADD +IF "%1"=="delete" GOTO DEL +:ERROR + +ECHO "Invalid argument. %1" +GOTO Exit; + + +:ADD +net stop OssecSvc +net start OssecSvc + +GOTO Exit; + +:DEL + +:Exit diff --git a/active-response/win/route-null.cmd b/active-response/win/route-null.cmd new file mode 100644 index 0000000..ffacc29 --- /dev/null +++ b/active-response/win/route-null.cmd @@ -0,0 +1,31 @@ +:: Simple script to null route an ip address. +@ECHO OFF +ECHO. + + +:: Logging it all +FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET DATE=%%B +FOR /F "TOKENS=1* DELIMS= " %%A IN ('TIME/T') DO SET TIME=%%A +ECHO %DATE% %TIME% %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 >> active-response/active-responses.log + + +IF "%1"=="add" GOTO ADD +IF "%1"=="delete" GOTO DEL +:ERROR + +ECHO "Invalid argument. %1" +GOTO Exit; + + +:: Adding to the blocked. + +:ADD +:: Extracts last ip address from ipconfig. +FOR /F "TOKENS=2* DELIMS=:" %%A IN ('IPCONFIG /ALL ^| FIND "IP Address"') DO FOR %%B IN (%%A) DO SET IPADDR=%%B +route add %3 mask 255.255.255.255 %IPADDR% +GOTO Exit; + +:DEL +route delete %3 + +:Exit diff --git a/contrib/add_localfile.sh b/contrib/add_localfile.sh new file mode 100755 index 0000000..a35958c --- /dev/null +++ b/contrib/add_localfile.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# Add a localfile to ossec. +# by Daniel B. Cid - dcid ( at ) ossec.net + +FILE=$1 +FORMAT=$2 + +if [ "X$FILE" = "X" ]; then + echo "$0: []" + exit 1; +fi + +if [ "X$FORMAT" = "X" ]; then + FORMAT="syslog" +fi + +# Checking if file is already configured +grep "$FILE" /var/ossec/etc/ossec.conf > /dev/null 2>&1 +if [ $? = 0 ]; then + echo "$0: File $FILE already configured at ossec." + exit 1; +fi + +# Checking if file exist +ls -la $FILE > /dev/null 2>&1 +if [ ! $? = 0 ]; then + echo "$0: File $FILE does not exist." + exit 1; +fi + +echo " + + + $FORMAT + $FILE + + +" >> /var/ossec/etc/ossec.conf + +echo "$0: File $FILE added."; +exit 0; diff --git a/contrib/compile_alerts.pl b/contrib/compile_alerts.pl new file mode 100755 index 0000000..62e5f70 --- /dev/null +++ b/contrib/compile_alerts.pl @@ -0,0 +1,83 @@ +#!/usr/bin/perl -w +use strict; +# Contrib by Meir Michanie +# meirm at riunx.com +# Licensed under GPL +my $VERSION='0.1'; +my $ossec_path='/var/ossec'; +my $rules_config="$ossec_path/etc/rules_config.xml"; +my $usersignatures_path="$ossec_path/user_signatures"; +my $signatures_path="$ossec_path/signatures"; +while ( @ARGV) { + $_=shift @ARGV; + if (m/^-u$|^--user-signatures$/) { + $usersignatures_path= shift @ARGV; + &help() unless -d $usersignatures_path; + }elsif (m/^-s$|^--signatures$/){ + $signatures_path= shift @ARGV; + &help() unless -d $signatures_path; + }elsif (m/^-c$|^--rules_config$/){ + $rules_config= shift @ARGV; + &help() unless -f $rules_config; + }elsif (m/^-h$|^--help$/){ + &help; + } +} +print STDERR "Adding $rules_config\n"; +my @rules_files=($rules_config); +opendir (USERDEFINED , "$usersignatures_path") || die ("Could not open dir $usersignatures_path\n"); +my @temparray=(); +while ($_ = readdir(USERDEFINED)){ + chomp; + next unless -f "$usersignatures_path/$_"; + print STDERR "Adding $usersignatures_path/$_\n"; + push @temparray, "$usersignatures_path/$_"; +} +close (USERDEFINED); +push @rules_files , sort (@temparray); + +@temparray=(); +opendir(RULES,"$signatures_path") || die ("Could not open dir $signatures_path\n"); +while ($_ = readdir(RULES)){ + chomp; + next unless -f "$signatures_path/$_"; + print STDERR "Adding $signatures_path/$_\n"; + push @temparray, "$signatures_path/$_"; +} +close (RULES); +push @rules_files , sort (@temparray); +map { print STDERR "processing: $_\n";} @rules_files; +foreach (@rules_files){ + open (RFILE, "$_") ||die ("Could not open file $_"); + my @content=; + close (RFILE); + print join ('',@content); +} + +sub help(){ + print STDERR "$0\nRules compilation tool for OSSEC \n"; + print "This tool facilitates the building of monolitic rules file to be included in ossec.xml.\n" + . "You only need one rules include entry in ossec.xml\n" + . "\n" + . "\tossec_rules.xml" + ."" + + . "$0 will print to STDOUT the result of the mixing.\n" + . "If no parameter are passed then the application will use the default locations.\n" + . "Default values:\n" + . "--user-signatures -> $usersignatures_path\n" + . "--signatures -> $signatures_path\n" + . "--rules-config -> $rules_config\n" + . "Compiling rules allows us to generate multiple configurations and even facilitate the upgrade of them.\n" + . "By instance, you can make a directory with symbolic links to rules you want to use without altering the standard repository.\n" + . "There are more examples of situation where you can use a subset of the rules repository\n" + . "I invite someone to reword this explanation.\n"; + + print STDERR "\n\nUsage:\n"; + print STDERR "$0 [-u|--user-signatures] [-s|--signatures] \n" + ."\n\nBUGS:\n" + . "I just wanted to deliver version one.\n" + . "I will change the script to read the directory sorted, so you can link signatures with names that would emulate the behavios of the sysV system.\n"; + + exit; +} diff --git a/contrib/compile_alerts.txt b/contrib/compile_alerts.txt new file mode 100755 index 0000000..a866d9a --- /dev/null +++ b/contrib/compile_alerts.txt @@ -0,0 +1,286 @@ +ossec rules reordering Mini Howto +by Meir Michanie + +Patching an Ossec installation +Reordering the rules + + * Stop ossec + +root@topgun:/var/ossec#/etc/init.d/ossec stop + + + + * Backup the whole ossec directory + +/root# tar -C /var -zcpvf ossec-orig.tar.gz ossec + + + + * Move the contrib directory from the source package to the oseec installation + +/var/ossec# cp -a /tmp/ossec/contrib . + + + * Create directories to host the rules + +/var/ossec# mkdir signatures user_signatures repository + + + * Move the file rules_config.xml to the etc directory. + +/var/ossec# mv rules/rules_config.xml etc/ + + + * Move the rest of the rules to the repository directory + +/var/ossec# mv rules/* repository/ + + + * copy the rules tag portion to a file under /var/ossec. i.e. rules.txt + * delete the rules opening and closing tags + * remove all xml code leaving only the list of the files. i.e. + +pam_rules.xml + sshd_rules.xml + telnetd_rules.xml + syslog_rules.xml + pix_rules.xml + named_rules.xml + smbd_rules.xml + vsftpd_rules.xml + pure-ftpd_rules.xml + proftpd_rules.xml + hordeimp_rules.xml + web_rules.xml + apache_rules.xml + ids_rules.xml + squid_rules.xml + firewall_rules.xml + netscreenfw_rules.xml + postfix_rules.xml + sendmail_rules.xml + imapd_rules.xml + spamd_rules.xml + msauth_rules.xml + policy_rules.xml + attack_rules.xml + + + * modify the rules tag to: + + + rules_ossec.xml + + + * list of repository directory. + +/var/ossec# ls -1 repository/ +apache_rules.xml +attack_rules.xml +firewall_rules.xml +ftpd_rules.xml +hordeimp_rules.xml +ids_rules.xml +imapd_rules.xml +msauth_rules.xml +named_rules.xml +netscreenfw_rules.xml +ossec_rules.xml +pam_rules.xml +pix_rules.xml +policy_rules.xml +postfix_rules.xml +proftpd_rules.xml +pure-ftpd_rules.xml +rules-backup +sendmail_rules.xml +smbd_rules.xml +spamd_rules.xml +squid_rules.xml +sshd_rules.xml +syslog_rules.xml +telnetd_rules.xml +vsftpd_rules.xml +web_rules.xml + + + + * Viewing the content of file rules.txt + +/var/ossec# cat rules.txt + pam_rules.xml + sshd_rules.xml + telnetd_rules.xml + syslog_rules.xml + pix_rules.xml + named_rules.xml + smbd_rules.xml + vsftpd_rules.xml + pure-ftpd_rules.xml + proftpd_rules.xml + hordeimp_rules.xml + web_rules.xml + apache_rules.xml + ids_rules.xml + squid_rules.xml + firewall_rules.xml + netscreenfw_rules.xml + postfix_rules.xml + sendmail_rules.xml + imapd_rules.xml + spamd_rules.xml + msauth_rules.xml + policy_rules.xml + attack_rules.xml + + + + * Build links to the original rules files under the signatures directory + +/var/ossec# COUNT=0; for i in `cat rules.txt`; do + (( COUNT = COUNT + 1)) ; + ln -s ../repository/$i `printf "signatures/%02d%s" $COUNT $i`; +done + + + + * If you wish to alterate a rule you should remove the link of the file from signature where XX denotes the two digits number prefixing the name of the file. + +/var/ossec# unlink signatures/XXattack_rules.xml + + + + * Copy the file to be modified + +/var/ossec# cp repository/attack_rules.xml signatures/XXattack_rules.xml + + + + * Edit your file. + + * write your own rules file under the directory user_signatures + +/var/ossec# cat user_signatures/user_defined.xml + + + Accepted publickey + Accepted publickey bypass + + + + + * List the rules under signature + +/var/ossec# ls -l signatures/ +total 0 +lrwxrwxrwx 1 root root 27 2006-07-24 23:37 01pam_rules.xml -> ../repository/pam_rules.xml +lrwxrwxrwx 1 root root 28 2006-07-24 23:37 02sshd_rules.xml -> ../repository/sshd_rules.xml +lrwxrwxrwx 1 root root 31 2006-07-24 23:37 03telnetd_rules.xml -> ../repository/telnetd_rules.xml +lrwxrwxrwx 1 root root 30 2006-07-24 23:37 04syslog_rules.xml -> ../repository/syslog_rules.xml +lrwxrwxrwx 1 root root 27 2006-07-24 23:37 05pix_rules.xml -> ../repository/pix_rules.xml +lrwxrwxrwx 1 root root 29 2006-07-24 23:37 06named_rules.xml -> ../repository/named_rules.xml +lrwxrwxrwx 1 root root 28 2006-07-24 23:37 07smbd_rules.xml -> ../repository/smbd_rules.xml +lrwxrwxrwx 1 root root 30 2006-07-24 23:37 08vsftpd_rules.xml -> ../repository/vsftpd_rules.xml +lrwxrwxrwx 1 root root 33 2006-07-24 23:37 09pure-ftpd_rules.xml -> ../repository/pure-ftpd_rules.xml +lrwxrwxrwx 1 root root 31 2006-07-24 23:37 10proftpd_rules.xml -> ../repository/proftpd_rules.xml +lrwxrwxrwx 1 root root 32 2006-07-24 23:37 11hordeimp_rules.xml -> ../repository/hordeimp_rules.xml +lrwxrwxrwx 1 root root 27 2006-07-24 23:37 12web_rules.xml -> ../repository/web_rules.xml +lrwxrwxrwx 1 root root 30 2006-07-24 23:37 13apache_rules.xml -> ../repository/apache_rules.xml +lrwxrwxrwx 1 root root 27 2006-07-24 23:37 14ids_rules.xml -> ../repository/ids_rules.xml +lrwxrwxrwx 1 root root 29 2006-07-24 23:37 15squid_rules.xml -> ../repository/squid_rules.xml +lrwxrwxrwx 1 root root 32 2006-07-24 23:37 16firewall_rules.xml -> ../repository/firewall_rules.xml +lrwxrwxrwx 1 root root 35 2006-07-24 23:37 17netscreenfw_rules.xml -> ../repository/netscreenfw_rules.xml +lrwxrwxrwx 1 root root 31 2006-07-24 23:37 18postfix_rules.xml -> ../repository/postfix_rules.xml +lrwxrwxrwx 1 root root 32 2006-07-24 23:37 19sendmail_rules.xml -> ../repository/sendmail_rules.xml +lrwxrwxrwx 1 root root 29 2006-07-24 23:37 20imapd_rules.xml -> ../repository/imapd_rules.xml +lrwxrwxrwx 1 root root 29 2006-07-24 23:37 21spamd_rules.xml -> ../repository/spamd_rules.xml +lrwxrwxrwx 1 root root 30 2006-07-24 23:37 22msauth_rules.xml -> ../repository/msauth_rules.xml +lrwxrwxrwx 1 root root 30 2006-07-24 23:37 23policy_rules.xml -> ../repository/policy_rules.xml +lrwxrwxrwx 1 root root 30 2006-07-24 23:37 24attack_rules.xml -> ../repository/attack_rules.xml + + + + * Compile the alerts into a monolitic rule file. + +/var/ossec# perl contrib/compile_alerts.pl --user-signatures /var/ossec/user_signatures --signatures \ +/var/ossec/signatures --rules-config /var/ossec/etc/rules_config.xml > rules/rules_ossec.xml +Adding /var/ossec/etc/rules_config.xml +Adding /var/ossec/user_signatures/user_defined_rules.xml +Adding /var/ossec/signatures/01pam_rules.xml +Adding /var/ossec/signatures/02sshd_rules.xml +Adding /var/ossec/signatures/03telnetd_rules.xml +Adding /var/ossec/signatures/04syslog_rules.xml +Adding /var/ossec/signatures/05pix_rules.xml +Adding /var/ossec/signatures/06named_rules.xml +Adding /var/ossec/signatures/07smbd_rules.xml +Adding /var/ossec/signatures/08vsftpd_rules.xml +Adding /var/ossec/signatures/09pure-ftpd_rules.xml +Adding /var/ossec/signatures/10proftpd_rules.xml +Adding /var/ossec/signatures/11hordeimp_rules.xml +Adding /var/ossec/signatures/12web_rules.xml +Adding /var/ossec/signatures/13apache_rules.xml +Adding /var/ossec/signatures/14ids_rules.xml +Adding /var/ossec/signatures/15squid_rules.xml +Adding /var/ossec/signatures/16firewall_rules.xml +Adding /var/ossec/signatures/17netscreenfw_rules.xml +Adding /var/ossec/signatures/18postfix_rules.xml +Adding /var/ossec/signatures/19sendmail_rules.xml +Adding /var/ossec/signatures/20imapd_rules.xml +Adding /var/ossec/signatures/21spamd_rules.xml +Adding /var/ossec/signatures/22msauth_rules.xml +Adding /var/ossec/signatures/23policy_rules.xml +Adding /var/ossec/signatures/24attack_rules.xml +processing: /var/ossec/etc/rules_config.xml +processing: /var/ossec/user_signatures/user_defined_rules.xml +processing: /var/ossec/signatures/01pam_rules.xml +processing: /var/ossec/signatures/02sshd_rules.xml +processing: /var/ossec/signatures/03telnetd_rules.xml +processing: /var/ossec/signatures/04syslog_rules.xml +processing: /var/ossec/signatures/05pix_rules.xml +processing: /var/ossec/signatures/06named_rules.xml +processing: /var/ossec/signatures/07smbd_rules.xml +processing: /var/ossec/signatures/08vsftpd_rules.xml +processing: /var/ossec/signatures/09pure-ftpd_rules.xml +processing: /var/ossec/signatures/10proftpd_rules.xml +processing: /var/ossec/signatures/11hordeimp_rules.xml +processing: /var/ossec/signatures/12web_rules.xml +processing: /var/ossec/signatures/13apache_rules.xml +processing: /var/ossec/signatures/14ids_rules.xml +processing: /var/ossec/signatures/15squid_rules.xml +processing: /var/ossec/signatures/16firewall_rules.xml +processing: /var/ossec/signatures/17netscreenfw_rules.xml +processing: /var/ossec/signatures/18postfix_rules.xml +processing: /var/ossec/signatures/19sendmail_rules.xml +processing: /var/ossec/signatures/20imapd_rules.xml +processing: /var/ossec/signatures/21spamd_rules.xml +processing: /var/ossec/signatures/22msauth_rules.xml +processing: /var/ossec/signatures/23policy_rules.xml +processing: /var/ossec/signatures/24attack_rules.xml + + + + * Now you can start again ossec + +/var/ossec#/etc/init.d/ossec start + Starting OSSEC Starting OSSEC HIDS v0.9 (by Daniel B. Cid)... + Started ossec-maild... + Started ossec-execd... + Started ossec-analysisd... + Started ossec-logcollector... + Started ossec-remoted... + Started ossec-syscheckd... + Completed. + + + +Extract of ossec.conf with the modified rules tag + +/var/ossec# cat etc/ossec.conf +... + + rules_ossec.xml + +... + + + diff --git a/contrib/config2xml b/contrib/config2xml new file mode 100755 index 0000000..fa05cd9 --- /dev/null +++ b/contrib/config2xml @@ -0,0 +1,194 @@ +#!/usr/bin/perl -w + +# +# +# config2xml +# +# Written by: Charlie Heselton (gentuxx@gmail.com) +# Date: 08/22/2006 +# Version: 0.1 +# +# Description: OSSEC-HIDS uses XML for it's configuration +# and rules files. This script allows a user to use a +# more traditional "key = value" format and convert it +# to the XML required by OSSEC. +# +# +require 5.006; +use strict; +use Getopt::Std; + +my (%opts, %config); +getopts('f:', \%opts); + +my $current_line = 0; +if ($opts{'f'}) { + # open the "traditional" file and parse the contents. + open CONF, $opts{'f'} or die "Couldn't open input config file ($opts{'f'}): $! \n"; + while () { + $current_line++; + # skip commented or blank lines + next if (/^#/); + next if (/^$/); + chomp; + # strip out any double quotes + #s/\"//g; + # strip out spaces or tabs + #s/(\s+|\t+)//g; + my ($key, $value); + #print STDERR "DEBUG: \$\_ ===> $_\n"; + if (/^\s*(\S+)\s*\=\s*\"?([^=]+)\"?/) { + $key = $1; $value = $2; + } else { + die "Config error! Found an extra equals sign (=) in line $current_line\. Input file not converted!\n"; + } + # the keys below will be repeated, but if the value is assigned initially, + # then the script fails when unwrapping the hash. + # key/value pairs that shouldn't be repeated throw a config error if they are repeated. + if ($key =~ /monitor_file|rules_include|active_response_command/) { + push @{$config{$key}}, $value; + } else { + if (exists($config{$key})) { die "$key has already been specified in the config file and can only be used once. Input file not converted!\n"; } + $config{$key} = $value; + } + } + close CONF; +} else { + die "No input file specified.\n"; +} +undef $current_line; + +# strip out any double-quotes +# this is handled for all the rest of the key/value pairs when the input file is initially parsed +foreach my $key ( qw/ active_response_command / ) { foreach ( @{$config{$key}} ) { s!\"!!g; } } +# separate the "complex" options into arrays +my @whitelisted = split(/\,/, $config{'whitelist_ips'}); +my @ignored = split(/\,/, $config{'ignore'}); + +# Write the xml file. Easiest way is just to be deliberate. Not the most elegant solution, but it should work. +print < + + + + $config{'email_notify'} + $config{'email_addr'} + $config{'smtp_server'} + $config{'email_from'} +END + +foreach my $wip ( sort( @whitelisted ) ) { + print " $wip\n"; +} + +print " \n\n"; +print " \n"; + +foreach my $rulesfile ( sort( @{$config{'rules_include'}} ) ) { + print " $rulesfile\n"; +} + +print < + + + + $config{'frequency'} + + + $config{'directories_check_all'} + + +END + +foreach my $ignored ( @ignored ) { + print " $ignored\n"; +} + +print < + + + $config{'rootkit_files_db'} + $config{'rootkit_trojans_db'} + + +END + +if ( exists($config{'remote'}) ) { + print " \n"; + if ((exists($config{'connection_type'})) && ($config{'connection_type'} eq 'secure')) { + print " $config{'connection_type'}\n"; + } + print " \n"; +} + +print < + $config{'log_alert_level'} + $config{'email_alert_level'} + + +END + +if ( exists($config{'active_response'}) ) { # should always be true + if ($config{'active_response'} eq 'disabled') { + print " \n yes\n \n\n"; + } else { + # Could use some comments/insight here, since I don't use the active response features. + foreach my $cmd ( sort(@{$config{'active-response-command'}}) ) { + my ( $name, $exe, $expect, $timeout ) = split(/\,/, $cmd); + print < + $name + $exe + $expect + $timeout + + +END + } + + print < + + + host-deny + local + 6 + 600 + + + + + firewall-drop + local + 6 + 600 + + + + +END + } +} + +foreach my $file ( sort( @{$config{'monitor_file'}} ) ) { + my ($fileloc, $fformat) = split(/\,/, $file); + print " \n"; + print " $fformat\n"; + print " $fileloc\n"; + print " \n"; +} + +print "\n"; diff --git a/contrib/ossec-batch-manager.pl b/contrib/ossec-batch-manager.pl new file mode 100755 index 0000000..dbd5988 --- /dev/null +++ b/contrib/ossec-batch-manager.pl @@ -0,0 +1,292 @@ +#!/usr/bin/perl +# vim:shiftwidth=2:tabstop=2:expandtab:textwidth=80:softtabstop=2:ai: + + ######################################################### + # Written Aug 4, 2007 and released under the GNU/GPLv2 ## + # by Jeff Schroeder (jeffschroeder@computer.org) # # +######################################################### # +# # # +# ossec-batch-manager.pl - Add and extract agents from # # +# the ossec client.keys file non-interactively. This # # +# started as a hack to properly script manage_agents. # # +# # # +########################################################## + +#$Id: ossec-batch-manager.pl,v 1.4 2007/11/05 21:05:39 jeff Exp $ +# TODO: +# - Add check for ossec 1.4 and support longer agent names +# - Add in eval so that older version of perl without +# Time::HiRes still can use this script. + +use strict; +use warnings; +require 5.8.2; # Time::HiRes is standard from this version forth +#use diagnostics; +use MIME::Base64; +use Digest::MD5 qw(md5_hex); +use Getopt::Long; + +use constant AUTH_KEY_FILE => "/var/ossec/etc/client.keys"; + +my ($key, $add, $remove, $extract, $import, $listagents); +my ($agentid, $agentname, $ipaddress); + +GetOptions( + 'k|key=s' => \$key, # Unencoded ssh key + 'a|add' => \$add, # Add a new agent + 'r|remove=s' => \$remove, # Remove an agent + 'e|extract=s' => \$extract, # Extract a key + 'm|import' => \$import, # Import a key + 'l|list' => \$listagents, # List all agents + 'i|id=s' => \$agentid, # Unique agent id + 'n|name=s' => \$agentname, # Agent name. 32 char max + 'p|ip=s' => \$ipaddress # IP Address in "dotted quad" notation +); + +# Spit out a list of available agents, their names, and ip information +if ($listagents) { + list_agents(); +} +# Decode and extract the key for $agentid +elsif ($extract) { + $agentid = $extract; + if ($agentid) { + extract_key($agentid); + } + else { + usage(); + } +} +# Adding a new agent +elsif ($add) { + if ($agentname && $ipaddress && $ipaddress =~ + m/(1?\d\d?|2[0-4]\d|25[0-5])(\.(1?\d\d?|2[0-4]\d|25[0-5])){3}/ && + # ossec doesn't like agent names > 32 characters. + length($agentname) <= 32) { + + # Autogenerate an id incremented 1 from the last in a sorted list of + # all current ones if it isn't specified from the command line. + if (!$agentid) { + + # Make a list of all of the used agentids and then sort it. + if (-r AUTH_KEY_FILE) { + my @used_agent_ids = (); + open (FH, "<", AUTH_KEY_FILE); + while () { + my ($id, $name, $ip, $key) = split; + push(@used_agent_ids, $id); + } + close(FH); + + if (@used_agent_ids) { + @used_agent_ids = sort(@used_agent_ids); + $agentid = sprintf("%03d", $used_agent_ids[-1] + 1); + } + } + # If the client.keys is empty or doesn't exist set the id to 001 + $agentid = sprintf("%03d", 001) if (!$agentid); + } + + # Autogenerate a key unless one was specified on the command line + if (!$key) { + use Time::HiRes; # Standard with perl >= 5.8.2 + + my $rand_str1 = time() . $agentname . rand(10000); + my $rand_str2 = Time::HiRes::time . $ipaddress . $agentid . rand(10000); + $key = md5_hex($rand_str1) . md5_hex($rand_str2); + } + + add_agent($agentid, $agentname, $ipaddress, $key); + } + else { + warn "Error: adding agents requires: --name and --ip options.\n"; + usage(); + } +} +elsif ($remove) { + if ($agentid) { + remove_agent($agentid); + } + else { + remove_agent($remove) + } +} +elsif ($import) { + # Every option needs to be specified and NOT autogenerated because what + # is autogenerated on the server and the agent will likely be different + if (!$agentid || !$agentname || !$ipaddress || !$key) { + warn "Error: importing requires: --id, --name, --ip, and --key\n"; + usage(); + } + else { + # The key extracted from the server needs to be decoded before being put + # into the client.keys + $key = MIME::Base64::decode($key); + + add_agent($agentid, $agentname, $ipaddress, $key); + } +} +else { + warn "Error: no options specified!\n"; + usage(); +} + +sub usage { + warn "Usage: $0 [OPERATION] [OPTIONS]\n"; + warn " [operations]\n"; + warn " -a or --add = Add a new agent\n"; + warn " -r or --remove [id] = Remove agent\n"; + warn " -e or --extract [id] = Extract key\n"; + warn " -m or --import [keydata] = Import key\n"; + warn " -l or --list = List available agents\n"; + warn " [options]\n"; + warn " -k or --key [keydata] = Key data\n"; + warn " -n or --name [name] = Agent name (32 character max)\n"; + warn " -i or --id [id] = Agent identification (integer)\n"; + warn " -p or --ip [ip] = IP address\n\n"; + exit 1; +} + +sub list_agents { + if (-r AUTH_KEY_FILE) { + open (FH, "<", AUTH_KEY_FILE); + } + else { + die "Error reading ".AUTH_KEY_FILE.": $!\n"; + } + print "Available Agents:\n"; + print "ID", " " x (25 - length('ID')), + "NAME", " " x (25 - length('NAME')), + "IP", " " x (25 - length('IP')); + print "\n"; + while () { + chomp; + my ($id, $name, $ip, $key) = split; + print "$id", " " x (25 - length($id)), + "$name", " " x (25 - length($name)), + "$ip", " " x (25 - length($ip)) . "\n"; + } + close(FH); + exit 0; +} + +sub extract_key { + my $extractid = shift; + my ($encoded, $decoded); + + if (-r AUTH_KEY_FILE) { + open (FH, "<", AUTH_KEY_FILE); + } + else { + die "No ".AUTH_KEY_FILE."!\n"; + } + while () { + chomp; + my ($id, $name, $ip, $key) = split; + if ($id == $extractid) { + # Newlines are valid base64 characters so use '' instead for \n + $decoded = MIME::Base64::encode($key, ''); + print "$decoded\n"; + exit 0; + } + } + warn "Error: Agent ID $extractid doesn't exist!\n"; +} + +sub add_agent { + my $id = shift; + my $name = shift; + my $ip = shift; + my $agentkey = shift; + + if ($name && $ip && $agentkey) { + # Valid example key: + # 5a832efb8f93660857ce2acf8eec66a19fd9d4fa58e3221bbd2927ca8a0b40c3 + if ($agentkey !~ m/[a-z0-9]{64}/) { + warn "Error: invalid keydata! Let this script autogenerate it.\n"; + usage(); + } + + my @newagent = ($id, $name, $ip, $agentkey); + my $exists = check_if_exists(\@newagent); + + if ($exists == 0) { + # Append if client.keys exists and create it if it doesn't + if (-e AUTH_KEY_FILE) { + open(FH, ">>", AUTH_KEY_FILE) or die AUTH_KEY_FILE." error: $!\n"; + } + else { + open(FH, ">", AUTH_KEY_FILE) or die AUTH_KEY_FILE." error: $!\n"; + } + print FH join(' ', @newagent), "\n"; + close(FH); + } + elsif ($exists == 1) { + warn "ID: $id already in ".AUTH_KEY_FILE."!\n"; + } + elsif ($exists == 2) { + warn "Agent: $name already in ".AUTH_KEY_FILE."!\n"; + } + elsif ($exists == 3) { + warn "IP: $ip already in ".AUTH_KEY_FILE."!\n"; + } + } + else { + warn "Missing options to --add or problem with ".AUTH_KEY_FILE.": $!\n"; + usage(); + } +} + +sub remove_agent { + my $removeid = shift; + my @agent_array; + + if (-r AUTH_KEY_FILE) { + open (FH, "<", AUTH_KEY_FILE); + } + else { + die "Error: with ".AUTH_KEY_FILE.": $!\n"; + } + while () { + push(@agent_array, $_); + } + close(FH); + + if (-w AUTH_KEY_FILE) { + open (FHRW, ">", AUTH_KEY_FILE); + } + else { + die "Error writing ".AUTH_KEY_FILE.": $!\n"; + } + foreach my $line (@agent_array) { + if ($line !~ $removeid) { + print FHRW "$line"; + } + } + close(FHRW); + exit 0; +} + +sub check_if_exists { + my $agentlist_ref = shift; + my ($newid, $newname, $newip); + my $rval = 0; + + $newid = $agentlist_ref->[0]; + $newname = $agentlist_ref->[1]; + $newip = $agentlist_ref->[2]; + + # If the file isn't readable, the id probably isn't already in it + if (-r AUTH_KEY_FILE) { + open (FH, "<", AUTH_KEY_FILE); + while () { + chomp; + my ($id, $name, $ip, $key) = split; + $rval = 1 if ($id == $newid && $rval == 0); + $rval = 2 if ($name eq $newname && $rval == 0); + $rval = 3 if ($ip eq $newip && $rval == 0); + } + close(FH); + } + return $rval; +} diff --git a/contrib/ossec2mysql.conf b/contrib/ossec2mysql.conf new file mode 100755 index 0000000..45fa23c --- /dev/null +++ b/contrib/ossec2mysql.conf @@ -0,0 +1,11 @@ +# PARAMS USED BY OSSEC2BASED +dbhost=localhost +database=ossecbase +debug=5 +dbport=3306 +dbpasswd=yourpassword +dbuser=youruser +daemonize=0 +sensor=centralserver +hids_interface=ossec +resolve=1 diff --git a/contrib/ossec2mysql.pl b/contrib/ossec2mysql.pl new file mode 100755 index 0000000..17acb4c --- /dev/null +++ b/contrib/ossec2mysql.pl @@ -0,0 +1,494 @@ +#!/usr/bin/perl -w +use Socket; +use POSIX 'setsid'; +use strict; +# --------------------------------------------------------------------------- +# Author: Meir Michanie (meirm@riunx.com) +# Co-Author: J.A.Senger (jorge@br10.com.br) +# $Id: ossec2mysql.pl,v 1.13 2007/09/05 00:38:26 dcid Exp $ +# --------------------------------------------------------------------------- +# http://www.riunx.com/ +# --------------------------------------------------------------------------- +# +# --------------------------------------------------------------------------- +# About this script +# --------------------------------------------------------------------------- +# +# "Ossec to Mysql" records the OSSEC HIDS alert logs in MySQL database. +# It can run as a daemon (ossec2mysqld.pl), recording in real-time the logs in database or +# as a simple script (ossec2mysql.pl). +# +# --------------------------------------------------------------------------- +# Prerequisites +# --------------------------------------------------------------------------- +# +# MySQL Server +# Perl DBD::mysql module +# Perl DBI module +# +# --------------------------------------------------------------------------- +# Installation steps +# --------------------------------------------------------------------------- +# +# 1) Create new database +# 2a) Run ossec2mysql.sql to create MySQL tables in your database +# 2b) Create BASE tables with snort tables extention +# 3) Create a user to access the database; +# 4) Copy ossec2mysql.conf to /etc/ossec2mysql.conf with 0600 permissions +# 3) Edit /etc/ossec2mysql.conf according to your configuration: +# dbhost=localhost +# database=ossecbase +# debug=5 +# dbport=3306 +# dbpasswd=mypassword +# dbuser=ossecuser +# daemonize=0 +# resolve=1 +# +# +# --------------------------------------------------------------------------- +# License +# --------------------------------------------------------------------------- +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# --------------------------------------------------------------------------- +# About OSSEC HIDS +# --------------------------------------------------------------------------- +# +# OSSEC HIDS is an Open Source Host-based Intrusion Detection System. +# It performs log analysis and correlation, integrity checking, +# rootkit detection, time-based alerting and active response. +# http://www.ossec.net +# +# --------------------------------------------------------------------------- + +# --------------------------------------------------------------------------- +# Parameters +# --------------------------------------------------------------------------- +$SIG{TERM} = sub { &gracefulend('TERM')}; +$SIG{INT} = sub { &gracefulend('INT')}; +my ($RUNASDAEMON)=0; +my ($DAEMONLOGFILE)='/var/log/ossec2mysql.log'; +my ($DAEMONLOGERRORFILE) = '/var/log/ossec2mysql.err'; +my ($LOGGER)='ossec2mysql'; +use ossecmysql; + +my %conf; +$conf{dbhost}='localhost'; +$conf{database}='snort'; +$conf{debug}=5; +$conf{dbport}='3306'; +$conf{dbpasswd}='password'; +$conf{dbuser}='user'; +$conf{daemonize}=0; +$conf{sensor}='sensor'; +$conf{hids_interface}='ossec'; +$conf{resolve}=1; + + +my($OCT) = '(?:25[012345]|2[0-4]\d|1?\d\d?)'; + +my($IP) = $OCT . '\.' . $OCT . '\.' . $OCT . '\.' . $OCT; + +my $VERSION="0.4"; +my $sig_class_id=1; +&help() unless @ARGV; +my $dump=0; +my ($hids_id,$hids,$hids_interface,$last_cid)=(undef, 'localhost', 'ossec',0); +my ($tempvar,$VERBOSE)=(0,0); +# --------------------------------------------------------------------------- +# Arguments parsing +# --------------------------------------------------------------------------- +while (@ARGV){ + $_= shift @ARGV; + if (m/^-d$|^--daemon$/){ + $conf{daemonize}=1; + }elsif ( m/^-h$|^--help$/){ + &help(); + }elsif ( m/^-n$|^--noname$/){ + $conf{'resolve'}=0; + }elsif ( m/^-v$|^--verbose$/){ + $VERBOSE=1; + }elsif ( m/^--interface$/){ + $conf{hids_interface}= shift @ARGV if @ARGV; # ossec-rt/ossec-feed + }elsif ( m/^--sensor$/){ + $conf{sensor}= shift @ARGV if @ARGV; # monitor + }elsif ( m/^--conf$/){ + $conf{conf}= shift @ARGV if @ARGV; # localhost + &loadconf(\%conf); + }elsif ( m/^--dbhost$/){ + $conf{dbhost}= shift @ARGV if @ARGV; # localhost + }elsif ( m/^--dbport$/){ + $conf{dbport}= shift @ARGV if @ARGV; # localhost + }elsif ( m/^--dbname$/){ + $conf{database}= shift @ARGV if @ARGV; # snort + }elsif ( m/^--dbuser$/){ + $conf{dbuser}= shift @ARGV if @ARGV; # root + }elsif ( m/^--dbpass$/){ + $conf{dbpasswd}= shift @ARGV if @ARGV; # monitor + } + +} +if ($conf{dbpasswd}=~ m/^--stdin$/){ + print "dbpassword:"; + $conf{dbpasswd}=<>; + chomp $conf{dbpasswd}; +} +$hids=$conf{sensor} if exists($conf{sensor}); +$hids_interface=$conf{hids_interface} if exists($conf{hids_interface}); + +&daemonize() if $conf{daemonize}; +my $dbi= ossecmysql->new(%conf) || die ("Could not connect to $conf{dbhost}:$conf{dbport}:$conf{database} as $conf{dbpasswd}\n"); +#### +# SQL vars; +my ($query,$numrows,$row_ref); +#### +#get sensor id +$query= 'select sid,last_cid from sensor where hostname=? and interface=?'; +$numrows= $dbi->execute($query,$hids,$hids_interface); +if (1==$numrows){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $hids_id=$row_ref->{sid}; + $last_cid=$row_ref->{last_cid}; +}else{ + $query="INSERT INTO sensor ( sid , hostname , interface , filter , detail , encoding , last_cid ) +VALUES ( +NULL , ?, ? , NULL , ? , ?, ? +)"; + $numrows= $dbi->execute($query,$hids,$hids_interface,1,2,0); + $hids_id=$dbi->lastid(); +} +$dbi->{sth}->finish; +&forceprintlog ("SENSOR:$hids; feed:$hids_interface; id:$hids_id; last cid:$last_cid"); + +my $newrecord=0; +my %stats; +my %resolv; +my ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); +my $lasttimestamp=0; +my $delta=0; +######################################################## +my $datepath=`date "+%Y/%b/ossec-alerts-%d.log"`; +my $LOG='/var/ossec/logs/alerts/'. $datepath; +chomp $LOG; +&taillog($last_cid,$LOG); +################################################################ +sub forceprintlog(){ + $tempvar=$VERBOSE; + $VERBOSE=1; + &printlog (@_); + $VERBOSE=$tempvar; +} + + +sub taillog { + my ($last_cid,$LOG)=@_; + while (<>) { + if (m/^$/){ + $newrecord=1; + next unless $timestamp; + $alerthostip=$alerthost if $alerthost=~ m/^$IP$/; + if ($alerthostip){ + $dstip=$alerthostip; + $resolv{$alerthost}=$dstip; + }else{ + if (exists $resolv{$alerthost}){ + $dstip=$resolv{$alerthost}; + }else{ + if ($conf{'resolve'}){ + $dstip=`host $alerthost 2>/dev/null | grep 'has address' `; + if ($dstip =~m/(\d+\.\d+\.\d+\.\d+)/ ){ + $dstip=$1; + }else{ + $dstip=$srcip; + } + }else{ + $dstip=$alerthost; + } + $resolv{$alerthost}=$dstip; + + } + } + # + $last_cid= &prepair2basedata( + $hids_id, + $last_cid, + $timestamp, + $sec, + $mail, + $date, + $alerthost, + $datasource, + $rule, + $level, + $description, + $srcip, + $dstip, + $user, + $text + ); + ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); + next ; + } + if (m/^\*\* Alert ([0-9]+).([0-9]+):(.*)$/){ + $timestamp=$1; + if ( $timestamp == $lasttimestamp){ + $delta++; + }else{ + $delta=0; + $lasttimestamp=$timestamp; + } + $sec=$2; + $mail=$3; + $mail=$mail ? $mail : 'nomail'; +#2006 Aug 29 17:19:52 firewall -> /var/log/messages +#2006 Aug 30 11:52:14 192.168.0.45->/var/log/secure +#2006 Sep 12 11:12:16 92382-Snort1 -> 172.16.176.132 +# + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $datasource=$3; + if ($datasource=~ m/(\d+\.\d+\.\d+\.\d+)/){ + $alerthost=$1; + $datasource="remoted"; + } + + +#2006 Aug 29 17:33:31 (recepcao) 10.0.3.154 -> syscheck + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+\((.*?)\)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $alerthostip=$3; + $datasource=$4; + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)$/){ + $date=$1; + $alerthost='localhost'; + $datasource=$2; + }elsif ( m/Rule: ([0-9]+) \(level ([0-9]+)\) -> (.*)$/ ){ + $rule=$1; + $level=$2; + $description= $3; + }elsif ( m/Src IP:/){ + if ( m/($IP)/){ + $srcip=$1; + }else{ + $srcip='0.0.0.0'; + } + }elsif ( m/User: (.*)$/){ + $user=$1; + }elsif( m/(.*)$/){ + $text .=$1; + } + + + } # End while read line +} + + +sub ossec_aton(){ + my ($ip)=@_; + if ($ip=~ m/(\d+)\.(\d+)\.(\d+)\.(\d+)/){ + my $num= ($1 * 256 ** 3) + ($2 * 256 ** 2)+ ($3 * 256 ** 1)+ ($4); + + return "$num"; + }else{ + return "0"; + } + +} + +sub prepair2basedata(){ + my ( + $hids_id, + $last_cid, + $timestamp, + $sec, + $mail, + $date, + $alerthost, + $datasource, + $rule, + $level, + $description, + $srcip, + $dstip, + $user, + $text + )=@_; + my ($count,$query,$row_ref,$sig_id); +### +# +# Get/Set signature id + $query = "SELECT sig_id FROM signature where sig_name=? and sig_class_id=? and sig_priority=? and sig_rev=? and sig_sid=? and sig_gid is NULL"; + $dbi->execute($query,$description,1,$level,0,$rule); + $count=$dbi->{sth}->rows; + if ($count){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $sig_id=$row_ref->{sig_id}; + &printlog ("REUSING SIGNATURE\n"); + }else{ + $query="INSERT INTO signature ( sig_id , sig_name , sig_class_id , sig_priority , sig_rev , sig_sid , sig_gid ) +VALUES ( +NULL ,?, ? , ? , ? , ?, NULL +)"; + $dbi->execute($query,$description,1,$level,0,$rule); + $sig_id = $dbi->lastid(); + } +$dbi->{sth}->finish; +&printlog ("SIGNATURE: $sig_id\n"); +####### +# +# Set event + $query="INSERT INTO event ( sid , cid , signature , timestamp ) +VALUES ( +? , ? , ? ,? +)"; + $last_cid++; + $dbi->execute($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)); + +&printlog ("EVENT: ($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)\n"); +$dbi->{sth}->finish; +######### +# +# Set acid_event + $query=" INSERT INTO acid_event ( sid , cid , signature , sig_name , sig_class_id , sig_priority , timestamp , ip_src , ip_dst , ip_proto , layer4_sport , layer4_dport ) +VALUES ( +? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ? +) "; + $dbi->execute($query,$hids_id,$last_cid,$sig_id,$description,1,$level,&fixdate2base($date),&ossec_aton($srcip),&ossec_aton($dstip),undef,undef,undef); +&printlog ("ACID_EVENT: ($query,$hids_id,$last_cid,$sig_id,$description,1,$level,&fixdate2base($date),&ossec_aton($srcip),&ossec_aton($dstip),undef,undef)\n"); +$dbi->{sth}->finish; + +######### +# +# +# Set data + $text = "** Alert $timestamp.$sec:\t$mail\n$date $alerthost -> $datasource\nRule: $rule (level $level) -> $description\nSrc IP: ($srcip)\nUser: $user\n$text"; + $query=" INSERT INTO data ( sid , cid , data_payload ) +VALUES ( +?,?,?)"; + $dbi->execute($query,$hids_id,$last_cid,$text); +&printlog ("DATA: ($query,$hids_id,$last_cid,$text)\n"); +$dbi->{sth}->finish; +########## +# + $query="UPDATE sensor SET last_cid=? where sid=? limit 1"; + $numrows= $dbi->execute($query,$last_cid,$hids_id); +# end sub +$dbi->{sth}->finish; +return $last_cid; +} + +sub fixdate2base(){ + my ($date)=@_; + $date=~ s/ Jan /-01-/; + $date=~ s/ Feb /-02-/; + $date=~ s/ Mar /-03-/; + $date=~ s/ Apr /-04-/; + $date=~ s/ May /-05-/; + $date=~ s/ Jun /-06-/; + $date=~ s/ Jul /-07-/; + $date=~ s/ Aug /-08-/; + $date=~ s/ Sep /-09-/; + $date=~ s/ Oct /-10-/; + $date=~ s/ Nov /-11-/; + $date=~ s/ Dec /-12-/; + $date=~ s/\s$//g; + return $date; +} +sub version(){ + print "OSSEC report tool $VERSION\n"; + print "Licensed under GPL\n"; + print "Contributor Meir Michanie\n"; +} + +sub help(){ + &version(); + print "This tool helps you import into base the alerts generated by ossec." + . " More info in the doc directory .\n"; + print "Usage:\n"; + print "$0 [-h|--help] # This text you read now\n"; + print "Options:\n"; + print "\t--dbhost \n"; + print "\t--dbname \n"; + print "\t--dbport <[0-9]+>\n"; + print "\t--dbpass \n"; + print "\t--dbuser \n"; + print "\t-d|--daemonize\n"; + print "\t-n|--noname\n"; + print "\t-v|--verbose\n"; + print "\t--conf \n"; + print "\t--sensor \n"; + print "\t--interface \n"; + + exit 0; +} + + +sub daemonize { + chdir '/' or die "Can't chdir to /: $!"; + open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; + open STDOUT, ">>$DAEMONLOGFILE" + or die "Can't write to $DAEMONLOGFILE: $!"; + defined(my $pid = fork) or die "Can't fork: $!"; + if ($pid){ + open (PIDFILE , ">/var/run/ossec2base2.pid") ; + print PIDFILE "$pid\n"; + close (PIDFILE); + exit 0; + } + setsid or die "Can't start a new session: $!"; + open STDERR, ">>$DAEMONLOGERRORFILE" or die "Can't write to $DAEMONLOGERRORFILE: $!"; +} + +sub gracefulend(){ + my ($signal)=@_; + &forceprintlog ("Terminating upon signal $signal"); + &forceprintlog ("Daemon halted"); + close STDOUT; + close STDERR; + exit 0; +} + +sub printlog(){ + return unless $VERBOSE; + my (@lines)=@_; + foreach my $line(@lines){ + chomp $line; + my ($date)=scalar localtime; + $date=~ s/^\S+\s+(\S+.*\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}).*$/$1/; + print "$date $LOGGER: $line\n"; + } +} + + +sub loadconf(){ + my ($hash_ref)=@_; + my $conf=$hash_ref->{conf}; + unless (-f $conf) { &printlog ("ERROR: I can't find config file $conf"); exit 1;} + unless (open ( CONF , "$conf")){ &printlog ("ERROR: I can't open file $conf");exit 1;} + while (){ + next if m/^$|^#/; + if ( m/^(\S+)\s?=\s?(.*?)$/) { + $hash_ref->{$1} = $2; + } + } + close CONF; +} + diff --git a/contrib/ossec2mysql.sql b/contrib/ossec2mysql.sql new file mode 100755 index 0000000..40f934b --- /dev/null +++ b/contrib/ossec2mysql.sql @@ -0,0 +1,96 @@ + +-- +-- Table structure for table `acid_event` +-- + +CREATE TABLE `acid_event` ( + `sid` int(10) unsigned NOT NULL, + `cid` int(10) unsigned NOT NULL, + `signature` varchar(255) NOT NULL, + `sig_name` varchar(255) default NULL, + `sig_class_id` int(10) unsigned default NULL, + `sig_priority` int(10) unsigned default NULL, + `timestamp` datetime NOT NULL, + `ip_src` int(10) unsigned default NULL, + `ip_dst` int(10) unsigned default NULL, + `ip_proto` int(11) default NULL, + `layer4_sport` int(10) unsigned default NULL, + `layer4_dport` int(10) unsigned default NULL, + `username` varchar(255) default NULL, + PRIMARY KEY (`sid`,`cid`), + KEY `signature` (`signature`), + KEY `sig_name` (`sig_name`), + KEY `sig_class_id` (`sig_class_id`), + KEY `sig_priority` (`sig_priority`), + KEY `timestamp` (`timestamp`), + KEY `ip_src` (`ip_src`), + KEY `ip_dst` (`ip_dst`), + KEY `ip_proto` (`ip_proto`), + KEY `layer4_sport` (`layer4_sport`), + KEY `layer4_dport` (`layer4_dport`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `data` +-- + +CREATE TABLE `data` ( + `sid` int(10) unsigned NOT NULL, + `cid` int(10) unsigned NOT NULL, + `data_payload` text, + PRIMARY KEY (`sid`,`cid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `event` +-- + +CREATE TABLE `event` ( + `sid` int(10) unsigned NOT NULL, + `cid` int(10) unsigned NOT NULL, + `signature` int(10) unsigned NOT NULL, + `timestamp` datetime NOT NULL, + PRIMARY KEY (`sid`,`cid`), + KEY `sig` (`signature`), + KEY `time` (`timestamp`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `sensor` +-- + +CREATE TABLE `sensor` ( + `sid` int(10) unsigned NOT NULL auto_increment, + `hostname` text, + `interface` text, + `filter` text, + `detail` tinyint(4) default NULL, + `encoding` tinyint(4) default NULL, + `last_cid` int(10) unsigned NOT NULL, + PRIMARY KEY (`sid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `signature` +-- + +CREATE TABLE `signature` ( + `sig_id` int(10) unsigned NOT NULL auto_increment, + `sig_name` varchar(255) NOT NULL, + `sig_class_id` int(10) unsigned NOT NULL, + `sig_priority` int(10) unsigned default NULL, + `sig_rev` int(10) unsigned default NULL, + `sig_sid` int(10) unsigned default NULL, + `sig_gid` int(10) unsigned default NULL, + PRIMARY KEY (`sig_id`), + KEY `sign_idx` (`sig_name`(20)), + KEY `sig_class_id_idx` (`sig_class_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=47 ; diff --git a/contrib/ossec2mysqld.pl b/contrib/ossec2mysqld.pl new file mode 100755 index 0000000..c2b61c7 --- /dev/null +++ b/contrib/ossec2mysqld.pl @@ -0,0 +1,524 @@ +#!/usr/bin/perl -w +use strict; +use Socket; +use POSIX 'setsid'; +# --------------------------------------------------------------------------- +# Author: Meir Michanie (meirm@riunx.com) +# Co-Author: J.A.Senger (jorge@br10.com.br) +# $Id: ossec2mysqld.pl,v 1.11 2007/09/05 00:38:26 dcid Exp $ +# $Revision: 1.11 $ +## --------------------------------------------------------------------------- +# http://www.riunx.com/ +# --------------------------------------------------------------------------- +# +# --------------------------------------------------------------------------- +# About this script +# --------------------------------------------------------------------------- +# +# "Ossec to Mysql" records the OSSEC HIDS alert logs in MySQL database. +# It can run as a daemon (ossec2mysqld.pl), recording in real-time the logs in database or +# as a simple script (ossec2mysql.pl). +# +# --------------------------------------------------------------------------- +# Prerequisites +# --------------------------------------------------------------------------- +# +# MySQL Server +# Perl DBD::mysql module +# Perl DBI module +# +# --------------------------------------------------------------------------- +# Installation steps +# --------------------------------------------------------------------------- +# +# 1) Create new database +# 2a) Run ossec2mysql.sql to create MySQL tables in your database +# 2b) Create BASE tables with snort tables extention +# 3) Create a user to access the database; +# 4) Copy ossec2mysql.conf to /etc/ossec2mysql.conf with 0600 permissions +# 3) Edit /etc/ossec2mysql.conf according to your configuration: +# dbhost=localhost +# database=ossecbase +# debug=5 +# dbport=3306 +# dbpasswd=mypassword +# dbuser=ossecuser +# daemonize=0 +# resolve=1 +# +# +# --------------------------------------------------------------------------- +# License +# --------------------------------------------------------------------------- +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# --------------------------------------------------------------------------- +# About OSSEC HIDS +# --------------------------------------------------------------------------- +# +# OSSEC HIDS is an Open Source Host-based Intrusion Detection System. +# It performs log analysis and correlation, integrity checking, +# rootkit detection, time-based alerting and active response. +# http://www.ossec.net +# +# --------------------------------------------------------------------------- + +# --------------------------------------------------------------------------- +# Parameters +# --------------------------------------------------------------------------- +$SIG{TERM} = sub { &gracefulend('TERM')}; +$SIG{INT} = sub { &gracefulend('INT')}; +my ($RUNASDAEMON)=0; +my ($DAEMONLOGFILE)='/var/log/ossec2mysql.log'; +my ($DAEMONLOGERRORFILE) = '/var/log/ossec2mysql.err'; +my ($LOGGER)='ossec2mysql'; +use ossecmysql; + +my %conf; +$conf{dbhost}='localhost'; +$conf{database}='snort'; +$conf{debug}=5; +$conf{dbport}='3306'; +$conf{dbpasswd}='password'; +$conf{dbuser}='user'; +$conf{daemonize}=0; +$conf{sensor}='sensor'; +$conf{hids_interface}='ossec'; +$conf{resolve}=1; + + +my($OCT) = '(?:25[012345]|2[0-4]\d|1?\d\d?)'; + +my($IP) = $OCT . '\.' . $OCT . '\.' . $OCT . '\.' . $OCT; + +my $VERSION="0.4"; +my $sig_class_id=1; +&help() unless @ARGV; +my $dump=0; +my ($hids_id,$hids,$hids_interface,$last_cid)=(undef, 'localhost', 'ossec',0); +my ($tempvar,$VERBOSE)=(0,0); +# --------------------------------------------------------------------------- +# Arguments parsing +# --------------------------------------------------------------------------- + +while (@ARGV){ + $_= shift @ARGV; + if (m/^-d$|^--daemon$/){ + $conf{daemonize}=1; + }elsif ( m/^-h$|^--help$/){ + &help(); + }elsif ( m/^-n$|^--noname$/){ + $conf{'resolve'}=0; + }elsif ( m/^-v$|^--verbose$/){ + $VERBOSE=1; + }elsif ( m/^--interface$/){ + $conf{hids_interface}= shift @ARGV if @ARGV; # ossec-rt/ossec-feed + }elsif ( m/^--sensor$/){ + $conf{sensor}= shift @ARGV if @ARGV; # monitor + }elsif ( m/^--conf$/){ + $conf{conf}= shift @ARGV if @ARGV; # localhost + &loadconf(\%conf); + }elsif ( m/^--dbhost$/){ + $conf{dbhost}= shift @ARGV if @ARGV; # localhost + }elsif ( m/^--dbport$/){ + $conf{dbport}= shift @ARGV if @ARGV; # localhost + }elsif ( m/^--dbname$/){ + $conf{database}= shift @ARGV if @ARGV; # snort + }elsif ( m/^--dbuser$/){ + $conf{dbuser}= shift @ARGV if @ARGV; # root + }elsif ( m/^--dbpass$/){ + $conf{dbpasswd}= shift @ARGV if @ARGV; # monitor + } + +} +if ($conf{dbpasswd}=~ m/^--stdin$/){ + print "dbpassword:"; + $conf{dbpasswd}=<>; + chomp $conf{dbpasswd}; +} +$hids=$conf{sensor} if exists($conf{sensor}); +$hids_interface=$conf{hids_interface} if exists($conf{hids_interface}); + +&daemonize() if $conf{daemonize}; +my $dbi= ossecmysql->new(%conf) || die ("Could not connect to $conf{dbhost}:$conf{dbport}:$conf{database} as $conf{dbpasswd}\n"); +#### +# SQL vars; +my ($query,$numrows,$row_ref); +#### +#get sensor id +$query= 'select sid,last_cid from sensor where hostname=? and interface=?'; +$numrows= $dbi->execute($query,$hids,$hids_interface); +if (1==$numrows){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $hids_id=$row_ref->{sid}; + $last_cid=$row_ref->{last_cid}; +}else{ + $query="INSERT INTO sensor ( sid , hostname , interface , filter , detail , encoding , last_cid ) +VALUES ( +NULL , ?, ? , NULL , ? , ?, ? +)"; + $numrows= $dbi->execute($query,$hids,$hids_interface,1,2,0); + $hids_id=$dbi->lastid(); +} +$dbi->{sth}->finish; +&forceprintlog ("SENSOR:$hids; feed:$hids_interface; id:$hids_id; last cid:$last_cid"); +#exit ; + +my $newrecord=0; +my %stats; +my %resolv; +my ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); +my $lasttimestamp=0; +my $delta=0; +######################################################## +my $datepath=`date "+%Y/%b/ossec-alerts-%d.log"`; +my $LOG='/var/ossec/logs/alerts/'. $datepath; +chomp $LOG; +&taillog($last_cid,$LOG); +############################################################### +sub forceprintlog(){ + $tempvar=$VERBOSE; + $VERBOSE=1; + &printlog (@_); + $VERBOSE=$tempvar; +} +sub taillog { + my ($last_cid,$LOG)=@_; + my($offset, $line, $stall) = ''; + + $offset = (-s $LOG); # Don't start at beginning, go to end + + while (1==1) { + sleep(1); + %resolv=(); + $| = 1; + $stall += 1; + $datepath=`date "+%Y/%b/ossec-alerts-%d.log"`; + $LOG='/var/ossec/logs/alerts/'. $datepath; + chomp $LOG; + unless ( -f $LOG){&forceprintlog ("Error -f $LOG"); next; } + if ((-s $LOG) < $offset) { + &forceprintlog ("Log shrunk, resetting.."); + $offset = 0; + } + + unless (open(TAIL, $LOG)){ &forceprintlog ("Error opening $LOG: $!\n");next ;} + + if (seek(TAIL, $offset, 0)) { + # found offset, log not rotated + } else { + # log reset, follow + $offset=0; + seek(TAIL, $offset, 0); + } + while () { + if (m/^$/){ + $newrecord=1; + next unless $timestamp; + $alerthostip=$alerthost if $alerthost=~ m/^$IP$/; + if ($alerthostip){ + $dstip=$alerthostip; + $resolv{$alerthost}=$dstip; + }else{ + if (exists $resolv{$alerthost}){ + $dstip=$resolv{$alerthost}; + }else{ + if ($conf{'resolve'}){ + $dstip=`host $alerthost 2>/dev/null | grep 'has address' `; + if ($dstip =~m/(\d+\.\d+\.\d+\.\d+)/ ){ + $dstip=$1; + }else{ + $dstip=$srcip; + } + }else{ + $dstip=$alerthost; + } + $resolv{$alerthost}=$dstip; + + } + } + $last_cid= &prepair2basedata( + $hids_id, + $last_cid, + $timestamp, + $sec, + $mail, + $date, + $alerthost, + $datasource, + $rule, + $level, + $description, + $srcip, + $dstip, + $user, + $text + ); + ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); + next ; + } + if (m/^\*\* Alert ([0-9]+).([0-9]+):(.*)$/){ + $timestamp=$1; + if ( $timestamp == $lasttimestamp){ + $delta++; + }else{ + $delta=0; + $lasttimestamp=$timestamp; + } + $sec=$2; + $mail=$3; + $mail=$mail ? $mail : 'nomail'; +#2006 Aug 29 17:19:52 firewall -> /var/log/messages +#2006 Aug 30 11:52:14 192.168.0.45->/var/log/secure +#2006 Sep 12 11:12:16 92382-Snort1 -> 172.16.176.132 +# + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $datasource=$3; + if ($datasource=~ m/(\d+\.\d+\.\d+\.\d+)/){ + $alerthost=$1; + $datasource="remoted"; + } + +#2006 Aug 29 17:33:31 (recepcao) 10.0.3.154 -> syscheck + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+\((.*?)\)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $alerthostip=$3; + $datasource=$4; + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)$/){ + $date=$1; + $alerthost='localhost'; + $datasource=$2; + }elsif ( m/Rule: ([0-9]+) \(level ([0-9]+)\) -> (.*)$/ ){ + $rule=$1; + $level=$2; + $description= $3; + }elsif ( m/Src IP:/){ + if ( m/($IP)/){ + $srcip=$1; + }else{ + $srcip='0.0.0.0'; + } + }elsif ( m/User: (.*)$/){ + $user=$1; + }elsif( m/(.*)$/){ + $text .=$1; + } + + + } # End while read line + $offset=tell(TAIL); + close(TAIL); + } +} + + +sub ossec_aton(){ + my ($ip)=@_; + if ($ip=~ m/(\d+)\.(\d+)\.(\d+)\.(\d+)/){ + my $num= ($1 * 256 ** 3) + ($2 * 256 ** 2)+ ($3 * 256 ** 1)+ ($4); + + return "$num"; + }else{ + return "0"; + } + +} + +sub prepair2basedata(){ + my ( + $hids_id, + $last_cid, + $timestamp, + $sec, + $mail, + $date, + $alerthost, + $datasource, + $rule, + $level, + $description, + $srcip, + $dstip, + $user, + $text + )=@_; + my ($count,$query,$row_ref,$sig_id); +### +# +# Get/Set signature id + $query = "SELECT sig_id FROM signature where sig_name=? and sig_class_id=? and sig_priority=? and sig_rev=? and sig_sid=? and sig_gid is NULL"; + $dbi->execute($query,$description,1,$level,0,$rule); + $count=$dbi->{sth}->rows; + if ($count){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $sig_id=$row_ref->{sig_id}; + &printlog ("REUSING SIGNATURE\n"); + }else{ + $query="INSERT INTO signature ( sig_id , sig_name , sig_class_id , sig_priority , sig_rev , sig_sid , sig_gid ) +VALUES ( +NULL ,?, ? , ? , ? , ?, NULL +)"; + $dbi->execute($query,$description,1,$level,0,$rule); + $sig_id = $dbi->lastid(); + } +$dbi->{sth}->finish; +&printlog ("SIGNATURE: $sig_id\n"); +####### +# +# Set event + $query="INSERT INTO event ( sid , cid , signature , timestamp ) +VALUES ( +? , ? , ? ,? +)"; + $last_cid++; + $dbi->execute($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)); + +&printlog ("EVENT: ($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)\n"); +$dbi->{sth}->finish; +######### +# +# Set acid_event + $query=" INSERT INTO acid_event ( sid , cid , signature , sig_name , sig_class_id , sig_priority , timestamp , ip_src , ip_dst , ip_proto , layer4_sport , layer4_dport ) +VALUES ( +? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ? +) "; + $dbi->execute($query,$hids_id,$last_cid,$sig_id,$description,1,$level,&fixdate2base($date),&ossec_aton($srcip),&ossec_aton($dstip),undef,undef,undef); +&printlog ("ACID_EVENT: ($query,$hids_id,$last_cid,$sig_id,$description,1,$level,&fixdate2base($date),&ossec_aton($srcip),&ossec_aton($dstip),undef,undef)\n"); +$dbi->{sth}->finish; + +######### +# +# +# Set data + $text = "** Alert $timestamp.$sec:\t$mail\n$date $alerthost -> $datasource\nRule: $rule (level $level) -> $description\nSrc IP: ($srcip)\nUser: $user\n$text"; + $query=" INSERT INTO data ( sid , cid , data_payload ) +VALUES ( +?,?,?)"; + $dbi->execute($query,$hids_id,$last_cid,$text); +&printlog ("DATA: ($query,$hids_id,$last_cid,$text)\n"); +$dbi->{sth}->finish; +########## +# + $query="UPDATE sensor SET last_cid=? where sid=? limit 1"; + $numrows= $dbi->execute($query,$last_cid,$hids_id); +# end sub +$dbi->{sth}->finish; +return $last_cid; +} + +sub fixdate2base(){ + my ($date)=@_; + $date=~ s/ Jan /-01-/; + $date=~ s/ Feb /-02-/; + $date=~ s/ Mar /-03-/; + $date=~ s/ Apr /-04-/; + $date=~ s/ May /-05-/; + $date=~ s/ Jun /-06-/; + $date=~ s/ Jul /-07-/; + $date=~ s/ Aug /-08-/; + $date=~ s/ Sep /-09-/; + $date=~ s/ Oct /-10-/; + $date=~ s/ Nov /-11-/; + $date=~ s/ Dec /-12-/; + $date=~ s/\s$//g; + return $date; +} +sub version(){ + print "OSSEC report tool $VERSION\n"; + print "Licensed under GPL\n"; + print "Contributor Meir Michanie\n"; +} + +sub help(){ + &version(); + print "This tool helps you import into base the alerts generated by ossec." + . " More info in the doc directory .\n"; + print "Usage:\n"; + print "$0 [-h|--help] # This text you read now\n"; + print "Options:\n"; + print "\t--dbhost \n"; + print "\t--dbname \n"; + print "\t--dbport <[0-9]+>\n"; + print "\t--dbpass \n"; + print "\t--dbuser \n"; + print "\t-d|--daemonize\n"; + print "\t-n|--noname\n"; + print "\t-v|--verbose\n"; + print "\t--conf \n"; + print "\t--sensor \n"; + print "\t--interface \n"; + + exit 0; +} + + +sub daemonize { + chdir '/' or die "Can't chdir to /: $!"; + open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; + open STDOUT, ">>$DAEMONLOGFILE" + or die "Can't write to $DAEMONLOGFILE: $!"; + defined(my $pid = fork) or die "Can't fork: $!"; + if ($pid){ + open (PIDFILE , ">/var/run/ossec2base2.pid") ; + print PIDFILE "$pid\n"; + close (PIDFILE); + exit 0; + } + setsid or die "Can't start a new session: $!"; + open STDERR, ">>$DAEMONLOGERRORFILE" or die "Can't write to $DAEMONLOGERRORFILE: $!"; +} + +sub gracefulend(){ + my ($signal)=@_; + &forceprintlog ("Terminating upon signal $signal"); + close TAIL; + &forceprintlog ("Daemon halted"); + close STDOUT; + close STDERR; + exit 0; +} + +sub printlog(){ + return unless $VERBOSE; + my (@lines)=@_; + foreach my $line(@lines){ + chomp $line; + my ($date)=scalar localtime; + $date=~ s/^\S+\s+(\S+.*\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}).*$/$1/; + print "$date $LOGGER: $line\n"; + } +} + + +sub loadconf(){ + my ($hash_ref)=@_; + my $conf=$hash_ref->{conf}; + unless (-f $conf) { &printlog ("ERROR: I can't find config file $conf"); exit 1;} + unless (open ( CONF , "$conf")){ &printlog ("ERROR: I can't open file $conf");exit 1;} + while (){ + next if m/^$|^#/; + if ( m/^(\S+)\s?=\s?(.*?)$/) { + $hash_ref->{$1} = $2; + } + } + close CONF; +} + diff --git a/contrib/ossec_report.txt b/contrib/ossec_report.txt new file mode 100755 index 0000000..9f83775 --- /dev/null +++ b/contrib/ossec_report.txt @@ -0,0 +1,26 @@ +OSSEC report tool 0.1 +Licensed under GPL +Contributor Meir Michanie +ossec_report_contrib.pl [-h|--help] # This text you read now +ossec_report_contrib.pl [-r|--report] # prints a report for each element +ossec_report_contrib.pl [-s|--summary] # prints a summary report +ossec_report_contrib.pl [-t|--top] #prints the top list + +How To: +======= + +ossec_report_contrib.pl OSSEC report tool 0.1 +ossec_report_contrib.pl is a GNU style program. +It reads from STDIN and write to stdout. This gives you the advantage to use it in pipes. +i.e. +cat ossec-alerts-05.log | ossec_report_contrib.pl -r | mail root -s 'OSSEC detailed report' +cat ossec-alerts-05.log | ossec_report_contrib.pl -s | mail root -s 'OSSEC summary report' +cat | ossec_report_contrib.pl -t | head -n 15 (for top 15) +cat | ossec_report_contrib.pl -s (for sumary) + +Crontab entry: +58 23 * * * (cat ossec-alerts-05.log | ossec_report_contrib.pl -s) + + +The could be any one of the variables used in ossec log: +mail,alerthost,datasource,rule,level,description,srcip,user. diff --git a/contrib/ossec_report_contrib.pl b/contrib/ossec_report_contrib.pl new file mode 100755 index 0000000..4278dfb --- /dev/null +++ b/contrib/ossec_report_contrib.pl @@ -0,0 +1,184 @@ +#!/usr/bin/perl -w +# by Meir Michanie +# GPL licensed +# meirm@riunx.com +my $VERSION="0.1"; +use strict; +&help() unless @ARGV; +if ($ARGV[0]=~ m/^-h$|^--help$/i){ + &help(); +} +&help unless $ARGV[0]=~ m/^-r$|^--report$|^-s$|^--summary$|^-t$|^--top$/; +my (@argv) = (); +while (@ARGV){ + push @argv, shift @ARGV; +} + +my $newrecord=0; +my %stats; +my ($timestamp,$sec,$mail,$date,$alerthost,$datasource,$rule,$level,$description, +$srcip,$user,$text); +while(<>){ + if (m/^$/){ + $newrecord=1; + $stats{$alerthost}{mail}{$mail}++; + $stats{$alerthost}{alerthost}{$alerthost}++; + $stats{$alerthost}{datasource}{$datasource}++; + $stats{$alerthost}{rule}{$rule}++; + $stats{$alerthost}{level}{$level}++; + $stats{$alerthost}{description}{$description}++; + $stats{$alerthost}{srcip}{$srcip}++; + $stats{$alerthost}{user}{$user}++; + next ; + } + if (m/^\*\* Alert ([0-9]+).([0-9]+):(.*)$/){ + $timestamp=$1; + $sec=$2; + $mail=$3; + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)->(.*)$/){ + $date=$1; + $alerthost=$2; + $datasource=$3; + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)$/){ + $date=$1; + $alerthost='none'; + $datasource=$2; + }elsif ( m/Rule: ([0-9]+) \(level ([0-9]+)\) -> (.*)$/ ){ + $rule=$1; + $level=$2; + $description= $3; + }elsif ( m/Src IP: (.*)$/){ + $srcip=$1; + }elsif ( m/User: (.*)$/){ + $user=$1; + }elsif( m/(.*)$/){ + $text=$1; + } + + +} +if ($argv[0]=~ m/^-r$|^--report$/i){ + &report(\%stats); +}elsif ($argv[0]=~ m/^-s$|^--summary$/){ + &summary(\%stats); +}elsif ($argv[0]=~ m/^-t$|^--top$/){ + $argv[1]= $argv[1] ? $argv[1] : 'srcip' ; + &top(\%stats,$argv[1]); +}else{ + &help(); +} + +sub printversion(){ + print "OSSEC report tool $VERSION\n"; + print "Licensed under GPL\n"; + print "Contributor Meir Michanie\n"; +} + +sub help(){ + &printversion(); + print "$0 [-h|--help] # This text you read now\n"; + print "$0 [-r|--report] # prints a report for each element\n"; + print "$0 [-s|--summary] # prints a summary report\n"; + print "$0 [-t|--top] #prints the top list\n"; + print "\nHow To:\n"; + print "=======\n"; + print "$0\tOSSEC report tool $VERSION\n"; + print " $0 is a GNU style program.\nIt reads from STDIN and write to stdout. "; + print "This gives you the advantage to use it in pipes.\n"; + print "i.e.\n"; + print " cat ossec-alerts-05.log | $0 -r | mail root -s 'OSSEC detailed report'\n"; + print " cat ossec-alerts-05.log | $0 -s | mail root -s 'OSSEC summary report'\n"; + print " cat ossec-alerts-05.log | $0 -t srcip | head -n 15 | mail root -s 'OSSEC top 15 offenders report'\n"; + print " Crontab entry:\n"; + print "58 23 * * * (cat ossec-alerts-05.log | $0 -s)\n"; + exit 0; +} + +sub report(){ + my ($statref)=@_; +my ($stat,$key,$value); +format TOPREPORT = +============================================================================= +| Summary report | +============================================================================= +|Alerthost | Stat | Key | Count | +============================================================================= +. +$~='TOPREPORT'; +write; +format REPORT = +|@<<<<<<<<<<|@<<<<<<<<<<<|@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<|@######| +$alerthost,$stat,$key,$value +. +$~='REPORT'; +foreach(sort keys %{$statref}){ + $alerthost=$_; + foreach(sort keys %{${$statref}{$alerthost}}){ + $stat=$_; + foreach(sort keys %{${$statref}{$alerthost}{$stat}}){ + $key=$_; + $value=${$statref}{$alerthost}{$stat}{$key}; + write; + } + } +} +} + +sub summary(){ +my ($statref)=@_; +my (%totals); +my ($stat,$key,$value); +foreach(sort keys %{$statref}){ + $alerthost=$_; + foreach(sort keys %{${$statref}{$alerthost}}){ + $stat=$_; + foreach(sort keys %{${$statref}{$alerthost}{$stat}}){ + $key=$_; + $value=${$statref}{$alerthost}{$stat}{$key}; + $totals{$stat}{$key}+=$value; + } + } +} +format TOPSUMREPORT = +================================================================= +| Statistic report | +================================================================= +|Stat | Key | Count | +================================================================= +. +$~='TOPSUMREPORT'; +write; +format SUMREPORT = +|@<<<<<<<<<<<|@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<|@######| +$stat,$key,$value +. +$~='SUMREPORT'; +foreach(sort keys %totals){ + $stat=$_; + foreach(sort keys %{$totals{$stat}}){ + $key=$_; + $value=$totals{$stat}{$key}; + write; + } +} +} + +sub top(){ +my ($statref,$stat)=@_; +my (%totals,%mytest); +my ($key,$value); +foreach(keys %{$statref}){ + $alerthost=$_; + foreach( keys %{${$statref}{$alerthost}{$stat}}){ + $key=$_; + $value=${$statref}{$alerthost}{$stat}{$key}; + $totals{$stat}{$key}+=$value; + } +} +foreach (keys %{$totals{$stat}}){ + $mytest{$totals{$stat}{$_}}=$_; +}; +foreach (sort {$b <=> $a} keys %mytest){ + print "$mytest{$_} => $_\n"; +} +} diff --git a/contrib/ossecmysql.pm b/contrib/ossecmysql.pm new file mode 100755 index 0000000..260c3e2 --- /dev/null +++ b/contrib/ossecmysql.pm @@ -0,0 +1,75 @@ +use DBI; +use strict; +package ossecmysql; + +sub new(){ + my $type = shift; + my %conf=@_; + my $self={}; + my $flag; + $self->{database}=$conf{database}; + $self->{dbhost}=$conf{dbhost}; + $self->{dbport}=$conf{dbport}; + $self->{dbuser}=$conf{dbuser}; + $self->{dbpasswd}=$conf{dbpasswd}; + + $self->{dsn} = "DBI:mysql:database=$self->{database};host=$self->{dbhost};port=$self->{dbport}"; + $self->{dbh} = DBI->connect($self->{dsn}, $self->{dbuser},$self->{dbpasswd}); + bless $self, $type; +} +sub fetchrecord(){ + my $self= shift ; + my ($rows)=@_; + my ($pointer,$numrows,$fields)=(${$rows}[0],${$rows}[1],${$rows}[2]); + my @result; + return if $pointer == $numrows; + for (my $i=0; $i < $fields; $i ++){ + my $field= @{$rows}[($pointer * $fields) + 3 + $i ]; + push (@result, $field); + } + ${$rows}[0] ++; + + return @result; +} +sub fetchrows(){ + my $self = shift ; + my ($query)=shift; + my @params= @_; + my @rows; + my $numFields; + my $numRows; + $numRows=$numFields=0; + $self->{sth}=$self->{dbh}->prepare($query); + $self->{sth}->execute(@params) ; + $numRows = $self->{sth}->rows; + my @row=(); + return @rows unless $numRows>0; + $numFields = $self->{sth}->{'NUM_OF_FIELDS'}; + push (@rows,0,$numRows,$numFields); + while(@row=$self->{sth}->fetchrow_array){ + push (@rows,@row); + } + + $self->{sth}->finish; + return @rows; + +} + +sub execute(){ + my $self = shift ; + my $flag; + my ($query)=shift; + my @params= @_; + my @rows= (); + my $numFields; + my $numRows; + $numRows=$numFields=0; + $self->{sth} = $self->{dbh}->prepare($query); + return $self->{sth}->execute(@params) ; +} + +sub lastid(){ + my $self = shift ; + return $self->{sth}->{mysql_insertid}; +} +1 diff --git a/contrib/ossectop.pl b/contrib/ossectop.pl new file mode 100755 index 0000000..995cfae --- /dev/null +++ b/contrib/ossectop.pl @@ -0,0 +1,244 @@ +#!/usr/bin/perl -w +#use strict; +use Socket; +use POSIX 'setsid'; +# --------------------------------------------------------------------------- +# Author: Meir Michanie (meirm@riunx.com) +# File: ossectop.pl +# Version 0.1 (09/2006) +# +# --------------------------------------------------------------------------- +# License +# --------------------------------------------------------------------------- +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# --------------------------------------------------------------------------- +# About OSSEC HIDS +# --------------------------------------------------------------------------- +# +# OSSEC HIDS is an Open Source Host-based Intrusion Detection System. +# It performs log analysis and correlation, integrity checking, +# rootkit detection, time-based alerting and active response. +# http://www.ossec.net +# +# --------------------------------------------------------------------------- + +# --------------------------------------------------------------------------- +# Parameters +# --------------------------------------------------------------------------- +$SIG{TERM} = sub { &gracefulend('TERM')}; +$SIG{INT} = sub { &gracefulend('INT')}; + +my %conf; +$conf{resolve}=1; + + +my($OCT) = '(?:25[012345]|2[0-4]\d|1?\d\d?)'; + +my($IP) = $OCT . '\.' . $OCT . '\.' . $OCT . '\.' . $OCT; + +my $VERSION="0.1"; +my $sig_class_id=1; +my $dump=0; +my ($hids_id,$hids,$hids_interface,$last_cid)=(undef, 'localhost', 'ossec',0); +my ($tempvar,$VERBOSE)=(0,0); +# --------------------------------------------------------------------------- +# Arguments parsing +# --------------------------------------------------------------------------- + +while (@ARGV){ + $_= shift @ARGV; + if ( m/^-h$|^--help$/){ + &help(); + }elsif ( m/^-n$|^--noname$/){ + $conf{'resolve'}=0; + } +} + + +my $newrecord=0; +my %stats; +my %resolv; +my ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); +my $lasttimestamp=0; +my $delta=0; +######################################################## +my $datepath=`date "+%Y/%b/ossec-alerts-%d.log"`; +my $LOG='/var/ossec/logs/alerts/'. $datepath; +chomp $LOG; +$date=''; +format TOPREPORT = + ========================================================================================================================== +| OSSEC-HIDS TOP | + ========================================================================================================================== +| Alert | Date | SRC | DST | LVL | Name | + ========================================================================================================================== +. +format REPORT = +|@<<<<< |@<<<<<<<<<<<<<<<<<<<<< |@<<<<<<<<<<<< |@<<<<<<<<<<<< |@<<< |@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | +$rule,$date,$srcip,$dstip,$level,$description +. +#$~='REPORT'; +#$~='TOPREPORT'; + +&taillog(); +############################################################### +sub taillog { + my($offset, $line, $stall) = ''; + + $offset = (-s $LOG); # Don't start at beginning, go to end + + my $count=10; + while (1==1) { + sleep(1); + %resolv=(); + $| = 1; + $stall += 1; + $datepath=`date "+%Y/%b/ossec-alerts-%d.log"`; + $LOG='/var/ossec/logs/alerts/'. $datepath; + chomp $LOG; + unless ( -f $LOG){print "Error -f $LOG\n"; next; } + if ((-s $LOG) < $offset) { + $offset = 0; + } + + unless (open(TAIL, $LOG)){ print "Error opening $LOG: $!\n";next ;} + + if (seek(TAIL, $offset, 0)) { + # found offset, log not rotated + } else { + # log reset, follow + $offset=0; + seek(TAIL, $offset, 0); + } + while () { + if (m/^$/){ + $newrecord=1; + next unless $timestamp; + $count++; + if ($count>10){ + system ("clear"); + $~='TOPREPORT'; + write; + $count=0; + } + + $alerthostip=$alerthost if $alerthost=~ m/^$IP$/; + if ($alerthostip){ + $dstip=$alerthostip; + $resolv{$alerthost}=$dstip; + }else{ + if (exists $resolv{$alerthost}){ + $dstip=$resolv{$alerthost}; + }else{ + if ($conf{'resolve'}){ + $dstip=`host $alerthost 2>/dev/null | grep 'has address' `; + if ($dstip =~m/(\d+\.\d+\.\d+\.\d+)/ ){ + $dstip=$1; + }else{ + $dstip=$srcip; + } + }else{ + $dstip=$alerthost; + } + $resolv{$alerthost}=$dstip; + + } + } + $~='REPORT'; + write; + ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); + next ; + } + if (m/^\*\* Alert ([0-9]+).([0-9]+):(.*)$/){ + $timestamp=$1; + if ( $timestamp == $lasttimestamp){ + $delta++; + }else{ + $delta=0; + $lasttimestamp=$timestamp; + } + $sec=$2; + $mail=$3; + $mail=$mail ? $mail : 'nomail'; +#2006 Aug 29 17:19:52 firewall -> /var/log/messages +#2006 Aug 30 11:52:14 192.168.0.45->/var/log/secure +# + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $datasource=$3; +#2006 Aug 29 17:33:31 (recepcao) 10.0.3.154 -> syscheck + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+\((.*?)\)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $alerthostip=$3; + $datasource=$4; + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)$/){ + $date=$1; + $alerthost='localhost'; + $datasource=$2; + }elsif ( m/Rule: ([0-9]+) \(level ([0-9]+)\) -> '(.*)'$/ ){ + $rule=$1; + $level=$2; + $description= $3; + }elsif ( m/Src IP:/){ + if ( m/($IP)/){ + $srcip=$1; + }else{ + $srcip='0.0.0.0'; + } + }elsif ( m/User: (.*)$/){ + $user=$1; + }elsif( m/(.*)$/){ + $text .=$1; + } + + + } # End while read line + $offset=tell(TAIL); + close(TAIL); + } +} + +sub version(){ + print "OSSEC report tool $VERSION\n"; + print "Licensed under GPL\n"; + print "Contributor Meir Michanie\n"; +} + +sub help(){ + &version(); + print "List alerts generated by ossec." + . " More info in the doc directory .\n"; + print "Usage:\n"; + print "$0 [-h|--help] # This text you read now\n"; + print "Options:\n"; + print "\t-n|--noname\n"; + + exit 0; +} + + +sub gracefulend(){ + my ($signal)=@_; + close TAIL; + close STDOUT; + close STDERR; + exit 0; +} diff --git a/contrib/specs/agent/ossec-hids-agent.spec b/contrib/specs/agent/ossec-hids-agent.spec new file mode 100644 index 0000000..c959b58 --- /dev/null +++ b/contrib/specs/agent/ossec-hids-agent.spec @@ -0,0 +1,220 @@ +# +# OSSEC 1.3 .spec file - AGENT +# Fri Aug 17 15:19:40 EDT 2007 +# +# +# TODO: +# +# o Safety checks for %clean +# +# o Remove script +# +# o create an RPM_README.txt and put it in the source tree +# +# + +Summary: Open Source Host-based Intrusion Detection System (Server) +Name: ossec-hids-agent-FC7 +Version: 1.3 +Release: 1 +License: GPLv3 +Group: Applications/Security +URL: http://www.ossec.net +Packager: Michael Williams (maverick@maverick.org) +Source: http://www.ossec.net/files/ossec-hids-1.3.tar.gz +Requires: /usr/sbin/useradd, /usr/sbin/groupadd, /usr/sbin/groupdel, /usr/sbin/userdel, /sbin/service, /sbin/chkconfig + +%description +OSSEC is an Open Source Host-based Intrusion +Detection System. It performs log analysis, +integrity checking, Windows registry monitoring, +rootkit detection, real-time alerting and active +response. + + +%prep + +%setup -n ossec-hids-1.3 + +%build +/bin/cp /usr/local/src/OSSEC-RPM/1.3/agent/preloaded-vars.conf ${RPM_BUILD_DIR}/ossec-hids-1.3/etc/ + +./install.sh + +%clean +rm -rf $RPM_BUILD_ROOT + +%pre +################################################################################ +# Create OSSEC group +# +if ! grep "^ossec" /etc/group > /dev/null ; then + /usr/sbin/groupadd ossec +fi + + +################################################################################ +# Create OSSEC users +# +for USER in ossec ; do + if ! grep "^${USER}" /etc/passwd > /dev/null ; then + /usr/sbin/useradd -d /var/ossec -s /bin/false -g ossec ${USER} + fi +done + +%post + + + +################################################################################ +# Create OSSEC /etc/init.d/ossec file +# +cat <> /etc/init.d/ossec +#!/bin/bash +# +# ossec Starts ossec +# +# +# chkconfig: 2345 12 88 +# description: OSSEC is an open source host based IDS +### BEGIN INIT INFO +# Provides: $ossec +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +[ -f /var/ossec/bin/ossec-control ] || exit 0 + +RETVAL=0 + +umask 077 + +case "\$1" in + start) + /var/ossec/bin/ossec-control start + ;; + stop) + /var/ossec/bin/ossec-control stop + ;; + status) + /var/ossec/bin/ossec-control status + ;; + restart|reload) + /var/ossec/bin/ossec-control restart + ;; + *) + echo "Usage: /var/ossec/bin/ossec-control {start|stop|status|restart}" + exit 1 +esac + +EOF + +/bin/chown root.root /etc/init.d/ossec +/bin/chmod 755 /etc/init.d/ossec + +################################################################################ +# Set configuration so OSSEC starts on reboot +# +/sbin/chkconfig --add ossec +/sbin/chkconfig ossec on + +%postun +# Run service command, make sure OSSEC is stopped +/sbin/service ossec stop + +# Run chkconfig, stop ossec from starting on boot +/sbin/chkconfig ossec off +/sbin/chkconfig --del ossec + +# Remove init.d file +[ -f /etc/init.d/ossec ] && rm /etc/init.d/ossec + +# Remove ossec users +for USER in ossec ossecm ossecr ; do + if grep "^${USER}" /etc/passwd > /dev/null ; then + /usr/sbin/userdel -r ${USER} + fi +done + +# Remove ossec group +if grep "^ossec" /etc/group > /dev/null ; then + /usr/sbin/groupdel ossec +fi + + +%files +%doc README BUGS CONFIG CONTRIB INSTALL LICENSE + +%dir /var/ossec/ +%attr(550, root, ossec) /var/ossec/ +%dir /var/ossec/var +%attr(550, root, ossec) /var/ossec/var +%dir /var/ossec/var/run +%attr(770, root, ossec) /var/ossec/var/run +%dir /var/ossec/active-response +%attr(550, root, ossec) /var/ossec/active-response +%dir /var/ossec/active-response/bin +%attr(550, root, ossec) /var/ossec/active-response/bin +/var/ossec/active-response/bin/route-null.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/route-null.sh +/var/ossec/active-response/bin/host-deny.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/host-deny.sh +/var/ossec/active-response/bin/firewall-drop.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/firewall-drop.sh +%dir /var/ossec/active-response/bin/firewalls +%attr(755, root, ossec) /var/ossec/active-response/bin/firewalls +/var/ossec/active-response/bin/firewalls/pf.sh +/var/ossec/active-response/bin/firewalls/ipfw.sh +/var/ossec/active-response/bin/firewalls/ipfw_mac.sh +/var/ossec/active-response/bin/disable-account.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/disable-account.sh +%dir /var/ossec/bin +%attr(550, root, ossec) /var/ossec/bin +/var/ossec/bin/ossec-agentd +%attr(550, root, ossec) /var/ossec/bin/ossec-agentd +/var/ossec/bin/ossec-logcollector +%attr(550, root, ossec) /var/ossec/bin/ossec-logcollector +/var/ossec/bin/ossec-control +%attr(550, root, ossec) /var/ossec/bin/ossec-control +/var/ossec/bin/ossec-syscheckd +%attr(550, root, ossec) /var/ossec/bin/ossec-syscheckd +/var/ossec/bin/manage_agents +%attr(550, root, ossec) /var/ossec/bin/manage_agents +/var/ossec/bin/ossec-execd +%attr(550, root, ossec) /var/ossec/bin/ossec-execd +%dir /var/ossec/etc +%attr(550, root, ossec) /var/ossec/etc +/var/ossec/etc/internal_options.conf +%attr(440, root, ossec) /var/ossec/etc/internal_options.conf +/var/ossec/etc/localtime +%attr(644, root, root) /var/ossec/etc/localtime +%dir /var/ossec/etc/shared +%attr(770, root, ossec) /var/ossec/etc/shared +/var/ossec/etc/shared/win_malware_rcl.txt +%attr(770, root, ossec) /var/ossec/etc/shared/win_malware_rcl.txt +/var/ossec/etc/shared/win_applications_rcl.txt +%attr(770, root, ossec) /var/ossec/etc/shared/win_applications_rcl.txt +/var/ossec/etc/shared/win_audit_rcl.txt +%attr(770, root, ossec) /var/ossec/etc/shared/win_audit_rcl.txt +/var/ossec/etc/shared/rootkit_files.txt +%attr(770, root, ossec) /var/ossec/etc/shared/rootkit_files.txt +/var/ossec/etc/shared/rootkit_trojans.txt +%attr(770, root, ossec) /var/ossec/etc/shared/rootkit_trojans.txt +/var/ossec/etc/ossec.conf +%attr(440, root, ossec) /var/ossec/etc/ossec.conf +%dir /var/ossec/logs +%attr(750, ossec, ossec) /var/ossec/logs +/var/ossec/logs/ossec.log +%attr(664, ossec, ossec) /var/ossec/logs/ossec.log +%dir /var/ossec/queue +%attr(550, root, ossec) /var/ossec/queue +%dir /var/ossec/queue/rids +%attr(775, root, ossec) /var/ossec/queue/rids +%dir /var/ossec/queue/alerts +%attr(550, root, ossec) /var/ossec/queue/alerts +%dir /var/ossec/queue/syscheck +%attr(550, root, ossec) /var/ossec/queue/syscheck +%dir /var/ossec/queue/ossec +%attr(770, ossec, ossec) /var/ossec/queue/ossec + diff --git a/contrib/specs/agent/preloaded-vars.conf b/contrib/specs/agent/preloaded-vars.conf new file mode 100755 index 0000000..dba7466 --- /dev/null +++ b/contrib/specs/agent/preloaded-vars.conf @@ -0,0 +1,121 @@ +# preloaded-vars.conf, Daniel B. Cid (dcid @ ossec.net). +# +# RPM: server/local/agent version, 1.2, 2007.07.23 +# +# +# Use this file to customize your installations. +# It will make the install.sh script pre-load some +# specific options to make it run automatically +# or with less questions. + +# PLEASE NOTE: +# When we use "n" or "y" in here, it should be changed +# to "n" or "y" in the language your are doing the +# installation. For example, in portuguese it would +# be "s" or "n". + + +# USER_LANGUAGE defines to language to be used. +# It can be "en", "br", "tr", "it", "de" or "pl". +# In case of an invalid language, it will default +# to English "en" +USER_LANGUAGE="en" # For english +#USER_LANGUAGE="br" # For portuguese + + +# If USER_NO_STOP is set to anything, the confirmation +# messages are not going to be asked. +USER_NO_STOP="y" + + +# USER_INSTALL_TYPE defines the installtion type to +# be used during install. It can only be "local", +# "agent" or "server". +#USER_INSTALL_TYPE="local" +USER_INSTALL_TYPE="agent" +#USER_INSTALL_TYPE="server" + + +# USER_DIR defines the location to install ossec +USER_DIR="/var/ossec" + + +# If USER_DELETE_DIR is set to "y", the directory +# to install OSSEC will be removed if present. +USER_DELETE_DIR="y" + + +# If USER_ENABLE_ACTIVE_RESPONSE is set to "n", +# active response will be disabled. +USER_ENABLE_ACTIVE_RESPONSE="n" + + +# If USER_ENABLE_SYSCHECK is set to "y", +# syscheck will be enabled. Set to "n" to +# disable it. +USER_ENABLE_SYSCHECK="y" + + +# If USER_ENABLE_ROOTCHECK is set to "y", +# rootcheck will be enabled. Set to "n" to +# disable it. +USER_ENABLE_ROOTCHECK="y" + + +# If USER_UPDATE is set to anything, the update +# installation will be done. +#USER_UPDATE="y" + +# If USER_UPDATE_RULES is set to anything, the +# rules will also be updated. +USER_UPDATE_RULES="y" + +# If USER_BINARYINSTALL is set, the installation +# is not going to compile the code, but use the +# binaries from ./bin/ +#USER_BINARYINSTALL="x" + + +### Agent Installation variables. ### + +# USER_AGENT_SERVER_IP specifies the IP address of the +# ossec server. Only used on agent installtions. +USER_AGENT_SERVER_IP="127.0.0.1" + + + +### Server/Local Installation variables. ### + +# USER_ENABLE_EMAIL enables or disables email alerting. +USER_ENABLE_EMAIL="n" + +# USER_EMAIL_ADDRESS defines the destination e-mail of the alerts. +#USER_EMAIL_ADDRESS="dcid@test.ossec.net" + +# USER_EMAIL_SMTP defines the SMTP server to send the e-mails. +#USER_EMAIL_SMTP="test.ossec.net" + + +# USER_ENABLE_SYSLOG enables or disables remote syslog. +USER_ENABLE_SYSLOG="n" + + +# USER_ENABLE_FIREWALL_RESPONSE enables or disables +# the firewall response. +USER_ENABLE_FIREWALL_RESPONSE="n" + + +# Enable PF firewall (OpenBSD and FreeBSD only) +USER_ENABLE_PF="n" + + +# PF table to use (OpenBSD and FreeBSD only). +#USER_PF_TABLE="ossec_fwtable" + + +# USER_WHITE_LIST is a list of IPs or networks +# that are going to be set to never be blocked. +#USER_WHITE_LIST="192.168.2.1 192.168.1.0/24" + + +#### exit ? ### diff --git a/contrib/specs/getattr.pl b/contrib/specs/getattr.pl new file mode 100755 index 0000000..3b05a89 --- /dev/null +++ b/contrib/specs/getattr.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl -w + +# +# find /var/ossec/ -exec ./getattr.pl {} \; +# + +use File::stat; + +my %UID; +my %GUID; + +$filename = shift || die "\nsyntax: $0 \n\n"; + +get_uid(); +get_gid(); + +$sb = stat($filename); + +die "\nUID $sb->uid doesn't exist?! ($filename)\n\n" if (! exists($UID[$sb->uid])); +die "\nGID $sb->uid doesn't exist?! ($filename)\n\n" if (! exists($GID[$sb->gid])); + +if ( -d $filename ) { ### directory + print '%dir ' . $filename . "\n"; +} elsif ( -f $filename ) { ### file + print $filename . "\n"; +} else { + die("\nI can't handle: $filename\n\n"); +} + +# %attr(550, root, ossec) /var/ossec/etc + +printf "%%attr(%03o, %s, %s) %s\n", + $sb->mode & 07777, + $UID[$sb->uid], $GID[$sb->gid], $filename; + +#printf "%s: perm %04o, owner: %s, group: %s \n", +# $filename, $sb->mode & 07777, +# $UID[$sb->uid], $GID[$sb->gid]; + +sub get_uid +{ + open(FP,') { + ($name,$id) = (split(/:/,$line,))[0,2]; + $UID[$id] = $name; + } + close(FP); +} + +sub get_gid +{ + open(FP,') { + ($name,$id) = (split(/:/,$line,))[0,2]; + $GID[$id] = $name; + } + close(FP); +} + diff --git a/contrib/specs/local/ossec-hids-local.spec b/contrib/specs/local/ossec-hids-local.spec new file mode 100644 index 0000000..63373c6 --- /dev/null +++ b/contrib/specs/local/ossec-hids-local.spec @@ -0,0 +1,331 @@ +# +# OSSEC 1.3 .spec file - LOCAL +# Fri Aug 17 15:13:04 EDT 2007 +# +# +# TODO: +# +# o Safety checks for %clean +# +# o Remove script +# +# o create an RPM_README.txt and put it in the source tree +# +# + +Summary: Open Source Host-based Intrusion Detection System (Server) +Name: ossec-hids-local-FC7 +Version: 1.3 +Release: 1 +License: GPLv3 +Group: Applications/Security +URL: http://www.ossec.net +Packager: Michael Williams (maverick@maverick.org) +Source: http://www.ossec.net/files/ossec-hids-1.3.tar.gz +Requires: /usr/sbin/useradd, /usr/sbin/groupadd, /usr/sbin/groupdel, /usr/sbin/userdel, /sbin/service, /sbin/chkconfig + +%description +OSSEC is an Open Source Host-based Intrusion +Detection System. It performs log analysis, +integrity checking, Windows registry monitoring, +rootkit detection, real-time alerting and active +response. + + +%prep + +%setup -n ossec-hids-1.3 + +%build +/bin/cp /usr/local/src/OSSEC-RPM/1.3/local/preloaded-vars.conf ${RPM_BUILD_DIR}/ossec-hids-1.3/etc/ + +./install.sh + +%clean +rm -rf $RPM_BUILD_ROOT + +%pre +################################################################################ +# Create OSSEC group +# +if ! grep "^ossec" /etc/group > /dev/null ; then + /usr/sbin/groupadd ossec +fi + + +################################################################################ +# Create OSSEC users +# +for USER in ossec ossecm ossecr ; do + if ! grep "^${USER}" /etc/passwd > /dev/null ; then + /usr/sbin/useradd -d /var/ossec -s /bin/false -g ossec ${USER} + fi +done + +%post + + + +################################################################################ +# Create OSSEC /etc/init.d/ossec file +# +cat <> /etc/init.d/ossec +#!/bin/bash +# +# ossec Starts ossec +# +# +# chkconfig: 2345 12 88 +# description: OSSEC is an open source host based IDS +### BEGIN INIT INFO +# Provides: $ossec +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +[ -f /var/ossec/bin/ossec-control ] || exit 0 + +RETVAL=0 + +umask 077 + +case "\$1" in + start) + /var/ossec/bin/ossec-control start + ;; + stop) + /var/ossec/bin/ossec-control stop + ;; + status) + /var/ossec/bin/ossec-control status + ;; + restart|reload) + /var/ossec/bin/ossec-control restart + ;; + *) + echo "Usage: /var/ossec/bin/ossec-control {start|stop|status|restart}" + exit 1 +esac + +EOF + +/bin/chown root.root /etc/init.d/ossec +/bin/chmod 755 /etc/init.d/ossec + +################################################################################ +# Set configuration so OSSEC starts on reboot +# +/sbin/chkconfig --add ossec +/sbin/chkconfig ossec on + +%postun +# Run service command, make sure OSSEC is stopped +/sbin/service ossec stop + +# Run chkconfig, stop ossec from starting on boot +/sbin/chkconfig ossec off +/sbin/chkconfig --del ossec + +# Remove init.d file +[ -f /etc/init.d/ossec ] && rm /etc/init.d/ossec + +# Remove ossec users +for USER in ossec ossecm ossecr ; do + if grep "^${USER}" /etc/passwd > /dev/null ; then + /usr/sbin/userdel -r ${USER} + fi +done + +# Remove ossec group +if grep "^ossec" /etc/group > /dev/null ; then + /usr/sbin/groupdel ossec +fi + + +%files +%doc README BUGS CONFIG CONTRIB INSTALL LICENSE + +%dir /var/ossec/ +%attr(550, root, ossec) /var/ossec/ +%dir /var/ossec/stats +%attr(750, ossec, ossec) /var/ossec/stats +%dir /var/ossec/var +%attr(550, root, ossec) /var/ossec/var +%dir /var/ossec/var/run +%attr(770, root, ossec) /var/ossec/var/run +%dir /var/ossec/active-response +%attr(550, root, ossec) /var/ossec/active-response +%dir /var/ossec/active-response/bin +%attr(550, root, ossec) /var/ossec/active-response/bin +/var/ossec/active-response/bin/route-null.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/route-null.sh +/var/ossec/active-response/bin/host-deny.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/host-deny.sh +/var/ossec/active-response/bin/firewall-drop.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/firewall-drop.sh +/var/ossec/active-response/bin/disable-account.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/disable-account.sh +%dir /var/ossec/tmp +%attr(550, root, ossec) /var/ossec/tmp +%dir /var/ossec/bin +%attr(550, root, ossec) /var/ossec/bin +/var/ossec/bin/ossec-agentd +%attr(550, root, ossec) /var/ossec/bin/ossec-agentd +/var/ossec/bin/ossec-logcollector +%attr(550, root, ossec) /var/ossec/bin/ossec-logcollector +/var/ossec/bin/ossec-control +%attr(550, root, ossec) /var/ossec/bin/ossec-control +/var/ossec/bin/ossec-syscheckd +%attr(550, root, ossec) /var/ossec/bin/ossec-syscheckd +/var/ossec/bin/manage_agents +%attr(550, root, ossec) /var/ossec/bin/manage_agents +/var/ossec/bin/ossec-remoted +%attr(550, root, ossec) /var/ossec/bin/ossec-remoted +/var/ossec/bin/ossec-monitord +%attr(550, root, ossec) /var/ossec/bin/ossec-monitord +/var/ossec/bin/list_agents +%attr(550, root, ossec) /var/ossec/bin/list_agents +/var/ossec/bin/clear_stats +%attr(550, root, ossec) /var/ossec/bin/clear_stats +/var/ossec/bin/ossec-execd +%attr(550, root, ossec) /var/ossec/bin/ossec-execd +/var/ossec/bin/ossec-maild +%attr(550, root, ossec) /var/ossec/bin/ossec-maild +/var/ossec/bin/ossec-analysisd +%attr(550, root, ossec) /var/ossec/bin/ossec-analysisd +/var/ossec/bin/syscheck_update +%attr(550, root, ossec) /var/ossec/bin/syscheck_update +%dir /var/ossec/etc +%attr(550, root, ossec) /var/ossec/etc +/var/ossec/etc/internal_options.conf +%attr(440, root, ossec) /var/ossec/etc/internal_options.conf +/var/ossec/etc/localtime +%attr(555, root, ossec) /var/ossec/etc/localtime +%dir /var/ossec/etc/shared +%attr(550, root, ossec) /var/ossec/etc/shared +/var/ossec/etc/shared/win_malware_rcl.txt +%attr(440, root, ossec) /var/ossec/etc/shared/win_malware_rcl.txt +/var/ossec/etc/shared/win_applications_rcl.txt +%attr(440, root, ossec) /var/ossec/etc/shared/win_applications_rcl.txt +/var/ossec/etc/shared/win_audit_rcl.txt +%attr(440, root, ossec) /var/ossec/etc/shared/win_audit_rcl.txt +/var/ossec/etc/shared/rootkit_files.txt +%attr(440, root, ossec) /var/ossec/etc/shared/rootkit_files.txt +/var/ossec/etc/shared/rootkit_trojans.txt +%attr(440, root, ossec) /var/ossec/etc/shared/rootkit_trojans.txt +/var/ossec/etc/ossec.conf +%attr(440, root, ossec) /var/ossec/etc/ossec.conf +/var/ossec/etc/decoder.xml +%attr(440, root, ossec) /var/ossec/etc/decoder.xml +%dir /var/ossec/rules +%attr(550, root, ossec) /var/ossec/rules +/var/ossec/rules/ms_ftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ms_ftpd_rules.xml +/var/ossec/rules/zeus_rules.xml +%attr(550, root, ossec) /var/ossec/rules/zeus_rules.xml +/var/ossec/rules/squid_rules.xml +%attr(550, root, ossec) /var/ossec/rules/squid_rules.xml +/var/ossec/rules/racoon_rules.xml +%attr(550, root, ossec) /var/ossec/rules/racoon_rules.xml +/var/ossec/rules/smbd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/smbd_rules.xml +/var/ossec/rules/proftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/proftpd_rules.xml +/var/ossec/rules/msauth_rules.xml +%attr(550, root, ossec) /var/ossec/rules/msauth_rules.xml +/var/ossec/rules/ms-exchange_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ms-exchange_rules.xml +/var/ossec/rules/symantec-ws_rules.xml +%attr(550, root, ossec) /var/ossec/rules/symantec-ws_rules.xml +/var/ossec/rules/sendmail_rules.xml +%attr(550, root, ossec) /var/ossec/rules/sendmail_rules.xml +/var/ossec/rules/web_rules.xml +%attr(550, root, ossec) /var/ossec/rules/web_rules.xml +/var/ossec/rules/netscreenfw_rules.xml +%attr(550, root, ossec) /var/ossec/rules/netscreenfw_rules.xml +/var/ossec/rules/attack_rules.xml +%attr(550, root, ossec) /var/ossec/rules/attack_rules.xml +/var/ossec/rules/hordeimp_rules.xml +%attr(550, root, ossec) /var/ossec/rules/hordeimp_rules.xml +/var/ossec/rules/postfix_rules.xml +%attr(550, root, ossec) /var/ossec/rules/postfix_rules.xml +/var/ossec/rules/rules_config.xml +%attr(550, root, ossec) /var/ossec/rules/rules_config.xml +/var/ossec/rules/spamd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/spamd_rules.xml +/var/ossec/rules/cisco-ios_rules.xml +%attr(550, root, ossec) /var/ossec/rules/cisco-ios_rules.xml +/var/ossec/rules/local_rules.xml +%attr(550, root, ossec) /var/ossec/rules/local_rules.xml +/var/ossec/rules/apache_rules.xml +%attr(550, root, ossec) /var/ossec/rules/apache_rules.xml +/var/ossec/rules/mailscanner_rules.xml +%attr(550, root, ossec) /var/ossec/rules/mailscanner_rules.xml +/var/ossec/rules/vpn_concentrator_rules.xml +%attr(550, root, ossec) /var/ossec/rules/vpn_concentrator_rules.xml +/var/ossec/rules/firewall_rules.xml +%attr(550, root, ossec) /var/ossec/rules/firewall_rules.xml +/var/ossec/rules/named_rules.xml +%attr(550, root, ossec) /var/ossec/rules/named_rules.xml +/var/ossec/rules/ossec_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ossec_rules.xml +/var/ossec/rules/courier_rules.xml +%attr(550, root, ossec) /var/ossec/rules/courier_rules.xml +/var/ossec/rules/vsftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/vsftpd_rules.xml +/var/ossec/rules/vpopmail_rules.xml +%attr(550, root, ossec) /var/ossec/rules/vpopmail_rules.xml +/var/ossec/rules/pure-ftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/pure-ftpd_rules.xml +/var/ossec/rules/telnetd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/telnetd_rules.xml +/var/ossec/rules/pix_rules.xml +%attr(550, root, ossec) /var/ossec/rules/pix_rules.xml +/var/ossec/rules/ftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ftpd_rules.xml +/var/ossec/rules/ids_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ids_rules.xml +/var/ossec/rules/symantec-av_rules.xml +%attr(550, root, ossec) /var/ossec/rules/symantec-av_rules.xml +/var/ossec/rules/arpwatch_rules.xml +%attr(550, root, ossec) /var/ossec/rules/arpwatch_rules.xml +/var/ossec/rules/policy_rules.xml +%attr(550, root, ossec) /var/ossec/rules/policy_rules.xml +/var/ossec/rules/sshd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/sshd_rules.xml +/var/ossec/rules/syslog_rules.xml +%attr(550, root, ossec) /var/ossec/rules/syslog_rules.xml +/var/ossec/rules/pam_rules.xml +%attr(550, root, ossec) /var/ossec/rules/pam_rules.xml +/var/ossec/rules/imapd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/imapd_rules.xml +%dir /var/ossec/logs +%attr(750, ossec, ossec) /var/ossec/logs +%dir /var/ossec/logs/alerts +%attr(750, ossec, ossec) /var/ossec/logs/alerts +%dir /var/ossec/logs/firewall +%attr(750, ossec, ossec) /var/ossec/logs/firewall +%dir /var/ossec/logs/archives +%attr(750, ossec, ossec) /var/ossec/logs/archives +/var/ossec/logs/ossec.log +%attr(664, ossec, ossec) /var/ossec/logs/ossec.log +%dir /var/ossec/queue +%attr(550, root, ossec) /var/ossec/queue +%dir /var/ossec/queue/fts +%attr(750, ossec, ossec) /var/ossec/queue/fts +%dir /var/ossec/queue/rids +%attr(755, ossecr, ossec) /var/ossec/queue/rids +%dir /var/ossec/queue/alerts +%attr(770, ossec, ossec) /var/ossec/queue/alerts +%dir /var/ossec/queue/rootcheck +%attr(750, ossec, ossec) /var/ossec/queue/rootcheck +%dir /var/ossec/queue/agent-info +%attr(755, ossecr, ossec) /var/ossec/queue/agent-info +%dir /var/ossec/queue/syscheck +%attr(750, ossec, ossec) /var/ossec/queue/syscheck +%dir /var/ossec/queue/ossec +%attr(770, ossec, ossec) /var/ossec/queue/ossec + + + diff --git a/contrib/specs/local/preloaded-vars.conf b/contrib/specs/local/preloaded-vars.conf new file mode 100755 index 0000000..1adaaa8 --- /dev/null +++ b/contrib/specs/local/preloaded-vars.conf @@ -0,0 +1,121 @@ +# preloaded-vars.conf, Daniel B. Cid (dcid @ ossec.net). +# +# RPM: server/local/agent version, 1.2, 2007.07.23 +# +# +# Use this file to customize your installations. +# It will make the install.sh script pre-load some +# specific options to make it run automatically +# or with less questions. + +# PLEASE NOTE: +# When we use "n" or "y" in here, it should be changed +# to "n" or "y" in the language your are doing the +# installation. For example, in portuguese it would +# be "s" or "n". + + +# USER_LANGUAGE defines to language to be used. +# It can be "en", "br", "tr", "it", "de" or "pl". +# In case of an invalid language, it will default +# to English "en" +USER_LANGUAGE="en" # For english +#USER_LANGUAGE="br" # For portuguese + + +# If USER_NO_STOP is set to anything, the confirmation +# messages are not going to be asked. +USER_NO_STOP="y" + + +# USER_INSTALL_TYPE defines the installtion type to +# be used during install. It can only be "local", +# "agent" or "server". +USER_INSTALL_TYPE="local" +#USER_INSTALL_TYPE="agent" +#USER_INSTALL_TYPE="server" + + +# USER_DIR defines the location to install ossec +USER_DIR="/var/ossec" + + +# If USER_DELETE_DIR is set to "y", the directory +# to install OSSEC will be removed if present. +USER_DELETE_DIR="y" + + +# If USER_ENABLE_ACTIVE_RESPONSE is set to "n", +# active response will be disabled. +USER_ENABLE_ACTIVE_RESPONSE="n" + + +# If USER_ENABLE_SYSCHECK is set to "y", +# syscheck will be enabled. Set to "n" to +# disable it. +USER_ENABLE_SYSCHECK="y" + + +# If USER_ENABLE_ROOTCHECK is set to "y", +# rootcheck will be enabled. Set to "n" to +# disable it. +USER_ENABLE_ROOTCHECK="y" + + +# If USER_UPDATE is set to anything, the update +# installation will be done. +#USER_UPDATE="y" + +# If USER_UPDATE_RULES is set to anything, the +# rules will also be updated. +USER_UPDATE_RULES="y" + +# If USER_BINARYINSTALL is set, the installation +# is not going to compile the code, but use the +# binaries from ./bin/ +#USER_BINARYINSTALL="x" + + +### Agent Installation variables. ### + +# USER_AGENT_SERVER_IP specifies the IP address of the +# ossec server. Only used on agent installtions. +#USER_AGENT_SERVER_IP="1.2.3.4" + + + +### Server/Local Installation variables. ### + +# USER_ENABLE_EMAIL enables or disables email alerting. +USER_ENABLE_EMAIL="n" + +# USER_EMAIL_ADDRESS defines the destination e-mail of the alerts. +#USER_EMAIL_ADDRESS="dcid@test.ossec.net" + +# USER_EMAIL_SMTP defines the SMTP server to send the e-mails. +#USER_EMAIL_SMTP="test.ossec.net" + + +# USER_ENABLE_SYSLOG enables or disables remote syslog. +USER_ENABLE_SYSLOG="n" + + +# USER_ENABLE_FIREWALL_RESPONSE enables or disables +# the firewall response. +USER_ENABLE_FIREWALL_RESPONSE="n" + + +# Enable PF firewall (OpenBSD and FreeBSD only) +USER_ENABLE_PF="n" + + +# PF table to use (OpenBSD and FreeBSD only). +#USER_PF_TABLE="ossec_fwtable" + + +# USER_WHITE_LIST is a list of IPs or networks +# that are going to be set to never be blocked. +#USER_WHITE_LIST="192.168.2.1 192.168.1.0/24" + + +#### exit ? ### diff --git a/contrib/specs/remove_ossec b/contrib/specs/remove_ossec new file mode 100755 index 0000000..980633c --- /dev/null +++ b/contrib/specs/remove_ossec @@ -0,0 +1,19 @@ +#!/bin/bash + +rpm -e ossec-hids-server-FC7 +rpm -e ossec-hids-local-FC7 +rpm -e ossec-hids-agent-FC7 + +rm -fr /var/ossec/ + +for A in ossec ossecm ossecr ; do /usr/sbin/userdel -r $A ; done + +/usr/sbin/groupdel ossec + +/sbin/chkconfig ossec off +/sbin/chkconfig --del ossec + +# Remove init.d file +[ -f /etc/init.d/ossec ] && rm /etc/init.d/ossec + + diff --git a/contrib/specs/server/ossec-hids-server.spec b/contrib/specs/server/ossec-hids-server.spec new file mode 100644 index 0000000..9fa7170 --- /dev/null +++ b/contrib/specs/server/ossec-hids-server.spec @@ -0,0 +1,329 @@ +# +# OSSEC 1.3 .spec file - SERVER +# Fri Aug 17 15:13:32 EDT 2007 +# +# +# TODO: +# +# o Safety checks for %clean +# +# o Remove script +# +# o create an RPM_README.txt and put it in the source tree +# +# + +Summary: Open Source Host-based Intrusion Detection System (Server) +Name: ossec-hids-server-FC7 +Version: 1.3 +Release: 1 +License: GPLv3 +Group: Applications/Security +URL: http://www.ossec.net +Packager: Michael Williams (maverick@maverick.org) +Source: http://www.ossec.net/files/ossec-hids-1.3.tar.gz +Requires: /usr/sbin/useradd, /usr/sbin/groupadd, /usr/sbin/groupdel, /usr/sbin/userdel, /sbin/service, /sbin/chkconfig + +%description +OSSEC is an Open Source Host-based Intrusion +Detection System. It performs log analysis, +integrity checking, Windows registry monitoring, +rootkit detection, real-time alerting and active +response. + + +%prep + +%setup -n ossec-hids-1.3 + +%build +/bin/cp /usr/local/src/OSSEC-RPM/1.3/server/preloaded-vars.conf ${RPM_BUILD_DIR}/ossec-hids-1.3/etc/ + +./install.sh + +%clean +rm -rf $RPM_BUILD_ROOT + +%pre +################################################################################ +# Create OSSEC group +# +if ! grep "^ossec" /etc/group > /dev/null ; then + /usr/sbin/groupadd ossec +fi + + +################################################################################ +# Create OSSEC users +# +for USER in ossec ossecm ossecr ; do + if ! grep "^${USER}" /etc/passwd > /dev/null ; then + /usr/sbin/useradd -d /var/ossec -s /bin/false -g ossec ${USER} + fi +done + +%post + + + +################################################################################ +# Create OSSEC /etc/init.d/ossec file +# +cat <> /etc/init.d/ossec +#!/bin/bash +# +# ossec Starts ossec +# +# +# chkconfig: 2345 12 88 +# description: OSSEC is an open source host based IDS +### BEGIN INIT INFO +# Provides: $ossec +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +[ -f /var/ossec/bin/ossec-control ] || exit 0 + +RETVAL=0 + +umask 077 + +case "\$1" in + start) + /var/ossec/bin/ossec-control start + ;; + stop) + /var/ossec/bin/ossec-control stop + ;; + status) + /var/ossec/bin/ossec-control status + ;; + restart|reload) + /var/ossec/bin/ossec-control restart + ;; + *) + echo "Usage: /var/ossec/bin/ossec-control {start|stop|status|restart}" + exit 1 +esac + +EOF + +/bin/chown root.root /etc/init.d/ossec +/bin/chmod 755 /etc/init.d/ossec + +################################################################################ +# Set configuration so OSSEC starts on reboot +# +/sbin/chkconfig --add ossec +/sbin/chkconfig ossec on + +%postun +# Run service command, make sure OSSEC is stopped +/sbin/service ossec stop + +# Run chkconfig, stop ossec from starting on boot +/sbin/chkconfig ossec off +/sbin/chkconfig --del ossec + +# Remove init.d file +[ -f /etc/init.d/ossec ] && rm /etc/init.d/ossec + +# Remove ossec users +for USER in ossec ossecm ossecr ; do + if grep "^${USER}" /etc/passwd > /dev/null ; then + /usr/sbin/userdel -r ${USER} + fi +done + +# Remove ossec group +if grep "^ossec" /etc/group > /dev/null ; then + /usr/sbin/groupdel ossec +fi + + +%files +%doc README BUGS CONFIG CONTRIB INSTALL LICENSE + +%dir /var/ossec/ +%attr(550, root, ossec) /var/ossec/ +%dir /var/ossec/stats +%attr(750, ossec, ossec) /var/ossec/stats +%dir /var/ossec/var +%attr(550, root, ossec) /var/ossec/var +%dir /var/ossec/var/run +%attr(770, root, ossec) /var/ossec/var/run +%dir /var/ossec/active-response +%attr(550, root, ossec) /var/ossec/active-response +%dir /var/ossec/active-response/bin +%attr(550, root, ossec) /var/ossec/active-response/bin +/var/ossec/active-response/bin/route-null.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/route-null.sh +/var/ossec/active-response/bin/host-deny.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/host-deny.sh +/var/ossec/active-response/bin/firewall-drop.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/firewall-drop.sh +/var/ossec/active-response/bin/disable-account.sh +%attr(755, root, ossec) /var/ossec/active-response/bin/disable-account.sh +%dir /var/ossec/tmp +%attr(550, root, ossec) /var/ossec/tmp +%dir /var/ossec/bin +%attr(550, root, ossec) /var/ossec/bin +/var/ossec/bin/ossec-agentd +%attr(550, root, ossec) /var/ossec/bin/ossec-agentd +/var/ossec/bin/ossec-logcollector +%attr(550, root, ossec) /var/ossec/bin/ossec-logcollector +/var/ossec/bin/ossec-control +%attr(550, root, ossec) /var/ossec/bin/ossec-control +/var/ossec/bin/ossec-syscheckd +%attr(550, root, ossec) /var/ossec/bin/ossec-syscheckd +/var/ossec/bin/manage_agents +%attr(550, root, ossec) /var/ossec/bin/manage_agents +/var/ossec/bin/ossec-remoted +%attr(550, root, ossec) /var/ossec/bin/ossec-remoted +/var/ossec/bin/ossec-monitord +%attr(550, root, ossec) /var/ossec/bin/ossec-monitord +/var/ossec/bin/list_agents +%attr(550, root, ossec) /var/ossec/bin/list_agents +/var/ossec/bin/clear_stats +%attr(550, root, ossec) /var/ossec/bin/clear_stats +/var/ossec/bin/ossec-execd +%attr(550, root, ossec) /var/ossec/bin/ossec-execd +/var/ossec/bin/ossec-maild +%attr(550, root, ossec) /var/ossec/bin/ossec-maild +/var/ossec/bin/ossec-analysisd +%attr(550, root, ossec) /var/ossec/bin/ossec-analysisd +/var/ossec/bin/syscheck_update +%attr(550, root, ossec) /var/ossec/bin/syscheck_update +%dir /var/ossec/etc +%attr(550, root, ossec) /var/ossec/etc +/var/ossec/etc/internal_options.conf +%attr(440, root, ossec) /var/ossec/etc/internal_options.conf +/var/ossec/etc/localtime +%attr(555, root, ossec) /var/ossec/etc/localtime +%dir /var/ossec/etc/shared +%attr(550, root, ossec) /var/ossec/etc/shared +/var/ossec/etc/shared/win_malware_rcl.txt +%attr(440, root, ossec) /var/ossec/etc/shared/win_malware_rcl.txt +/var/ossec/etc/shared/win_applications_rcl.txt +%attr(440, root, ossec) /var/ossec/etc/shared/win_applications_rcl.txt +/var/ossec/etc/shared/win_audit_rcl.txt +%attr(440, root, ossec) /var/ossec/etc/shared/win_audit_rcl.txt +/var/ossec/etc/shared/rootkit_files.txt +%attr(440, root, ossec) /var/ossec/etc/shared/rootkit_files.txt +/var/ossec/etc/shared/rootkit_trojans.txt +%attr(440, root, ossec) /var/ossec/etc/shared/rootkit_trojans.txt +/var/ossec/etc/ossec.conf +%attr(440, root, ossec) /var/ossec/etc/ossec.conf +/var/ossec/etc/decoder.xml +%attr(440, root, ossec) /var/ossec/etc/decoder.xml +%dir /var/ossec/rules +%attr(550, root, ossec) /var/ossec/rules +/var/ossec/rules/ms_ftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ms_ftpd_rules.xml +/var/ossec/rules/zeus_rules.xml +%attr(550, root, ossec) /var/ossec/rules/zeus_rules.xml +/var/ossec/rules/squid_rules.xml +%attr(550, root, ossec) /var/ossec/rules/squid_rules.xml +/var/ossec/rules/racoon_rules.xml +%attr(550, root, ossec) /var/ossec/rules/racoon_rules.xml +/var/ossec/rules/smbd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/smbd_rules.xml +/var/ossec/rules/proftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/proftpd_rules.xml +/var/ossec/rules/msauth_rules.xml +%attr(550, root, ossec) /var/ossec/rules/msauth_rules.xml +/var/ossec/rules/ms-exchange_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ms-exchange_rules.xml +/var/ossec/rules/symantec-ws_rules.xml +%attr(550, root, ossec) /var/ossec/rules/symantec-ws_rules.xml +/var/ossec/rules/sendmail_rules.xml +%attr(550, root, ossec) /var/ossec/rules/sendmail_rules.xml +/var/ossec/rules/web_rules.xml +%attr(550, root, ossec) /var/ossec/rules/web_rules.xml +/var/ossec/rules/netscreenfw_rules.xml +%attr(550, root, ossec) /var/ossec/rules/netscreenfw_rules.xml +/var/ossec/rules/attack_rules.xml +%attr(550, root, ossec) /var/ossec/rules/attack_rules.xml +/var/ossec/rules/hordeimp_rules.xml +%attr(550, root, ossec) /var/ossec/rules/hordeimp_rules.xml +/var/ossec/rules/postfix_rules.xml +%attr(550, root, ossec) /var/ossec/rules/postfix_rules.xml +/var/ossec/rules/rules_config.xml +%attr(550, root, ossec) /var/ossec/rules/rules_config.xml +/var/ossec/rules/spamd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/spamd_rules.xml +/var/ossec/rules/cisco-ios_rules.xml +%attr(550, root, ossec) /var/ossec/rules/cisco-ios_rules.xml +/var/ossec/rules/local_rules.xml +%attr(550, root, ossec) /var/ossec/rules/local_rules.xml +/var/ossec/rules/apache_rules.xml +%attr(550, root, ossec) /var/ossec/rules/apache_rules.xml +/var/ossec/rules/mailscanner_rules.xml +%attr(550, root, ossec) /var/ossec/rules/mailscanner_rules.xml +/var/ossec/rules/vpn_concentrator_rules.xml +%attr(550, root, ossec) /var/ossec/rules/vpn_concentrator_rules.xml +/var/ossec/rules/firewall_rules.xml +%attr(550, root, ossec) /var/ossec/rules/firewall_rules.xml +/var/ossec/rules/named_rules.xml +%attr(550, root, ossec) /var/ossec/rules/named_rules.xml +/var/ossec/rules/ossec_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ossec_rules.xml +/var/ossec/rules/courier_rules.xml +%attr(550, root, ossec) /var/ossec/rules/courier_rules.xml +/var/ossec/rules/vsftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/vsftpd_rules.xml +/var/ossec/rules/vpopmail_rules.xml +%attr(550, root, ossec) /var/ossec/rules/vpopmail_rules.xml +/var/ossec/rules/pure-ftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/pure-ftpd_rules.xml +/var/ossec/rules/telnetd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/telnetd_rules.xml +/var/ossec/rules/pix_rules.xml +%attr(550, root, ossec) /var/ossec/rules/pix_rules.xml +/var/ossec/rules/ftpd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ftpd_rules.xml +/var/ossec/rules/ids_rules.xml +%attr(550, root, ossec) /var/ossec/rules/ids_rules.xml +/var/ossec/rules/symantec-av_rules.xml +%attr(550, root, ossec) /var/ossec/rules/symantec-av_rules.xml +/var/ossec/rules/arpwatch_rules.xml +%attr(550, root, ossec) /var/ossec/rules/arpwatch_rules.xml +/var/ossec/rules/policy_rules.xml +%attr(550, root, ossec) /var/ossec/rules/policy_rules.xml +/var/ossec/rules/sshd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/sshd_rules.xml +/var/ossec/rules/syslog_rules.xml +%attr(550, root, ossec) /var/ossec/rules/syslog_rules.xml +/var/ossec/rules/pam_rules.xml +%attr(550, root, ossec) /var/ossec/rules/pam_rules.xml +/var/ossec/rules/imapd_rules.xml +%attr(550, root, ossec) /var/ossec/rules/imapd_rules.xml +%dir /var/ossec/logs +%attr(750, ossec, ossec) /var/ossec/logs +%dir /var/ossec/logs/alerts +%attr(750, ossec, ossec) /var/ossec/logs/alerts +%dir /var/ossec/logs/firewall +%attr(750, ossec, ossec) /var/ossec/logs/firewall +%dir /var/ossec/logs/archives +%attr(750, ossec, ossec) /var/ossec/logs/archives +/var/ossec/logs/ossec.log +%attr(664, ossec, ossec) /var/ossec/logs/ossec.log +%dir /var/ossec/queue +%attr(550, root, ossec) /var/ossec/queue +%dir /var/ossec/queue/fts +%attr(750, ossec, ossec) /var/ossec/queue/fts +%dir /var/ossec/queue/rids +%attr(755, ossecr, ossec) /var/ossec/queue/rids +%dir /var/ossec/queue/alerts +%attr(770, ossec, ossec) /var/ossec/queue/alerts +%dir /var/ossec/queue/rootcheck +%attr(750, ossec, ossec) /var/ossec/queue/rootcheck +%dir /var/ossec/queue/agent-info +%attr(755, ossecr, ossec) /var/ossec/queue/agent-info +%dir /var/ossec/queue/syscheck +%attr(750, ossec, ossec) /var/ossec/queue/syscheck +%dir /var/ossec/queue/ossec +%attr(770, ossec, ossec) /var/ossec/queue/ossec + diff --git a/contrib/specs/server/preloaded-vars.conf b/contrib/specs/server/preloaded-vars.conf new file mode 100755 index 0000000..c5d02be --- /dev/null +++ b/contrib/specs/server/preloaded-vars.conf @@ -0,0 +1,121 @@ +# preloaded-vars.conf, Daniel B. Cid (dcid @ ossec.net). +# +# RPM: server/local/agent version, 1.2, 2007.07.23 +# +# +# Use this file to customize your installations. +# It will make the install.sh script pre-load some +# specific options to make it run automatically +# or with less questions. + +# PLEASE NOTE: +# When we use "n" or "y" in here, it should be changed +# to "n" or "y" in the language your are doing the +# installation. For example, in portuguese it would +# be "s" or "n". + + +# USER_LANGUAGE defines to language to be used. +# It can be "en", "br", "tr", "it", "de" or "pl". +# In case of an invalid language, it will default +# to English "en" +USER_LANGUAGE="en" # For english +#USER_LANGUAGE="br" # For portuguese + + +# If USER_NO_STOP is set to anything, the confirmation +# messages are not going to be asked. +USER_NO_STOP="y" + + +# USER_INSTALL_TYPE defines the installtion type to +# be used during install. It can only be "local", +# "agent" or "server". +#USER_INSTALL_TYPE="local" +#USER_INSTALL_TYPE="agent" +USER_INSTALL_TYPE="server" + + +# USER_DIR defines the location to install ossec +USER_DIR="/var/ossec" + + +# If USER_DELETE_DIR is set to "y", the directory +# to install OSSEC will be removed if present. +USER_DELETE_DIR="y" + + +# If USER_ENABLE_ACTIVE_RESPONSE is set to "n", +# active response will be disabled. +USER_ENABLE_ACTIVE_RESPONSE="n" + + +# If USER_ENABLE_SYSCHECK is set to "y", +# syscheck will be enabled. Set to "n" to +# disable it. +USER_ENABLE_SYSCHECK="y" + + +# If USER_ENABLE_ROOTCHECK is set to "y", +# rootcheck will be enabled. Set to "n" to +# disable it. +USER_ENABLE_ROOTCHECK="y" + + +# If USER_UPDATE is set to anything, the update +# installation will be done. +#USER_UPDATE="y" + +# If USER_UPDATE_RULES is set to anything, the +# rules will also be updated. +USER_UPDATE_RULES="y" + +# If USER_BINARYINSTALL is set, the installation +# is not going to compile the code, but use the +# binaries from ./bin/ +#USER_BINARYINSTALL="x" + + +### Agent Installation variables. ### + +# USER_AGENT_SERVER_IP specifies the IP address of the +# ossec server. Only used on agent installtions. +#USER_AGENT_SERVER_IP="1.2.3.4" + + + +### Server/Local Installation variables. ### + +# USER_ENABLE_EMAIL enables or disables email alerting. +USER_ENABLE_EMAIL="n" + +# USER_EMAIL_ADDRESS defines the destination e-mail of the alerts. +#USER_EMAIL_ADDRESS="dcid@test.ossec.net" + +# USER_EMAIL_SMTP defines the SMTP server to send the e-mails. +#USER_EMAIL_SMTP="test.ossec.net" + + +# USER_ENABLE_SYSLOG enables or disables remote syslog. +USER_ENABLE_SYSLOG="n" + + +# USER_ENABLE_FIREWALL_RESPONSE enables or disables +# the firewall response. +USER_ENABLE_FIREWALL_RESPONSE="y" + + +# Enable PF firewall (OpenBSD and FreeBSD only) +USER_ENABLE_PF="n" + + +# PF table to use (OpenBSD and FreeBSD only). +#USER_PF_TABLE="ossec_fwtable" + + +# USER_WHITE_LIST is a list of IPs or networks +# that are going to be set to never be blocked. +#USER_WHITE_LIST="192.168.2.1 192.168.1.0/24" + + +#### exit ? ### diff --git a/doc/README.config b/doc/README.config new file mode 100755 index 0000000..c460150 --- /dev/null +++ b/doc/README.config @@ -0,0 +1,3 @@ +Configuration options: + +http://www.ossec.net/en/manual.html diff --git a/doc/active-response-internal.txt b/doc/active-response-internal.txt new file mode 100755 index 0000000..5cefb23 --- /dev/null +++ b/doc/active-response-internal.txt @@ -0,0 +1,29 @@ +OSSEC HIDS 0.6 +Copyright (c) 2004-2006 Daniel B. Cid + + + +How the active response works internally: + +- Read active-respose-doc.txt for details on configuration + + +1 - The analysis server receives an event that matches the + active response policy. + +2 - The analysis server verifies that all required fields + are provided with the event. It means that the analysis + server was able to decode the event and extract the + necessary information. One example is if it was able + to extract the IP address from the event to send to + the firewall to be blocked. + +3 - If the active response policy specify that the action + must be executed locally on the AS, a message is sent + to the execd directly. + +4 - If the active response policy specify that the action + must be executed remotelly, a message is sent to the + "Active response forwarder" (remoted) to forward the + event to the specified agent. + diff --git a/doc/active-response.txt b/doc/active-response.txt new file mode 100755 index 0000000..154d928 --- /dev/null +++ b/doc/active-response.txt @@ -0,0 +1,6 @@ +OSSEC HIDS v0.7 +Copyright (c) 2004-2006 Daniel B. Cid + + + +http://www.ossec.net/en/manual.html#active-response diff --git a/doc/br/INSTALL.br b/doc/br/INSTALL.br new file mode 100755 index 0000000..ba888b5 --- /dev/null +++ b/doc/br/INSTALL.br @@ -0,0 +1,65 @@ +OSSEC HIDS 0.7 +Copyright (c) 2004-2006 Daniel B. Cid + + + +** Traduzido por Willian Itiho Amano + + += Informações dobre o OSSEC HIDS = + +Visite http://www.ossec.net + + += Instalação recomendada = + +A instalação do OSSEC HIDS é muito simples. Você pode executa-la pela +maneira rápida (usando o script 'install.sh' com os valores padroes) +ou customizada (mudando na mão os valores do script install.sh). +Eu REALMENTE recomento SEMPRE o uso da maneira rápida. + +**Apenas desenvolvedores ou pessoas experientes devem usar outro método. + +Passos do processo rápido: + +1- Rode o script ./install.sh. Ele irá guia-lo pelo processo de instalação. + +2- O script criará tudo em /var/ossec e tentará criar um script de + inicialização em seu sistema (/etc/rc.local ou /etc/rc.d/init.d/ossec). + Se o script de inicialização não for criado, siga as instruções do + para iniciar o OSSEC HIDS durante o boot. Para iniciar na mão, digite + /var/ossec/bin/ossec-control start + +3- Se você for rodar em vários clientes, Instale o servidor primeiro. + Use o manage_agents para criar as chaves de encriptação. + +4- Aproveite. + + += Instalação e execução (99,99% da vezes, leia acima) = + + +Passos para instalação na mão: + +1- Crie os diretórios necessários (por default /var/ossec). +2- Mova os arquivos necessários para o diretório ossec. +3- Compile tudo. +4- Mova os binários para o diretório default. +5- Crie os usuários necessários. +6- Sete todas as permições dos arquivos. + + +As 5 etapas do Makefile (veja como criar o servidor). + +O Makefile lê as opções do arquivo LOCATION. Mude +o que necessitar de lá. + +Para compilar tudo use: + + % make clean + % make all (step 3) + % su + # make server (will do steps 1,2,4 and 6 above) + +*Antes de rodas make server, make sure Deverá ter os usuários criados. +O Makefile não fará isso. diff --git a/doc/br/README.config b/doc/br/README.config new file mode 100755 index 0000000..ce7e8fb --- /dev/null +++ b/doc/br/README.config @@ -0,0 +1,3 @@ +Opções de configuração: + +http://www.ossec.net/en/manual.html diff --git a/doc/br/TRANSLATION b/doc/br/TRANSLATION new file mode 100755 index 0000000..e682ee5 --- /dev/null +++ b/doc/br/TRANSLATION @@ -0,0 +1,2 @@ +** Traduzido por Willian Itiho Amano +** Translated by Willian Itiho Amano diff --git a/doc/br/active-response-internal.txt b/doc/br/active-response-internal.txt new file mode 100755 index 0000000..979461e --- /dev/null +++ b/doc/br/active-response-internal.txt @@ -0,0 +1,28 @@ +OSSEC HIDS 0.6 +Copyright (c) 2004-2006 Daniel B. Cid + + + +Como a resposta ativa trabalha internamente: + +- Leia o arquivo active-respose-doc.txt para maiores detalhes + de configuração + + +1 - O servidor de análize recebe um evento que acione a + política de resposta ativa. + +2 - O servidor de análize verifica todos os campos requeridos + fornecidos pelo evento. Isto significa que o servidor + de análise decodificará o evento e irá extrair as informações + necessárias. Um exemplo disto é que pode-se extrair o número + de IP de um evento e enviálo para o firewall bloquear. + +3 - Se a política de resposta ativa especificar esta ação, e esta + dever ser executada localmente no AS, uma mensagem deve ser + enviada diretamente. + +4 - Se a política de resposta ativa especificar uma ação, + e esta deve ser executada remotamente, uma mensagem é enviada para + o servidor (remoted) para enviar o evento ao cliente especificado. + diff --git a/doc/br/active-response.txt b/doc/br/active-response.txt new file mode 100755 index 0000000..154d928 --- /dev/null +++ b/doc/br/active-response.txt @@ -0,0 +1,6 @@ +OSSEC HIDS v0.7 +Copyright (c) 2004-2006 Daniel B. Cid + + + +http://www.ossec.net/en/manual.html#active-response diff --git a/doc/br/logs.txt b/doc/br/logs.txt new file mode 100755 index 0000000..d8131e2 --- /dev/null +++ b/doc/br/logs.txt @@ -0,0 +1,51 @@ +OSSEC HIDS 0.5 +Copyright (c) 2004,2005 Daniel B. Cid + + + + +OSSEC Hids Logging + +== Introdução == + +O sistema suporta dois tipos de logs. Logs de alertas e eventos +ou arquivos de logs. + +Todas as mensagens recebidas são tratadas como um envento. Todas as +mensagens de log, avisos de integridade, informações de sistema são +tratadas como tal. Fazer log de é muito pesado para o sistema pois +o sistema tem de arquivar cada evendo. Entretanto, é muito bom para +se ter uma visão geral de tentativas de ataque. + +Criar logs de alertas é muito importante. Pode ser gerado quando um evento +vai de encontro com uma regra de detecção. Adicionalmente o OSSEC hids +suporta envio de em-ails e execução de comandos esternos como método de alerta. + +== Criando logs de eventos == + +O diretório de logs do OSSEC (by default /var/ossec/logs) +possúi entrada para arquivos (/var/ossec/logs/archives). Dentro deste diretório, +todos os enventos são classificados por data. +Por exemplo, todos os eventos recebidos em 22 de maio de 2004, serão guardados em: + +/var/ossec/logs/archives/2004/May/events-22.log + +Após cada dia, uma combinação será criada para cada dia específico. + +/var/ossec/logs/archives/2004/May/events-22.log.md5 + +Este será uma combinação do arquivo do dia 22 com o do dia 21. + +A combinação do dia 1, será feita com o dia 31(ou 30 ou 28) do mes anterior. + +Isto assegurará que o log não seja modificado. Para que isto aconteça, +todos os logs (desde o primeiro dia) deverão ser modificados. + + +== Criando logs de alerta == + +Haverá um diretório de alerta dentro do diretório default do OSSEC. +Este será organizado da mesma forma que os logs de envetos. Por facor leia +a explicação acima. + + diff --git a/doc/br/manager.txt b/doc/br/manager.txt new file mode 100755 index 0000000..d43427c --- /dev/null +++ b/doc/br/manager.txt @@ -0,0 +1,20 @@ +OSSEC HIDS 0.5 +Copyright (c) 2004,2005 Daniel B. Cid + + + + +Como usar o gerenciamento de clientes do servidor. + +-A máquina cliente deve abrir a porta 1514 (por default) para enviará + mensagens para o server. Somente o IP do servidor será liberado. + +-A cada 10 minutos, o cliente envia uma notificação com o status para + o servidor. Esta mensagem de status contem informações sobre o + sistema do cliente e sobre os arquivos do diretório compartilhado. + +-O servidor recebe a mensagem de status, atualiza o arquivo de status + do cliente e checa se há algum arquivo para ser enviado para o cliente. + Se ouver, este conectará com o cliente e enviará o arquivo. + +-Todas as mensagens são criptografadas. \ No newline at end of file diff --git a/doc/br/rootcheck.txt b/doc/br/rootcheck.txt new file mode 100755 index 0000000..1e917b5 --- /dev/null +++ b/doc/br/rootcheck.txt @@ -0,0 +1,64 @@ +Técnicas de detecção de Rootkit usadas pelo OSSEC HIDS +por Daniel B. Cid, daniel.cid@gmail.com + + +Començando na versão 0.4, o OSSEC HIDS executará a detecção +de rootkit em todos os sistemas que o cliente estiver instalado. +O rootcheck (Sistema de detecção de rootkit) será executado +a cada X minutos (Especificado pelo usuário --por default +a cada 2 horas) para detectar possiveis rootkits instalados. +Em conjunto com a análize de logs e o sistema de checagem de integridade, +ele torna-se uma solução poderosa de monitoramento (o OSSEC HIDS executa +a análize de logs e verificação de integridade desde a versão 0.1). + +Outra característica incluída na versão 0.4 é que o servidor de análize +enviará automaticamente as assinaturas de detecção de rootkit aos +clientes, reduzindo o trabalho com administração para o administrador +de sistemas. Os clientes e servidor manterão contato a cada 10 minutos +e se o servidor for atualizado com um novo arquivo de assinatura, ele enviará +para todos os clientes configurados. De uma olhada na documentação para maiores +informações. + +O rootcheck executará as seguintes etapas para verificar a presença de +rootkits: + + +1- Lerá o arquivo rootkit_files.txt que contem um grande banco de dados + de rootkits e arquivos usados pelo mesmo. Tentará usar as funções + fopen e opendir no arquivo especificado. Nós usamos todas a chamadas do + sistema,por causa de que rootkits que rodam a nivel de kernel, escondem as + chamadas dos sistema. Nós tentamos melhoras as coutras chamadas do sistema, + para uma melhor detecção. Este método é mais parecido com uma regra de + antí-virus, que necessita ser atualizado contantemente. As chances de + falso-positivos são pequenas, mas falso-negativos podem ser produzidos + modificando os rootkits. + +2- Lerá o arquivo rootkit_trojans.txt que contem um banco de dados de + assinaturas de arquivos infectados por rootkits. Esta técnica verifica + binários modificados por trojans conhecidos. Este método de detecção + não encontra nenhum rootkit a nivel de kernel ou nenhum rootkit desconhecido. + +3- Escaneia o diretório /dev procurando por anomalias. O /dev contém todos os + arquivos de device e scripts de Makedev. Vários rootkits usam arquivos + escondidoso no /dev. Esta técnica pode detectar rootkits desconhecidos. + +4- Escaneia o sistema de arquivos a procura por arquivos incomuns e problema de + permição. Arquivos setados para root, com permição de escrita para outros + são muito perigosos e a detecção de rootkit olha isso. Arquivos com Suid, + diretórios e arquivos escondidos são inspecionados. + +5- Procura pela presença de processos ocultos. Nós usamos as funções getsid e + kill para checar se algum PID está sendo usado ou não. Se estiver, mas a função + não pode ve-lo, é uma indicação de rootkit a nivel de kernel ou o ps foi + infectado. Nós verificamos também a saída do kill e do getid que deve ser a mesma. + +6- Olha a presença de portas escondidas. Nós usamos a função bind para checar todas + as portas TCP e UDP to do sistema. Se não podemos usar o bind na porta (ele está + sendo usado), mas o netsatat não mostra, provavelmente há um rootkit instalado. + +7- Escaneia todas a interfaces do sistema e procura por alguma com módo "promisc" + abilitado. Se a interface está neste modo, a saída do ifconfig mostrará. Se não, + há a possibilidade de haver um rootkit instalado. + + +EOF diff --git a/doc/br/rule_ids.txt b/doc/br/rule_ids.txt new file mode 100755 index 0000000..bb75448 --- /dev/null +++ b/doc/br/rule_ids.txt @@ -0,0 +1,29 @@ +0100 - 0199 Mensagens de erro do Syslog +0200 - 0299 Mensagens NFS +0300 - 0399 Mensagens do Xinetd +0400 - 0499 Mensagens do controle de acesso +0500 - 0599 Mensagens do Sendmail +0600 - 0699 Mensagens do Ftp +0700 - 0799 Mensagens do Smartd +0800 - 0899 Mensagens do Kernel +0900 - 0949 Mensagens do Crond +0950 - 0999 Mensagens automáticas +1000 - 1099 Mensagens do Syslog a respeito do Squid +1100 - 1199 Mensagens do su +1200 - 1299 Mensagens do tripwire +1300 - 1399 Mensagens do adduser +1400 - 1499 Mensagens do sudo +1500 - 1599 Mensagens do sshd +1600 - 1699 Testes padrões de ataques +1700 - 1799 Testes padrões da escala de privilégios +1800 - 1899 Testes padrões de scaners +1900 - 1999 Regras de DNS +2000 - 2499 Regras de PIX +2500 - 2599 Regras do proftpd +2600 - 2699 Mensagens do PPTP +2700 - 2799 Regras do FTS +2800 - 2899 Regras do Pure-FTPD +3000 - 3099 Regras do log de erro do Apache +3100 - 3199 Regras do log de acesso do Apache +4000 - 4999 Regras de IDS +5000 - 5999 Regras do Squid diff --git a/doc/br/rules.txt b/doc/br/rules.txt new file mode 100755 index 0000000..751c5bb --- /dev/null +++ b/doc/br/rules.txt @@ -0,0 +1,66 @@ +OSSEC HIDS v0.7 +Copyright (c) 2004-2006 Daniel B. Cid + + + + +--- Classidicação das regras --- + + +-- Classificação -- + +As regras são classificadas em vários niveis, indo do menos (00) para o maior (16). +Alguns níveis não estão sendo usados. Você pode adicionar mais entre ou após estes. + +**As regras serão lidas partindo do menor nivel para o maior. ** + +00 - Ignorado - Não há nehum ação. Usado para evitar falso positivos. Estas regras + são escaneadas antes das demias e incluem eventos sem relevância de segurança. +01 - Nenhuma - +02 - Notificação do sistema com baixa prioridade - Notificações do sistema ou mensagens + de status. Estas regras não posseum relevância de segurança. +03 - Eventos de sucesso/Autorizado - Estes incluem tentativas de logins com sucesso, + eventos permitidos pelo, etc. +04 - Erros de sistema com baixa prioridade - Erros relatados por má configuração ou + devices/aplicações não usadas. Estas não apresentam relevância de segurança e + normalmente são causadas por instalações padrões ou software em testes. +05 - Erros gerados pelo usuário - Este incluem senhas erradas, ações não permitidas, + etc, mas não tem relevância de segurança. +06 - Ataque de baixa relevância - Estas indicam que um worm ou vírus que não afetam + o sistema (como o code red para servidores apache, etc). Incluem também eventos + de IDS ou erros frequentes. +07 - Combinação de "Bad word". Estas incluem palavras como "bad", "error", etc. Estes + eventos normalmente não são classificados e possuem alguma relevância de segurança. +08 - Visto pela primeira vez - Incluem eventos vistos pela primeira vez, primeira vez + de ventos de IDS ou primeira vez que um usuário loga. Se você estiver começando a + usar o OSSEC HIDS, estas mensagens serão frequêntes mas depois devem diminuir. + Estas incluem também ações de segurança relevantes (como iniciar um sniffer ou + algo do gênero). +09 - Erro de fonte inválida - Inclue tentativas de login com um usuário desconhecido + ou de uma fonte inválida. Pode haver relevância de segurança (princilmente se ocorrer + repetidamente). Incluem também erros a respeito do usuário "root". +10 - Erros gerador por vários usuários - Estas incluem vários bad passwords, + vários logins falhos, etc. Podem indicar um ataque ou um usuário que esqueceu + suas credenciais. +11 - Advertência de checagem de integridade -Estas incluem mensagens a respeito da + modificação de binários ou a presença de rootkits (pelo rootcheck). Se você + houver modificado apenas a configuração do seu sistema, deve ficar atento as mensagens + do "syscheck". Pode indicar um ataque com sucesso. +12 - Evento de alta importância - Estas incluem erros ou avisos vindos do sistema, kernel, + etc. Podem indicar um ataque a uma aplicação específica. +13 - Erros incomuns (alta importância) - A maioria das vezes mostra um ataque padrão. +14 - Evendo de segurança de alta importância - Na maioria das vezes são eventos de + corelação e indicam um ataque. +15 - Ataque severo - Não há chanses de falso positivo. É necessária atenção imediata. + + +== Grupos de regras == + +-Nós podemos especificar grupos para regras específicas. Isto é usado para +razões de resposta ativa ou para corelação. + + +== Configuração das regras == + +http://www.ossec.net/en/manual.html#rules + diff --git a/doc/logs.txt b/doc/logs.txt new file mode 100755 index 0000000..269068c --- /dev/null +++ b/doc/logs.txt @@ -0,0 +1,53 @@ +OSSEC v0.9 +Copyright (C) 2009 Trend Micro Inc. + + +OSSEC Logging + +== Introduction == + +Ossec supports three types of logs. Alert logging, firewall +logging and event (archiving) logging. + +Every message received is treated as an event. +Any log message, integrity report, system information will be treated +as such. Event logging is very expensive for the system because +it will archive every event. However, they can be usefull to get +the big picture if some attack happens. + +Alert logging is the most useful one. An alert is generated when +an event is matched against one of the detection rules. In addition +to the logging, OSSEC can also generate e-mail notifications or +execute external commands for them. + + +== Event logging == + +Inside the OSSEC default log directory (by default /var/ossec/logs) +there is an entry for "archives" (/var/ossec/logs/archives). Inside this +directory, all events will be stored by date. +For example, all events received on May 22 of 2004, will be stored on: + +/var/ossec/logs/archives/2004/May/events-22.log + +After each day, a hash will be created for this specific day at + +/var/ossec/logs/archives/2004/May/events-22.log.md5 + +This hash will be the hash of the file from the day 22 plus the hash +from the day 21. + +The hash from the day 1, will be the hash from the day 31 (or 30 or 28) +from the previous month. + +This will ensure that no log will be modified. Also, for this to happen, +all the logs (since the first day) will need to be modified. + + +== Alert logging == + +There will be a "alerts" directory on the OSSEC default logging directory. +It will be organized on the same way the event logging is. Please read +above to understand it. + + diff --git a/doc/manager.txt b/doc/manager.txt new file mode 100755 index 0000000..660c03b --- /dev/null +++ b/doc/manager.txt @@ -0,0 +1,21 @@ +OSSEC v0.9 +Copyright (C) 2009 Trend Micro Inc. + + +How do the server manager the agents. + +-The server will open port 1514 (by default) and listen for + messages from the clients. Only the IP of the clients will be + allowed. + +-Every 10 minutes, the client will send an status notification + to the server. This status message contain some information + about the agent system and information about the files it + has on the shared directory. + +-The server will receive the status message, update the agent + status file and check if it has any file to be sent to the + agent. If it has, it will connect to the agent and send + the file. + +-Every message will be encrypted. diff --git a/doc/nmap.txt b/doc/nmap.txt new file mode 100755 index 0000000..9c8e1b1 --- /dev/null +++ b/doc/nmap.txt @@ -0,0 +1,59 @@ +OSSEC +Copyright (C) 2009 Trend Micro Inc. + + +** Nmap correlation ** + +Ossec can read nmap grepable output files to use as a +correlation tool and also to alert based on host information +changes. Follow the step by step below on how to configure +ossec: + + +1- Add the nmap output file on ossec.conf (generally + at /var/ossec/etc/ossec.conf): + + + + nmapg + /var/log/nmap-out.log + + + + +2- If the file does not exist, touch it: + +ossec-test# touch /var/log/nmap-out.log + + +3- Restart ossec: + +ossec-test# /var/ossec/bin/ossec-control restart + + +4- Run your nmap scans (example scanning 192.168.2.0/24 network): + +ossec-test# nmap --append_output -sU -sT -oG /var/log/nmap-out.log 192.168.2.0-255 + + + +*** Example of alert when a new host is found: + +** Alert 1152058913.238: mail +2006 Jul 04 20:21:53 /var/log/nmap-out.log +Rule: 15 (level 8) -> 'New host information added.' +Src IP: (none) +User: (none) +Host: 192.168.2.10, open ports: 21(tcp) 22(tcp) 80(tcp) 113(tcp) 514(udp) 1514(udp) 4500(udp) + + +*** Example of alert when a new a host information is changed: + +** Alert 1152058983.487: mail +2006 Jul 04 20:23:03 /var/log/nmap-out.log +Rule: 15 (level 8) -> 'Host information changed.' +Src IP: (none) +User: (none) +Host: 192.168.2.1, open ports: 54(udp) 8080(tcp) 161(udp) 520(udp) 1025(udp) 1900(udp) +Previously open ports: 53(udp) 80(tcp) 161(udp) 520(udp) 1025(udp) 1900(udp) + diff --git a/doc/pl/INSTALL.pl b/doc/pl/INSTALL.pl new file mode 100755 index 0000000..e43ec86 --- /dev/null +++ b/doc/pl/INSTALL.pl @@ -0,0 +1,66 @@ +OSSEC HIDS 0.8 +Copyright (c) 2004-2006 Daniel B. Cid + + + += Informacje o OSSEC HIDS = + +Zobacz http://www.ossec.net + + += Zalecana instalacja = + +Instalacja OSSEC HIDS jest bardzo prosta. Może być przeprowadzona +w szybki sposób (przy użyciu skryptu install.sh z domyślnymi +wartościami) lub dostosowana do użytkownika (ręcznie lub poprzez +zmianę domyślnych wartości w skrypcie install.sh). POLECAM KAÅ»DEMU +używanie SZYBKIEGO SPOSOBU! Tylko developerzy i zaawansowani +użytkownicy powinni używać innych metod. + +Kroki szybkiego sposobu: + +1- Uruchom skrypt ./install.sh. Poprowadzi Cie on przez proces + instalacji. + +2- Skrypt zainstaluje wszystko do katalogu /var/ossec oraz + spróbuje stworzyć w systemie skrypt inicjujący (w katalogu + /etc/rc.local lub /etc/rc.d/init.d/ossec). Jeśli skrypt nie + zostanie utworzony, można postępując zgodnie z instrukcjami + z install.sh spowodować uruchamianie OSSEC HIDS podczas + startu systemu. Aby wystartować ręcznie wystarczy uruchomić + /var/ossec/bin/ossec-control start + +3- Jeśli zamierzasz używać kilku klientów, powinieneś najpierw + zainstalowac serwer. Do stworzenia odpowiednich kluczy użyj + narzędzia manage_agents. + +4- Miłego użytkowania. + + += Instalacja i uruchmienie (99,99% powinieneś przeczytać POWYÅ»EJ) = + + +Kroki ręcznej instalacji: + +1- Utwórz potrzebne katalogi (domyślnie /var/ossec). +2- Przenieś odpowiednie pliki do katalogu ossec. +3- Skompiluj wszystko. +4- Przenieś binaria do katalodu domyślnego. +5- Dodaj odpowiednich użytkowników. +6- Ustaw odpowiednie prawa dla plików. + + +Powyższe 5 (bez 5) kroków jest wykonywane w Makefile (zobasz make server). + +Makefile czyta opcje z pliku LOCATION. Możesz w nim zmienić +wszystko co potrzebujesz. + +Aby skompilować wszystko samemu: + + % make clean + % make all (step 3) + % su + # make server (odpowiada za kroki 1,2,4 oraz 6) + +*Przed uruchomieniem make server, upewnij się, że masz utworzonych +odpowiednich użytkowników. Makefile nie utworzy ich. diff --git a/doc/pl/README.config b/doc/pl/README.config new file mode 100755 index 0000000..eaffda5 --- /dev/null +++ b/doc/pl/README.config @@ -0,0 +1,3 @@ +Opcje konfiguracyjne: + +http://www.ossec.net/en/manual.html diff --git a/doc/pl/TRANSLATION b/doc/pl/TRANSLATION new file mode 100755 index 0000000..ebc7de6 --- /dev/null +++ b/doc/pl/TRANSLATION @@ -0,0 +1,2 @@ +** Tłumaczenie Krzysztof Dziankowski +** Translated by Krzysztof Dziankowski diff --git a/doc/pl/active-response-internal.txt b/doc/pl/active-response-internal.txt new file mode 100755 index 0000000..c9e28de --- /dev/null +++ b/doc/pl/active-response-internal.txt @@ -0,0 +1,27 @@ +OSSEC HIDS 0.6 +Copyright (c) 2004-2006 Daniel B. Cid + + + +Jak działa aktywa ochrona (od środka): + +- Przeczytaj active-respose-doc.txt aby dowiedzieć się więcej + o konfiguracji + +1 - Zdarzenie które pasuje do polityki aktywnej ochrony jest + wysyłane do serwera analizującego. + +2 - Serwer weryfikuje czy wszystkie wymagane pola są są + dostarczone w zdarzeniu. Oznacza to, że serwer zdekodował + zdarzenie i odczytał wszystkie pożądane informacje. Np. + musi odczytac adres IP aby podjąć akcję o zablokwaniu go + na firewall-u. + +3 - Jeśli aktywna ochrona jest skonfigurowana aby akcje były + wykonywane lokalnie, widomość zostaje bezpośrednio wysyłana + do execd. + +4 - Jeśli aktywna ochrona jest skonfigurowana aby akcje były + wykonywane zdalnie, wiadomość jest wysyłana do remoted + (forwarder aktywnej ochrony), który przekazuje ją dalej + do odpowiedniego agenta. \ No newline at end of file diff --git a/doc/pl/active-response.txt b/doc/pl/active-response.txt new file mode 100755 index 0000000..154d928 --- /dev/null +++ b/doc/pl/active-response.txt @@ -0,0 +1,6 @@ +OSSEC HIDS v0.7 +Copyright (c) 2004-2006 Daniel B. Cid + + + +http://www.ossec.net/en/manual.html#active-response diff --git a/doc/pl/logs.txt b/doc/pl/logs.txt new file mode 100755 index 0000000..46c7ee3 --- /dev/null +++ b/doc/pl/logs.txt @@ -0,0 +1,52 @@ +OSSEC HIDS 0.5 +Copyright (c) 2004,2005 Daniel B. Cid + + + +Logi OSSEC Hids + + +== Wprowadzenie == + +System wspiera dwa typy logowania. Logowanie alarmów i zdarzeń lub +logowanie z archiwizacją. + +Każda otrzymana wiadomość jest traktowana jako zdarzenie. +Raporty integralności systemu, informacje systemowe lub zwykłe +wiadomości logów są traktowane jako zdarzenia. Logowanie zdarzeń bardzo +obciąża system, ponieważ archiwizuje każde zdarzenie. Mimo to, jest +przydatne, ponieważ może dać nam dokładny obraz wydarzeń po włamaniu. + +Logowanie alarmów jest najbardziej użyteczne. Alarm jest generowany +kiedy zdarzenie zostaje dopasowane do jednej z reguł wykrywania. Poza +logowaniem OSSEC hids posiada powiadomnienie poprzez e-mail oraz +zewnętrzne wykonywanie komend jako metodę alarmu. + + +== Logowanie zdarzeń == + +W domyślnym katalogu logów OSSEC (/var/ossec/logs) jeden jest +przezaczony na archiwa (/var/ossec/logs/archives). W tym +katalogu wszystkie zdarzenia są przechowywane według daty. +Np. wszystkie zdarzenia otrzymane 22.05.2005, będą przechowywane w: + +/var/ossec/logs/archives/2004/May/events-22.log + +Na koniec każdego dnia, jest tworzony hash i przechowywany w: + +/var/ossec/logs/archives/2004/May/events-22.log.md5 + +Jest to hash z pliku z dnia 22 plus hash z dnia 21. + +Hash z dnia pierwszego, jest hashem z dnia 31 (30 lub 28) poprzedniego +miesiąca. + +Hash jest tworzony aby mieć pewność, że logi nie były modyfikowane. +Dodatkowo zabezpiecza wszystkie poprzednie logi począwszy od pierwszego. + +== Logowanie alarmów == + +W domyślnym katalogu logów OSSEC jest katalogo alarmów +(/var/ossec/logs/alerts). Zorganizowany w taki sam sposób jak +katalog zdarzeń. Przeczytaj powyżej aby zrozumieć. + diff --git a/doc/pl/manager.txt b/doc/pl/manager.txt new file mode 100755 index 0000000..b133e71 --- /dev/null +++ b/doc/pl/manager.txt @@ -0,0 +1,19 @@ +OSSEC HIDS 0.5 +Copyright (c) 2004,2005 Daniel B. Cid + + + +Jak serwer zarządza agentami. + +-Klient otwiera port 1514 (domyślnie) i nasłuchuje na wiadomości od + serwera. Wyłącznie IP serwera jest akceptowane. + +-Co 10 minut, klient wysyła powiadomienie o stanie do serwera. + Powiadomienie zawiera niektóre informacje o systemie klienckim oraz + informacje o plikach które posiada w katalogu shared. + +-Serwer otrzymuje wiadomości statusu, aktualizuje plik statusu agenta + oraz sprawdza czy posiada jakiś plik do wysłania dla agenta. Jeśli ma, + to łączy się z klientem i wysyła go. + +-Każda wiadomość jest szyfrowana. diff --git a/doc/pl/rootcheck.txt b/doc/pl/rootcheck.txt new file mode 100755 index 0000000..6a664f4 --- /dev/null +++ b/doc/pl/rootcheck.txt @@ -0,0 +1,67 @@ +Rootkit detection techniques used by the OSSEC HIDS +by Daniel B. Cid, daniel.cid@gmail.com + +Zaczynając od wersji 0.4, OSSEC HIDS dokonuje wykrywania rootkitów na +każdym systemnie na którym jest zainstalowany agent. Mechanizm +wykrywania rootkitów (rootcheck) jest wykonywany co X minut +(wyspecyfikowane przez użytkownika - domyśnie co dwie godziny) w celu +wykrycia zinstalowanych rootkitów. Używany razem z analizatorem logów +oraz mechanizmem sprawdzania integralności, staje się bardzo wydajnym +systemem monitorowania (OSSEC HIDS dokonuje analizy logów i sprawdzania +integralności od wersji 0.1). + +Inną właściwością dołączoną do wersji 0.4 jest automatyczne rozsyłanie +sygnatur wykrywania rootkitów do wszystkich agentów przez serwer. +Redukuje to ilość obowiązków administratora. Serwer z agentami utrzymuje +kontakt co 10 minut. Dodatkowo jeśli serwer zostanie zaktualizowany +nowymi sygnaturami, przekazuje je wszystkim skonfigurowanym agentom. +Aby uzyskać więcej informacji zajżyj do dokumentacji zarządzania. + + +Kroki wykonywane przez rootcheck w celu wykrycia rootkitów: + +1- Czyta plik rootkit_files.txt, który zawiera sporą baze danych o + rootkitach i używanych przez nie plików. Próbuje wykonać: stats, + fopen i opendir na każdym z takich plików. Używa wszystkich tych + wywołań systemowych, ponieważ istnieją rootkity pracujące na poziomie + jądra, które ukrywają pliki przed niektórymi wywołaniami. Im więcej + użyjemy wywołań, tym lepsza będzie detekcja. Metoda jest podobna do + reguły anty-virusa, potrzebuje nieustanntgo uaktualniania. Szanse + detekcji rootkita którego nie ma (false-positive) są małe, za to już + szanse nie wykrycie rootkita (false-negative) rosną wraz z + modyfikacjami rootkitów. + +2- Czyta plik rootkit_trojans.txt który zawiera baze danych sygnatur + plików modyfikowanych na trojany przez rootkity. Technika modyfikacji + binariów na wersje z trojanami jest powszechnie używana przez + większość dostępnych rootkitów. Nastepująca metoda nie wykrywa + rootkitów poziomu jądra ani żadnych jeszcze nie znanych. + +3- Skanuje katalog /dev wyszukując anomali. /dev powinien tylko zawierać + pliki urządzeń oraz skrypt Makedev. Duża część rootkitów używa + katalogu /dev w celu ukrycia plików. Ta metoda może wykryć nieznane + dotąd rootkity. + +4- Skanuje cały system plików szukając niespotykanych plików oraz + tych z podejrzanymi uprawnieiami. Pliki użytkownika root z + możliwością zapisu dla innych są bardzo niebezpieczne, dlatego + rootkit wyszukuje takie. Pliki z ustawionym suid oraz ukryte katalogi + również są sprawdane. + +5- Szuja ukrytych procesów. Używa getsid() oraz kill() do sprawdzenia + czy dany pid jest używany. Jeśli dany pid jest używany, a "ps" nie + widzi go, wskazuje to na obecność rootkita poziomu jądra lub + zmodyfikowaną wersję "ps". Weryfikuje także wyniki kill i getsid, + które powinny być identyczne. + +6- Wyszukuje ukrytych portów. Używa bind() do sprawdzenia każdego portu + tcp i udp w systemie. Jeśli nie możemy wykonać bind na danym porcie + (czyli jest używany), a "netstat" go nie pokazuje, to prawdopodobnie + mamy zainstalowanego rootkita. + +7- Skanuje wszystkie interfejsy w systemnie i wyszukuje te z włączonym + trybem "promisc". Jeśli interfejs jest w trybie "promisc", "ifconfig" + tego powinien pokazać to, jeśli nie prawdopodobnie mamy + zainstalowanego rootkita. + +EOF diff --git a/doc/pl/rule_ids.txt b/doc/pl/rule_ids.txt new file mode 100755 index 0000000..3ff8975 --- /dev/null +++ b/doc/pl/rule_ids.txt @@ -0,0 +1,35 @@ +0100 - 0199 Wiadomości błędów Syslog +0200 - 0299 Wiadomości NFS +0300 - 0399 Wiadomości Xinetd +0400 - 0499 Wiadomości kontroli dostępu +0500 - 0599 Wiadomości Sendmail +0600 - 0699 Wiadomości Ftp +0700 - 0799 Wiadomości Smartd +0800 - 0899 Wiadomości Kernel +0900 - 0949 Wiadomości Crond +0950 - 0999 Wiadomości Automount +1000 - 1099 Wiadomości Squid syslog +1100 - 1199 Wiadomości Su +1200 - 1299 Wiadomości Tripwire +1300 - 1399 Wiadomości Adduser +1400 - 1499 Wiadomości Sudo +1500 - 1599 Wiadomości sshd +1600 - 1699 Wzorce ataków +1700 - 1799 Wzorce przejmowania uprawnień +1800 - 1899 Wzorce skanowań +1900 - 1999 Reguły DNS +2000 - 2499 Reguły PIX +2500 - 2599 Reguły Proftpd +2600 - 2699 Wiadomości PPTP +2700 - 2799 Reguły Reguły FTS +2800 - 2899 Reguły Pure-FTPD +2900 - 2999 Reguły Spamd +3000 - 3099 Reguły błędów dla Apache'a (dla logów) +3100 - 3199 Reguły dostępu dla Apache'a (dla logów) +4000 - 4999 Reguły IDS +5000 - 5999 Reguły Squid +6000 - 6199 Reguły Postfix +6200 - 6499 Reguły Sendmail +7000 - 7499 Reguły Firewall +8000 - 8999 Reguły Windows +100000 - 199999 Reguły zdefiniowane przez użytkownika diff --git a/doc/pl/rules.txt b/doc/pl/rules.txt new file mode 100755 index 0000000..e68991c --- /dev/null +++ b/doc/pl/rules.txt @@ -0,0 +1,85 @@ +OSSEC HIDS v0.7 +Copyright (c) 2004-2006 Daniel B. Cid + + + + +--- Klasyfikacja reguł --- + + +-- Klasyfikacja -- + +Reguły są podzielone na 16 poziomów. Niektóre poziomy są aktualnie nie używane. +Inne mogą być dodane pomiędzy nimi lub za. + +**Reguły są czytane od najwyższego do najniższego poziomu. ** + +00 - Ignorowane - Nie jest podejmowana żadna akcja. Używane aby uniknąć + fałszywych ataków. Te reguły są przetwarzane przed wszystkimi pozostałymi. + Zawierają zdarzenia nie związane z bezpieczeństwem. +01 - Brak - +02 - Niski priorytet powiadomień systemowych - Powiadomienia systemowe lub + wiadomości statusu. Nie związane z bezpieczeństwem. +03 - Pomyślne/Autoryzowane akcje - Zawiera pomyślne próby logowania, dozwolone + akcje firewall'a, itd. +04 - Niski priorytet błędów systemowych - Błędy związane ze złą konfiguracją lub + nieużywanymi urządzeniami/aplikacjami. Nie są związane z bezpieczeństwem, + zazwyczaj są powodowane poprzez instalacje lub testowanie aplikacji. +05 - Błędy wygenerowane przez użytkownika - Zawierają błędne logowania, + zabronione akcje, itp. Nie mają wpływu na bezpieczeństwo, ponieważ już są + blokowane. +06 - Atak o niskim znaczeniu - Powodowane przez robaki lub wirusy które nie mają + wpływu na system (takie jak code red dla serwera apache, itp). Zawierają + także często akcje IDS oraz błędy. +07 - Dopasowanie *bad word* - Zawierają słowa "bad', "error", itp. W większości + niesklasyfikowane akcje, które mogą mieć wpływ na bezpieczeństwo. +08 - Widziane poraz pierwszy - Zawierają akcje widziane poraz pierwszy. Np. + pierwszy raz jest generowana akcja IDS albo pierwsze logowanie użytkownika. + Jeśli dopiero zacząłeś używać OSSEC HIDS, takie akcje najprawsopodobniej + będą występować często. Lecz po jakimś czasie znikną. Zawierają także akcje + związane z bezpieczeństwem (takie jak uruchomienie sniffera lub podobnego + narzędzia). +09 - Błędy z nieznanego źródła - Zawierają próby logowania jako nieznany + użytkownik lub z niepoprawnego źródła. Mogą mieć wpływ na bezpieczeństwo + (szczególnie gdy powtarzane). Obejmują także błędy związane z kontem + "administratora", root'a. +10 - Powtarzalne błędy generowane przez użytkownika - Zawierają wielokrotne + nieudane próby logowania, błędy autoryzacji itp. Mogą oznaczać atak lub + poprostu użytkownik zapomiał swoich danych autoryzujących. +11 - Ostrzeżenie, sprawdzanie spójności - Zawiera wiadomości oznaczające + modyfikacje plików binarnych lub obecność rootkit'ów (generowane przez + rootcheck). Jeśli aktualizowałeś system nie powinieneś się przejmować tymi + ostrzeżeniami. Mogą oznaczać udany atak. +12 - Wysoce istotne zdarzenia - Zawierają wiadomości błądów lub ostrzeżeń od + systemu, jądra, itp. Moga oznaczać atak na konkretną aplikacje. +13 - Niespotykane błędy (wysoce istotne) - W większości dopasowane do wzorców + znanych ataków. +14 - Wysoce istotne zdarzenia bezpieczeństwa - Akcje wykrywane poprzez związki + ze sobą, zazwyczaj oznaczają atak. +15 - Poważny atak - Natychmiastowa reakcja jest potrzebna (nie może być mowy tu + o fałszywym ataku). + + +== Grupa reguł == + +-Możemy wyspecyfikować grupy dla specyficznych reguł. Jest to używane do + aktywnej ochrony oraz do relacji. +-Aktualnie używamy następujących grup: + +- invalid_login +- authentication_success +- authentication_failed +- connection_attempt +- attacks +- adduser +- sshd +- ids +- firewall +- squid +- apache +- syslog + + +== Konfiguracja reguł == + +http://www.ossec.net/en/manual.html#rules \ No newline at end of file diff --git a/doc/rootcheck.txt b/doc/rootcheck.txt new file mode 100755 index 0000000..40e13a7 --- /dev/null +++ b/doc/rootcheck.txt @@ -0,0 +1,74 @@ +Rootkit detection techniques used by the OSSEC HIDS +by Daniel B. Cid, daniel.cid@gmail.com + + +Starting on version 0.4, the OSSEC HIDS will perform +rootkit detection on every system where the agent is +installed. The rootcheck (rootkit detection engine) will +be executed every X minutes (user specified --by default +every 2 hours) to detect any possible rootkit installed. +Used witht the log analysis and the integrity checking +engine, it will become a very powerful monitoring solution +(the OSSEC HIDS performs log analysis and integrity +checking since version 0.1). + +Other feature included on version 0.4 is that the analysis +server will automatically forward the rootkit detection +signatures to the agents, reducing the administration +overhead for the system admin. The agents and server will +keep contact every 10 minutes and if the server is +updated with a new signature file, it will forward them +to all configured agents. Take a look at the management +documentation for more information. + +The rootcheck will perform the following steps on the +system trying to find rootkits: + + +1- Read the rootkit_files.txt which contains a big database + of rootkits and files used by them. It will try to stats, + fopen and opendir each specified file. We use all these + system calls, because some kernel-level rootkits, hide + files from some system calls. The more system calls we + try, the better the detection. This method is more like + an anti-virus rule that needs to be updated constantly. + The chances of false-positives are small, but false + negatives can be produced by modifying the rootkits. + +2- Read the rootkit_trojans.txt which contains a database + of signatures of files trojaned by rootkits. This + technique of modifying binaries with trojaned versions + was commonly used by most of the popular rootkits + available. This detection method will not find any + kernel level rootkit or any unknown rootkit. + +3- Scan the /dev directory looking for anomalies. The /dev + should only have device files and the Makedev script. + A lot of rootkits use the /dev to hide files. This + technique can detect even non-public rootkits. + +4- Scan the whole filesystem looking for unusual files and + permission problems. Files owned by root, with written + permission to others are very dangerous and the rootkit + detection will look for them. Suid files, hidden directories + and files will also be inspected. + +5- Look for the presence of hidden processes. We use getsid() + and kill() to check if any pid is being used or not. If + the pid is being used, but "ps" can't see it, it is the + indication of kernel-level rootkit or a trojaned version + of "ps". We also verify the output of kill and getsid that + should be the same. + +6- Look for the presence of hidden ports. We use bind() to + check every tcp and udp port on the system. If we can't + bind to the port (it's being used), but netstat does not + show it, we probably have a rootkit installed. + +7- Scan all interfaces on the system and look for the ones + with "promisc" mode enabled. If the interface is in promiscuous + mode, the output of "ifconfig" should show that. If not, + we probably have a rootkit installed. + + +EOF diff --git a/doc/rule_ids.txt b/doc/rule_ids.txt new file mode 100755 index 0000000..edbf1a8 --- /dev/null +++ b/doc/rule_ids.txt @@ -0,0 +1,77 @@ +# ossec Rules ids. +# +# Ossec official rules should be under some of these +# assignments. +# +# Local rules should go from 100000 to 120000. +# +# Every rule will also have a revision attribute (if modified). +# *default revision is 0 (when first added). + +00000 - 00999 Internally reserved for ossec +01000 - 01999 General syslog +02100 - 02299 NFS +02300 - 02499 Xinetd +02500 - 02699 Access control +02700 - 02729 Mail/procmail +02800 - 02829 Smartd +02830 - 02859 Crond +02860 - 02899 Mount/Automount + +03100 - 03299 Sendmail +03300 - 03499 Postfix +03500 - 03599 Spamd +03600 - 03699 Imapd +03700 - 03799 MailScanner + +04100 - 04299 Generic Firewall +04300 - 04499 Cisco PIX Firewall +04500 - 04699 Netscreen Firewall + +05100 - 05299 Kernels (Linux, Unix, etc) +05300 - 05399 Su +05400 - 05499 sudo +05500 - 05599 Pam unix +05600 - 05699 Telnetd +05700 - 05899 sshd +05900 - 05999 Adduser or user deletion. + +07100 - 07199 Tripwire +07200 - 07299 Arpwatch +07300 - 07399 Symantec Anti Virus + +09100 - 09199 PPTP +09200 - 09299 Squid syslog +09300 - 09399 Horde IMP + +10100 - 10199 FTS + +11100 - 11199 FTPd +11200 - 11299 ProFTPD +11300 - 11399 Pure-FTPD +11400 - 11499 vs-FTPD + +12100 - 12299 Named (bind DNS) + +13100 - 13299 Samba (smbd) + +14100 - 14199 Racoon SSL +14200 - 14299 Cisco VPN Concentrator + +17100 - 17399 Policy + +18100 - 18499 Windows system + +20100 - 20299 IDS +20300 - 20499 IDS (Snort specific) + +30100 - 30999 Apache error log. +31100 - 31199 Web access log + +35000 - 35999 Squid + +40100 - 40499 Attack patterns. +40500 - 40599 Privilege scalation. +40600 - 40999 Scan patterns. + +100000 - 109999 User defined rules diff --git a/doc/rules.txt b/doc/rules.txt new file mode 100755 index 0000000..2d8e09e --- /dev/null +++ b/doc/rules.txt @@ -0,0 +1,90 @@ +OSSEC HIDS v0.9 +Copyright (C) 2009 Trend Micro Inc. + + + +--- Rules Classification --- + + +-- Classification -- + +The rules are classified in multiple levels. From the lowest (00) to the maximum +level 16. Some levels are not used right now. Other levels can be added between +them or after them. + +**The rules will be read from the highest to the lowest level. ** + +00 - Ignored - No action taken. Used to avoid false positives. These rules + are scanned before all the others. They include events with no + security relevance. +01 - None - +02 - System low priority notification - System notification or + status messages. They have no security relevance. +03 - Successful/Authorized events - They include successful login attempts, + firewall allow events, etc. +04 - System low priority error - Errors related to bad configurations or + unused devices/applications. They have no security relevance and + are usually caused by default installations or software testing. +05 - User generated error - They include missed passwords, denied + actions, etc. By itself they have no security relevance. +06 - Low relevance attack - They indicate a worm or a virus that have + no affect to the system (like code red for apache servers, etc). + They also include frequently IDS events and frequently errors. +07 - "Bad word" matching. They include words like "bad", "error", etc. + These events are most of the time unclassified and may have + some security relevance. +08 - First time seen - Include first time seen events. First time + an IDS event is fired or the first time an user logged in. + If you just started using OSSEC HIDS these messages will + probably be frequently. After a while they should go away. + It also includes security relevant actions (like the starting + of a sniffer or something like that). +09 - Error from invalid source - Include attempts to login as + an unknown user or from an invalid source. May have security + relevance (specially if repeated). They also include errors + regarding the "admin" (root) account. +10 - Multiple user generated errors - They include multiple bad + passwords, multiple failed logins, etc. They may indicate an + attack or may just be that a user just forgot his credencials. +11 - Integrity checking warning - They include messages regarding + the modification of binaries or the presence of rootkits (by + rootcheck). If you just modified your system configuration + you should be fine regarding the "syscheck" messages. They + may indicate a successful attack. Also included IDS events + that will be ignored (high number of repetitions). +12 - High importancy event - They include error or warning messages + from the system, kernel, etc. They may indicate an attack against + a specific application. +13 - Unusual error (high importance) - Most of the times it matches a + common attack pattern. +14 - High importance security event. Most of the times done with + correlation and it indicates an attack. +15 - Severe attack - No chances of false positives. Immediate + attention is necessary. + + +== Rules Group == + +-We can specify groups for specific rules. It's used for active +response reasons and for correlation. +- We currently use the following groups: + +- invalid_login +- authentication_success +- authentication_failed +- connection_attempt +- attacks +- adduser +- sshd +- ids +- firewall +- squid +- apache +- syslog + + + +== Rules Config == + +http://www.ossec.net/en/manual.html#rules + diff --git a/etc/decoder.xml b/etc/decoder.xml new file mode 100755 index 0000000..c809108 --- /dev/null +++ b/etc/decoder.xml @@ -0,0 +1,1881 @@ + + + + + + + + + (pam_unix)$ + + + + + ^pam_unix|^\(pam_unix\) + + + + pam + ^session \w+ + ^for user (\S+) + user + + + + pam + rhost=\S+\s+user=\S+ + rhost=(\S+)\s+user=(\S+) + srcip, user + + + + pam + rhost + ^=(\S+) + srcip + + + + + + + + ^sshd + + + + sshd + ^Accepted + ^ \S+ for (\S+) from (\S+) port + user, srcip + name, user, location + + + + sshd + ^User \S+ from + ^User (\S+) from (\S+) + user, srcip + + + + sshd + ^User + ^(\S+), coming from (\S+), + user, srcip + name, user, location + + + + sshd + ^Failed \S+ for invalid user|^Failed \S+ for illegal user + from (\S+) port \d+ \w+$ + srcip + + + + sshd + ^Failed \S+ + ^for (\S+) from (\S+) port \d+ \w+$ + user, srcip + + + + sshd + ^error: PAM: Authentication \w+ + ^for (\S+) from (\S+)$ + user, srcip + + + + sshd + ^reverse mapping checking + ^\w+ for (\S+) + srcip + + + + sshd + ^Invalid user|^Illegal user + from (\S+)$ + srcip + + + + sshd + ^scanned from + (\S+) + srcip + + + + sshd + ^Did not receive identification|^Bad protocol version + from (\S+)$ + srcip + + + + + + + ^telnetd|^in.telnetd + + + + telnetd + from (\d+.\d+.\d+.\d+)$ + srcip + + + + + + + + ^smbd + + + + smbd + User name: + ^ (\S+). + user + + + + smbd + from \((\d+.\d+.\d+.\d+)\) + srcip + + + + + + + ^sudo + ^\s+(\S+)\s: + user + name,user,location + First time user executed the sudo command + + + + + + ^su$ + + + + su + ^'su + ^'su (\S+)' \S+ for (\S+) on \S+$ + dstuser, srcuser + name, srcuser, location + + + + su + ^BAD SU (\S+) to (\S+) on| + ^failed: \S+ changing from (\S+) to (\S+)| + ^\S \S+ (\S+)\p(\S+)$|^(\S+) to (\S+) on + srcuser, dstuser + name, srcuser, location + + + + ^SU \S+ \S+ + ^\S \S+ (\S+)-(\S+)$ + srcuser, dstuser + name, srcuser, location + + + + + + + ^proftpd + + + + proftpd + : Login successful + ^\S+ \(\S+[(\S+)]\)\s*\S \w+ (\S+): + Login successful + srcip, user + name, user, srcip, location + + + + proftpd + ^\S+ \(\S+[(\S+)]\) + srcip + + + + + + + ^pure-ftpd + + + + pure-ftpd + ^\S+ [INFO] \S+ is now logged in + ^\(?@(\S+)\) [INFO] (\S+) is now logged in + srcip, user + name, user, srcip, location + + + + pure-ftpd + ^\((\S+)@(\S+)\) [ + user,srcip + + + + + + + ^\w\w\w \w\w\w\s+\d+ \S+ \d+ [pid \d+] + Client "(\d+.\d+.\d+.\d+)"$ + srcip + + + + ^vsftpd + ^\w\w\w \w\w\w\s+\d+ \S+ \d+ [pid \d+] + Client "(\d+.\d+.\d+.\d+)"$ + srcip + + + + + + + ^ftpd|^in.ftpd + + + + ftpd + ^Failed authentication from: \S+ | + ^repeated login failures from + [(\d+.\d+.\d+.\d+)]$ + srcip + + + + ftpd + ^FTP LOGIN REFUSED + [(\d+.\d+.\d+.\d+)]$ + srcip + + + + ftpd + from (\d+.\d+.\d+.\d+)$ + srcip + + + + + + + ^arpwatch + + + + arpwatch + ^new station |^bogon + ^(\d+.\d+.\d+.\d+) (\S+) + srcip, extra_data + name, srcip, extra_data + + + + + + + ^MySQL log: + + + + + + + ^[\d\d\d\d-\d\d-\d\d \S+ \w+] + ^\S+ (\w+): + status + + + + + + + ^imapd + user=(\S+) \.+ [(\d+.\d+.\d+.\d+)]$ + user,srcip + + + + + + + ^vpopmail + + + + vpopmail + ^vchkpw-\S+: password fail + (\S+)@\S+:(\d+.\d+.\d+.\d+)$ + user, srcip + + + + vpopmail + ^vchkpw-\S+: vpopmail user not + ^found (\S+):(\d+.\d+.\d+.\d+)$ + user, srcip + + + + vpopmail + ^vchkpw-\S+: null password + ^given (\S+):(\d+.\d+.\d+.\d+)$ + user, srcip + + + + vpopmail + ^vchkpw-\S+: \(\S+\) login + ^success (\S+):(\d+.\d+.\d+.\d+)$ + user, srcip + + + + + + + ^vm-pop3d + + + + vm-pop3d + ^User ' + ^(\S+)' - \w+ auth, + from=(\d+.\d+.\d+.\d+)$ + user, srcip + + + + + + + ^pop3d|^courierpop3login|^imaplogin + + + + courier + ^LOGIN, + ^user=(\S+), ip=[(\S+\d)]$ + user, srcip + + + + courier + , ip=[(\S+\d)]$ + srcip + + + + + + + + ^dovecot + + + + dovecot + ^\w\w\w\w-login: Login: + ^user=\p(\S+)\p, method=\S+, rip=(\S+), + user, srcip + + + + dovecot + ^\w\w\w\w-login: Aborted login + user=\p\S+>, method=\w+, rip=(\S+), lip=\S+ + srcip + + + + dovecot + ^\w\w\w\w-login: Disconnected: + ^rip=(\S+), + srcip + + + + + + + ^named + + + + named + ^client + ^(\d+.\d+.\d+.\d+)# + srcip + + + + named + from [(\d+.\d+.\d+.\d+)] + srcip + + + + + + + + ^postfix + + + + true + postfix + ^NOQUEUE: reject: \w\w\w\w from + [(\d+.\d+.\d+.\d+)]: (\d+) + srcip,id + + + + postfix + ^warning: \S+: SASL + ^warning: \S+[(\d+.\d+.\d+.\d+)]: + srcip + + + + + + ^sendmail|^sm-mta|^sm-msp-queue + + + + sendmail-reject + ^\S+: rejecting commands from + ^ \S+ [(\d+.\d+.\d+.\d+)] + srcip + + + + sendmail-reject + relay=[ + ^(\d+.\d+.\d+.\d+)] + srcip + + + + sendmail-reject + relay=\S+ [ + ^(\d+.\d+.\d+.\d+)] + srcip + + + + + + + + ^smf-sav + ^sender check failed| + ^sender check tempfailed + ^ \(cached\): \S+, (\d+.\d+.\d+.\d+),| + ^: \S+, (\d+.\d+.\d+.\d+), + srcip + + + + + + + ^MailScanner + + + + mailscanner + ^Message \S+ from + ^(\d+.\d+.\d+.\d+) \S+ to \S+ is (\w+) + srcip, action + + + + + + ^kernel + + + + iptables + firewall + ^[\d+.\d+] \S+ IN= + + ^[\d+.\d+] (\S+) \.+ SRC=(\S+) DST=(\S+) + \.+ PROTO=(\w+) + action,srcip,dstip,protocol + + + + iptables + firewall + ^SPT=(\d+) DPT=(\d+) + srcport,dstport + + + + iptables + firewall + ^\S+ IN= + + ^(\S+) \.+ SRC=(\S+) DST=(\S+) \.+ + PROTO=(\w+) + action,srcip,dstip,protocol + + + + iptables + firewall + ^SPT=(\d+) DPT=(\d+) + srcport,dstport + + + + iptables + firewall + ^Shorewall:\S+: + + ^(\S+):\.+ SRC=(\S+) DST=(\S+) \.+ + PROTO=(\w+) + action,srcip,dstip,protocol + + + + iptables + firewall + ^SPT=(\d+) DPT=(\d+) + srcport,dstport + + + + + + + firewall + ^ipmon + (\w) (\d+.\d+.\d+.\d+),(\d+) -> + (\d+.\d+.\d+.\d+),(\d+) PR (\w+) + action,srcip,srcport,dstip,dstport,protocol + + + + + + firewall + ^ipsec_logd + R:(\w) \w:\S+ S:(\d+.\d+.\d+.\d+) + D:(\d+.\d+.\d+.\d+) P:(\S+) SP:(\d+) DP:(\d+) + action,srcip,dstip,protocol,srcport,dstport + + + + + + + firewall + ^pf$ + PF_Decoder + + + + + + + firewall + ^id=\w+ sn=\w+ time=\S+ \S+ fw=\S+ pri=\d + SonicWall_Decoder + + + + + + + + ^NetScreen device_id + + + + netscreenfw + firewall + + system-notification-00257 + \(traffic\): + + proto=(\w+) \.+action=(\w+) + \.+src=(\S+) dst=(\S+) src_port=(\d+) dst_port=(\d+) + protocol, action, srcip, dstip, srcport, dstport + + + + netscreenfw + system-critical-\.+ from | + system-alert-\.+ from + + system-(\w+)-(\d+): \.+ + from\.+(\d+.\d+.\d+.\d+) + action, id, srcip + + + + netscreenfw + system-(\w+)-(\d+): + action, id + + + + + + ^%PIX-|^\w\w\w \d\d \d\d\d\d \d\d:\d\d:\d\d: %PIX-| + ^%ASA-|^\w\w\w \d\d \d\d\d\d \d\d:\d\d:\d\d: %ASA-| + ^%FWSM-|^\w\w\w \d\d \d\d\d\d \d\d:\d\d:\d\d: %FWSM- + + + + pix + firewall + ^2-106001 + ^(\S+): \w+ (\w+) \S+ (\S+) from + (\S+)/(\S+) to (\S+)/(\S+) + id, protocol, action, srcip, srcport, dstip, dstport + + + + pix + firewall + ^3-710003|^7-710002|^7-710005 + ^(\S+): (\S+) \w+ (\w+)\.+from + (\S+)/(\S+) to \w+:(\S+)/(\S+) + id, protocol, action, srcip, srcport, dstip, dstport + + + + pix + firewall + ^4-106023 + ^(\S+): (\w+) (\w+) src \w+: + (\S+)/(\S+) dst \w+:(\S+)/(\S+) + id, action, protocol, srcip, srcport, dstip, dstport + + + + pix + firewall + ^4-106019 + ^(\S+): IP packet from (\S+) to + (\S+), protocol (\w+) (\w+) + id, srcip, dstip, protocol, action + + + + pix + firewall + ^2-106006|^2-106007 + ^(\S+): (\w+) \S+ (\w+) from + (\d+.\d+.\d+.\d+)/(\d+) to (\d+.\d+.\d+.\d+)/(\d+) + id, action, protocol, srcip, srcport, dstip, dstport + + + + pix + firewall + ^6-106015 + ^(\S+): (\w+) (\w+) \S+ \S+ (\S+) from + (\S+)/(\S+) to (\S+)/(\S+) + id, action, protocol, srcip, srcport, dstip, dstport + + + + pix + firewall + ^6-305012 + ^(\S+): (\w+) \w+ (\w+) translation + from \w+:(\S+)/(\d+) to \w+:(\S+)/(\d+) + id, action, protocol, srcip, srcport, dstip, dstport + + + + pix + firewall + ^3-106011|^3-106010 + ^(\S+): (\w+) \.+ (\w+) src + \w+:(\S+)/(\d+) dst \w+:(\S+)/(\d+) + id, action, protocol, srcip, srcport, dstip, dstport + + + + pix + ^2-106012: |^2-106017: | + ^2-106020|^1-106021|^1-106022| + ^4-4000 + ^(\S+): \.+ from (\d+.\d+.\d+.\d+) + id, srcip + + + + pix + ^6-605004|^6-308001|^6-605005 + ^(\S+): \.+ (\d+.\d+.\d+.\d+) + id, srcip + + + + pix + ^(\S+): + id + + + + + + + ^\d+ \d\d/\d\d/\d\d\d\d \S+ SEV=\d + ^(\S+) RPT=\d+ (\d+.\d+.\d+.\d+) + id, srcip + + + + + + + + ^snort + + + + ids + ^[**] [\d+:\d+:\d+] + + + + snort + ids + ^[**] |^[\d+:\d+:\d+] + ^[**] [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> + (\d+.\d+.\d+.\d+)|^[(\d+:\d+:\d+)] \.+ + (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+) + id,srcip,dstip + name,id,srcip,dstip + + + + + + + ^suhosin + ids + ^ALERT - (\.+) \(attacker '(\d+.\d+.\d+.\d+)', + id, srcip + name, location, id + + + + + + + ids + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\| + ^\S+\|(\S+)\| + (\d+.\d+.\d+.\d+)\|(\d+.\d+.\d+.\d+)\| + id, srcip, dstip + name, id, srcip, dstip + + + + + + + ^[\w+] [imp] |^[\w+] [horde] + + + + horde_imp + ^Login success + ^for (\S+) [(\d+.\d+.\d+.\d+)] + user, srcip + + + + horde_imp + ^FAILED LOGIN + ^ (\d+.\d+.\d+.\d+) to \S+ as (\S+) + srcip, user + + + + + + + ^WPsyslog + ^[ + ^(\d+.\d+.\d+.\d+) + srcip + + + + + + + ^roundcube + ^[\d\d-\w\w\w-\d\d\d\d \d\d:\d\d:\d\d \S+] + + + + roundcube + ^: Successful login for + ^(\S+) \(id \d+\) from (\d+.\d+.\d+.\d+)$ + user, srcip + + + + roundcube + ^ \w+ Error: Authentication + ^for (\.+) failed + user + + + + + + + ^httpd + + + + ^[warn] |^[notice] |^[error] + + + + apache-errorlog + + ^[client + ^ (\d+.\d+.\d+.\d+)] + srcip + + + + + + + + ^20\d\d/\d\d/\d\d \d\d:\d\d:\d\d [ + + + + nginx-errorlog + , client: \S+, server: \S+, request: "\S+ + , client: (\d+.\d+.\d+.\d+), + srcip + + + + + + + + web-log + ^\d+.\d+.\d+.\d+ + ^(\d+.\d+.\d+.\d+) \S+ \S+ [\S+ \S\d+] + "\w+ (\S+) HTTP\S+ (\d+) + srcip, url, id + + + + + + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d + + + + + + + windows-date-format + firewall + true + ^OPEN|^CLOSE|^DROP + ^(\w+) (\w+) + (\S+) (\S+) (\d+) (\d+) + action, protocol, srcip, dstip, srcport, dstport + + + + + + windows-date-format + web-log + true + ^\d+.\d+.\d+.\d+ \S+ W3SVC + ^(\d+.\d+.\d+.\d+) \S+ \S+ \S+ \S+ + \d+ \S+ (\S+ \S+) (\d+) + srcip,url,id + + + + + + windows-date-format + web-log + true + ^W3SVC\d+ \S+ \S+ \S+ + ^(\S+ \S+) \d+ \S+ (\d+.\d+.\d+.\d+) + \S+ \S+ \S+ \S+ \S+ (\d+) + url, srcip, id + + + + + + windows-date-format + true + ^\d+.\d+.\d+.\d+ \S+ MSFTPSVC + ^(\d+.\d+.\d+.\d+) (\S+) \S+ \S+ \S+ + \d+ [\d+](\S+) \S+ \S+ (\d+) + srcip,user,action,id + + + + + + + windows-date-format + true + ^\d+.\d+.\d+.\d+ \S+ SMTPSVC + ^(\d+.\d+.\d+.\d+) \S+ \S+ \S+ \S+ + \d+ (\S+) \S+ \S+ (\d+) + srcip, action, id + + + + + + + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d: + + + + racoon + true + + ^ERROR: couldn't find the pskey + ^for (\d+.\d+.\d+.\d+) + srcip + + + + racoon + ^(\w+): + action + + + + + + + squid + ^\d+ \d+.\d+.\d+.\d+ + ^\d+ (\d+.\d+.\d+.\d+) (\w+)/(\d+) \d+ \w+ (\S+) + srcip,action,id,url + + + + + + windows + ^WinEvtLog: + ^\.+: (\w+)\((\d+)\): (\.+): + (\.+): \.+: (\S+): + status, id, extra_data, user, system_name + name, location, user, system_name + + + + + + windows + ^security[\w+] \d+ + ^(\w+)[(\w+)] (\d+) + extra_data, status, id + + + + + + windows + ^MSWinEventLog\t\d\t\.+\t\d+\t\w\w\w \w\w\w \d\d \d\d + ^:\d\d:\d\d \d\d\d\d\t(\d+)\t(\.+) + \t(\.+)\t\.+\t(\.+)\t(\.+)\t + id, extra_data, user, status, system_name + name, id, location, user, system_name + + + + + + ^\w\w\w\w\w\w\w\w\w\w\w\w, + ^(\d+),\d+,\d+,(\S+),(\.+), + id, system_name, extra_data + name, location, id, system_name, extra_data + + + + + + ^\d\d\d\d\d\d\d\d,\d\d\d+, + SymantecWS_Decoder + + + + + + + ^20\d\d\d\d\d\d\<;> + ^\d+\<;>\S+\<;>(\d+)\<; + id + + + + + + + ^ossec: + ossec + + + + ossec + ossec + ^Agent started: + ^ '(\S+)' + extra_data + name, location, extra_data + + + + ^ossec$ + OSSECAlert_Decoder + + + + + + + ^[\d\d/\w\w\w/\d\d\d\d:\d\d:\d\d:\d\d \S+] + host=(\S+), + srcip + + + + + + + ^[\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d.\d\d\d '\S+' \d+ + + + + vmware + ^(\w+)] \S+ \S+ + status + + + + vmware + ^: User (\w+)@(\d+.\d+.\d+.\d+) + logged |^: Failed login \w+ for (\w+)@(\d+.\d+.\d+.\d+) + user, srcip + + + + vmware + + + + vmware-syslog + ^Accepted|^Rejected + ^ \S+ for user (\S+) from (\S+)$ + user, srcip + + + + vmware-syslog + ^login from + ^(\S+) as + srcip + + + + + + + ^audit$ + + + + solaris_bsm + \w+ session \d+ by + (\w+) session \d+ by + status + + + + solaris_bsm + ^ \S+ as \S+:\S+ from (\S+) + srcip + + + + + + + ^asterisk + + + + asterisk + ^NOTICE[\d+]: \S+ in \S+: Registration from + ^\S+ failed for '(\d+.\d+.\d+.\d+)' + srcip + + + + + + + ^%\w+-\d-\w+: + + + + + ^%\w+-\d-\w+: + + + + + + cisco-ios + firewall + ^%SEC-6-IPACCESSLOGP: + ^list \S+ (\w+) (\w+) + (\S+)\((\d+)\) -> (\S+)\((\d+)\), + action, protocol, srcip, srcport, dstip, dstport + + + + + + cisco-ios + ids + ^%IPS-4-SIGNATURE: + ^Sig:(\d+) \.+[(\S+):(\d+) -> + (\S+):(\d+)] + id, srcip, srcport, dstip, dstport + name, id, srcip, dstip + First time Cisco IOS IDS/IPS module rule fired. + + + + + + cisco-ios + ^(%\w+-\d-\w+): + id + + + + + + + + + ^Checkpoint + ^\s+\S+ \d\d:\d\d:\d\d + + + + checkpoint-syslog + firewall + ^drop|^accept|^reject + ^(\w+)\s+\S+ \p\S+ rule:\.+ + src: (\d+.\d+.\d+.\d+); dst: (\d+.\d+.\d+.\d+); proto: (\S+); + action,srcip,dstip,protocol + + + + checkpoint-syslog + firewall + service: (\d+); s_port: (\d+); + dstport,srcport + + + + checkpoint-syslog + ids + ^monitor|^drop + attack: (\.+); + src: (\d+.\d+.\d+.\d+); dst: (\d+.\d+.\d+.\d+); + proto: (\S+); + extra_data, srcip, dstip, protocol + name, extra_data, srcip, dstip + First time Checkpoint rule fired. + + + + + + + + + + ^\d\d,\d+/\d+/\d\d\d\d,\d+:\d+:\d+, + ^(\d\d), + id + + + +11020,05/05/09,00:00:38,DHCPV6 + + ^\d\d\d\d\d,\d\d/\d\d/\d\d,\d\d:\d\d:\d\d, + ^(\d\d\d\d\d), + id + + + + + diff --git a/etc/internal_options.conf b/etc/internal_options.conf new file mode 100755 index 0000000..e404271 --- /dev/null +++ b/etc/internal_options.conf @@ -0,0 +1,109 @@ +# internal_options.conf, Daniel B. Cid (dcid @ ossec.net). +# +# DO NOT TOUCH THIS FILE. The default configuration +# is at ossec.conf. More information at: +# http://www.ossec.net/en/manual.html +# +# This file should be handled with care. It contain +# run time modifications that can affect the use +# of ossec. Only change it if you know what you +# are doing. Again, look first at ossec.conf +# for most of the things you want to change. + + +# Analysisd default rule timeframe. +analysisd.default_timeframe=360 +# Analysisd stats maximum diff. +analysisd.stats_maxdiff=25000 +# Analysisd stats minimum diff. +analysisd.stats_mindiff=250 +# Analysisd stats percentage (how much to differ from average) +analysisd.stats_percent_diff=30 +# Analysisd FTS list size. +analysisd.fts_list_size=32 +# Analysisd FTS minimum string size. +analysisd.fts_min_size_for_str=14 +# Analysisd Enable the firewall log (at logs/firewall/firewall.log) +# 1 to enable, 0 to disable. +analysisd.log_fw=1 + + +# Logcollector file loop timeout (check every 2 seconds for file changes) +logcollector.loop_timeout=2 + +# Logcollector number of attempts to open a log file. +logcollector.open_attempts=8 + + +# Remoted counter io flush. +remoted.recv_counter_flush=128 + +# Remoted compression averages printout. +remoted.comp_average_printout=19999 + +# Verify msg id (set to 0 to disable it) +remoted.verify_msg_id=1 + + +# Maild strict checking (0=disabled, 1=enabled) +maild.strict_checking=1 + +# Maild grouping (0=disabled, 1=enabled) +# Groups alerts within the same e-mail. +maild.groupping=1 + +# Maild full subject (0=disabled, 1=enabled) +maild.full_subject=0 + + +# Monitord day_wait. Ammount of seconds to wait before compressing/signing +# the files. +monitord.day_wait=10 + +# Monitord compress. (0=do not compress, 1=compress) +monitord.compress=1 + +# Monitord sign. (0=do not sign, 1=sign) +monitord.sign=1 + +# Monitord monitor_agents. (0=do not monitor, 1=monitor) +monitord.monitor_agents=1 + + +# Syscheck checking/usage speed. To avoid large cpu/memory +# usage, you can specify how much to sleep after generating +# the checksum of X files. The default is to sleep 2 seconds +# after reading 15 files. +syscheck.sleep=2 +syscheck.sleep_after=15 + + +# Database - maximum number of reconnect attempts +dbd.reconnect_attempts=10 + + +# Debug options. +# Debug 0 -> no debug +# Debug 1 -> first level of debug +# Debug 2 -> full debugging + +# Windows debug (used by the windows agent) +windows.debug=0 + +# Syscheck (local, server and unix agent) +syscheck.debug=0 + +# Remoted (server debug) +remoted.debug=0 + +# Analysisd (server or local) +analysisd.debug=0 + +# Log collector (server, local or unix agent) +logcollector.debug=0 + +# Unix agentd +agent.debug=0 + + +# EOF diff --git a/etc/ossec-agent.conf b/etc/ossec-agent.conf new file mode 100755 index 0000000..3afca95 --- /dev/null +++ b/etc/ossec-agent.conf @@ -0,0 +1,64 @@ + + + + + 192.168.10.100 + + + + + 7200 + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin + + + /etc/mtab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/adjtime + /etc/httpd/logs + + + + /var/ossec/etc/shared/rootkit_files.txt + /var/ossec/etc/shared/rootkit_trojans.txt + + + + syslog + /var/log/messages + + + + syslog + /var/log/authlog + + + + syslog + /var/log/secure + + + + syslog + /var/log/xferlog + + + + syslog + /var/log/maillog + + + + apache + /var/www/logs/access_log + + + + apache + /var/www/logs/error_log + + diff --git a/etc/ossec-local.conf b/etc/ossec-local.conf new file mode 100755 index 0000000..1816a69 --- /dev/null +++ b/etc/ossec-local.conf @@ -0,0 +1,148 @@ + + + + + yes + daniel.cid@xxx.com + smtp.xxx.com. + ossecm@ossec.xxx.com. + + + + rules_config.xml + sshd_rules.xml + syslog_rules.xml + pix_rules.xml + named_rules.xml + pure-ftpd_rules.xml + proftpd_rules.xml + web_rules.xml + apache_rules.xml + ids_rules.xml + squid_rules.xml + firewall_rules.xml + postfix_rules.xml + sendmail_rules.xml + spamd_rules.xml + msauth_rules.xml + attack_rules.xml + + + + + 7200 + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin + + + /etc/mtab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/adjtime + /etc/httpd/logs + + + + /var/ossec/etc/shared/rootkit_files.txt + /var/ossec/etc/shared/rootkit_trojans.txt + + + + 127.0.0.1 + 192.168.2.1 + 192.168.2.190 + 192.168.2.32 + 192.168.2.10 + + + + 1 + 7 + + + + host-deny + host-deny.sh + srcip + yes + + + + firewall-drop + firewall-drop.sh + srcip + yes + + + + disable-account + disable-account.sh + user + yes + + + + + + + host-deny + local + 6 + 600 + + + + + firewall-drop + local + 6 + 600 + + + + + + syslog + /var/log/messages + + + + syslog + /var/log/authlog + + + + syslog + /var/log/secure + + + + syslog + /var/log/xferlog + + + + syslog + /var/log/maillog + + + + apache + /var/www/logs/access_log + + + + apache + /var/www/logs/error_log + + diff --git a/etc/ossec-server.conf b/etc/ossec-server.conf new file mode 100755 index 0000000..6b67971 --- /dev/null +++ b/etc/ossec-server.conf @@ -0,0 +1,152 @@ + + + + + yes + daniel.cid@xxx.com + smtp.xxx.com. + ossecm@ossec.xxx.com. + + + + rules_config.xml + sshd_rules.xml + syslog_rules.xml + pix_rules.xml + named_rules.xml + pure-ftpd_rules.xml + proftpd_rules.xml + web_rules.xml + apache_rules.xml + ids_rules.xml + squid_rules.xml + firewall_rules.xml + postfix_rules.xml + sendmail_rules.xml + spamd_rules.xml + msauth_rules.xml + attack_rules.xml + + + + + 7200 + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin + + + /etc/mtab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/adjtime + /etc/httpd/logs + + + + /var/ossec/etc/shared/rootkit_files.txt + /var/ossec/etc/shared/rootkit_trojans.txt + + + + 127.0.0.1 + 192.168.2.1 + 192.168.2.190 + 192.168.2.32 + 192.168.2.10 + + + + secure + + + + 1 + 7 + + + + host-deny + host-deny.sh + srcip + yes + + + + firewall-drop + firewall-drop.sh + srcip + yes + + + + disable-account + disable-account.sh + user + yes + + + + + + + host-deny + local + 6 + 600 + + + + + firewall-drop + local + 6 + 600 + + + + + + syslog + /var/log/messages + + + + syslog + /var/log/authlog + + + + syslog + /var/log/secure + + + + syslog + /var/log/xferlog + + + + syslog + /var/log/maillog + + + + apache + /var/www/logs/access_log + + + + apache + /var/www/logs/error_log + + diff --git a/etc/ossec.conf b/etc/ossec.conf new file mode 100755 index 0000000..3136722 --- /dev/null +++ b/etc/ossec.conf @@ -0,0 +1,153 @@ + + + + + yes + daniel.cid@xxx.com + smtp.xxx.com. + ossecm@ossec.xxx.com. + no + + + + rules_config.xml + sshd_rules.xml + syslog_rules.xml + pix_rules.xml + named_rules.xml + pure-ftpd_rules.xml + proftpd_rules.xml + web_rules.xml + apache_rules.xml + ids_rules.xml + squid_rules.xml + firewall_rules.xml + postfix_rules.xml + sendmail_rules.xml + spamd_rules.xml + msauth_rules.xml + attack_rules.xml + + + + + 7200 + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin + + + /etc/mtab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/adjtime + /etc/httpd/logs + + + + /var/ossec/etc/shared/rootkit_files.txt + /var/ossec/etc/shared/rootkit_trojans.txt + + + + 127.0.0.1 + 192.168.2.1 + 192.168.2.190 + 192.168.2.32 + 192.168.2.10 + + + + secure + + + + 1 + 7 + + + + host-deny + host-deny.sh + srcip + yes + + + + firewall-drop + firewall-drop.sh + srcip + yes + + + + disable-account + disable-account.sh + user + yes + + + + + + + host-deny + local + 6 + 600 + + + + + firewall-drop + local + 6 + 600 + + + + + + syslog + /var/log/messages + + + + syslog + /var/log/authlog + + + + syslog + /var/log/secure + + + + syslog + /var/log/xferlog + + + + syslog + /var/log/maillog + + + + apache + /var/www/logs/access_log + + + + apache + /var/www/logs/error_log + + diff --git a/etc/preloaded-vars.conf b/etc/preloaded-vars.conf new file mode 100755 index 0000000..d5cb0d2 --- /dev/null +++ b/etc/preloaded-vars.conf @@ -0,0 +1,118 @@ +# preloaded-vars.conf, Daniel B. Cid (dcid @ ossec.net). +# +# Use this file to customize your installations. +# It will make the install.sh script pre-load some +# specific options to make it run automatically +# or with less questions. + +# PLEASE NOTE: +# When we use "n" or "y" in here, it should be changed +# to "n" or "y" in the language your are doing the +# installation. For example, in portuguese it would +# be "s" or "n". + + +# USER_LANGUAGE defines to language to be used. +# It can be "en", "br", "tr", "it", "de" or "pl". +# In case of an invalid language, it will default +# to English "en" +#USER_LANGUAGE="en" # For english +#USER_LANGUAGE="br" # For portuguese + + +# If USER_NO_STOP is set to anything, the confirmation +# messages are not going to be asked. +#USER_NO_STOP="y" + + +# USER_INSTALL_TYPE defines the installation type to +# be used during install. It can only be "local", +# "agent" or "server". +#USER_INSTALL_TYPE="local" +#USER_INSTALL_TYPE="agent" +#USER_INSTALL_TYPE="server" + + +# USER_DIR defines the location to install ossec +#USER_DIR="/var/ossec" + + +# If USER_DELETE_DIR is set to "y", the directory +# to install OSSEC will be removed if present. +#USER_DELETE_DIR="y" + + +# If USER_ENABLE_ACTIVE_RESPONSE is set to "n", +# active response will be disabled. +#USER_ENABLE_ACTIVE_RESPONSE="y" + + +# If USER_ENABLE_SYSCHECK is set to "y", +# syscheck will be enabled. Set to "n" to +# disable it. +#USER_ENABLE_SYSCHECK="y" + + +# If USER_ENABLE_ROOTCHECK is set to "y", +# rootcheck will be enabled. Set to "n" to +# disable it. +#USER_ENABLE_ROOTCHECK="y" + + +# If USER_UPDATE is set to anything, the update +# installation will be done. +#USER_UPDATE="y" + +# If USER_UPDATE_RULES is set to anything, the +# rules will also be updated. +#USER_UPDATE_RULES="y" + +# If USER_BINARYINSTALL is set, the installation +# is not going to compile the code, but use the +# binaries from ./bin/ +#USER_BINARYINSTALL="x" + + +### Agent Installation variables. ### + +# USER_AGENT_SERVER_IP specifies the IP address of the +# ossec server. Only used on agent installations. +#USER_AGENT_SERVER_IP="1.2.3.4" + + + +### Server/Local Installation variables. ### + +# USER_ENABLE_EMAIL enables or disables email alerting. +#USER_ENABLE_EMAIL="y" + +# USER_EMAIL_ADDRESS defines the destination e-mail of the alerts. +#USER_EMAIL_ADDRESS="dcid@test.ossec.net" + +# USER_EMAIL_SMTP defines the SMTP server to send the e-mails. +#USER_EMAIL_SMTP="test.ossec.net" + + +# USER_ENABLE_SYSLOG enables or disables remote syslog. +#USER_ENABLE_SYSLOG="y" + + +# USER_ENABLE_FIREWALL_RESPONSE enables or disables +# the firewall response. +#USER_ENABLE_FIREWALL_RESPONSE="y" + + +# Enable PF firewall (OpenBSD and FreeBSD only) +#USER_ENABLE_PF="y" + + +# PF table to use (OpenBSD and FreeBSD only). +#USER_PF_TABLE="ossec_fwtable" + + +# USER_WHITE_LIST is a list of IPs or networks +# that are going to be set to never be blocked. +#USER_WHITE_LIST="192.168.2.1 192.168.1.0/24" + + +#### exit ? ### diff --git a/etc/rules/apache_rules.xml b/etc/rules/apache_rules.xml new file mode 100755 index 0000000..1a723dc --- /dev/null +++ b/etc/rules/apache_rules.xml @@ -0,0 +1,170 @@ + + + + + + apache-errorlog + Apache messages grouped. + + + + 30100 + ^[error] + Apache error messages grouped. + + + + 30100 + ^[warn] + Apache warn messages grouped. + + + + 30100 + ^[notice] + Apache notice messages grouped. + + + + 30103 + exit signal Segmentation Fault + Apache segmentation fault. + http://www.securityfocus.com/infocus/1633 + service_availability, + + + + 30101 + denied by server configuration + Attempt to access forbidden file or directory. + access_denied, + + + + 30101 + Directory index forbidden by rule + Attempt to access forbidden directory index. + access_denied, + + + + 30101 + Client sent malformed Host header + Code Red attack. + http://www.cert.org/advisories/CA-2001-19.html + automatic_attack, + + + + 30102 + authentication failed + User authentication failed. + authentication_failed, + + + + 30101 + user \S+ not found + Attempt to login using a non-existent user. + invalid_login, + + + + 30101 + authentication failure + User authentication failed. + authentication_failed, + + + + 30101 + File does not exist: | + failed to open stream: No such file or directory| + Failed opening + Attempt to access an non-existent file (those are reported on the access.log). + unknown_resource, + + + + + 30101 + Invalid URI in request + Invalid URI (bad client request). + invalid_request, + + + + 30115 + + Multiple Invalid URI requests from + same source. + invalid_request, + + + + 30101 + File name too long|request failed: URI too long + Invalid URI, file name too long. + invalid_request, + + + + + 30101 + mod_security: Access denied|ModSecurity: Access denied + Access attempt blocked by Mod Security. + access_denied, + + + + 30118 + + Multiple attempts blocked by Mod Security. + access_denied, + + + + 30101 + Resource temporarily unavailable: + Apache without resources to run. + service_availability, + + + + ^mod_security-message: + Modsecurity alert. + + + + 30200 + ^mod_security-message: Access denied + Modsecurity access denied. + access_denied, + + + + 30201 + Multiple attempts blocked by Mod Security. + access_denied, + + + + + + diff --git a/etc/rules/arpwatch_rules.xml b/etc/rules/arpwatch_rules.xml new file mode 100755 index 0000000..4afb4c5 --- /dev/null +++ b/etc/rules/arpwatch_rules.xml @@ -0,0 +1,66 @@ + + + + + + arpwatch + Grouping of the arpwatch rules. + + + + 7200 + alert_by_email + + Arpwatch new host detected. + new_host, + + + + 7200 + flip flop + Arpwatch "flip flop" message. + IP address/MAC relation changing too often. + ip_spoof, + + + + 7200 + reaper: pid + Arpwatch exiting. + service_availability, + + + + 7200 + changed ethernet address + Changed network interface for ip address. + ip_spoof, + + + + 7200 + bad interface eth0|exiting|Running as + Arpwatch startup/exiting messages. + + + + 7200 + sent bad addr len + Arpwatch detected bad address len (ignored). + + + + + diff --git a/etc/rules/asterisk_rules.xml b/etc/rules/asterisk_rules.xml new file mode 100755 index 0000000..a12711d --- /dev/null +++ b/etc/rules/asterisk_rules.xml @@ -0,0 +1,82 @@ + + + + + + + asterisk + Asterisk messages grouped. + + + + 6200 + ^NOTICE + Asterisk notice messages grouped. + + + + 6200 + ^WARN + Asterisk warning message. + + + + 6200 + ^ERROR + Asterisk error message. + + + + 6201 + Wrong password + Login session failed. + authentication_failed, + + + + 6201 + Username/auth name mismatch + Login session failed (invalid user). + invalid_login, + + + + 6201 + No matching peer found + Login session failed (invalid extension). + invalid_login, + + + + 6211 + + Multiple failed logins (user enumeration in process). + + + + 6210 + + Multiple failed logins. + + + + 6212 + + Extension enumeration. + + + + + diff --git a/etc/rules/attack_rules.xml b/etc/rules/attack_rules.xml new file mode 100755 index 0000000..bcc5195 --- /dev/null +++ b/etc/rules/attack_rules.xml @@ -0,0 +1,121 @@ + + + + +^apache$|^mysql$|^www$|^nobody$|^nogroup$|^portmap$|^named$|^rpc$|^mail$|^ftp$|^shutdown$|^halt$|^daemon$|^bin$|^postfix$|^shell$|^info$|^guest$|^psql$|^user$|^users$|^console$|^uucp$|^lp$|^sync$|^sshd$|^cdrom$|^ossec$ + + + + + + authentication_success + $SYS_USERS + System user successfully logged to the system. + invalid_login, + + + + ^rpc.statd[\d+]: gethostbyname error for \W+ + Buffer overflow attack on rpc.statd + exploit_attempt, + + + + ftpd[\d+]: \S+ FTP LOGIN FROM \.+ 0bin0sh + Buffer overflow on WU-FTPD versions prior to 2.6 + exploit_attempt, + + + + ????????????????????? + Possible buffer overflow attempt. + exploit_attempt, + + + + changed by \(\(null\) + "Null" user changed some information. + exploit_attempt, + + + + @@@@@@@@@@@@@@@@@@@@@@@@@ + Buffer overflow attempt (probably on yppasswd). + exploit_attempt, + + + + cachefsd: Segmentation Fault - core dumped + Heap overflow in the Solaris cachefsd service. + 2002-0033 + exploit_attempt, + + + + attempt to execute code on stack by + Stack overflow attempt or program exiting + with SEGV (Solaris). + http://snap.nlc.dcccd.edu/reference/sysadmin/julian/ch18/389-392.html + exploit_attempt, + + + + authentication_failed + Multiple authentication failures. + authentication_failures, + + + + authentication_success + authentication_failures + + Multiple authentication failures followed + by a success. + + + + virus + Multiple viruses detected - Possible outbreak. + virus, + + + + + + + + + + adduser + attacks + Attacks followed by the addition + of an user. + + + + + + + + + connection_attempt + Network scan from same source ip. + + http://project.honeynet.org/papers/enemy2/ + + + + + diff --git a/etc/rules/cisco-ios_rules.xml b/etc/rules/cisco-ios_rules.xml new file mode 100755 index 0000000..bbb9993 --- /dev/null +++ b/etc/rules/cisco-ios_rules.xml @@ -0,0 +1,95 @@ + + + + + + cisco-ios + Grouping of Cisco IOS rules. + + + + 4700 + -0- + Cisco IOS emergency message. + + + + + 4700 + -1- + Cisco IOS alert message. + + + + 4700 + -2- + Cisco IOS critical message. + + + + 4700 + -3- + Cisco IOS error message. + + + + 4700 + -4- + Cisco IOS warning message. + + + + 4700 + -5- + Cisco IOS notification message. + + + + 4700 + -6- + Cisco IOS informational message. + + + + 4700 + -7- + Cisco IOS debug message. + + + + 4715 + ^%SYS-5-CONFIG + Cisco IOS router configuration changed. + config_changed, + + + + 4715 + ^%SEC_LOGIN-5-LOGIN_SUCCESS + Successful login to the router. + authentication_success, + + + + 4714 + ^%SEC_LOGIN-4-LOGIN_FAILED + Failed login to the router. + authentication_failed, + + + + + + diff --git a/etc/rules/courier_rules.xml b/etc/rules/courier_rules.xml new file mode 100755 index 0000000..92a449e --- /dev/null +++ b/etc/rules/courier_rules.xml @@ -0,0 +1,66 @@ + + + + + + + courier + Grouping for the courier rules. + + + + 3900 + ^Connection, + New courier (imap/pop3) connection. + connection_attempt, + + + + 3900 + ^LOGIN FAILED, + Courier (imap/pop3) authentication failed. + authentication_failed, + + + + 3900 + ^LOGOUT,|^DISCONNECTED + Courier logout/timeout. + + + + 3900 + ^LOGIN, + Courier (imap/pop3) authentication success. + authentication_success, + + + + 3902 + Courier brute force (multiple failed logins). + authentication_failures, + + + + + 3901 + + Multiple connection attempts from same source. + recon, + + + + + diff --git a/etc/rules/dovecot_rules.xml b/etc/rules/dovecot_rules.xml new file mode 100644 index 0000000..61fa2f3 --- /dev/null +++ b/etc/rules/dovecot_rules.xml @@ -0,0 +1,77 @@ + + + + + + dovecot + Dovecot Messages Grouped. + + + + 9700 + login: Login: + Dovecot Authentication Success. + authentication_success, + + + + 9700 + Password mismatch$ + Dovecot Authentication Failed. + authentication_failed, + + + + 9700 + starting up + Dovecot is Starting Up. + + + + 9700 + ^Fatal: + alert_by_email + Dovecot Fatal Failure. + + + + 9700 + user not found|User not known|unknown user + Dovecot Invalid User Login Attempt. + invalid_login,authentication_failed, + + + + 9700 + : Disconnected: + Dovecot Session Disconnected. + + + + 9700 + : Aborted login + Dovecot Aborted Login. + invalid_login, + + + + + + 9702 + + Dovecot Multiple Authentication Failures. + authentication_failures, + + + + 9705 + + Dovecot brute force attack (multiple auth failures). + authentication_failures, + + diff --git a/etc/rules/firewall_rules.xml b/etc/rules/firewall_rules.xml new file mode 100755 index 0000000..09418f3 --- /dev/null +++ b/etc/rules/firewall_rules.xml @@ -0,0 +1,39 @@ + + + + + + firewall + Firewall rules grouped. + + + + + 4100 + DROP + no_log + Firewall drop event. + firewall_drop, + + + + 4101 + + Multiple Firewall drop events from same source. + multiple_drops, + + diff --git a/etc/rules/ftpd_rules.xml b/etc/rules/ftpd_rules.xml new file mode 100755 index 0000000..813ae81 --- /dev/null +++ b/etc/rules/ftpd_rules.xml @@ -0,0 +1,95 @@ + + + + + + ftpd + Grouping for the ftpd rules. + + + + 11100 + FTP LOGIN REFUSED + FTP connection refused. + authentication_failed,access_denied, + + + + 11100 + created + File created via FTP + + + + 11100 + deleted + File deleted via FTP + + + + 11100 + FTPD: IMPORT file + User uploaded a file to server. + + + + 11100 + FTPD: EXPORT file + User downloaded a file to server. + + + + 11100 + FTP LOGIN FROM|connection from|connect from + connection_attempt + Remote host connected to FTP server. + + + + 11100 + refused connect from + access_denied, + Connection blocked by Tcp Wrappers. + + + + 11100 + warning: can't verify hostname: |gethostbyaddr: + Reverse lookup error (bad ISP config). + client_misconfig, + + + + 11100 + repeated login failures + Multiple FTP failed login attempts. + authentication_failures, + + + + 11100 + timed out after + User disconnected due to time out. + + + + 11100 + PAM_ERROR_MSG: Account is disabled + Attempt to login with disabled account. + authentication_failed, + + + + 11100 + ^Failed authentication from + FTP authentication failure. + authentication_failed, + + + + + diff --git a/etc/rules/hordeimp_rules.xml b/etc/rules/hordeimp_rules.xml new file mode 100755 index 0000000..cbefa50 --- /dev/null +++ b/etc/rules/hordeimp_rules.xml @@ -0,0 +1,77 @@ + + + + + + horde_imp + Grouping for the Horde imp rules. + + + + 9300 + ^[info] + Horde IMP informational message. + + + + 9300 + ^[notice] + Horde IMP notice message. + + + + 9300 + ^[error] + Horde IMP error message. + + + + 9300 + ^[emergency] + Horde IMP emergency message. + service_availability, + + + + 9302 + Login success for + Horde IMP successful login. + authentication_success, + + + + 9303 + FAILED LOGIN + Horde IMP Failed login. + authentication_failed, + + + + 9306 + + Horde brute force (multiple failed logins). + authentication_failures, + + + + 9304 + Multiple Horde emergency messages. + service_availability, + + + + + + diff --git a/etc/rules/ids_rules.xml b/etc/rules/ids_rules.xml new file mode 100755 index 0000000..1461c93 --- /dev/null +++ b/etc/rules/ids_rules.xml @@ -0,0 +1,103 @@ + + + +8 + + + + ids + + First time this IDS alert is generated. + fts, + + + + ids + srcip, id + IDS event. + + + + + 20100, 20101 + snort + + ^1:1852:|^1:368:|^1:384:|^1:366:|^1:402:|^1:408:|^1:1365:| + ^1:480:|^1:399:|^1:2925: + Ignored snort ids. + + + + + 20100, 20101 + dragon-nids + + ^EOL$|^SOF$|^HEARTBEAT$|^DYNAMIC-TCP$|^DYNAMIC-UDP$ + Ignored snort ids. + + + + 20101 + + id + Multiple IDS alerts for same id. + + + + 20101 + + srcip, id + Multiple IDS events from same source ip. + + + + + + 20151 + + + srcip, id + Multiple IDS events from same source ip + (ignoring now this srcip and id). + + + + 20152 + + id + Multiple IDS alerts for same id + (ignoring now this id). + + diff --git a/etc/rules/imapd_rules.xml b/etc/rules/imapd_rules.xml new file mode 100755 index 0000000..ae470e8 --- /dev/null +++ b/etc/rules/imapd_rules.xml @@ -0,0 +1,51 @@ + + + +6 + + + + imapd + Grouping of the imapd rules. + + + + 3600 + Login failed user=|AUTHENTICATE LOGIN failure + Imapd user login failed. + authentication_failed, + + + + 3600 + Authenticated user= + Imapd user login. + authentication_success, + + + + 3600 + Logout user= + Imapd user logout. + + + + 3601 + + Multiple failed logins from same source ip. + authentication_failures, + + + diff --git a/etc/rules/local_rules.xml b/etc/rules/local_rules.xml new file mode 100644 index 0000000..4d05be2 --- /dev/null +++ b/etc/rules/local_rules.xml @@ -0,0 +1,56 @@ + + + + + + + + + + 5711 + 1.1.1.1 + Example of rule that will ignore sshd + failed logins from IP 1.1.1.1. + + + + + + + + + + + + + + diff --git a/etc/rules/mailscanner_rules.xml b/etc/rules/mailscanner_rules.xml new file mode 100755 index 0000000..18329a2 --- /dev/null +++ b/etc/rules/mailscanner_rules.xml @@ -0,0 +1,41 @@ + + + + + + mailscanner + Grouping of mailscanner rules. + + + + 3700 + not + Non spam message. Ignored. + + + + 3700 + spam + Mail Scanner spam detected. + spam, + + + + 3702 + + Multiple attempts of spam. + multiple_spam, + + diff --git a/etc/rules/mcafee_av_rules.xml b/etc/rules/mcafee_av_rules.xml new file mode 100644 index 0000000..cf61928 --- /dev/null +++ b/etc/rules/mcafee_av_rules.xml @@ -0,0 +1,124 @@ + + +^259|^100|^1000|^1001|^1002|^1003|^1004|^1005|^1006|^1007|^1008|^5003|^5005|^5008|^5010|^5011|^5019|^5020|^5021|^5022|^5030|^5031|^5032|^5033|^5034|^5035|^5046|^5047|^5048|^5049|^5051|^5054|^5057|^5059|^5060|^5063|^5063 +^258|^5001|^5028|^5036|^5037|^5038|^5039|^5040|^5041|^5053|^5056|^5061|^5062|^5065 +^257|^5000|^5026|^5052|^5055 +quarantined|moved to quarantine|file was deleted|deleted successfully|has been deleted|message deleted|deleted after|cleaned|successfully deleted +The file \.+ contain|infected with|User defined detection|scan found|error attempting to clean +10 + + + + 18101,18102,18103 + windows + ^McLogEvent + Grouping of McAfee Windows AV rules. + + + + 7500 + $MCAFEE_INFO + McAfee Windows AV informational event. + + + + 7500 + $MCAFEE_WARN + McAfee Windows AV warning event. + + + + 7500 + $MCAFEE_ERROR + McAfee Windows AV error event. + + + + 7500 + $MCAFEE_VIRUS + virus + McAfee Windows AV - Virus detected and not removed. + + + + 7504 + $MCAFEE_VIRUS_OK + virus + McAfee Windows AV - Virus detected and properly removed. + + + + 7504 + Will be deleted + virus + McAfee Windows AV - Virus detected and file will be deleted. + + + + 7500 + scan started|scan stopped + McAfee Windows AV - Scan started or stopped. + + + + 7501 + ^257 + completed. No detections + McAfee Windows AV - Scan completed with no viruses found. + + + + 7500 + scan was cancelled |has taken too long + McAfee Windows AV - Virus scan cancelled. + + + + 7500 + scan was canceled because + McAfee Windows AV - Virus scan cancelled due to shutdown. + + + + 7500 + update was successful + McAfee Windows AV - Virus program or DAT update succeeded. + + + + 7500 + update failed + McAfee Windows AV - Virus program or DAT update failed. + + + + 7500 + update was cancelled + McAfee Windows AV - Virus program or DAT update cancelled. + + + + 7505 + contains the EICAR test file + alert_by_email + McAfee Windows AV - EICAR test file detected. + + + + + + 7502 + Multiple McAfee AV warning events. + + + + diff --git a/etc/rules/ms-exchange_rules.xml b/etc/rules/ms-exchange_rules.xml new file mode 100755 index 0000000..0206d3d --- /dev/null +++ b/etc/rules/ms-exchange_rules.xml @@ -0,0 +1,55 @@ + + + + + + + + + msexchange + Grouping of Exchange rules. + + + + 3800 + RCPT + ^550 + E-mail rcpt is not valid (invalid account). + spam, + + + + 3800 + ^5 + E-mail 500 error code. + spam, + + + + 3801 + + Multiple e-mail attempts to an invalid account. + multiple_spam, + + + + 3802 + + Multiple e-mail 500 error code (spam). + multiple_spam, + + + + diff --git a/etc/rules/ms_dhcp_rules.xml b/etc/rules/ms_dhcp_rules.xml new file mode 100644 index 0000000..6e25158 --- /dev/null +++ b/etc/rules/ms_dhcp_rules.xml @@ -0,0 +1,435 @@ + + + + + + + + + + + + + ms-dhcp-ipv4 + Grouping for the MS-DHCP rules. + + + + 6300 + ^00 + The log was started. + service_start, + + + + 6300 + ^01 + The log was stopped. + service_availability, + + + + 6300 + ^02 + The log was temporarily paused due to low disk space. + system_error, + + + + 6300 + ^10 + A new IP address was leased to a client. + dhcp_lease_action, + + + + 6300 + ^11 + A lease was renewed by a client. + dhcp_lease_action, + + + + 6300 + ^12 + A lease was released by a client. + dhcp_lease_action, + + + + 6300 + ^13 + An IP address was found to be in use on the network. + dhcp_lease_action, + + + + 6300 + ^14 + A lease request could not be satisfied because the scope's address pool was exhausted. + service_availability,dhcp_lease_action, + + + + 6300 + ^15 + A lease was denied. + dhcp_lease_action, + + + + 6300 + ^16 + A lease was deleted. + dhcp_lease_action, + + + + 6300 + ^17 + A lease was expired and DNS records for an expired leases have not been deleted. + dhcp_lease_action, + + + + 6300 + ^18 + A lease was expired and DNS records were deleted. + dhcp_lease_action,dhcp_dns_maintenance + + + + 6300 + ^20 + A BOOTP address was leased to a client. + dhcp_lease_action, + + + + 6300 + ^21 + A dynamic BOOTP address was leased to a client. + dhcp_lease_action, + + + + + 6300 + ^22 + A BOOTP request could not be satisfied because the scope's address pool for BOOTP was exhausted. + dhcp_lease_action, + + + + 6300 + ^23 + A BOOTP IP address was deleted after checking to see it was not in use. + dhcp_lease_action, + + + + 6300 + ^24 + IP address cleanup operation has began. + dhcp_maintenance, + + + + 6300 + ^25 + IP address cleanup statistics. + dhcp_maintenance, + + + + 6300 + ^30 + DNS update request to the named DNS server. + dhcp_dns_maintenance, + + + + 6300 + ^31 + DNS update failed. + dhcp_dns_maintenance, + + + + 6300 + ^32 + DNS update successful. + dhcp_dns_maintenance, + + + + 6300 + ^33 + Packet dropped due to NAP policy. + dhcp_lease_action, + + + + + 6300 + ^5 + Codes above 50 are used for Rogue Server Detection information. + dhcp_rogue_server, + + + + + + + + + ms-dhcp-ipv6 + Grouping for the MS-DHCP rules. + + + + 6350 + ^11000 + Solicit. + dhcp_ipv6, + + + + 6350 + ^11001|^11002 + Advertise. + dhcp_ipv6, + + + + 6350 + ^11003 + Confirm. + dhcp_ipv6, + + + + 6350 + ^11004 + Renew. + dhcp_ipv6, + + + + 6350 + ^11005 + Rebind. + dhcp_ipv6, + + + + + 6350 + ^11006 + DHCP Decline. + dhcp_ipv6, + + + + 6350 + ^11007 + Release. + dhcp_ipv6, + + + + 6350 + ^11008 + Information Request. + dhcp_ipv6, + + + + 6350 + ^11009 + Scope Full. + dhcp_ipv6, + + + + 6350 + ^11010 + Started. + service_start, + + + + 6350 + ^11011 + Stopped. + service_availability, + + + + 6350 + ^11012 + Audit log paused. + service_availability, + + + + + 6350 + ^11013 + DHCP Log File. + system_error, + + + + 6350 + ^11014 + Bad Address. + dhcp_ipv6, + + + + 6350 + ^11015 + Address is already in use. + dhcp_ipv6, + + + + 6350 + ^11016 + Client deleted. + dhcp_ipv6, + + + + 6350 + ^11017 + DNS record not deleted. + dhcp_ipv6, + + + + 6350 + ^11018 + Expired. + dhcp_ipv6, + + + + 6350 + ^11019 + Expired and Deleted count. + dhcp_ipv6, + + + + 6350 + ^11020 + Database cleanup begin. + dhcp_ipv6, + + + + + 6350 + ^11021 + Database cleanup end. + dhcp_ipv6, + + + + 6350 + ^11023 + Service not authorized in AD. + dhcp_ipv6, + + + + 6350 + ^11024 + Service authorized in AD. + dhcp_ipv6, + + + + 6350 + ^11025 + Service has not determined if it is authorized in AD. + dhcp_ipv6, + + + diff --git a/etc/rules/ms_ftpd_rules.xml b/etc/rules/ms_ftpd_rules.xml new file mode 100755 index 0000000..2df8255 --- /dev/null +++ b/etc/rules/ms_ftpd_rules.xml @@ -0,0 +1,72 @@ + + + + + + msftp + Grouping for the Microsoft ftp rules. + + + + 11500 + USER + New FTP connection. + connection_attempt, + + + + 11500 + PASS + 530 + FTP Authentication failed. + authentication_failed, + + + + 11500 + PASS + 230 + FTP Authentication success. + authentication_success, + + + + 11500 + ^5 + FTP client request failed. + + + + 11502 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11501 + + Multiple connection attempts from same source. + recon, + + + + 11504 + + Multiple FTP errors from same source. + + + + + diff --git a/etc/rules/msauth_rules.xml b/etc/rules/msauth_rules.xml new file mode 100755 index 0000000..a822465 --- /dev/null +++ b/etc/rules/msauth_rules.xml @@ -0,0 +1,440 @@ + + + +6 + + + + windows + Group of windows rules. + + + + 18100 + ^INFORMATION + Windows informational event. + + + + 18100 + ^WARNING + Windows warning event. + + + + 18100 + ^ERROR + Windows error event. + system_error, + + + + 18100 + ^AUDIT_SUCCESS|^success + Windows audit success event. + + + + 18100 + ^AUDIT_FAILURE|^failure + Windows audit failure event. + + + + 18105 + ^529|^530|^531|^532|^533|^534|^535|^536|^537|^539|^4625 + Windows Logon Failure. + win_authentication_failed, + + + + 18104 + ^528|^540|^672|^673|^4624|^4769 + Windows Logon Success. + authentication_success, + + + + 18105 + ^577 + Failed attempt to perform a privileged + operation. + + + + 18104 + ^682|^683 + Session reconnected/disconnected to winstation. + + + + 18104 + ^624|^626|^645|^4720|^4722 + User account enabled or created. + adduser,account_changed, + + + + 18104 + ^628|^642|^685|^4738|^4781 + User account changed. + account_changed, + + + + 18104 + ^630|^629|^4725|^4726 + User account disabled or deleted. + adduser,account_changed, + + + + 18104 + ^612|^643|^4719|^4907|^4912 + Windows Audit Policy changed. + policy_changed, + + + + 18104 + ^63|^641|^664|^658|^659|^660|^662|^668|^4907 + Group account changed. + adduser,account_changed, + + + + 18104 + ^640 + General account database changed. + http://www.ultimatewindowssecurity.com/events/com259.html + adduser,account_changed, + + + + 18104 + ^644|^4740 + User account locked out (multiple login errors). + authentication_failures, + + + + 18104 + ^513|^4609 + Windows is shutting down. + system_shutdown, + + + + 18104 + ^517 + Windows audit log was cleared. + logs_cleared, + + + + 18107 + alert_by_email + + First time this user logged in this system. + authentication_success, + + + + 18105 + ^680 + Windows login attempt (ignored). Duplicated. + + + + 18102, 18103 + ^20187|^20014|^20078|^20050|^20049|^20189 + Remote access login failure. + authentication_failed, + + + + 18101 + ^20158 + Remote access login success. + authentication_success, + + + + 18104 + ^646|^647 + Computer account changed/deleted. + account_changed, + + + + 18104 + ^65|^66 + Group account added/changed/deleted. + account_changed, + + + + 18103 + ^13570 + Windows file system full. + low_diskspace, + + + + + + 18106 + ^529 + Logon Failure - Unknown user or bad password. + http://www.ultimatewindowssecurity.com/events/com190.html + win_authentication_failed, + + + + 18106 + ^530 + Logon Failure - Account logon time restriction + violation. + http://www.ultimatewindowssecurity.com/events/com191.html + win_authentication_failed,login_denied, + + + + 18106 + ^531 + Logon Failure - Account currently disabled. + http://www.ultimatewindowssecurity.com/events/com192.html + win_authentication_failed,login_denied, + + + + 18106 + ^532 + Logon Failure - Specified account expired. + http://www.ultimatewindowssecurity.com/events/com193.html + win_authentication_failed,login_denied, + + + + 18106 + ^533 + Logon Failure - User not allowed to login at + this computer. + http://www.ultimatewindowssecurity.com/events/com194.html + win_authentication_failed,login_denied, + + + + 18106 + ^534 + Logon Failure - User not granted logon type. + http://www.ultimatewindowssecurity.com/events/com195.html + win_authentication_failed, + + + + 18106 + ^535 + Logon Failure - Account's password expired. + http://www.ultimatewindowssecurity.com/events/com196.html + win_authentication_failed, + + + + 18106 + ^536|^537 + Logon Failure - Internal error. + win_authentication_failed, + + + + 18106 + ^539 + Logon Failure - Account locked out. + win_authentication_failed, + + + + 18105 + ^672|^673|^675|^676|^681|^4769 + Windows DC Logon Failure. + win_authentication_failed, + + + + 18104 + ^520 + System time changed. + time_changed, + + + + 18102 + ^1076 + unexpected shutdown + system_error, system_shutdown, + Unexpected Windows shutdown. + + + + 18104 + ^671|^4767 + User account unlocked. + http://www.ultimatewindowssecurity.com/events/com291.html + account_changed, + + + + 18114 + ^631|^635|^658 + Security enabled group created. + adduser,account_changed, + + + + 18114 + ^634|^638|^662 + Security enabled group deleted. + adduser,account_changed, + + + + + 18101 + ^7040 + policy_changed, + Service startup type was changed. + This does not appear to be logged on Windows 2000. + + + + 18101 + ^11724 + alert_by_email + Application Uninstalled. + + + + 18101 + ^11707 + alert_by_email + Application Installed. + + + + 18104 + ^4608 + Windows is starting up. + + + + 18104 + ^538|^4634|^4647 + Windows User Logoff. + + + + + + 18107,18149 + ^528|^538|^540 + ^LOCAL SERVICE|^NETWORK SERVICE|^ANONYMOUS LOGON + Windows Logon Success (ignored). + + + + + + 18139 + Failure Code: 0x1F + Windows DC integrity check on decrypted + field failed. + http://www.ultimatewindowssecurity.com/kerberrors.html + win_authentication_failed,attacks, + + + + 18139 + Failure Code: 0x22 + Windows DC - Possible replay attack. + http://www.ultimatewindowssecurity.com/kerberrors.html + win_authentication_failed,attacks, + + + + 18139 + Failure Code: 0x25 + Windows DC - Clock skew too great. + http://www.ultimatewindowssecurity.com/kerberrors.html + win_authentication_failed,attacks, + + + + + + 18105 + ^18456 + win_authentication_failed, + MS SQL Server Logon Failure. + + + + 18104 + ^18454|^18453 + MS SQL Server Logon Success. + authentication_success, + + + + + + + 18108 + + Multiple failed attempts to perform a + privileged operation by the same user. + + + + win_authentication_failed + Multiple Windows Logon Failures. + authentication_failures, + + + + 18105 + Multiple Windows audit failure events. + + + + 18103 + Multiple Windows error events. + + + + 18102 + Multiple Windows warning events. + + + + 18125 + Multiple remote access login failures. + authentication_failures, + + + + diff --git a/etc/rules/mysql_rules.xml b/etc/rules/mysql_rules.xml new file mode 100755 index 0000000..8c30c09 --- /dev/null +++ b/etc/rules/mysql_rules.xml @@ -0,0 +1,84 @@ + + + + + + + mysql_log + MySQL messages grouped. + + + + 50100 + ^MySQL log: \d+ \S+ \d+ Connect + Database authentication success. + authentication_success, + + + + 50105 + Access denied for user + Database authentication failure. + authentication_failed, + + + + 50100 + ^MySQL log: \d+ \S+ \d+ Query + Database query. + + + + 50100 + ^MySQL log: \d+ \S+ \d+ Quit + User disconnected from database. + + + + 50100 + mysqld ended|Shutdown complete + Database shutdown messge. + service_availability, + + + + 50100 + mysqld started|mysqld restarted + Database startup message. + service_availability, + + + + 50100 + ^MySQL log: \d+ \S+ \d+ [ERROR] + Database error. + + + + 50125 + Fatal error: + Database fatal error. + service_availability, + + + + 50125 + Multiple database errors. + service_availability, + + + + + diff --git a/etc/rules/named_rules.xml b/etc/rules/named_rules.xml new file mode 100755 index 0000000..b99e063 --- /dev/null +++ b/etc/rules/named_rules.xml @@ -0,0 +1,104 @@ + + + + + + named + Grouping of the named rules + + + + 12100 + dropping source port zero packet from + Invalid DNS packet. Possibility of attack. + invalid_access, + + + + 12100 + denied AXFR from + Failed attempt to perform a zone transfer. + access_denied, + + + + 12100 + denied update from|unapproved update from + DNS update denied. + Generally mis-configuration. + http://seclists.org/lists/incidents/2000/May/0217.html + client_misconfig, + + + + 12100 + unable to rename log file + Log permission misconfiguration in Named. + system_error, + + + + 12100 + unexpected RCODE + Unexpected error while resolving domain. + + + + 12100 + refused notify from non-master + DNS configuration error. + + + + 12100 + update \S+ denied + DNS update using RFC2136 Dynamic protocol. + http://www.isc.org/index.pl?/sw/bind/FAQ.php + + + + 12100 + query (cache) denied + Query cache denied (maybe config error). + http://www.reedmedia.net/misc/dns/errors.html + + + + 12100 + exiting (due to fatal error) + Named fatal error. DNS service going down. + service_availability, + + + + ^zone \S+ serial number \S+ received from master + \S+ \S ours (\S+) + Serial number from master is lower + than stored. + system_error, + + + + ^transfer of \S+ from \S+ failed while receiving \S+ REFUSED + Unable to perform zone transfer. + system_error, + + + + ^zone \S+: expired + Zone transfer error. + + + diff --git a/etc/rules/netscreenfw_rules.xml b/etc/rules/netscreenfw_rules.xml new file mode 100755 index 0000000..839c917 --- /dev/null +++ b/etc/rules/netscreenfw_rules.xml @@ -0,0 +1,112 @@ + + + + + + netscreenfw + Grouping for the Netscreen Firewall rules + + + + 4500 + notification + Netscreen notification message. + + + + 4500 + warning + Netscreen warning message. + + + + 4500 + critical + Netscreen critical/alert message. + + + + 4500 + alert + Netscreen critical/alert message. + + + + 4500 + information + Netscreen informational message. + + + + + 4503 + ^00027 + Netscreen Erase sequence started. + service_availability, + + + + 4501 + ^00002 + Successfull admin login to the Netscreen firewall + authentication_success, + + + + 4502 + ^00515 + Successfull admin login to the Netscreen firewall + authentication_success, + + + + 4501 + ^00018 + Firewall policy changed. + config_changed, + + + + 4504 + ^00767 + Firewall configuration changed. + config_changed, + + + + 4503 + + Multiple Netscreen critical messages from + same source IP. + + + + 4503 + Multiple Netscreen critical messages. + + + + 4513 + + Multiple Netscreen alert messages from + same source IP. + + + + 4513 + Multiple Netscreen alert messages. + + diff --git a/etc/rules/nginx_rules.xml b/etc/rules/nginx_rules.xml new file mode 100755 index 0000000..8fde0ab --- /dev/null +++ b/etc/rules/nginx_rules.xml @@ -0,0 +1,81 @@ + + + + + + nginx-errorlog + Nginx messages grouped. + + + + 31300 + ^\S+ \S+ [error] + Nginx error message. + + + + 31300 + ^\S+ \S+ [warn] + Nginx warning message. + + + + 31300 + ^\S+ \S+ [crit] + Nginx critical message. + + + + 31301 + failed (2: No such file or directory)|is not found (2: No such file or directory) + Server returned 404 (reported in the access.log). + + + + 31301 + accept() failed (53: Software caused connection abort) + Incomplete client request. + + + + 31301 + no user/password was provided for basic authentication + Initial 401 authentication request. + + + + 31301 + password mismatch, client| was not found in + Web authentication failed. + authentication_failed, + + + + 31315 + + Multiple web authentication failures. + authentication_failures, + + + + 31303 + failed (63: File name too long) + Invalid URI, file name too long. + invalid_request, + + + + + diff --git a/etc/rules/ossec_rules.xml b/etc/rules/ossec_rules.xml new file mode 100755 index 0000000..7ec5559 --- /dev/null +++ b/etc/rules/ossec_rules.xml @@ -0,0 +1,219 @@ + + + + + + + ossec + ossec + Grouping of ossec rules. + + + + 500 + + alert_by_email + Agent started + New ossec agent connected. + + + + 500 + alert_by_email + Ossec started + Ossec server started. + + + + 500 + alert_by_email + Agent started + Ossec agent started. + + + + 500 + alert_by_email + Agent disconnected + Ossec agent disconnected. + + + + ossec + rootcheck + Rootcheck event. + rootcheck, + + + + 509 + Host-based anomaly detection event (rootcheck). + rootcheck, + + + + + 510 + ^NTFS Alternate data stream found + Thumbs.db:encryptable'.|:Zone.Identifier'.| + Exchsrvr/Mailroot/vsi + Ignored common NTFS ADS entries. + rootcheck, + + + + 510 + ^Windows Audit + Windows Audit event. + rootcheck, + + + + 510 + ^Windows Malware + Windows malware detected. + rootcheck, + + + + 510 + ^Application Found + Windows application monitor event. + rootcheck, + + + + 510 + ^Starting rootcheck scan|^Ending rootcheck scan.| + ^Starting syscheck scan|^Ending syscheck scan. + Ignoring rootcheck/syscheck scan messages. + rootcheck,syscheck + + + + 510 + ^System Audit + System Audit event. + rootcheck, + + + + 514 + Adware|Spyware + Windows Adware/Spyware application found. + rootcheck, + + + + + 500 + ^ossec: output: + OSSEC process monitoring rules. + process_monitor, + + + + 530 + ossec: output: 'df -h': /dev/ + 100% + Partition usage reached 100% (disk space monitor). + low_diskspace, + + + + 531 + cdrom|/media|usb|/mount|floppy|dvd + Ignoring external medias. + + + + ossec + syscheck_integrity_changed + Integrity checksum changed. + syscheck, + + + + ossec + syscheck_integrity_changed_2nd + Integrity checksum changed again (2nd time). + syscheck, + + + + ossec + syscheck_integrity_changed_3rd + Integrity checksum changed again (3rd time). + syscheck, + + + + ossec + syscheck_deleted + File deleted. Unable to retrieve checksum. + syscheck, + + + + ossec + syscheck_new_entry + File added to the system. + syscheck, + + + + 500 + ^ossec: agentless: + Integrity checksum for agentless device changed. + syscheck,agentless + + + + + ossec + hostinfo_modified + Host information changed. + hostinfo, + + + + ossec + hostinfo_new + Host information added. + hostinfo, + + + + + + 500 + ^ossec: File rotated + Log file rotated. + + + + 500 + ^ossec: File size reduced + Log file size reduced. + attacks, + + + + 500 + ^ossec: Event log cleared + Microsoft Event log cleared. + logs_cleared, + + diff --git a/etc/rules/pam_rules.xml b/etc/rules/pam_rules.xml new file mode 100755 index 0000000..03aab46 --- /dev/null +++ b/etc/rules/pam_rules.xml @@ -0,0 +1,74 @@ + + + + + + pam + Grouping of the pam_unix rules. + + + + 5500 + session opened for user + Login session opened. + authentication_success, + + + + 5500 + session closed for user + Login session closed. + + + + 5500 + authentication failure; logname= + User login failed. + authentication_failed, + + + + 5500 + check pass; user unknown + Attempt to login with an invalid user. + invalid_login + + + + + 5501 + ^CRON$ + ^pam_unix(cron:session): session opened for user + Ignoring Annoying Ubuntu/debian cron login events. + + + + 5502 + ^CRON$ + ^pam_unix(cron:session): session closed for user root$ + Ignoring Annoying Ubuntu/debian cron login events. + + + + 5503 + + Multiple failed logins in a small period of time. + authentication_failures, + + + + + + diff --git a/etc/rules/php_rules.xml b/etc/rules/php_rules.xml new file mode 100755 index 0000000..4f5eba2 --- /dev/null +++ b/etc/rules/php_rules.xml @@ -0,0 +1,103 @@ + + + + + + 31301, 30101 + PHP Warning: + PHP Warning message. + + + + 31301, 30101 + PHP Fatal error: + PHP Fatal error. + + + + 31301, 30101 + PHP Parse error: + PHP Parse error. + + + + ^PHP Warning: + PHP Warning message. + + + + ^PHP Fatal error: + PHP Fatal error. + + + + ^PHP Parse error: + PHP Parse error. + + + + + + 31401, 31404 + PHP Warning message. + + + + 31410 + expects parameter 1 to be string, array given in + attack, + PHP web attack. + + + + 31410 + Failed opening|failed to open stream + PHP internal error (missing file). + alert_by_email + + + + + + + 31402, 31405 + PHP Fatal error. + + + + 31420 + Failed opening required |Call to undefined function + PHP internal error (missing file or function). + alert_by_email + + + + + + + 31403, 31406 + PHP Parse error. + alert_by_email + + + + + + diff --git a/etc/rules/pix_rules.xml b/etc/rules/pix_rules.xml new file mode 100755 index 0000000..b4c7206 --- /dev/null +++ b/etc/rules/pix_rules.xml @@ -0,0 +1,236 @@ + + + + + + + + + pix + Grouping of PIX rules + + + + 4300 + ^1- + PIX alert message. + + + + 4300 + ^2- + PIX critical message. + + + + 4300 + ^3- + PIX error message. + + + + 4300 + ^4- + PIX warning message. + + + + 4300 + ^5-|^6- + PIX notification/informational message. + + + + 4300 + ^7- + PIX debug message. + + + + 4314 + ^6-605004 + Failed login attempt at the PIX firewall. + authentication_failed, + + + + 4314 + ^5-502103 + Privilege changed in the PIX firewall. + + + + 4314 + ^6-605005 + Successful login to the PIX firewall. + authentication_success, + + + + 4314 + ^6-308001 + Password mismatch while running 'enable' + on the PIX. + authentication_failed, + + + + 4313 + ^4-405001 + ARP collision detected by the PIX. + + + + 4313 + ^4-401004 + Attempt to connect from a blocked (shunned) IP. + access_denied, + + + + 4313 + ^4-710004 + Connection limit exceeded. + + + + 4310 + ^1-106021|^1-106022 + Attack in progress detected by the PIX. + + + + 4311 + ^2-106012|^2-106017|^2-106020 + Attack in progress detected by the PIX. + + + + 4313 + ^4-4000 + Attack in progress detected by the PIX. + + + + + 4330, 4331, 4332 + Attack in progress detected by the PIX. + ids, + + + + 4314 + ^6-113005 + AAA (VPN) authentication failed. + authentication_failed, + + + + 4314 + ^6-113004 + AAA (VPN) authentication successful. + authentication_success, + + + + 4314 + ^6-113006 + AAA (VPN) user locked out. + authentication_failed, + + + + 4312 + ^3-201008 + The PIX is disallowing new connections. + service_availability, + + + + 4310 + ^1-105005|^1-105009|^1-105043 + Failed|Lost Failover + Firewall failover pair communication problem. + service_availability, + + + + 4314 + ^5-111003 + Firewall configuration deleted. + config_changed, + + + + 4314 + ^5-111005|^5-111004|^5-111002|^5-111007 + Firewall configuration changed. + config_changed, + + + + 4314 + ^5-111008|^7-111009 + Firewall command executed (for accounting only). + + + + 4314 + ^5-502101|^5-502102 + User created or modified on the Firewall. + adduser,account_changed, + + + + 4310 + Multiple PIX alert messages. + + + + 4311 + Multiple PIX critical messages. + + + + 4312 + Multiple PIX error messages. + system_error, + + + + 4313 + Multiple PIX warning messages. + + + + 4333 + + Multiple attack in progress messages. + + + + 4334 + Nultiple AAA (VPN) authentication failures. + authentication_failures, + + + + + diff --git a/etc/rules/policy_rules.xml b/etc/rules/policy_rules.xml new file mode 100755 index 0000000..0b73220 --- /dev/null +++ b/etc/rules/policy_rules.xml @@ -0,0 +1,33 @@ + + + + + + authentication_success + + Successful login during non-business hours. + login_time, + + + + authentication_success + weekends + Successful login during weekend. + login_day, + + + + + diff --git a/etc/rules/postfix_rules.xml b/etc/rules/postfix_rules.xml new file mode 100755 index 0000000..fe82aeb --- /dev/null +++ b/etc/rules/postfix_rules.xml @@ -0,0 +1,148 @@ + + +6 + + + + postfix-reject + Grouping of the postfix reject rules. + + + + 3300 + ^554$ + Attempt to use mail server as relay + (client host rejected). + spam, + + + + 3300 + ^550$ + Rejected by access list + (Requested action not taken). + spam, + + + + 3300 + ^450$ + Sender domain is not found + (450: Requested mail action not taken). + spam, + + + + 3300 + ^503$ + Improper use of SMTP command pipelining + (503: Bad sequence of commands). + spam, + + + + 3300 + ^504$ + Receipent address must contain FQDN + (504: Command parameter not implemented). + spam, + + + + 3301, 3302 + blocked using + IP Address black-listed by anti-spam (blocked). + spam, + + + + postfix + Grouping of the postfix rules. + + + + 3320 + defer service failure|Resource temporarily unavailable| + ^fatal: the Postfix mail system is not running + Postfix process error. + service_availability, + + + + 3320 + authentication failed + Postfix SASL authentication failure. + authentication_failed, + + + + 3300 + ^452 + Postfix insufficient disk space error. + service_availability, + + + + 3301 + + Multiple relaying attempts of spam. + multiple_spam, + + + + 3302 + + Multiple attempts to send e-mail from a + rejected sender IP (access). + multiple_spam, + + + + 3303 + + Multiple attempts to send e-mail from + invalid/unknown sender domain. + multiple_spam, + + + + 3304 + + Multiple misuse of SMTP service + (bad sequence of commands). + multiple_spam, + + + + 3305 + + Multiple attempts to send e-mail to + invalid recipient or from unknown sender domain. + multiple_spam, + + + + 3306 + + Multiple attempts to send e-mail from + black-listed IP address (blocked). + multiple_spam, + + + + 3332 + + Multiple SASL authentication failures. + authentication_failures, + + + + ^clamsmtpd: + Grouping of the clamsmtpd rules. + + diff --git a/etc/rules/postgresql_rules.xml b/etc/rules/postgresql_rules.xml new file mode 100755 index 0000000..ab67af0 --- /dev/null +++ b/etc/rules/postgresql_rules.xml @@ -0,0 +1,101 @@ + + + + + + + postgresql_log + PostgreSQL messages grouped. + + + + 50500 + ^LOG + PostgreSQL log message. + + + + 50500 + ^NOTICE|INFO + PostgreSQL informational message. + + + + 50500 + ^ERROR + PostgreSQL error message. + + + + 50500 + ^FATAL + PostgreSQL error message. + + + + 50500 + ^DEBUG + PostgreSQL debug message. + + + + 50501 + duration: | statement: + Database query. + + + + 50501 + connection authorized + Database authentication success. + authentication_success, + + + + 50504 + authentication failed + Database authentication failure. + authentication_failed, + + + + 50504 + terminating connection due + Database shutdown messge. + service_availability, + + + + 50501 + aborting any active transactions|shutting down + Database shutdown messge. + service_availability, + + + + 50504 + Multiple database errors. + service_availability, + + + + 50503 + Multiple database errors. + service_availability, + + + + + diff --git a/etc/rules/proftpd_rules.xml b/etc/rules/proftpd_rules.xml new file mode 100755 index 0000000..b069fe0 --- /dev/null +++ b/etc/rules/proftpd_rules.xml @@ -0,0 +1,186 @@ + + + + + + + proftpd + Grouping for the proftpd rules. + + + + 11200 + FTP session opened.$ + FTP session opened. + connection_attempt, + + + + 11200 + FTP session closed.$ + FTP session closed. + + + + 11200 + no such user + Attempt to login using a non-existent user. + invalid_login, + + + + 11200 + Incorrect password.$|Login failed + Login failed accessing the FTP server + authentication_failed, + + + + 11200 + Login successful + FTP Authentication success. + authentication_success, + + + + 11200 + Connection from \S+ [\S+] denied + Connection denied by ProFTPD configuration. + access_denied, + + + + 11200 + refused connect from + Connection refused by TCP Wrappers. + access_denied, + + + + 11200 + unable to find open port in PassivePorts range + Small PassivePorts range in config file. + Server misconfiguration. + + + + 11200 + Refused PORT + Attempt to bypass firewall that can't adequately + keep state of FTP traffic. + http://www.kb.cert.org/vuls/id/328867 + + + + 11200 + Maximum login attempts + Multiple failed login attempts. + authentication_failures, + + + + 11200 + host name/name mismatch|host name/address mismatch + Mismatch in server's hostname. + + + + 11200 + warning: can't verify hostname: + Reverse lookup error (bad ISP config). + + + + 11200 + connect from + Remote host connected to FTP server. + connection_attempt, + + + + 11200 + FTP no transfer timeout, disconnected + Remote host disconnected due to inactivity. + + + + 11200 + FTP login timed out, disconnected + Remote host disconnected due to login time out. + + + + 11200 + FTP session idle timeout, disconnected + Remote host disconnected due to time out. + + + + 11200 + Data transfer stall timeout: + Data transfer stalled. + + + + 11200 + ProFTPD terminating (signal 11) + FTP process crashed. + service_availability, + + + + 11200 + Reallocating sreaddir buffer + FTP server Buffer overflow attempt. + + + + 11200 + listen() failed in + Unable to bind to adress. + + + + 11200 + error setting IPV6_V6ONLY: Protocol not available| + - mod_delay/|PAM(setcred): System error| + PAM(close_session): System error + IPv6 error and mod-delay info (ignored). + + + + 11204 + + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11201 + + Multiple connection attempts from same source. + recon, + + + + 11215 + + Multiple timed out logins from same source. + + + + + + diff --git a/etc/rules/pure-ftpd_rules.xml b/etc/rules/pure-ftpd_rules.xml new file mode 100755 index 0000000..249f02f --- /dev/null +++ b/etc/rules/pure-ftpd_rules.xml @@ -0,0 +1,68 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] New connection from + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Authentication failed for user + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Can't change directory to + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ is now logged in + FTP Authentication success. + authentication_success, + + + + + diff --git a/etc/rules/racoon_rules.xml b/etc/rules/racoon_rules.xml new file mode 100755 index 0000000..a71de7c --- /dev/null +++ b/etc/rules/racoon_rules.xml @@ -0,0 +1,70 @@ + + + + + + + + racoon + Grouping of racoon rules. + + + + racoon-failed + VPN authentication failed. + authentication_failed, + + + + 14100 + INFO + Racoon informational message. + + + + 14100 + ERROR + Racoon error message. + + + + 14100 + WARNING + Racoon warning message. + + + + 14110 + ISAKMP-SA established + authentication_success + VPN established. + + + + 14111 + such policy does not already exist + Roadwarrior configuration (ignored error). + + + + 14112 + ignore INITIAL-CONTACT notification + Roadwarrior configuration (ignored warning). + + + + 14111 + ERROR: invalid attribute|ERROR: rejected + Invalid configuration settings (ignored error). + + + + 14101 + + Multiple failed VPN logins. + + diff --git a/etc/rules/roundcube_rules.xml b/etc/rules/roundcube_rules.xml new file mode 100755 index 0000000..062b13f --- /dev/null +++ b/etc/rules/roundcube_rules.xml @@ -0,0 +1,36 @@ + + + + + roundcube + Roundcube messages groupe.d + + + + 9400 + failed (LOGIN) + Roundcube authentication failed. + authentication_failed, + + + + 9400 + Successful login + Roundcube authentication succeeded. + authentication_success, + + + + + diff --git a/etc/rules/rules_config.xml b/etc/rules/rules_config.xml new file mode 100755 index 0000000..c5a3a81 --- /dev/null +++ b/etc/rules/rules_config.xml @@ -0,0 +1,68 @@ + + + + + + syslog + Generic template for all syslog rules. + + + + + + firewall + Generic template for all firewall rules. + + + + + + ids + Generic template for all ids rules. + + + + + + web-log + Generic template for all web rules. + + + + + + squid + Generic template for all web proxy rules. + + + + + + windows + Generic template for all windows rules. + + + + + + ossec + Generic template for all ossec rules. + + + + + diff --git a/etc/rules/sendmail_rules.xml b/etc/rules/sendmail_rules.xml new file mode 100755 index 0000000..1ed8199 --- /dev/null +++ b/etc/rules/sendmail_rules.xml @@ -0,0 +1,149 @@ + + + + + + sendmail-reject + Grouping of the sendmail rules. + + + + 3100 + reject= + Grouping of the sendmail reject rules. + + + + 3101 + reject=451 4.1.8 + Sender domain does not have any valid + MX record (Requested action aborted). + spam, + + + + 3101 + reject=550 5.0.0 |reject=553 5.3.0 + Rejected by access list + (55x: Requested action not taken). + spam, + + + + 3101 + reject=550 5.7.1 + Attepmt to use mail server as relay + (550: Requested action not taken). + spam, + + + + 3101 + reject=553 5.1.8 + Sender domain is not found + (553: Requested action not taken). + spam, + + + + 3101 + reject=553 5.5.4 + Sender address does not have domain + (553: Requested action not taken). + spam, + + + + 3101 + Sendmail rejected message. + + + + 3100 + rejecting commands from + Sendmail rejected due to pre-greeting. + spam, + + + + 3100 + savemail panic + Sendmail save mail panic. + system_error, + + + + 3102 + + Sender domain has bogus MX record. + It should not be sending e-mail. + multiple_spam, + + + + 3103 + + Multiple attempts to send e-mail from a + previously rejected sender (access). + multiple_spam, + + + + 3104 + + Multiple relaying attempts of spam. + multiple_spam, + + + + 3105 + + Multiple attempts to send e-mail + from invalid/unknown sender domain. + multiple_spam, + + + + 3106 + + Multiple attempts to send e-mail from + invalid/unknown sender. + multiple_spam, + + + + 3107 + + Multiple rejected e-mails from same source ip. + multiple_spam, + + + + 3108 + + Multiple pre-greetings rejects. + multiple_spam, + + + + + + smf-sav-reject + Grouping of the smf-sav sendmail milter rules. + smf-sav, + + + + 3190 + ^sender check failed|^sender check tempfailed + SMF-SAV sendmail milter unable to verify + address (REJECTED). + smf-sav,spam, + + + diff --git a/etc/rules/smbd_rules.xml b/etc/rules/smbd_rules.xml new file mode 100755 index 0000000..62148dd --- /dev/null +++ b/etc/rules/smbd_rules.xml @@ -0,0 +1,59 @@ + + + + + + + ^smbd + Grouping for the smbd rules. + + + + 13100 + getpeername failed. Error was Transport endpoint + Samba network problems. + + + + 13100 + Denied connection from|Connection denied from + Samba connection denied. + access_denied, + + + + 13100 + Connection reset by peer + Samba network problems. + + + + 13100 + Permission denied-- + User action denied by configuration. + access_denied, + + + + 13100 + Unable to connect to CUPS server + Samba network problems (unable to connect). + + + + + diff --git a/etc/rules/solaris_bsm_rules.xml b/etc/rules/solaris_bsm_rules.xml new file mode 100755 index 0000000..814797e --- /dev/null +++ b/etc/rules/solaris_bsm_rules.xml @@ -0,0 +1,64 @@ + + + + + + + solaris_bsm + Solaris BSM Auditing messages grouped. + + + + 6100 + ^failed + Auditing session failed. + + + + 6100 + ^ok + Auditing session succeeded. + + + + 6102 + ^login + Login session succeeded. + authentication_success, + + + + 6101 + ^login + Login session failed. + authentication_failed, + + + + 6102 + ^su + User successfully changed UID. + authentication_success, + + + + 6103 + ^su + User failed to change UID (user id). + authentication_failed, + + + + diff --git a/etc/rules/sonicwall_rules.xml b/etc/rules/sonicwall_rules.xml new file mode 100755 index 0000000..430b945 --- /dev/null +++ b/etc/rules/sonicwall_rules.xml @@ -0,0 +1,92 @@ + + + + + + + sonicwall + SonicWall messages grouped. + + + + 4800 + ^1 + SonicWall critical message. + + + + 4800 + ^2 + SonicWall critical message. + + + + 4800 + ^3 + SonicWall error message. + + + + 4800 + ^4 + SonicWall warning message. + + + + 4800 + ^5 + SonicWall notice message. + + + + 4800 + ^6 + SonicWall informational message. + + + + 4800 + ^7 + SonicWall debug message. + + + + 4806 + ^236$ + Firewall administrator login. + authentication_success, + + + + 4801 + ^30$|^32$ + Firewall authentication failure. + authentication_failed, + + + + 4804 + Multiple firewall warning messages. + service_availability, + + + + 4803 + Multiple firewall error messages. + service_availability, + + + + diff --git a/etc/rules/spamd_rules.xml b/etc/rules/spamd_rules.xml new file mode 100755 index 0000000..1f567cf --- /dev/null +++ b/etc/rules/spamd_rules.xml @@ -0,0 +1,30 @@ + + + + + + + ^spamd + Grouping for the spamd rules + + + + 3500 + : result: + SPAMD result message (not very usefull here). + + + + 3500 + checking message | processing message + Spamd debug event (reading message). + + + + + diff --git a/etc/rules/squid_rules.xml b/etc/rules/squid_rules.xml new file mode 100755 index 0000000..491b1e0 --- /dev/null +++ b/etc/rules/squid_rules.xml @@ -0,0 +1,209 @@ + + + + + + + +8 + + + + + squid + Squid messages grouped. + + + + + + 35000 + ^4|^5|^6 + Squid generic error codes. + + + + 35002 + ^400 + Bad request/Invalid syntax. + + + + 35002 + ^401 + Unauthorized: Failed attempt to access + authorization-required file or directory. + + + + 35002 + ^403 + Forbidden: Attempt to access forbidden file + or directory. + + + + 35002 + ^404 + Not Found: Attempt to access non-existent + file or directory. + + + + 35002 + ^407 + Proxy Authentication Required: User is not + authorized to use proxy. + + + + 35002 + ^4 + Squid 400 error code (request failed). + + + + 35002 + ^5|^6 + Squid 500/600 error code (server error). + + + + 35009 + ^503 + Squid 503 error code (server unavailable). + + + + + 35006 + blst.php|xxx3.php|ngr7.php|ngr2.php|/nul.php$|/mul.php$|/444.php + Attempt to access a Beagle worm (or variant) + file. + http://www.symantec.com/avcenter/venc/data/w32.beagle.dp.html + automatic_attack, + + + + + 35006 + /jk/exp.wmf$|/PopupSh.ocx$ + Attempt to access a worm/trojan related site. + automatic_attack, + + + + + 35004, 35005, 35006, 35009 + .jpg|.gif|favicon.ico$|.png$|.swf|.txt$|.zip|.css|.xml|.js|.bmp$| + windowsupdate/redir/wuredir.cab| + ^http://codecs.microsoft.com/isapi/ocget.dll| + ^http://activex.microsoft.com/objects/ocget.dll| + ^http://webmessenger.msn.com/session/null| + ^http://sqm.msn.com/sqm/wmp/sqmserver.dll| + ^http://config.messenger.msn.com/Config/MsgrConfig.asmx| + kaspersky-labs.com/| + ^http://liveupdate.symantecliveupdate.com/| + _vti_bin/owssvr.dll|MSOffice/cltreq.asp| + google.com/mt?| + google.com/kh?| + ^http://kh.google.com/flatfile + + + + Ignored files on a 40x error. + + + + + 35005 + + + Multiple attempts to access forbidden file + or directory from same source ip. + + + + 35007 + + Multiple unauthorized attempts to use proxy. + + + + 35003 + + + Multiple Bad requests/Invalid syntax. + + + + 35021 + + Infected machine with W32.Beagle.DP. + http://www.symantec.com/avcenter/venc/data/w32.beagle.dp.html + + + + 35006 + + + Multiple attempts to access a non-existent file. + + + + 35022 + + Multiple attempts to access a worm/trojan/virus + related web site. System probably infected. + + + + 35008 + + + Multiple 400 error codes (requests failed). + + + + 35009 + + + Multiple 500/600 error codes (server error). + + + + 35055 + + Ignoring multiple attempts from same source ip + (alert only once). + + + + + + diff --git a/etc/rules/sshd_rules.xml b/etc/rules/sshd_rules.xml new file mode 100755 index 0000000..40de3fa --- /dev/null +++ b/etc/rules/sshd_rules.xml @@ -0,0 +1,154 @@ + + + + + + + sshd + SSHD messages grouped. + + + + 5700 + Bad protocol version identification + Possible attack on the ssh server + (or version gathering). + + + + 5700 + ^reverse mapping + failed - POSSIBLE BREAK + Reverse lookup error (bad ISP or attack). + + + + 5702 + Possible breakin attempt + (high number of reverse lookup errors). + + + + 5700 + fatal: Timeout before authentication for + Timeout while logging in (sshd). + + + + 5704 + Possible scan or breakin attempt + (high number of login timeouts). + + + + 5700 + Did not receive identification string from + SSH insecure connection attempt (scan). + recon, + + + + 5700 + fatal: buffer_get_string: bad string + OpenSSH challenge-response exploit. + exploit_attempt, + + + + 5700 + error: Could not get shadow information for NOUSER| + fatal: Read from socket failed: |error: ssh_msg_send: write + Useless SSHD message without an user/ip and context. + + + + 5700 + illegal user|invalid user + Attempt to login using a non-existent user + invalid_login,authentication_failed, + + + + 5700 + authentication failure; logname= uid=0 euid=0 tty=ssh| + input_userauth_request: invalid user| + PAM: User not known to the underlying authentication module for illegal user + Useless/Duplicated SSHD message without a user/ip. + + + + 5710 + SSHD brute force trying to get access to + the system. + + authentication_failures, + + + + 5700 + Corrupted check bytes on + Corrupted bytes on SSHD. + + + + 5713 + Local: crc32 compensation attack + SSH CRC-32 Compensation attack + 2001-0144 + http://www.securityfocus.com/bid/2347/info/ + exploit_attempt, + + + + 5700 + ^Accepted|authenticated.$ + SSHD authentication success. + authentication_success, + + + + 5700 + ^Failed|^error: PAM: Authentication + SSHD authentication failed. + authentication_failed, + + + + 5700 + error: Bad prime description in line + SSHD configuration error (moduli). + + + + 5700 + not allowed because + Attempt to login using a denied user. + invalid_login, + + + + 5718 + Multiple access attempts using a denied user. + + + + 5716 + + Multiple SSHD authentication failures. + authentication_failures, + + + + diff --git a/etc/rules/symantec-av_rules.xml b/etc/rules/symantec-av_rules.xml new file mode 100755 index 0000000..96d6266 --- /dev/null +++ b/etc/rules/symantec-av_rules.xml @@ -0,0 +1,50 @@ + + + + + + + + + symantec-av + Grouping of Symantec AV rules. + + + + windows + ^Symantec AntiVirus + Grouping of Symantec AV rules from eventlog. + + + + 7300, 7301 + ^5$|^17$ + virus + Virus detected. + + + + 7300, 7301 + ^2$|^3$|^4$|^13$ + Virus scan updated,started or stopped. + + + + + + diff --git a/etc/rules/symantec-ws_rules.xml b/etc/rules/symantec-ws_rules.xml new file mode 100755 index 0000000..8a2ce2a --- /dev/null +++ b/etc/rules/symantec-ws_rules.xml @@ -0,0 +1,63 @@ + + + + + + + + + + symantec-websecurity + Grouping of Symantec Web Security rules. + + + + 7400 + ^3=2,2=1 + Login failed accessing the web proxy. + authentication_failed, + + + + 7400 + ^3=1,2=1 + Login success accessing the web proxy. + authentication_success, + + + + 7415 + virtadmin + Admin Login success to the web proxy. + authentication_success, + + + + + + + + diff --git a/etc/rules/syslog_rules.xml b/etc/rules/syslog_rules.xml new file mode 100755 index 0000000..06b61f6 --- /dev/null +++ b/etc/rules/syslog_rules.xml @@ -0,0 +1,565 @@ + + + + + + +core_dumped|failure|error|attack|bad |illegal |denied|refused|unauthorized|fatal|failed|Segmentation Fault|Corrupted + + + + + + ^Couldn't open /etc/securetty + File missing. Root access unrestricted. + + + + $BAD_WORDS + alert_by_email + Unknown problem somewhere in the system. + + + + Non standard syslog message (size too large). + + + + ^exiting on signal + Syslogd exiting (logging stopped). + + + + syslogd + ^restart + Syslogd restarted. + + + + ^syslogd \S+ restart + Syslogd restarted. + + + + file system full|No space left on device + File system full. + low_diskspace, + + + + + + + + + + ^automount|^mount + NFS rules grouped. + + + + 2100 + nfs: mount failure + Unable to mount the NFS share. + + + + 2100 + reason given by server: Permission denied + Unable to mount the NFS directory. + + + + ^rpc.mountd: refused mount request from + Unable to mount the NFS directory. + + + + 2100 + lookup for \S+ failed + Automount informative message + + + + + + + + + ^Deactivating service + Excessive number connections to a service. + + + + + + + + + FAILED LOGIN |authentication failure| + Authentication failed for|invalid password for| + LOGIN FAILURE|auth failure: |authentication error| + authinternal failed|Failed to authorize| + Wrong password given for|login failed|Auth: Login incorrect + authentication_failed, + User authentication failure. + + + + more authentication failures;|REPEATED login failures + User missed the password more than one time + authentication_failed, + + + + ^refused connect from| + ^libwrap refused connection| + Connection from \S+ denied + Connection blocked by Tcp Wrappers. + access_denied, + + + + ILLEGAL ROOT LOGIN|ROOT LOGIN REFUSED + Illegal root login. + invalid_login, + + + + ^ROOT LOGIN on + Physical root login. + + + + ^Authentication passed + Pop3 Authentication passed. + + + + + + + + + ^procmail + Ignoring procmail messages. + + + + + + + + + ^smart + Pre-match rule for smartd. + + + + 2800 + No configuration file /etc/smartd.conf found + Smartd Started but not configured + + + + 2800 + Unable to register ATA device + Smartd configuration problem + + + + 2800 + No such device or address + Device configured but not available to Smartd + + + + + + + + + ^kernel + Pre-match rule for kernel messages + + + + 5100 + PCI: if you experience problems, try using option + Informative message from the kernel. + + + + 5100 + modprobe: Can't locate module sound + Informative message from the kernel + + + + 5100 + Oversized packet received from + Error message from the kernel. + Ping of death attack. + + + + 5100 + Promiscuous mode enabled| + device \S+ entered promiscuous mode + Interface entered in promiscuous(sniffing) mode. + promisc, + + + + 5100 + end_request: I/O error, dev fd0, sector 0| + Buffer I/O error on device fd0, logical block 0 + Invalid request to /dev/fd0 (bug on the kernel). + + + + 5100 + svc: unknown program 100227 (me 100003) + NFS incompability between Linux and Solaris. + + + + 5100 + svc: bad direction + NFS incompability between Linux and Solaris. + + + + 5100 + Out of Memory: + System running out of memory. + Availability of the system is in risk. + service_availability, + + + + 5100 + I/O error: dev |end_request: I/O error, dev + Kernel Input/Output error + + + + 5100 + Forged DCC command from + IRC misconfiguration + + + + 5100 + ipw2200: Firmware error detected. + Kernel device error. + + + + 5100 + usbhid: probe of + Kernel usbhid probe error (ignored). + + + + 5100 + Kernel log daemon terminating + system_shutdown, + System is shutting down. + + + + 5100 + ADSL line is down + Monitor ADSL line is down. + + + + 5100 + ADSL line is up + Monitor ADSL line is up. + + + + ^hpiod: unable to ParDevice + Ignoring hpiod for producing useless logs. + + + + + + + + + crond|crontab + Crontab rule group. + + + + 2830 + ^unable to exec + Wrong crond configuration + + + + 2830 + BEGIN EDIT + Crontab opened for editing. + + + + 2830 + REPLACE + Crontab entry changed. + + + + 2832 + ^(root) + Root's crontab entry changed. + + + + + + + + + + su + Initial grouping for su messages. + + + + 5300 + authentication failure; |failed|BAD su|^-| - + User missed the password to change UID (user id). + authentication_failed, + + + + 5301 + ^root + User missed the password to change UID to root. + authentication_failed, + + + + 5300 + session opened for user root|^'su root'| + ^+ \S+ \S+\proot$|^\S+ to root on|^SU \S+ \S+ + \S+ \S+-root$ + User successfully changed UID to root. + authentication_success, + + + + 5300 + session opened for user|succeeded for| + ^+|^\S+ to |^SU \S+ \S+ + + User successfully changed UID. + authentication_success, + + + + 5303, 5304 + + alert_by_email + First time (su) is executed by user. + + + + + + + + + Integrity Check failed: File could not + Problems with the tripwire checking + + + + + + + + + ^new group + New group added to the system + + + + ^new user|^new account added + New user added to the system + + + + ^delete user|^account deleted|^remove group + Group (or user) deleted from the system + + + + ^changed user + Information from the user was changed + + + + + + + + + sudo + Initial group for sudo messages + + + + 5400 + 3 incorrect password attempts + Three failed attempts to run sudo + + + + 5400 + ; USER=root ; COMMAND= + Successful sudo to ROOT executed + + + + 5400 + alert_by_email + + First time user executed sudo. + + + + + + + + ^pptpd + PPTPD messages grouped + + + + 9100 + ^GRE: \S+ from \S+ failed: status = -1 + PPTPD failed message (communication error) + poptop.sourceforge.net/dox/gre-protocol-unavailable.phtml + + + + 9100 + ^tcflush failed: Bad file descriptor + PPTPD communication error + + + + + + + + + authentication_success + alert_by_email + + authentication_success + First time user logged in. + + + + + + + ^squid + Squid syslog messages grouped + + + + 9200 + ^ctx: enter level|^sslRead|^urlParse: Illegal | + ^httpReadReply: Request not yet |^httpReadReply: Excess data + Squid debug message + + + + + + + windows-date-format + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d \w+ + Dpkg (Debian Package) log. + + + + 2900 + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d install + New dpkg (Debian Package) requested to install. + + + + 2900 + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d status installed + New dpkg (Debian Package) installed. + config_changed, + + + + 2900 + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d remove| + ^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d purge + Dpkg (Debian Package) removed. + config_changed, + + + + + + + ^yum + Yum logs. + + + + yum.log$ + ^Installed|^Updated|^Erased + Yum logs. + + + + 2930,2931 + ^Installed + config_changed, + New Yum package installed. + + + + 2930,2931 + ^Updated + config_changed, + Yum package updated. + + + + 2930,2931 + ^Erased + config_changed, + Yum package deleted. + + + + + diff --git a/etc/rules/telnetd_rules.xml b/etc/rules/telnetd_rules.xml new file mode 100755 index 0000000..661f61a --- /dev/null +++ b/etc/rules/telnetd_rules.xml @@ -0,0 +1,44 @@ + + + + + + telnetd + Grouping for the telnetd rules + + + + 5600 + refused connect from + Connection refused by TCP Wrappers. + + + + 5600 + : connect from + Remote host established a telnet connection. + + + + ttloop: peer died:|ttloop: read: + 5602 + Remote host invalid connection. + + + + warning: can't verify hostname: + Reverse lookup error (bad hostname config). + + + + 5602 + + Multiple connection attempts from same source + (possible scan). + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_da.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_da.xml new file mode 100755 index 0000000..56f6b46 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_da.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Ny forbindelse fra + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Godkendelse mislykkedes for + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Kan ikke ændre mappen til + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ er logget pÃ¥ nu + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_de.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_de.xml new file mode 100755 index 0000000..d3c2bf8 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_de.xml @@ -0,0 +1,68 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Neue Verbindung von + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Authentifizierung fehlgeschlagen + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout | [INFO] Zeitüberschreitung + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Kann nicht ins Verzeichnis \S+ wechseln + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ ist jetzt eingeloggt + FTP Authentication success. + authentication_success, + + + + + \ No newline at end of file diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_en.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_en.xml new file mode 100755 index 0000000..2bb38b2 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_en.xml @@ -0,0 +1,68 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] New connection from + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Authentication failed for user + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Can't change directory to + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ is now logged in + FTP Authentication success. + authentication_success, + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_es.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_es.xml new file mode 100755 index 0000000..5b39462 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_es.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nueva conexión desde + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Autentificación fallida para el usuario + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Fin de sesión.| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] No puedo cambiar al directorio + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ está ahora dentro del sistema + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_fr.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_fr.xml new file mode 100755 index 0000000..8f21907 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_fr.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nouvelle connexion de + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Erreur d'authentification pour l'utilisateur + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Deloggue.| [INFO] Temps de reponse depasse + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Ne peut changer le repertoire en + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ est maintenant loggue + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_fr_funny.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_fr_funny.xml new file mode 100755 index 0000000..c7b057d --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_fr_funny.xml @@ -0,0 +1,68 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] \S+ ramene son cul + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] \S+ c'est un batard, il connait pas son code + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Cassos | [INFO] Putain mais achete-toi des doigts + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] C'est quoi ce delire, je peux pas aller dans + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ vient de debarquer + FTP Authentication success. + authentication_success, + + + + + \ No newline at end of file diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_it.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_it.xml new file mode 100755 index 0000000..116aa56 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_it.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nuova connessione da + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Autenticazione falita per l'utente + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout.| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Impossibile cambiare la directory in + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ è ora loggato + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_nl.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_nl.xml new file mode 100755 index 0000000..03129dd --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_nl.xml @@ -0,0 +1,68 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nieuwe verbinding vanaf + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Autorisatie faalde voor gebruiker + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout | [INFO] Onderbreking + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Kan de directory niet veranderen naar + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ is nu ingelogd + FTP Authentication success. + authentication_success, + + + + + \ No newline at end of file diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_no.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_no.xml new file mode 100755 index 0000000..00c16f7 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_no.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Ny tilkobling fra + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Godkjennelse mislyktes for + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logg ut.| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Kan ikke skifte katalog til + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ er nÃ¥ logget inn + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_pt_br.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_pt_br.xml new file mode 100755 index 0000000..c176d58 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_pt_br.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nova conexão a partir de + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Autenticação falhou para usuário + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Fim de sessão.| [INFO] Tempo expirado + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Não foi possível entrar no diretório + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ agora está logado + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_ro.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_ro.xml new file mode 100755 index 0000000..2530ec5 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_ro.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Conexiune noua de la + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Autentificare esuata pentru utilizatorul + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Iesire.| [INFO] Temporizare expirata + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Nu pot intra in directorul + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ este acum logat + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_sk.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_sk.xml new file mode 100755 index 0000000..40a0a25 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_sk.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nove spojenie z + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Autentifikacia uzivatela zlyhala + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout.| [INFO] Cas vyprsal + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Nemozem prejst do adresara + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ je prave prihlaseny + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_sv.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_sv.xml new file mode 100755 index 0000000..45fc1f2 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_sv.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] Nyanslutning frÃ¥n + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] Behörighetskontroll misslyckas för användare + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Logout| [INFO] Timeout + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Kan ej ändra bibliotek till + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ har loggat in + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/translated/pure_ftpd/pure-ftpd_rules_tr.xml b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_tr.xml new file mode 100755 index 0000000..6d27a89 --- /dev/null +++ b/etc/rules/translated/pure_ftpd/pure-ftpd_rules_tr.xml @@ -0,0 +1,69 @@ + + + + + + pure-ftpd + Grouping for the pure-ftpd rules. + + + + 11300 + [INFO] \S+ den yeni baðlantý + New FTP connection. + connection_attempt, + + + + 11300 + [WARNING] \S+ kullanýcýsý için giriþ hatalý + FTP Authentication failed. + authentication_failed, + + + + 11300 + [INFO] Çýkýþ.| [INFO] Zaman Aþýmý + FTP user logout/timeout + + + + 11300 + [NOTICE] + FTP notice messages + + + + 11300 + [INFO] Klasör deðiþtirilemedi + Attempt to access invalid directory + + + + 11302 + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11301 + + Multiple connection attempts from same source. + recon, + + + + [INFO] \S+ giriþ yaptý + FTP Authentication success. + authentication_success, + + + + + + diff --git a/etc/rules/trend-osce_rules.xml b/etc/rules/trend-osce_rules.xml new file mode 100755 index 0000000..a75a9eb --- /dev/null +++ b/etc/rules/trend-osce_rules.xml @@ -0,0 +1,55 @@ + + + + + + + + + trend-osce + Grouping of Trend OSCE rules. + + + + 7600 + ^0|$|^1$|^2$|^33|^10$|^11$|^12$ + virus + Virus detected and cleaned/quarantined/remved + + + + 7600 + ^5$|^6$|^7$|^8$|^14$|^15$|^16$ + virus + Virus detected and unable to clean up. + + + + 7600 + ^4$|^13$ + Virus scan completed with no errors detected. + + + + 7600 + ^25$ + Virus scan passed by found potential security risk. + + + + + diff --git a/etc/rules/vmpop3d_rules.xml b/etc/rules/vmpop3d_rules.xml new file mode 100644 index 0000000..3508ad6 --- /dev/null +++ b/etc/rules/vmpop3d_rules.xml @@ -0,0 +1,31 @@ + + + + + + vm-pop3d + Grouping for the vm-pop3d rules. + + + + 9800 + failed auth + authentication_failed, + Login failed accessing the pop3 server. + + + + 9801 + + POP3 brute force (multiple failed logins). + authentication_failures, + + + + + + diff --git a/etc/rules/vmware_rules.xml b/etc/rules/vmware_rules.xml new file mode 100755 index 0000000..42a5a22 --- /dev/null +++ b/etc/rules/vmware_rules.xml @@ -0,0 +1,156 @@ + + + + + + + vmware + VMWare messages grouped. + + + + vmware-syslog + VMWare ESX syslog messages grouped. + + + + 19100 + ^crit|^fatal + VMware ESX critical message. + + + + 19100 + ^error + VMware ESX error message. + + + + 19100 + ^warn + VMware ESX warning message. + + + + 19100 + ^notice + VMware ESX notice message. + + + + 19100 + ^info + VMware ESX informational message. + + + + 19100 + ^verbose + VMware ESX verbose message. + + + + + + + 19106 + logged in$ + VMWare ESX authentication success. + authentication_success, + + + + 19106 + Failed login attempt for + VMWare ESX authentication failure. + authentication_failed, + + + + 19101 + vmware-hostd|vmware-authd + Accepted password for|login from + VMWare ESX user login. + authentication_success, + + + + 19101 + vmware-hostd|vmware-authd + Rejected password for + VMWare ESX user authentication failure. + authentication_failed, + + + + + + 19106 + -> VM_STATE_OFF + Virtual machine state changed to OFF. + service_availability, + + + + 19106 + -> VM_STATE_POWERING_ON + Virtual machine being turned ON. + + + + 19106 + -> VM_STATE_ON + Virtual machine state changed to ON. + alert_by_email + + + + 19106 + -> VM_STATE_RECONFIGURING + Virtual machine being reconfigured. + config_changed, + alert_by_email + + + + + + + 19104 + Multiple VMWare ESX warning messages. + service_availability, + + + + 19103 + Multiple VMWare ESX error messages. + service_availability, + + + + 19111 + Multiple VMWare ESX authentication failures. + authentication_failures, + + + + 19113 + Multiple VMWare ESX user authentication failures. + authentication_failures, + + + + + diff --git a/etc/rules/vpn_concentrator_rules.xml b/etc/rules/vpn_concentrator_rules.xml new file mode 100755 index 0000000..7828efd --- /dev/null +++ b/etc/rules/vpn_concentrator_rules.xml @@ -0,0 +1,59 @@ + + + + + + + + + cisco-vpn-concentrator + Grouping of Cisco VPN concentrator rules + + + + 14200 + ^IKE/52$ + VPN authentication successful. + authentication_success, + + + + 14200 + ^AUTH/5$|^AUTH/9$|^IKE/167$|^PPP/9$|^SSH/33$|^PSH/23$ + VPN authentication failed. + authentication_failed, + + + + 14200 + ^HTTP/47$|^SSH/16$ + alert_by_email + VPN Admin authentication successful. + authentication_success, + + + + 14202 + + Multiple VPN authentication failures. + authentication_failures, + + + + + diff --git a/etc/rules/vpopmail_rules.xml b/etc/rules/vpopmail_rules.xml new file mode 100644 index 0000000..67d74f1 --- /dev/null +++ b/etc/rules/vpopmail_rules.xml @@ -0,0 +1,67 @@ + + + + + + vpopmail + Grouping for the vpopmail rules. + + + + 9900 + password fail + authentication_failed, + Login failed for vpopmail. + + + + 9900 + vpopmail user not found + invalid_login, + Attempt to login to vpopmail with invalid username. + + + + 9900 + null password given + authentication_failed, + Attempt to login to vpopmail with empty password. + + + + 9900 + login success + authentication_success, + Vpopmail successful login. + + + + + 9901 + + Vpopmail brute force (multiple failed logins). + authentication_failures, + + + + 9902 + + Vpopmail brute force (email harvesting). + authentication_failures, + + + + 9903 + + VPOPMAIL brute force (empty password). + authentication_failures, + + + + + diff --git a/etc/rules/vsftpd_rules.xml b/etc/rules/vsftpd_rules.xml new file mode 100755 index 0000000..e7f01e1 --- /dev/null +++ b/etc/rules/vsftpd_rules.xml @@ -0,0 +1,61 @@ + + + + + + vsftpd + Grouping for the vsftpd rules. + + + + 11400 + CONNECT: Client + connection_attempt + FTP session opened. + + + + 11400 + OK LOGIN: + FTP Authentication success. + authentication_success, + + + + 11400 + FAIL LOGIN: + Login failed accessing the FTP server. + authentication_failed, + + + + 11400 + OK UPLOAD: + FTP server file upload. + + + + 11403 + + FTP brute force (multiple failed logins). + authentication_failures, + + + + 11401 + + Multiple FTP connection attempts from + same source IP. + recon, + + + + + + diff --git a/etc/rules/web_rules.xml b/etc/rules/web_rules.xml new file mode 100755 index 0000000..ff185a2 --- /dev/null +++ b/etc/rules/web_rules.xml @@ -0,0 +1,175 @@ + + + + + + web-log + Access log messages grouped. + + + + 31100 + ^4 + Web server 400 error code. + + + + 31101 + ^403|^404 + .jpg$|.gif$|favicon.ico$|.png$|robots.txt$|.css$ + + + + Ignored extensions on 400 error codes. + + + + 31100 + ='|select%20|select+|insert%20|%20from%20|%20where%20|union%20| + union+|where+|null,null|xp_cmdshell + SQL injection attempt. + attack,sql_injection, + + + + 31100 + + + %027|%00|%01|%7f|%2E%2E|%0A|%0D|../..|..\..|echo;|.. + cmd.exe|root.exe|_mem_bin|msadc|/winnt/| + /x90/|default.ida|/sumthin|nsiislog.dll|chmod%|wget%|cd%| + cat%|exec%|rm%20 + Common web attack. + attack, + + + + 31100 + %3Cscript|%2Fscript|script>|script%3E|SRC=javascript|IMG%20| + %20ONLOAD=|INPUT%20|iframe%20 + XSS (Cross Site Scripting) attempt. + attack, + + + + 31103, 31104, 31105 + ^200 + A web attack returned code 200 (success). + attack, + + + + + 31103, 31104, 31105 + ^/search.php?search=|^index.php?searchword= + Ignored URLs for the web attacks + + + + 31100 + URL too long. Higher than allowed on most + browsers. Possible attack. + invalid_access, + + + + + 31100 + ^50 + Web server 500 error code (server error). + + + + 31120 + ^501 + Web server 501 error code (Not Implemented). + + + + 31120 + ^500 + alert_by_email + Web server 500 error code (Internal Error). + system_error, + + + + 31120 + ^503 + alert_by_email + Web server 503 error code (Service unavailable). + + + + 31101 + + Mutiple web server 400 error codes + from same source ip. + web_scan,recon, + + + + 31103 + + Multiple SQL injection attempts from same + souce ip. + attack,sql_injection, + + + + 31104 + + Multiple common web attacks from same souce ip. + attack, + + + + 31105 + + Multiple XSS (Cross Site Scripting) attempts + from same souce ip. + attack, + + + + 31121 + + Multiple web server 501 error code (Not Implemented). + web_scan,recon, + + + + 31122 + + Multiple web server 500 error code (Internal Error). + system_error, + + + + 31123 + + Multiple web server 503 error code (Service unavailable). + web_scan,recon, + + diff --git a/etc/rules/wordpress_rules.xml b/etc/rules/wordpress_rules.xml new file mode 100755 index 0000000..7009d3d --- /dev/null +++ b/etc/rules/wordpress_rules.xml @@ -0,0 +1,68 @@ + + + + + wordpress + Wordpress messages grouped. + + + + 9500 + User authentication failed + Wordpress authentication failed. + authentication_failed, + + + + 9500 + User logged in + Wordpress authentication succeeded. + authentication_success, + + + + 9500 + WPsyslog was successfully initiali + WPsyslog was successfully initialized. + + + + 9500 + Plugin deactivated + Wordpress plugin deactivated. + + + + 9500 + Warning: Comment flood attempt + Wordpress Comment Flood Attempt. + + + + 9500 + Warning: IDS: + Attack against Wordpress detected. + + + + 9501 + + Multiple wordpress authentication failures. + authentication_failures, + + + + + + diff --git a/etc/rules/zeus_rules.xml b/etc/rules/zeus_rules.xml new file mode 100755 index 0000000..b954ca0 --- /dev/null +++ b/etc/rules/zeus_rules.xml @@ -0,0 +1,74 @@ + + + + + + + + + zeus + Grouping of Zeus rules. + + + + 31200 + ^[\S+ \S+] INFO:|^[\S+ \S+] SSL: + Grouping of Zeus informational logs. + + + + 31200 + ^[\S+ \S+] WARN: + Zeus warning log. + + + + 31200 + ^[\S+ \S+] SERIOUS: + Zeus serious log. + + + + 31200 + ^[\S+ \S+] FATAL: + Zeus fatal log. + + + + 31202 + admin:Authentication failure + Admin authentication failed. + authentication_failed, + + + + 31202 + Unknown directive + Configuration warning (ignored). + + + + 31202 + Multiple Zeus warnings. + + + + + diff --git a/etc/templates/br/errors/0x1-location.txt b/etc/templates/br/errors/0x1-location.txt new file mode 100755 index 0000000..2cceba1 --- /dev/null +++ b/etc/templates/br/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Erro 0x1. + Este script só pode ser executado a partir do mesmo diretório. + Altere o diretório para onde está este script antes de rodá-lo. + Você deve rodá-lo como "./install.sh" + diff --git a/etc/templates/br/errors/0x2-beroot.txt b/etc/templates/br/errors/0x2-beroot.txt new file mode 100755 index 0000000..68c6d8c --- /dev/null +++ b/etc/templates/br/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Erro 0x2. + Você necessita ser root para rodar este script. + diff --git a/etc/templates/br/errors/0x3-dependencies.txt b/etc/templates/br/errors/0x3-dependencies.txt new file mode 100755 index 0000000..a9352fb --- /dev/null +++ b/etc/templates/br/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Erro 0x3. + Você necessita de um compilador (como gcc ou cc) para continuar + a instalação. + diff --git a/etc/templates/br/errors/0x4-installtype.txt b/etc/templates/br/errors/0x4-installtype.txt new file mode 100755 index 0000000..f75b6dc --- /dev/null +++ b/etc/templates/br/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Erro 0x4. + Modalidade de instalação errada. Deve ser apenas [S]ervidor, [A]gente ou [L]ocal. + diff --git a/etc/templates/br/errors/0x5-build.txt b/etc/templates/br/errors/0x5-build.txt new file mode 100755 index 0000000..fe66155 --- /dev/null +++ b/etc/templates/br/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Erro 0x5. + Erro na Compilação. Não foi possível finalizar a instalação. + diff --git a/etc/templates/br/language.txt b/etc/templates/br/language.txt new file mode 100755 index 0000000..b98a3fb --- /dev/null +++ b/etc/templates/br/language.txt @@ -0,0 +1 @@ + ** Para instalação em português, escolha [br]. diff --git a/etc/templates/br/messages.txt b/etc/templates/br/messages.txt new file mode 100755 index 0000000..86b8a53 --- /dev/null +++ b/etc/templates/br/messages.txt @@ -0,0 +1,109 @@ +# Configuração +yes="s" +no="n" +yesmatch="s" +nomatch="n" +server="servidor" +agent="cliente" +local="local" +help="ajuda" + + +# Global +moreinfo="Maiores informações em: " +starting="Iniciando o OSSEC HIDS" +systemis="O Sistema é" +modifiedinit="O script de inicialização foi modificado para executar o OSSEC HIDS durante o boot." +noboot="Sistema desconhecido. Nenhum script de incialização foi adicionado." + +# Parte 1 +installscript="Script de instalação" +system="Sistema" +user="Usuário" +host="Host" +hitanyorabort="Aperte ENTER para continuar ou Ctrl+C para abortar." +whattoinstall="Que tipo de instalação você deseja (servidor, cliente, local ou ajuda)?" +serverchose="Escolhida instalação servidor" +clientchose="Escolhida instalação cliente" +localchose="Escolhida instalação local" + +# Parte 2 +settingupenv="Configurando o ambiente de instalação" +wheretoinstall="Escolha onde instalar o OSSEC HIDS" +installat="A instalação será feita no diretório" +deletedir="O diretório de instalação já existe. Deseja removê-lo?" + +# Parte 3 +configuring="Configurando o" +mailnotify="Deseja receber notificações por e-mail?" +nomail="Notificação por e-mail desabilitada" +whatsemail="Qual é o seu endereço de e-mail?" +yoursmtp="Seu servidor SMTP foi encontrado como" +usesmtp="Deseja usá-lo?" +usingsmtp="Usando servidor SMTP: " +whatsmtp="Qual é o ip/host de seu servidor SMTP?" + +# Parte 3.1/agente +serverip="Qual é o endereço de IP do servidor OSSEC HIDS?" +addingip="Adicionando IP do servidor" + + +# Parte 3.2 +runsyscheck="Deseja habilitar o sistema de verificação de integridade?" +nosyscheck="Syscheck (Sistema de verificação de integridade) desabilitado" +yessyscheck="Syscheck (Sistema de verificação de integridade) habilitado" + +# Parte 3.3 +runrootcheck="Deseja habilitar o sistema de detecção de rootkis?" +norootcheck="Rootcheck (Sistema de detecção de rootkits) desabilitado" +yesrootcheck="Rootcheck (Sistema de detecção de rootkits) habilitado" + +# Parte 3.4/servidor/local +enable_ar="Deseja habilitar o sistema de respostas automáticas?" +noactive="Sistema de respostas automáticas desabilitado" +nohosts="host-deny desabilitado" +yeshosts="host-deny habilitado (local) para niveis >= 6" +firewallar="Deseja habilitar o firewall-drop?" +nofirewall="firewall-drop desabilitado." +yesfirewall="firewall-drop habilitado (local) para níveis >= 6" +defaultwhitelist="Lista de endereços que não serão bloqueados pela resposta automática:" +addwhite="Deseja adicionar mais algum endereço a essa lista?" +ipswhite="Endereços de IP (separados por espaço): " + + +# Parte 3.5/servidor/local +syslog="Deseja habilitar o syslog remoto (514 udp)?" +nosyslog="Syslog desabilitado" +yessyslog="Syslog habilitado" + +# Parte 3.4/3.5 +readlogs="Ajustando a configuração para analisar os seguintes logs:" + +# Parte 5 +installing="Instalando o sistema" +runningmake="Executando o Makefile" + +# Final +configurationdone="Configuração finalizada corretamente" +tostart="Para iniciar o OSSEC HIDS" +tostop="Para parar o OSSEC HIDS" +configat="A configuração pode ser vista ou modificada em" +addserveragent="Você precisa adicionar cada um dos clientes antes que estejam autorizados a acessar o servidor." +runma="Execute o 'manage_agents' para adicioná-los ou removê-los" +presskey="Pressione ENTER para continuar." + +# Update +wanttoupdate="OSSEC ja esta instalado. Deseja atualiza-lo?" +unabletoupdate="Error na atualizacao. Sera necessario reinstala-lo." +updatecompleted="Atualizacao completada." +updatefailed="Erro na atualizacao." +updaterules="Voce deseja atualizar as regras?" +updatingrules="Atualizando as regras." +notupdatingrules="Nao atualizando as regras." + +# Pf support +pfenable="Deseja utilizar o firewall PF nas respostas automaticas?" +nopf="Respostas automaticas com o PF desabilitadas." +pftablename="Qual o nome da tabela no PF que deseja utilizar?" +pfmessage="Adicione as seguintes linhas na configuracao do seu firewall" + diff --git a/etc/templates/br/messages/0x101-initial.txt b/etc/templates/br/messages/0x101-initial.txt new file mode 100755 index 0000000..424d315 --- /dev/null +++ b/etc/templates/br/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + Você está iniciando o processo de instalação do OSSEC HIDS. + Você precisará de um compilador C pré-instalado em seu sistema. + Qualquer dúvida, sugestões ou comentários, por favor, mande um e-mail para + dcid@ossec.net (ou daniel.cid@gmail.com). + diff --git a/etc/templates/br/messages/0x102-installhelp.txt b/etc/templates/br/messages/0x102-installhelp.txt new file mode 100755 index 0000000..d75184d --- /dev/null +++ b/etc/templates/br/messages/0x102-installhelp.txt @@ -0,0 +1,26 @@ + + - Você tem três opções de instalação: servidor, cliente ou local. + + - Se você escolher 'servidor', você poderá analizar todos os logs, + criar notificações de e-mail e respostas, e também receber + logs de máquinas remotas e de sistemas com 'clientes' rodando + (de onde o tráfego é enviado criptografado para o servidor). + + - Se você escolher 'cliente'(agente), você poderá ler arquivos + locais (do syslog, snort, apache, etc) e encaminhá-los + (criptografados) ao servidor para análise. + + - Se você escolher 'local', você poderá fazer tudo o que o + o servidor faz, exceto receber mensagens dos clientes. + + - Utilize 'servidor' se você estiver configurando um servidor de análise de logs. + + - Utilize 'cliente' se você tiver outra máquina rodando como servidor de logs + e quiser encaminhar os logs ao servidor para análise. + (ideal para webservers, servidores de banco de dados, etc) + + - Utilize 'local' se você apenas tem um sistema para monitorar. + + - Maiores informações: http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/br/messages/0x103-thanksforusing.txt b/etc/templates/br/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..08eb145 --- /dev/null +++ b/etc/templates/br/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Obrigado por usar o OSSEC HIDS. + Se você tiver alguma pergunta, sugestão ou encontrar algum + "bug", nos contate através do e-mail contact@ossec.net ou + utilize nossa lista de e-mail: + ( http://www.ossec.net/main/support/ ). + + Maiores informações podem ser encontradas em http://www.ossec.net + + --- Pressione ENTER para continuar --- + diff --git a/etc/templates/br/messages/0x104-client.txt b/etc/templates/br/messages/0x104-client.txt new file mode 100755 index 0000000..60bee9d --- /dev/null +++ b/etc/templates/br/messages/0x104-client.txt @@ -0,0 +1,6 @@ + + - Para se comunicar com o servidor, você primeiro precisa + adicionar este cliente a ele. Quando você tiver terminado, + use a ferramenta 'manage_agents' para importar a chave de + autenticação do servidor. + diff --git a/etc/templates/br/messages/0x105-noboot.txt b/etc/templates/br/messages/0x105-noboot.txt new file mode 100755 index 0000000..ade60c3 --- /dev/null +++ b/etc/templates/br/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - Nenhuma ação foi tomada para que OSSEC HIDS inicie + durrante o 'boot'. Adicione a seguinte linha em seu + script de inicialização: + diff --git a/etc/templates/br/messages/0x106-logs.txt b/etc/templates/br/messages/0x106-logs.txt new file mode 100755 index 0000000..c0244b3 --- /dev/null +++ b/etc/templates/br/messages/0x106-logs.txt @@ -0,0 +1,7 @@ + - Se quiser monitorar qualquer outro arquivo, modifique + o ossec.conf e adicione uma nova entrada para o arquivo. + Qualquer dúvida sobre a configuração, visite http://www.ossec.net/hids/ . + + + --- Pressione ENTER para continuar --- + diff --git a/etc/templates/br/messages/0x107-ar.txt b/etc/templates/br/messages/0x107-ar.txt new file mode 100755 index 0000000..3c3f8cd --- /dev/null +++ b/etc/templates/br/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- Respostas automáticas permitem você executar um comando + específico baseado nos eventos recebidos. Você pode + bloquear um endereço de IP ou desabilitar o acesso de + um usuário específico, por exemplo. + Maiores informações: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/br/messages/0x108-ar-enabled.txt b/etc/templates/br/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..1938f72 --- /dev/null +++ b/etc/templates/br/messages/0x108-ar-enabled.txt @@ -0,0 +1,11 @@ + - Sistema de respostas automáticas habilitado. + + - Por padrão, nós podemos habilitar o 'host-deny' e + o 'firewall-drop'. O primeiro adicionará um host + ao /etc/hosts.deny e o segundo bloqueará o host + no 'iptables' (se linux) ou no ipfilter (se Solaris, + FreeBSD ou NetBSD). + - Eles podem ser usados para parar 'SSHD brute force + scans', portscans e outras formas de ataque. + Você pode também realizar bloqueios baseados nos + alertas do snort, por exemplo. diff --git a/etc/templates/cn/errors/0x1-location.txt b/etc/templates/cn/errors/0x1-location.txt new file mode 100755 index 0000000..51d2325 --- /dev/null +++ b/etc/templates/cn/errors/0x1-location.txt @@ -0,0 +1,5 @@ + + 错误代码 0x1. + 该脚本只能在安装文件的同目录运行. + 请到脚本所在目录运行它. + 你必须以 ./install.sh 的形式运行他. diff --git a/etc/templates/cn/errors/0x2-beroot.txt b/etc/templates/cn/errors/0x2-beroot.txt new file mode 100755 index 0000000..5278e75 --- /dev/null +++ b/etc/templates/cn/errors/0x2-beroot.txt @@ -0,0 +1,3 @@ + + 错误代码 0x2. + 你必须以 root 的身份运行该脚本. diff --git a/etc/templates/cn/errors/0x3-dependencies.txt b/etc/templates/cn/errors/0x3-dependencies.txt new file mode 100755 index 0000000..3b713e0 --- /dev/null +++ b/etc/templates/cn/errors/0x3-dependencies.txt @@ -0,0 +1,3 @@ + + 错误代码 0x3. + 在继续安装之前,您必须安装并配置好编译器(如 gcc 或 cc). diff --git a/etc/templates/cn/errors/0x4-installtype.txt b/etc/templates/cn/errors/0x4-installtype.txt new file mode 100755 index 0000000..51fc004 --- /dev/null +++ b/etc/templates/cn/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + 错误代码 0x4. + 错误的安装类型. 安装类型只能是代理端安装(agent), 服务器端安装(server) + 或本地安装(local). diff --git a/etc/templates/cn/errors/0x5-build.txt b/etc/templates/cn/errors/0x5-build.txt new file mode 100755 index 0000000..d607a73 --- /dev/null +++ b/etc/templates/cn/errors/0x5-build.txt @@ -0,0 +1,6 @@ + + Error 0x5. + Building error. Unable to finish the installation. + + 错误代码 0x5. + 编译错误. 不能完成安装. diff --git a/etc/templates/cn/language.txt b/etc/templates/cn/language.txt new file mode 100755 index 0000000..3c4fe18 --- /dev/null +++ b/etc/templates/cn/language.txt @@ -0,0 +1 @@ + ** 要使用中文进行安装, 请选择 [cn]. diff --git a/etc/templates/cn/messages.txt b/etc/templates/cn/messages.txt new file mode 100755 index 0000000..6d8575a --- /dev/null +++ b/etc/templates/cn/messages.txt @@ -0,0 +1,106 @@ +# Configuration +yes="y" +no="n" +yesmatch="y" +nomatch="n" +agent="agent" +local="local" +server="server" +help="help" + +# Global +moreinfo="详细信息请参考: " +starting="正在启动 OSSEC HIDS " +systemis="系统类型是 " +modifiedinit="修改启动脚本使 OSSEC HIDS 在系统启动时自动运行 " +noboot="未知系统,启动脚本未能添加." + +# Part 1 +installscript="安装脚本" +system="系统类型" +user="用户" +host="主机" +hitanyorabort="按 ENTER 继续或 Ctrl-C 退出." +whattoinstall="您希望哪一种安装 (server, agent, local or help)?" +serverchose="选择了 Server 类型的安装" +clientchose="选择了 Agent(client) 类型的安装" +localchose="选择了 Local 类型的安装" + +# Part 2 +settingupenv="正在初始化安装环境" +wheretoinstall="请选择 OSSEC HIDS 的安装路径" +installat="OSSEC HIDS 将安装在 " +deletedir="安装路径已存在. 要删除它吗?" + +# Part 3 +configuring="正在配置" +mailnotify="您希望收到e-mail告警吗?" +nomail="Email告警没有启用 " +whatsemail="请输入您的 e-mail 地址?" +yoursmtp="我们找到您的 SMTP 服务器为" +usesmtp="您希望使用它吗?" +usingsmtp="使用 SMTP 服务器: " +whatsmtp="请输入您的 SMTP 服务器IP或主机名 ?" + +# Part 3.1/agent +serverip="请输入 OSSEC HIDS 服务器的IP地址" +addingip="添加服务器IP " + + +# Part 3.2 +runsyscheck="您希望运行系统完整性检测模块吗?" +nosyscheck="系统完整性检测模块将不被部署" +yessyscheck="系统完整性检测模块将被部署" + +# Part 3.3 +runrootcheck="您希望运行 rootkit检测吗?" +norootcheck="rootkit检测将不被部署" +yesrootcheck="rootkit检测将被部署" + +# Part 3.4/server/local +enable_ar="您希望开启联动(active response)功能吗?" +noactive="联动功能(Active response)被关闭" +nohosts="主机联动(host-deny) 被关闭" +yeshosts="主机联动(host-deny) 当事件级别 >= 6 时被启动" +firewallar="您希望开启防火墙联动(firewall-drop)功能吗?" +nofirewall="防火墙联动(firewall-drop)被关闭." +yesfirewall="防火墙联动(firewall-drop)当事件级别 >= 6 时被启动" +defaultwhitelist="联动功能默认的白名单是:" +addwhite="您希望添加更多的IP到白名单吗?" +ipswhite="请输入IP (用空格进行分隔): " + +# Part 3.5/server/local +syslog="您希望接收远程机器syslog吗 (port 514 udp)?" +nosyslog="远程机器syslog将不被接收" +yessyslog="远程机器syslog将被接收" + +# Part 3.4/3.5 +readlogs="设置配置文件以分析一下日志:" + +# Part 5 +installing="正在安装系统" +runningmake="正在运行Makefile" + +# Final +configurationdone="已正确完成系统配置" +tostart="要启动 OSSEC HIDS" +tostop="要停止 OSSEC HIDS" +configat="要查看或修改系统配置,请编辑 " +addserveragent="为使代理能够联接服务器端, 您需要将每个代理添加到服务器." +runma="允许'manage_agents'来添加活删除代理" +presskey="请按ENTER继续" + +# Update +wanttoupdate="您已经安装过 OSSEC ,要升级它吗?" +unabletoupdate="不能对原版本进行升级. 必须进行全新安装." +updatecompleted="升级完成." +updatefailed="升级失败." +updaterules="您希望升级规则(rules文件)吗?" +updatingrules="升级规则(rules文件)." +notupdatingrules="不升级规则(rules文件)." + +# Pf support +pfenable="你希望在联动功能中使用 PF 防火墙吗?" +nopf="PF 防火墙联动被禁止." +pftablename="请输入希望使用的 PF 表?" +pfmessage="请将以下几行添加到 PF 规则的前面" diff --git a/etc/templates/cn/messages/0x101-initial.txt b/etc/templates/cn/messages/0x101-initial.txt new file mode 100755 index 0000000..ef89f8b --- /dev/null +++ b/etc/templates/cn/messages/0x101-initial.txt @@ -0,0 +1,5 @@ + + 您将开始 OSSEC HIDS 的安装. + 请确认在您的机器上已经正确安装了 C 编译器. + 如果您有任何疑问或建议,请给 dcid@ossec.net (或 daniel.cid@gmail.com) 发邮件. + diff --git a/etc/templates/cn/messages/0x102-installhelp.txt b/etc/templates/cn/messages/0x102-installhelp.txt new file mode 100755 index 0000000..dd6c963 --- /dev/null +++ b/etc/templates/cn/messages/0x102-installhelp.txt @@ -0,0 +1,22 @@ + + - 您可以有三种安装选项:服务器端安装(server),代理端(agent)或本地安装(local). + + -如果选择'服务器端安装(server)', 您将可以分析所有日志, + 发送e-mail告警及联动,接收远端机器的syslog日志, + 接收代理端发回的日志(代理端发回的日志是经过加密的). + + -如果您选择'代理端安装(agent)', 您将可以读取本机文件(syslog, snort, + apache等)并将它们发送给服务器端(加密过后)进行分析. + + -如果选择'本地安装(local)',除了不能接收远程机器或代理端发回的信息外,你可以 + 作服务器(server)安装能做的任何事情. + + - 如果您希望安装一个日志分析服务器,请选择'server'. + + - 如果您已经有一台日志分析服务器并且希望将本机的日志传送给它,请选择'agent'. + (这是web服务器, 数据库服务器等的理想配置方法) + + - 如果您只有一台机器要监控,那么请选择'local'. + + - 要获得更多的信息, 请访问: + http://www.ossec.net/en/manual.html#starting diff --git a/etc/templates/cn/messages/0x103-thanksforusing.txt b/etc/templates/cn/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..f76d41c --- /dev/null +++ b/etc/templates/cn/messages/0x103-thanksforusing.txt @@ -0,0 +1,10 @@ + + + 感谢使用 OSSEC HIDS. + 如果您有任何疑问,建议或您找到任何bug, + 请通过 contact@ossec.net 或邮件列表 ossec-list@ossec.net 联系我们. + ( http://www.ossec.net/en/mailing_lists.html ). + + 您可以在 http://www.ossec.net 获得更多信息 + + --- 请按 ENTER 结束安装 (下面可能有更多信息). --- diff --git a/etc/templates/cn/messages/0x104-client.txt b/etc/templates/cn/messages/0x104-client.txt new file mode 100755 index 0000000..eeb7bad --- /dev/null +++ b/etc/templates/cn/messages/0x104-client.txt @@ -0,0 +1,4 @@ + + - 您必须首先将该代理添加到服务器端以使他们能够相互通信. + 这样做了以后,您可以运行'manage_agents'工具导入 + 服务器端产生的认证密匙. diff --git a/etc/templates/cn/messages/0x105-noboot.txt b/etc/templates/cn/messages/0x105-noboot.txt new file mode 100755 index 0000000..c8b50d7 --- /dev/null +++ b/etc/templates/cn/messages/0x105-noboot.txt @@ -0,0 +1,3 @@ + + - 未能配置 OSSEC HIDS 在系统启动时自动允许. + 请将以下行添加到启动脚本. diff --git a/etc/templates/cn/messages/0x106-logs.txt b/etc/templates/cn/messages/0x106-logs.txt new file mode 100755 index 0000000..571607a --- /dev/null +++ b/etc/templates/cn/messages/0x106-logs.txt @@ -0,0 +1,7 @@ + + -如果你希望监控其他文件, 只需要在配置文件ossec.conf中 + 添加新的一项. + 任何关于配置的疑问您都可以在 http://www.ossec.net 找到答案. + + + --- 按 ENTER 以继续 --- diff --git a/etc/templates/cn/messages/0x107-ar.txt b/etc/templates/cn/messages/0x107-ar.txt new file mode 100755 index 0000000..9ca50cc --- /dev/null +++ b/etc/templates/cn/messages/0x107-ar.txt @@ -0,0 +1,6 @@ + + 3.4- 关联响应允许您在分析已接收事件的基础上执行一个 + 已定义的命令. + 例如,你可以阻止某个IP地址的访问或禁止某个用户的访问权限. + 更多的信息,您可以访问: + http://www.ossec.net/en/manual.html#active-response diff --git a/etc/templates/cn/messages/0x108-ar-enabled.txt b/etc/templates/cn/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..6c1d8de --- /dev/null +++ b/etc/templates/cn/messages/0x108-ar-enabled.txt @@ -0,0 +1,10 @@ + + - 关联响应已开启 + + - 默认情况下, 我们开启了主机拒绝和防火墙拒绝两种响应. + 第一种情况将添加一个主机到 /etc/hosts.deny. + 第二种情况将在iptables(linux)或ipfilter(Solaris, + FreeBSD 或 NetBSD)中拒绝该主机的访问. + - 该功能可以用以阻止 SSHD 暴力攻击, 端口扫描和其他 + 一些形式的攻击. 同样你也可以将他们添加到其他地方, + 例如将他们添加为 snort 的事件. diff --git a/etc/templates/config/active-response.template b/etc/templates/config/active-response.template new file mode 100755 index 0000000..c3ba8b1 --- /dev/null +++ b/etc/templates/config/active-response.template @@ -0,0 +1,23 @@ + + + + host-deny + local + 6 + 600 + + + + + firewall-drop + local + 6 + 600 + diff --git a/etc/templates/config/apache-logs.template b/etc/templates/config/apache-logs.template new file mode 100755 index 0000000..915cb3a --- /dev/null +++ b/etc/templates/config/apache-logs.template @@ -0,0 +1,10 @@ +/var/log/apache/error.log +/var/log/apache/error_log +/var/log/apache/access.log +/var/log/apache/access_log +/var/www/logs/access_log +/var/www/logs/error_log +/var/log/httpd/error_log +/var/log/httpd/access_log +/var/log/apache2/error.log +/var/log/apache2/access.log diff --git a/etc/templates/config/ar-disable-account.template b/etc/templates/config/ar-disable-account.template new file mode 100755 index 0000000..176296b --- /dev/null +++ b/etc/templates/config/ar-disable-account.template @@ -0,0 +1,13 @@ + + disable-account + disable-account.sh + user + yes + + + + restart-ossec + restart-ossec.sh + + + diff --git a/etc/templates/config/ar-firewall-drop.template b/etc/templates/config/ar-firewall-drop.template new file mode 100755 index 0000000..b11d11f --- /dev/null +++ b/etc/templates/config/ar-firewall-drop.template @@ -0,0 +1,6 @@ + + firewall-drop + firewall-drop.sh + srcip + yes + diff --git a/etc/templates/config/ar-host-deny.template b/etc/templates/config/ar-host-deny.template new file mode 100755 index 0000000..7b1b7bc --- /dev/null +++ b/etc/templates/config/ar-host-deny.template @@ -0,0 +1,6 @@ + + host-deny + host-deny.sh + srcip + yes + diff --git a/etc/templates/config/ar-routenull.template b/etc/templates/config/ar-routenull.template new file mode 100644 index 0000000..dbd9775 --- /dev/null +++ b/etc/templates/config/ar-routenull.template @@ -0,0 +1,6 @@ + + route-null + route-null.sh + srcip + yes + diff --git a/etc/templates/config/pgsql-logs.template b/etc/templates/config/pgsql-logs.template new file mode 100644 index 0000000..4d4fafa --- /dev/null +++ b/etc/templates/config/pgsql-logs.template @@ -0,0 +1,2 @@ +/var/log/postgresql/postgresql-8.1-main.log +/var/log/postgresql/postgresql.log diff --git a/etc/templates/config/rootcheck.template b/etc/templates/config/rootcheck.template new file mode 100755 index 0000000..9528072 --- /dev/null +++ b/etc/templates/config/rootcheck.template @@ -0,0 +1,9 @@ + + + 36000 + + + /var/ossec/etc/shared/rootkit_files.txt + /var/ossec/etc/shared/rootkit_trojans.txt + /var/ossec/etc/shared/system_audit_rcl.txt + diff --git a/etc/templates/config/rules.template b/etc/templates/config/rules.template new file mode 100755 index 0000000..d888483 --- /dev/null +++ b/etc/templates/config/rules.template @@ -0,0 +1,57 @@ + + rules_config.xml + pam_rules.xml + sshd_rules.xml + telnetd_rules.xml + syslog_rules.xml + arpwatch_rules.xml + symantec-av_rules.xml + symantec-ws_rules.xml + pix_rules.xml + named_rules.xml + smbd_rules.xml + vsftpd_rules.xml + pure-ftpd_rules.xml + proftpd_rules.xml + ms_ftpd_rules.xml + ftpd_rules.xml + hordeimp_rules.xml + roundcube_rules.xml + wordpress_rules.xml + vpopmail_rules.xml + vmpop3d_rules.xml + courier_rules.xml + web_rules.xml + apache_rules.xml + nginx_rules.xml + php_rules.xml + mysql_rules.xml + postgresql_rules.xml + ids_rules.xml + squid_rules.xml + firewall_rules.xml + cisco-ios_rules.xml + netscreenfw_rules.xml + sonicwall_rules.xml + postfix_rules.xml + sendmail_rules.xml + imapd_rules.xml + mailscanner_rules.xml + dovecot_rules.xml + ms-exchange_rules.xml + racoon_rules.xml + vpn_concentrator_rules.xml + spamd_rules.xml + msauth_rules.xml + mcafee_av_rules.xml + trend-osce_rules.xml + + zeus_rules.xml + solaris_bsm_rules.xml + vmware_rules.xml + ms_dhcp_rules.xml + asterisk_rules.xml + ossec_rules.xml + attack_rules.xml + local_rules.xml + diff --git a/etc/templates/config/snort-logs.template b/etc/templates/config/snort-logs.template new file mode 100755 index 0000000..30b1bc6 --- /dev/null +++ b/etc/templates/config/snort-logs.template @@ -0,0 +1 @@ +/var/log/snort/alert diff --git a/etc/templates/config/syscheck.template b/etc/templates/config/syscheck.template new file mode 100755 index 0000000..37f4129 --- /dev/null +++ b/etc/templates/config/syscheck.template @@ -0,0 +1,37 @@ + + + 79200 + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin + + + /etc/mtab + /etc/mnttab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/adjtime + /etc/httpd/logs + /etc/utmpx + /etc/wtmpx + /etc/cups/certs + /etc/dumpdates + /etc/svc/volatile + + + C:\WINDOWS/System32/LogFiles + C:\WINDOWS/Debug + C:\WINDOWS/WindowsUpdate.log + C:\WINDOWS/iis6.log + C:\WINDOWS/system32/wbem/Logs + C:\WINDOWS/system32/wbem/Repository + C:\WINDOWS/Prefetch + C:\WINDOWS/PCHEALTH/HELPCTR/DataColl + C:\WINDOWS/SoftwareDistribution + C:\WINDOWS/Temp + C:\WINDOWS/system32/config + C:\WINDOWS/system32/spool + C:\WINDOWS/system32/CatRoot + diff --git a/etc/templates/config/syslog-logs.template b/etc/templates/config/syslog-logs.template new file mode 100755 index 0000000..04460ca --- /dev/null +++ b/etc/templates/config/syslog-logs.template @@ -0,0 +1,30 @@ +/var/log/messages +/var/log/authlog +/var/log/auth.log +/var/log/secure +/var/log/secure.log +/var/log/system.log +/var/log/syslog +/var/log/ipfilter.log +/var/adm/ipsec.log +/var/adm/syslog +/var/adm/auth.log +/var/adm/syslog.log +/var/adm/messages +/var/adm/syslog/syslog.log +/var/log/userlog +/var/log/security +/var/log/xferlog +/var/log/proftpd.log +/var/log/vsftpd.log +/var/log/radius.log +/var/log/radius/radius.log +/var/log/mail.info +/var/log/mail.notice +/var/log/maillog +/usr/local/squid/var/logs/access.log +/var/log/squid/access.log +/var/log/horde.log +/var/log/asl.log +/var/log/dpkg.log +/var/log/vmware/hostd.log diff --git a/etc/templates/de/errors/0x1-location.txt b/etc/templates/de/errors/0x1-location.txt new file mode 100755 index 0000000..9dbcd20 --- /dev/null +++ b/etc/templates/de/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Fehler 0x1. + Dieses Script kann nur aus dem gleichen Verzeichniss ausgeführt + werden. Wechseln Sie in das Verzeichniss in dem das Script liegt + und führen Sie ./install.sh als root aus." + diff --git a/etc/templates/de/errors/0x2-beroot.txt b/etc/templates/de/errors/0x2-beroot.txt new file mode 100755 index 0000000..cbc9979 --- /dev/null +++ b/etc/templates/de/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Fehler 0x2. + Dieses Script kann nur mit root Rechten ausgeführt werden. + diff --git a/etc/templates/de/errors/0x3-dependencies.txt b/etc/templates/de/errors/0x3-dependencies.txt new file mode 100755 index 0000000..c05e1d6 --- /dev/null +++ b/etc/templates/de/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Fehler 0x3. + Sie benötigen einen Compiler (zB gcc or cc) um mit der Installation + fortzufahren. + diff --git a/etc/templates/de/errors/0x4-installtype.txt b/etc/templates/de/errors/0x4-installtype.txt new file mode 100755 index 0000000..ad35734 --- /dev/null +++ b/etc/templates/de/errors/0x4-installtype.txt @@ -0,0 +1,5 @@ + + Fehler 0x4. + Falscher Installationstyp. Bitte wählen Sie zwischen agent, server + und local. + diff --git a/etc/templates/de/errors/0x5-build.txt b/etc/templates/de/errors/0x5-build.txt new file mode 100755 index 0000000..ce04542 --- /dev/null +++ b/etc/templates/de/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Fehler 0x5. + Fehler beim compilieren. Das Paket kann nicht installiert werden. + diff --git a/etc/templates/de/language.txt b/etc/templates/de/language.txt new file mode 100755 index 0000000..4db52d7 --- /dev/null +++ b/etc/templates/de/language.txt @@ -0,0 +1 @@ + ** Fur eine deutsche Installation wohlen Sie [de]. diff --git a/etc/templates/de/messages.txt b/etc/templates/de/messages.txt new file mode 100755 index 0000000..53731ee --- /dev/null +++ b/etc/templates/de/messages.txt @@ -0,0 +1,110 @@ +# Configuration +yes="j" +no="n" +yesmatch="j" +nomatch="n" +agent="agent" +local="lokal" +server="server" +help="hilfe" + + +# Global +moreinfo="Weitere Informationen unter: " +starting="Starte OSSEC HIDS" +systemis="Erkanntes System " +modifiedinit="Init script wurde verändert um OSSEC HIDS beim boot zu starten." +noboot="Unbekanntes system. Es wurde kein Init-Script kopiert." + +# Part 1 +installscript="Installations Script" +system="System" +user="User" +host="Host" +hitanyorabort="Drücken Sie eine Taste zum fortfahren oder Ctrl-C zum abbrechen" +whattoinstall="Welche Art der Installation möchten Sie starten (server,agent,lokal oder hilfe)?" +serverchose="Server installation ausgewählt" +clientchose="Agent(client) installation ausgewählt" +localchose="Lokale installation ausgewählt" + +# Part 2 +settingupenv="Die Installation wird vorbereitet" +wheretoinstall="Bitte wählen Sie wo OSSEC HIDS installiert werden soll" +installat="Die Installation wird kopiert nach " +deletedir="Das Installationsverzeichniss existiert bereits. Soll es gelöscht werden? " + +# Part 3 +configuring="Konfiguration " +mailnotify="Möchten Sie Benachrichtigungen per E-Mail? " +nomail="E-Mail Benachrichtigung wird übersprungen " +whatsemail="Wie lautet die E-Mail Adresse? " +yoursmtp="Es wurde dieser SMTP Server gefunden" +usesmtp="Soll er benutzt werden?" +usingsmtp="Benutze SMTP Server: " +whatsmtp="Wie lautet die Adresse des SMTP Servers? (IP/Host) " + +# Part 3.1/agent +serverip="Wiw lautet die IP Addresse des OSSEC HIDS Servers?" +addingip="Server IP hinzugefügt" + + +# Part 3.2 +runsyscheck="Möchten Sie den syscheck (integrity check daemon) benutzen?" +nosyscheck="Syscheck (integrity check daemon) wird nicht benutzt" +yessyscheck="Syscheck (integrity check daemon) wird gestartet" + +# Part 3.3 +runrootcheck="Möchten Sie die rootkit detection engine benutzen?" +norootcheck="Rootcheck (rootkit detection) wird nicht benutzt" +yesrootcheck="Rootcheck (rootkit detection) wird gestartet" + +# Part 3.4/server/local +enable_ar="Möchten Sie active response benutzen?" +noactive="Active response wird nicht benutzt" +nohosts="host-deny ausgeschaltet" +yeshosts="host-deny (local) für level >= 6 eingeschaltet " +firewallar="Möchten Sie firewall-drop benutzen?" +nofirewall="firewall-drop ausgeschaltet" +yesfirewall="firewall-drop (local) für level >= 6 eingeschaltet" +defaultwhitelist="Standard Ausnahmeliste (White-list) für active response:" +addwhite="Möchten Sie weitere IPs zur White-list hinzufügen?" +ipswhite="IPs (Durch Leerzeichen getrennt): " + + +# Part 3.5/server/local +syslog="Möchten Sie Nachrichten von einem remote syslog (514 udp) empfangen?" +nosyslog="Remote syslog empfang ausgeschaltet" +yessyslog="Remote syslog empfang eingeschaltet" + +# Part 3.4/3.5 +readlogs="Die folgenden Log-Files werden analysiert:" + +# Part 5 +installing="Installiere das System" +runningmake="make wird ausgeführt" + +# Final +configurationdone="Konfguration erfolgreich durchgeführt " +tostart="Um OSSEC HIDS zu starten" +tostop="Um OSSEC HIDS zu stoppen" +configat="Die Konfiguration kann angesehen oder verändert werden unter: " +addserveragent="Agenten müssen hinzugefügt werden bevor sie zugreifen können. " +runma="Run the 'Benutzen Sie manage_agents um Agenten hinzuzufügen oder zu entfernen" +presskey="Drücken Sie eine Taste" + +# Update +wanttoupdate="OSSEC ist bereits installiert. Möchten Sie es updaten?" +unabletoupdate="Update nicht möglich. Es muß eine Neuinstallation durchgeführt werden." +updatecompleted="Update durchgeführt." +updatefailed="Update fehlgeschlagen." +updaterules="Möchten Sie die Regeln updaten?" +updatingrules="Regeln werden upgedated." +notupdatingrules="Regeln werden nicht verändert." + +# Pf support +pfenable="Moechten Sie die PF Firewall für active response benutzen?" +nopf="active response fuer PF Firewall ausgeschaltet." +pftablename="Name der PF Tabelle die benutzt werden soll?" +pfmessage="Fuegen Sie die folgende Zeile am Anfang Ihrer Regeln ein " + + diff --git a/etc/templates/de/messages/0x101-initial.txt b/etc/templates/de/messages/0x101-initial.txt new file mode 100755 index 0000000..b815f74 --- /dev/null +++ b/etc/templates/de/messages/0x101-initial.txt @@ -0,0 +1,5 @@ + + Um OSSEC HIDS zu installieren muß auf Ihrem System ein C-Compiler + installiert sein. Bei Fragen, Anregungen oder sonstigen Kommentaren + senden Sie eine E-Mail an dcid@ossec.net (or daniel.cid@gmail.com). + diff --git a/etc/templates/de/messages/0x102-installhelp.txt b/etc/templates/de/messages/0x102-installhelp.txt new file mode 100755 index 0000000..15c64b8 --- /dev/null +++ b/etc/templates/de/messages/0x102-installhelp.txt @@ -0,0 +1,28 @@ + + - Es gibt drei Arten der Installation: agent, local oder server. + + - Wenn Sie Server wählen, können Logfiles analysiert werden, + es werden Benachrichtigungen per E-Mail verschickt und es + können Logs von Agenten auf entfernten Rechnern empfangen + werden. + + - Wenn Sie Agent auswählen, können Logfiles ausgelesen werden + (zb syslog, snort, apache) und verschlüsselt an einen + Server zur analyse geschickt werden. + + - Wenn Sie local auswählen, können alle Funktionen eines + Servers, bis auf den Empfang von Agentennachrichten ausge- + führt werden. + + - Wählen Sie 'Server' wenn Sie Nachrichten von fremden Agenten + empfangen und verarbeiten möchten. + + - Wählen Sie 'Agent' wenn Sie einen anderen Rechner haben, der + als Server dient und an den die Logs zur Analyse geschickt + werden (sinnvoll zb für Webserver, Datenbankserver usw). + + - Wählen Sie 'Local' wenn nur ein System analysiert werden soll. + + - weitere Informationen unter: http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/de/messages/0x103-thanksforusing.txt b/etc/templates/de/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..5f972ab --- /dev/null +++ b/etc/templates/de/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Danke das Sie OSSEC HIDS benutzen. + Bei Fragen, Anregungen oder wenn Sie einen Fehler gefunden + haben, können Sie die Entwickler per E-Mail contact@ossec.net + oder über die Mailingliste unter ossec-list@ossec.net erreichen + ( http://www.ossec.net/en/mailing_lists.html ). + + Weitere Informtionen finden Sie unter http://www.ossec.net/hids/ + + --- Drücken Sie eine Taste um fortzufahren --- + diff --git a/etc/templates/de/messages/0x104-client.txt b/etc/templates/de/messages/0x104-client.txt new file mode 100755 index 0000000..afb4438 --- /dev/null +++ b/etc/templates/de/messages/0x104-client.txt @@ -0,0 +1,5 @@ + + - Um mit dem Server zu kommunizieren müssen Sie erst den + Agent auf dem Server hinzufügen. Danach kann der Schlüssel + mit dem Tool 'manage_agents' importiert werden. + diff --git a/etc/templates/de/messages/0x105-noboot.txt b/etc/templates/de/messages/0x105-noboot.txt new file mode 100755 index 0000000..425b014 --- /dev/null +++ b/etc/templates/de/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - Es wurde kein Startup Script erstellt. Um OSSEC HIDS beim + booten automatisch zu starten, sollten Sie die folgende Zeile + in ein init Script aufnehmen: + diff --git a/etc/templates/de/messages/0x106-logs.txt b/etc/templates/de/messages/0x106-logs.txt new file mode 100755 index 0000000..a207da6 --- /dev/null +++ b/etc/templates/de/messages/0x106-logs.txt @@ -0,0 +1,8 @@ + - Wenn Sie weitere Files überwachen möchten, fügen Sie + einen weiteren 'localfile' Eintrag in der Datei + ossec.conf hinzu. Alle Konfigurationsoptionen werden + unter http://www.ossec.net/hids/ beschrieben. + + + --- Drücken Sie eine Taste um fortzufahren --- + diff --git a/etc/templates/de/messages/0x107-ar.txt b/etc/templates/de/messages/0x107-ar.txt new file mode 100755 index 0000000..1850e6c --- /dev/null +++ b/etc/templates/de/messages/0x107-ar.txt @@ -0,0 +1,7 @@ + + 3.4- Mit 'Active Response' können Befehle abhängig von + Events ausführen. Dadurch können zB IP-Adressen + geblockt werden oder der Zugriff für bestimmte + Benutzer abgeschaltet werden. + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/de/messages/0x108-ar-enabled.txt b/etc/templates/de/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..50cf396 --- /dev/null +++ b/etc/templates/de/messages/0x108-ar-enabled.txt @@ -0,0 +1,11 @@ + - Active response eingeschaltet." + + - Standardmässig kann 'host-deny' und 'firewall-drop' + aktiviert werden. 'host-deny' fügt eine IP in die + Datei /etc/hosts.deny ein. 'firewall-response' fügt + eine IP per iptables (Linux) oder ipfilter (Solaris, + FreeBSD usw) in die Firewall Regeln ein. + + - Beide können benutzt werden um SSH Brute-Force scans, + Portscans oder andere Attacken zu verhindern. Es kann + auch durch einen Snort-Event geblockt werden. diff --git a/etc/templates/el/errors/0x1-location.txt b/etc/templates/el/errors/0x1-location.txt new file mode 100755 index 0000000..b20887e --- /dev/null +++ b/etc/templates/el/errors/0x1-location.txt @@ -0,0 +1,7 @@ + + Σφάλμα 0x1. + Το αρχείο αυτό μπορεί να εκτελεστεί μόνο από τον κατάλογο + στον οποίο βρίσκεται. + Μεταβείτε στον κατάλογο που βρίσκεται αυτό το αρχείο και + τρέξτε την εντολή ./install.sh + diff --git a/etc/templates/el/errors/0x2-beroot.txt b/etc/templates/el/errors/0x2-beroot.txt new file mode 100755 index 0000000..997c616 --- /dev/null +++ b/etc/templates/el/errors/0x2-beroot.txt @@ -0,0 +1,5 @@ + + Σφάλμα 0x2. + Πρέπει να είστε συνδεδεμένος ως root + για να εγκαταστήσετε αυτό το πρόγραμμα. + diff --git a/etc/templates/el/errors/0x3-dependencies.txt b/etc/templates/el/errors/0x3-dependencies.txt new file mode 100755 index 0000000..054079e --- /dev/null +++ b/etc/templates/el/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Σφάλμα 0x3. + Χρειάζεστε έναν μεταγλωττιστή (όπως gcc ή cc) για να + συνεχίσετε με την εγκατάσταση. + diff --git a/etc/templates/el/errors/0x4-installtype.txt b/etc/templates/el/errors/0x4-installtype.txt new file mode 100755 index 0000000..0a02b8f --- /dev/null +++ b/etc/templates/el/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Σφάλμα 0x4. + Λάθος τύπος εγκατάστασης. Μπορεί μόνο να είναι agent, server ή local. + diff --git a/etc/templates/el/errors/0x5-build.txt b/etc/templates/el/errors/0x5-build.txt new file mode 100755 index 0000000..030ae34 --- /dev/null +++ b/etc/templates/el/errors/0x5-build.txt @@ -0,0 +1,5 @@ + + Σφάλμα 0x5. + Λάθος στην δημιουργία του εκτελέσιμου προγράμματος. + Δεν είναι δυνατό να ολοκληρωθεί η εγκατάσταση. + diff --git a/etc/templates/el/language.txt b/etc/templates/el/language.txt new file mode 100755 index 0000000..c4f27ef --- /dev/null +++ b/etc/templates/el/language.txt @@ -0,0 +1 @@ + ** Για εγκατάσταση στα Ελληνικά, επιλέξτε [el]. diff --git a/etc/templates/el/messages.txt b/etc/templates/el/messages.txt new file mode 100755 index 0000000..2afe6dc --- /dev/null +++ b/etc/templates/el/messages.txt @@ -0,0 +1,106 @@ +# Configuration +yes="y" +no="n" +yesmatch="y" +nomatch="n" +agent="agent" +local="local" +server="server" +help="help" + +# Global +moreinfo="Περισσότερες πληροφορίες στο: " +starting="Εκκινώντας το OSSEC HIDS" +systemis="Το σύστημα είναι" +modifiedinit="To init script τροποποιήθηκε προκειμένου να ξεκινάει το OSSEC HIDS κατά την εκκίνηση του συστήματος." +noboot="Άγνωστο σύστημα. Το init script δεν προστέθηκε." + +# Part 1 +installscript="πρόγραμμα εγκατάστασης" +system="Σύστημα" +user="Χρήστης" +host="Υπολογιστής" +hitanyorabort="Πατήστε ENTER για να συνεχίσετε ή Ctrl-C για ακύρωση." +whattoinstall="Τι τύπου εγκατάσταση επιθυμείτε (server, agent, local ή help);" +serverchose="Επιλέχθηκε η εγκατάσταση διακομιστή (server)" +clientchose="Επιλέχθηκε η εγκατάσταση πελάτη (agent)" +localchose="Επιλέχθηκε η τοπική (local) εγκατάσταση" + +# Part 2 +settingupenv="Ρυθμίζεται το περιβάλλον εγκατάστασης" +wheretoinstall="Επιλέξτε την τοποθεσία εγκατάστασης του OSSEC HIDS" +installat="Η εγκατάσταση θα γίνει στο " +deletedir="Ο κατάλογος εγκατάστασης υπάρχει ήδη. Θέλετε να διαγραφεί;" + +# Part 3 +configuring="Ρυθμίζοντας το" +mailnotify="Θέλετε να ειδοποιήστε μέσω e-mail;" +nomail="Οι ειδοποιήσεις με e-mail απενεργοποιήθηκαν" +whatsemail="Ποιά είναι η διεύθυνση του ηλεκτρονικού σας ταχυδρομείου;" +yoursmtp="Βρήκαμε ότι ο διακομιστής της εξερχόμενης αλληλογραφίας σας είναι ο " +usesmtp="Θέλετε να τον χρησιμοποιήσετε;" +usingsmtp="Διακομιστής εξερχόμενης αλληλογραφίας: " +whatsmtp="Ποιά είναι η διεύθυνση του διακομιστή της εξερχόμενης αλληλογραφίας σας ip/host?" + +# Part 3.1/agent +serverip="Ποιά είναι η διεύθυνση IP του διακομιστή OSSEC HIDS;" +addingip="Προστέθηκε η διεύθυνση διακομιστή" + + +# Part 3.2 +runsyscheck="Θέλετε να εκτελέσετε τον δαίμονα ελέγχου ακεραιότητας (integrity check daemon);" +nosyscheck="Ο δαίμονας ελέγχου ακεραιότητας (integrity check daemon) δεν εκτελέστηκε" +yessyscheck="Ο δαίμονας ελέγχου ακεραιότητας (integrity check daemon) ξεκίνησε" + +# Part 3.3 +runrootcheck="Θέλετε να εκτελέσετε την μηχανή ανίχνευσης rootkit;" +norootcheck="Η μηχανή ανίχνευσης rootkit δεν εκτελέστηκε" +yesrootcheck="Η μηχανή ανίχνευσης rootkit ξεκίνησε" + +# Part 3.4/server/local +enable_ar="Θέλετε να ενεργοποιήσετε την ενεργή αντίδραση (active response);" +noactive="Η ενεργή αντίδραση (active response) απενεργοποιήθηκε" +nohosts="Το host-deny απενεργοποιήθηκε" +yeshosts="Το host-deny ενεργοποιήθηκε (local) για επίπεδα >= 6" +firewallar="Θέλετε να ενεργοποιήσετε την αντίδραση firewall-drop;" +nofirewall="Η αντίδραση firewall-drop απενεργοποιήθηκε." +yesfirewall="Η αντίδραση firewall-drop ενεργοποιήθηκε (local) για επίπεδα >= 6" +defaultwhitelist="Προεπιλεγμένη white list για την ενεργή αντίδραση (active response):" +addwhite="Θέλετε να προσθέσετε περισσότερες IPs στην white list;" +ipswhite="Διευθύνσεις IPs (χωρισμένες με κενό): " + +# Part 3.5/server/local +syslog="Θέλετε να ενεργοποιήσετε την καταγραφή συμβάντων σε απομακρυσμένο syslog διακομιστή (port 514 udp);" +nosyslog="Η απομακρυσμένη καταγραφή συμβάντων απενεργοποιήθηκε" +yessyslog="Η απομακρυσμένη καταγραφή συμβάντων ενεργοποιήθηκε" + +# Part 3.4/3.5 +readlogs="Ρυθμίζοντας το αρχείο ρυθμίσεων για να αναλυθούν τα παρακάτω αρχεία καταγραφής (logs):" + +# Part 5 +installing="Το σύστημα εγκαθίσταται" +runningmake="Το Makefile εκτελείται" + +# Final +configurationdone="Οι ρυθμίσεις πραγματοποιήθηκαν με επιτυχία" +tostart="Για να ξεκινήσετε το OSSEC HIDS" +tostop="Για να σταματήσετε το OSSEC HIDS" +configat="Το αρχείο ρυθμίσεων μπορεί να αναγνωστεί ή να τροποποιηθεί στην τοποθεσία" +addserveragent="Προκειμένου να διασυνδέσετε τον agent με τον server, πρέπει να προσθέσετε κάθε agent στο server." +runma="Εκτελέστε το αρχείο 'manage_agents' για να τους προσθέσετε ή να τους αφαιρέσετε" +presskey="Πατήστε ENTER για να συνεχίσετε" + +# Update +wanttoupdate="Βρέθηκε εγκατεστημένο OSSEC. Θέλετε να το ενημερώσετε;" +unabletoupdate="Η ενημέρωση απέτυχε. Απαιτείται νέα πλήρης εγκατάσταση." +updatecompleted="Η ενημέρωση ολοκληρώθηκε." +updatefailed="Η ενημέρωσε απέτυχε." +updaterules="Θέλετε να ενημερώσετε τους κανόνες (rules);" +updatingrules="Οι κανόνες (rules) ενημερώνονται." +notupdatingrules="Οι κανόνες (rules) δεν ενημερώνονται." + +# Pf support +pfenable="Θέλετε να χρησιμοποιήσετε το PF firewall για ενεργή αντίδραση (active response);" +nopf="Η αντίδραση (response) με το PF απενεργοποιήθηκε." +pftablename="Πιό είναι το όνομα του πίνακα (table) PF που θέλετε να χρησιμοποιήσετε;" +pfmessage="Προσθέστε τις παρακάτω γραμμές στην αρχή των PF κανόνων σας" diff --git a/etc/templates/el/messages/0x101-initial.txt b/etc/templates/el/messages/0x101-initial.txt new file mode 100755 index 0000000..6705d5d --- /dev/null +++ b/etc/templates/el/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + Πρόκειται να ξεκινήσετε τη διαδικασία εγκατάστασης του OSSEC HIDS. + Για την εγκατάσταση θα πρέπει να έχετε προ-εγκατεστημένο + ένα μεταγλωττιστή της γλώσσας C στον υπολογιστή σας. + Αν έχετε ερωτήσεις ή σχόλια, στείλτε email στη διεύθυνση + dcid@ossec.net (ή daniel.cid@gmail.com). diff --git a/etc/templates/el/messages/0x102-installhelp.txt b/etc/templates/el/messages/0x102-installhelp.txt new file mode 100755 index 0000000..09007b8 --- /dev/null +++ b/etc/templates/el/messages/0x102-installhelp.txt @@ -0,0 +1,30 @@ + - Έχετε τρείς επιλογές εγκατάστασης: server, agent ή local. + + - Αν επιλέξετε 'server', θα έχετε τη δυνατότητα να αναλύετε + τα αρχεία συμβάντων (logs), να δημιουργείτε ειδοποιήσεις μέσω email + και αντιδράσεις (responses), καθώς επίσης και να λαμβάνετε logs από + απομακρυσμένους syslog υπολογιστές και συστήματα τα οποία τρέχουν + τους 'agents' (από τους οποίους η δικτυακή κίνηση αποστέλλεται + κρυπτογραφημένα στον διακομιστή). + + - Αν επιλέξετε 'agent'(client), θα έχετε τη δυνατότητα να διαβάσετε + τοπικά αρχεία (από syslog, snort, apache, κλπ) καθώς επίσης και να + τα προωθήσετε (κρυπτογραφημένα) στον διακομιστή (server) για ανάλυση. + + - Αν επιλέξετε 'local', θα έχετε τη δυνατότητα να κάνετε οτιδήποτε κάνει + ο server, εκτός από το να λαμβάνετε απομακρυσμένα μηνύματα από + 'agents' ή εξωτερικές συσκευές syslog. + + + - Επιλέξτε 'server' αν εγκαθιστάτε log/analysis server. + + - Επιλέξτε 'agent' αν έχετε άλλο υπολογιστή ο οποίος τρέχει ως + log server και θέλετε να προωθείτε εκεί τα logs για ανάλυση + (ιδανικό για webservers, database servers, κλπ). + + - Επιλέξτε 'local' αν έχετε μόνο ένα υπολογιστή για να παρακολουθείτε. + + - Περισσότερες πληροφορίες στη διεύθυνση: + http://www.ossec.net/el/manual.html#starting + + diff --git a/etc/templates/el/messages/0x103-thanksforusing.txt b/etc/templates/el/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..d2b5d40 --- /dev/null +++ b/etc/templates/el/messages/0x103-thanksforusing.txt @@ -0,0 +1,13 @@ + + Ευχαριστούμε για τη χρησιμοποίηση του OSSEC HIDS. + Αν έχετε κάποια ερώτηση, πρόταση ή αν βρείτε κάποιο bug, + επικοινωνήστε μαζί μας στο contact@ossec.net ή χρησιμοποιώντας + την λίστα ταχυδρομείου (maillist) στο ossec-list@ossec.net + ( http://www.ossec.net/main/support/ ). + + Περισσότερες πληροφορίες στη διεύθυνση: + http://www.ossec.net/ + + --- Πατήστε ENTER για να ολοκληρωθεί η εγκατάσταση + (μπορεί να ακολουθούν περισσότερες πληροφορίες) + diff --git a/etc/templates/el/messages/0x104-client.txt b/etc/templates/el/messages/0x104-client.txt new file mode 100755 index 0000000..d3a5124 --- /dev/null +++ b/etc/templates/el/messages/0x104-client.txt @@ -0,0 +1,7 @@ + + - Αρχικά πρέπει να προσθέσετε αυτόν τον agent στο server + προκειμένου να μπορέσουν να επικοινωνήσουν μεταξύ τους. + Όταν το κάνετε, μπορείτε να εκτελέσετε το εργαλείο + 'manage_agents' προκειμένου να εισαγάγετε το authentication key + από τον server. + diff --git a/etc/templates/el/messages/0x105-noboot.txt b/etc/templates/el/messages/0x105-noboot.txt new file mode 100755 index 0000000..4958b65 --- /dev/null +++ b/etc/templates/el/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - Δεν έγινε καμία ενέργεια για να ρυθμιστεί το OSSEC HIDS + να ξεκινάει κατά της εκκίνηση του υπολογιστή. + Προσθέστε την ακόλουθη γραμμή στο init script: + diff --git a/etc/templates/el/messages/0x106-logs.txt b/etc/templates/el/messages/0x106-logs.txt new file mode 100755 index 0000000..965ed29 --- /dev/null +++ b/etc/templates/el/messages/0x106-logs.txt @@ -0,0 +1,9 @@ + - Αν θέλετε να ελέγξετε οποιοδήποτε άλλο αρχείο, αλλάξτε + το ossec.conf και προσθέστε μια νέα εγγραφή για τοπικό + αρχείο (localfile). + Για να λάβετε απαντήσεις σχετικά με τις ρυθμίσεις, + επισκευθείτε μας στη διεύθυνση http://www.ossec.net/ . + + + --- Πατήστε ENTER για να συνεχίσετε --- + diff --git a/etc/templates/el/messages/0x107-ar.txt b/etc/templates/el/messages/0x107-ar.txt new file mode 100755 index 0000000..36fe847 --- /dev/null +++ b/etc/templates/el/messages/0x107-ar.txt @@ -0,0 +1,10 @@ + + 3.4- Η ενεργή αντίδραση (active response) σας επιτρέπει + να εκτελέσετε μια συγκεκριμένη εντολή βασισμένη στα + γεγονότα (events) που λήφθησαν. Για παράδειγμα, + μπορείτε να μπλοκάρετε μια διεύθυνση IP ή να + απενεργοποιήσετε την πρόσβαση για ένα συγκεκριμένο + χρήστη. + Περισσότερες πληροφορίες στη διεύθυνση: + http://www.ossec.net/el/manual.html#active-response + diff --git a/etc/templates/el/messages/0x108-ar-enabled.txt b/etc/templates/el/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..f56d97c --- /dev/null +++ b/etc/templates/el/messages/0x108-ar-enabled.txt @@ -0,0 +1,14 @@ + - Η ενεργή αντίδραση (active response) ενεργοποιήθηκε. + + - Εξ ορισμού, μπορούμε να ενεργοποιήσουμε τις host-deny + και firewall-drop αντιδράσεις (responses). Η πρώτη θα + προσθέσει ένα υπολογιστή στο αρχείο /etc/hosts.deny. + Η δεύτερη θα μπλοκάρει τον υπολογιστή μέσω + iptables (για linux) ή μέσω ipfilter + (για Solaris, FreeBSD ή NetBSD). + + - Μπορούν να χρησιμοποιηθούν για να σταματήσουν + SSHD brute force scans, portscans και κάποιων άλλων + ειδών επιθέσεις. Μπορείτε επίσης να τις προσθέσετε + για να μπλοκάρετε γενονότα που παράγονται από το + snort, για παράδειγμα. diff --git a/etc/templates/en/errors/0x1-location.txt b/etc/templates/en/errors/0x1-location.txt new file mode 100755 index 0000000..ca78c3f --- /dev/null +++ b/etc/templates/en/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Error 0x1. + This script can only be executed from the same directory. + Change directory to where this script is before running it. + You must run it as ./install.sh ." + diff --git a/etc/templates/en/errors/0x2-beroot.txt b/etc/templates/en/errors/0x2-beroot.txt new file mode 100755 index 0000000..c976eb6 --- /dev/null +++ b/etc/templates/en/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Error 0x2. + You must be root to use this script. + diff --git a/etc/templates/en/errors/0x3-dependencies.txt b/etc/templates/en/errors/0x3-dependencies.txt new file mode 100755 index 0000000..e147628 --- /dev/null +++ b/etc/templates/en/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Error 0x3. + You need a compiler (like gcc or cc) to continue with the + with the installation. + diff --git a/etc/templates/en/errors/0x4-installtype.txt b/etc/templates/en/errors/0x4-installtype.txt new file mode 100755 index 0000000..eef8906 --- /dev/null +++ b/etc/templates/en/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Error 0x4. + Wrong installation type. It can only be agent, server or local. + diff --git a/etc/templates/en/errors/0x5-build.txt b/etc/templates/en/errors/0x5-build.txt new file mode 100755 index 0000000..caa15bb --- /dev/null +++ b/etc/templates/en/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Error 0x5. + Building error. Unable to finish the installation. + diff --git a/etc/templates/en/language.txt b/etc/templates/en/language.txt new file mode 100755 index 0000000..d5548a8 --- /dev/null +++ b/etc/templates/en/language.txt @@ -0,0 +1 @@ + ** For installation in English, choose [en]. diff --git a/etc/templates/en/messages.txt b/etc/templates/en/messages.txt new file mode 100755 index 0000000..abf9aee --- /dev/null +++ b/etc/templates/en/messages.txt @@ -0,0 +1,106 @@ +# Configuration +yes="y" +no="n" +yesmatch="y" +nomatch="n" +agent="agent" +local="local" +server="server" +help="help" + +# Global +moreinfo="More information at: " +starting="Starting OSSEC HIDS" +systemis="System is" +modifiedinit="Init script modified to start OSSEC HIDS during boot." +noboot="Unknown system. No init script added." + +# Part 1 +installscript="Installation Script" +system="System" +user="User" +host="Host" +hitanyorabort="Press ENTER to continue or Ctrl-C to abort." +whattoinstall="What kind of installation do you want (server, agent, local or help)?" +serverchose="Server installation chosen" +clientchose="Agent(client) installation chosen" +localchose="Local installation chosen" + +# Part 2 +settingupenv="Setting up the installation environment" +wheretoinstall="Choose where to install the OSSEC HIDS" +installat="Installation will be made at " +deletedir="The installation directory already exists. Should I delete it?" + +# Part 3 +configuring="Configuring the" +mailnotify="Do you want e-mail notification?" +nomail="Email notification disabled" +whatsemail="What's your e-mail address?" +yoursmtp="We found your SMTP server as" +usesmtp="Do you want to use it?" +usingsmtp="Using SMTP server: " +whatsmtp="What's your SMTP server ip/host?" + +# Part 3.1/agent +serverip="What's the IP Address of the OSSEC HIDS server?" +addingip="Adding Server IP" + + +# Part 3.2 +runsyscheck="Do you want to run the integrity check daemon?" +nosyscheck="Not running syscheck (integrity check daemon)" +yessyscheck="Running syscheck (integrity check daemon)" + +# Part 3.3 +runrootcheck="Do you want to run the rootkit detection engine?" +norootcheck="Not running rootcheck (rootkit detection)" +yesrootcheck="Running rootcheck (rootkit detection)" + +# Part 3.4/server/local +enable_ar="Do you want to enable active response?" +noactive="Active response disabled" +nohosts="host-deny disabled" +yeshosts="host-deny enabled (local) for levels >= 6" +firewallar="Do you want to enable the firewall-drop response?" +nofirewall="firewall-drop disabled." +yesfirewall="firewall-drop enabled (local) for levels >= 6" +defaultwhitelist="Default white list for the active response:" +addwhite="Do you want to add more IPs to the white list?" +ipswhite="IPs (space separated): " + +# Part 3.5/server/local +syslog="Do you want to enable remote syslog (port 514 udp)?" +nosyslog="Remote syslog disabled" +yessyslog="Remote syslog enabled" + +# Part 3.4/3.5 +readlogs="Setting the configuration to analyze the following logs:" + +# Part 5 +installing="Installing the system" +runningmake="Running the Makefile" + +# Final +configurationdone="Configuration finished properly" +tostart="To start OSSEC HIDS" +tostop="To stop OSSEC HIDS" +configat="The configuration can be viewed or modified at" +addserveragent="In order to connect agent and server, you need to add each agent to the server." +runma="Run the 'manage_agents' to add or remove them" +presskey="Press ENTER to continue" + +# Update +wanttoupdate="You already have OSSEC installed. Do you want to update it?" +unabletoupdate="Unable to perform update. A full new install will be required." +updatecompleted="Update completed." +updatefailed="Update failed." +updaterules="Do you want to update the rules?" +updatingrules="Updating rules." +notupdatingrules="Not updating rules." + +# Pf support +pfenable="Do you want to use the PF firewall in the active response?" +nopf="PF response disabled." +pftablename="Name of the PF table to use?" +pfmessage="Add the following lines to the beginning of your PF rules" diff --git a/etc/templates/en/messages/0x101-initial.txt b/etc/templates/en/messages/0x101-initial.txt new file mode 100755 index 0000000..3e3ce85 --- /dev/null +++ b/etc/templates/en/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + You are about to start the installation process of the OSSEC HIDS. + You must have a C compiler pre-installed in your system. + If you have any questions or comments, please send an e-mail + to dcid@ossec.net (or daniel.cid@gmail.com). + diff --git a/etc/templates/en/messages/0x102-installhelp.txt b/etc/templates/en/messages/0x102-installhelp.txt new file mode 100755 index 0000000..a8111f8 --- /dev/null +++ b/etc/templates/en/messages/0x102-installhelp.txt @@ -0,0 +1,29 @@ + + - You have three installation options: server, agent or local. + + - If you choose 'server', you will be able to analyze all + the logs, create e-mail notifications and responses, + and also receive logs from remote syslog machines and + from systems running the 'agents' (from where traffic + is sent encrypted to the server). + + - If you choose 'agent'(client), you will be able to read + local files (from syslog, snort, apache, etc) and forward + them (encrypted) to the server for analysis. + + - If you choose 'local', you will be able to do everything + the server does, except receiving remote messages from + the agents or external syslog devices. + + - Choose 'server' if you are setting up a log/analysis server. + + - Choose 'agent' if you have another machine to run as a log + server and want to forward the logs to the server for analysis. + (ideal for webservers, database servers ,etc) + + - Choose 'local' if you only have one system to monitor. + + - More information at: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/en/messages/0x103-thanksforusing.txt b/etc/templates/en/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..37a3aaf --- /dev/null +++ b/etc/templates/en/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Thanks for using the OSSEC HIDS. + If you have any question, suggestion or if you find any bug, + contact us at contact@ossec.net or using our public maillist at + ossec-list@ossec.net + ( http://www.ossec.net/main/support/ ). + + More information can be found at http://www.ossec.net + + --- Press ENTER to finish (maybe more information below). --- + diff --git a/etc/templates/en/messages/0x104-client.txt b/etc/templates/en/messages/0x104-client.txt new file mode 100755 index 0000000..eac94be --- /dev/null +++ b/etc/templates/en/messages/0x104-client.txt @@ -0,0 +1,6 @@ + + - You first need to add this agent to the server so they + can communicate with each other. When you have done so, + you can run the 'manage_agents' tool to import the + authentication key from the server. + diff --git a/etc/templates/en/messages/0x105-noboot.txt b/etc/templates/en/messages/0x105-noboot.txt new file mode 100755 index 0000000..8420a18 --- /dev/null +++ b/etc/templates/en/messages/0x105-noboot.txt @@ -0,0 +1,4 @@ + + - No action was made to configure the OSSEC HIDS to start + during the boot. Add the following line to your init script: + diff --git a/etc/templates/en/messages/0x106-logs.txt b/etc/templates/en/messages/0x106-logs.txt new file mode 100755 index 0000000..a81aea1 --- /dev/null +++ b/etc/templates/en/messages/0x106-logs.txt @@ -0,0 +1,8 @@ + - If you want to monitor any other file, just change + the ossec.conf and add a new localfile entry. + Any questions about the configuration can be answered + by visiting us online at http://www.ossec.net . + + + --- Press ENTER to continue --- + diff --git a/etc/templates/en/messages/0x107-ar.txt b/etc/templates/en/messages/0x107-ar.txt new file mode 100755 index 0000000..cd1a4a8 --- /dev/null +++ b/etc/templates/en/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- Active response allows you to execute a specific + command based on the events received. For example, + you can block an IP address or disable access for + a specific user. + More information at: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/en/messages/0x108-ar-enabled.txt b/etc/templates/en/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..9f33b44 --- /dev/null +++ b/etc/templates/en/messages/0x108-ar-enabled.txt @@ -0,0 +1,10 @@ + - Active response enabled. + + - By default, we can enable the host-deny and the + firewall-drop responses. The first one will add + a host to the /etc/hosts.deny and the second one + will block the host on iptables (if linux) or on + ipfilter (if Solaris, FreeBSD or NetBSD). + - They can be used to stop SSHD brute force scans, + portscans and some other forms of attacks. You can + also add them to block on snort events, for example. diff --git a/etc/templates/es/errors/0x1-location.txt b/etc/templates/es/errors/0x1-location.txt new file mode 100755 index 0000000..cac0c83 --- /dev/null +++ b/etc/templates/es/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Error 0x1. + El programa puede ser solo ejecutado desde su mismo directorio. + Cambie al directorio donde se encuentra el programa antes de ejecutarlo. + Debe de ejecutarlo como ./install.sh ." + diff --git a/etc/templates/es/errors/0x2-beroot.txt b/etc/templates/es/errors/0x2-beroot.txt new file mode 100755 index 0000000..6f748bb --- /dev/null +++ b/etc/templates/es/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Error 0x2. + Usted debe ser root en orden de usar el programa. + diff --git a/etc/templates/es/errors/0x3-dependencies.txt b/etc/templates/es/errors/0x3-dependencies.txt new file mode 100755 index 0000000..fa86e72 --- /dev/null +++ b/etc/templates/es/errors/0x3-dependencies.txt @@ -0,0 +1,4 @@ + + Error 0x3. + Usted necesita un compilador (semejante a gcc ó cc) para continuar con la instalación. + diff --git a/etc/templates/es/errors/0x4-installtype.txt b/etc/templates/es/errors/0x4-installtype.txt new file mode 100755 index 0000000..eef8906 --- /dev/null +++ b/etc/templates/es/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Error 0x4. + Wrong installation type. It can only be agent, server or local. + diff --git a/etc/templates/es/errors/0x5-build.txt b/etc/templates/es/errors/0x5-build.txt new file mode 100755 index 0000000..caa15bb --- /dev/null +++ b/etc/templates/es/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Error 0x5. + Building error. Unable to finish the installation. + diff --git a/etc/templates/es/language.txt b/etc/templates/es/language.txt new file mode 100755 index 0000000..471191b --- /dev/null +++ b/etc/templates/es/language.txt @@ -0,0 +1 @@ + ** Para instalar en Español , eliga [es]. diff --git a/etc/templates/es/messages.txt b/etc/templates/es/messages.txt new file mode 100755 index 0000000..ca7000b --- /dev/null +++ b/etc/templates/es/messages.txt @@ -0,0 +1,106 @@ +# Configuration +yes="s" +no="n" +yesmatch="s" +nomatch="n" +agent="agente" +local="local" +server="servidor" +help="ayuda" + +# Global +moreinfo="Más información en: " +starting="Comenzando OSSEC HIDS" +systemis="El sistema es" +modifiedinit="Init script modificado para empezar OSSEC HIDS durante el arranque." +noboot="Sistema desconocido. El guión init no fué agregado" + +# Part 1 +installscript="Guión de instalación" +system="Sistema" +user="Usuario" +host="servidor" +hitanyorabort="Presione ENTER para continuar ó Ctrl-C para abortar." +whattoinstall="Que tipo de instalación Usted desea (servidor, agente, local ó ayuda)?" +serverchose="Usted eligió instalación de Servidor" +clientchose="Usted eligió instalación de Agente(cliente)" +localchose="Usted eligió instalación Local" + +# Part 2 +settingupenv="Configurando las variables de entorno de la instalación" +wheretoinstall="Eliga donde instalar OSSEC HIDS" +installat="La instalación se realizará en " +deletedir="El directorio de instalación ya existe. Desea removerlo?" + +# Part 3 +configuring="Configurando el sistema" +mailnotify="Desea recibir notificación por correo electrónico?" +nomail="Notificación por correo electrónico deshabilitado" +whatsemail="Cuál es vuestra dirección de correo electrónico?" +yoursmtp="Hemos encontrado vuestro servidor de correo (SMTP)" +usesmtp="Desea Usted usarlo?" +usingsmtp="Usando el servidor SMTP: " +whatsmtp="Cuál es la direccion ó nombre de vuestro servidor de correo SMTP?" + +# Part 3.1/agent +serverip="Cuál es la direccion del servidor OSSEC HIDS?" +addingip="Agregando el IP del servidor" + + +# Part 3.2 +runsyscheck="Desea Usted agregar el servidor de integridad del sistema?" +nosyscheck="No se ejecutará syscheck (servidor de integridad del sistema)" +yessyscheck="Ejecutando syscheck (servidor de integridad del sistema)" + +# Part 3.3 +runrootcheck="Desea Usted agregar el sistema de detección de rootkit?" +norootcheck="No se ejecutará rootcheck (sistema de detección de rootkit)" +yesrootcheck="Ejecutando rootcheck (sistema de detección de rootkit)" + +# Part 3.4/server/local +enable_ar="Desea Usted habilitar respuesta activa?" +noactive="Respuesta activa deshabilitada" +nohosts="host-deny deshabilitado" +yeshosts="host-deny habilitado (local) para niveles >= 6" +firewallar="Desea Usted habilitar la respuesta desechar en el Firewall?" +nofirewall="Respuesta desechar en el Firewall deshabilitada." +yesfirewall="Respuesta desechar en el Firewall habilitada (local) para niveles >= 6" +defaultwhitelist="Lista blanca para respuesta activa por omisión:" +addwhite="Desea Usted agregar más IPs a la lista blanca?" +ipswhite="IPs (lista separada por blancos): " + +# Part 3.5/server/local +syslog="Desea Usted habilitarsyslog remoto (puerto 514 udp)?" +nosyslog="Syslog remoto deshabilitado" +yessyslog="Syslog remoto habilitado" + +# Part 3.4/3.5 +readlogs="Estableciendo la configuración para analizar los siguientes registros:" + +# Part 5 +installing="Instalando el sistema" +runningmake="Ejecutando el Makefile" + +# Final +configurationdone="Configuración finalizada correctamente" +tostart="Para comenzar OSSEC HIDS" +tostop="Para detener OSSEC HIDS" +configat="La configuración puede ser leída ó mofificada en" +addserveragent="Para connectar el agente con el servidor, debe Usted agregar cada uno de los agentes en el servidor." +runma="Ejecute el programa 'manage_agents' para agregarlos ó removerlos " +presskey="Press ENTER to continue" + +# Update +wanttoupdate="Usted ya ha instalado OSSEC previamente. Desea Usted actualizarlo?" +unabletoupdate="He sido incapaz de actualizar el sistema. Una nueva y completa instalación es requerida." +updatecompleted="Actualización completa." +updatefailed="La actualización ha fallado." +updaterules="Desea Usted actualizar las reglas?" +updatingrules="Actualizando las reglas." +notupdatingrules="No se actualiza las reglas." + +# Pf support +pfenable="Desea Usted usar el PF firewall en la respuesta activa?" +nopf="respuesta PF deshabilitada." +pftablename="Nombre de la tabla de PF table a usar?" +pfmessage="Agregar las siguientes lineas al principio de las reglas del PF" diff --git a/etc/templates/es/messages/0x101-initial.txt b/etc/templates/es/messages/0x101-initial.txt new file mode 100755 index 0000000..014a7ed --- /dev/null +++ b/etc/templates/es/messages/0x101-initial.txt @@ -0,0 +1,7 @@ + + + Usted esta por comenzar el proceso de instalación del OSSEC HIDS. + Usted debe tener un compilador de C previamente instalado en el sistema. + Si usted tiene alguna pregunta o comentario, por favor envie un correo + electrónico a dcid@ossec.net (daniel.cid@gmail.com + ) diff --git a/etc/templates/es/messages/0x102-installhelp.txt b/etc/templates/es/messages/0x102-installhelp.txt new file mode 100755 index 0000000..73163d5 --- /dev/null +++ b/etc/templates/es/messages/0x102-installhelp.txt @@ -0,0 +1,31 @@ + + - Usted tiene tres posibilidades de instalación: servidor, + agente ó local. + + - Si Usted elige 'servidor', Usted sera capaz de analizar + todo los registros, crear notificaciónes de correo y + respuestas, asi com otambien recibir registros desde equipos + syslog remotos y sistemas ejecutando el 'agente' + (quienes transmitiran su traffico cifrado hacia el servidor). + + - Si Usted elige 'agente'(cliente), Usted sera capaz de leer + registros locales ( de syslog, snort, apache, etc) y + retransmitir retrasmitirlos al servidor de analysis. + + - Si Usted elige local Usted sera capaz de todo lo que es capaz + de hacer el servidor, excepto recibir mensajes remotos de los + agentes ó fuentes externas de syslog. + + - Elija 'servidor' si Usted desea instalar un servidor de registros + ó análisis. + + - Elija 'agente' si Usted tiene otra maquina ejecutando el servidor + de lectura de registros y desea transmitir los registros a él para + análisis. (ideal para servidore WEB, base de datos, etc) + + -Elija 'local' si Usted tiene que monitear un solo sistema . + + - Para más información dirijase a: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/es/messages/0x103-thanksforusing.txt b/etc/templates/es/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..510b811 --- /dev/null +++ b/etc/templates/es/messages/0x103-thanksforusing.txt @@ -0,0 +1,10 @@ + + Gracias por usar OSSEC HIDS. + Si tuviera Usted alguna duda, sugerencia ó haya encontrado + algun desperfecto, contactese con nosotros a contact@ossec.net + ó usando nuestrs lista pública de correo en ossec-list@ossec.net + + Más información puede ser encontrada en http://www.ossec.net + + --- Presione ENTER para finalizar. --- + (Tal vez encuentre más información a continuación). diff --git a/etc/templates/es/messages/0x104-client.txt b/etc/templates/es/messages/0x104-client.txt new file mode 100755 index 0000000..bacba6b --- /dev/null +++ b/etc/templates/es/messages/0x104-client.txt @@ -0,0 +1,6 @@ + + - Usted debe de añadir este agente en el servidor así podran + comunicarse el úno con el ótro. Una vez culminada la tarea + podra ejecutar la herramienta 'manage_agents' para importar + la autentificación de llaves extraidas del servidor. + diff --git a/etc/templates/es/messages/0x105-noboot.txt b/etc/templates/es/messages/0x105-noboot.txt new file mode 100755 index 0000000..dd1f020 --- /dev/null +++ b/etc/templates/es/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - No se ha tomado acción para configurar OSSEC HIDS de ejecutar + durante el encendido de la maquina. Agrege las siguiente linea + a vuestro archivo código init: + diff --git a/etc/templates/es/messages/0x106-logs.txt b/etc/templates/es/messages/0x106-logs.txt new file mode 100755 index 0000000..0934661 --- /dev/null +++ b/etc/templates/es/messages/0x106-logs.txt @@ -0,0 +1,9 @@ + + - Si Usted deseara monitorear algún otro registro, solo + tendrá que editar el archivo ossec.conf y agregar una + nueva entrada de tipo localfile. + Cualquier otra pregunta de configuración podra ser + respondida visitandonos en linea en http://www.ossec.net . + + --- Presione ENTER para continuar --- + diff --git a/etc/templates/es/messages/0x107-ar.txt b/etc/templates/es/messages/0x107-ar.txt new file mode 100755 index 0000000..67da20c --- /dev/null +++ b/etc/templates/es/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- Respuestas activas le permitirán ejecutar un comando + específico en base a los eventos recibidos. Por ejemplo, + Usted podra bloquear una dirección IP ó deshabilitar el acceso + de un usuario específico. + Más información en: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/es/messages/0x108-ar-enabled.txt b/etc/templates/es/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..eb66f5c --- /dev/null +++ b/etc/templates/es/messages/0x108-ar-enabled.txt @@ -0,0 +1,15 @@ + + - Respuesta activa habilitada. + + - Por omición, podemos habilitar el rechazo de servicio + o el abandono del paquete por medio del Firewall. + El rechazo agregara el ofendedor en el archivo etc/hosts.deny + y el abandono bloquara la comunicación con el ofendedor en iptables + (si el sistema fuera linux) ó ipfilter (si el sistema fuera + Solaris, FreeBSD or NetBSD). + + - Las dos repuestas pueden ser utilizadas para detener un escaneo + de fuerza bruta contra SSHD, escaneo de puertos y otras formas + de ataque. Por ejemplo Usted podra tambien agregar los ofensores + de acuerdo a eventos registrados por medio de snort. + diff --git a/etc/templates/fr/errors/0x1-location.txt b/etc/templates/fr/errors/0x1-location.txt new file mode 100755 index 0000000..b78a097 --- /dev/null +++ b/etc/templates/fr/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Error 0x1. + Ce script ne peut être exécuté que depuis le même répertoire. + Déplacez vous où est le script avant de l'exécuter. + Vous devez le lancer par ./install.sh ." + diff --git a/etc/templates/fr/errors/0x2-beroot.txt b/etc/templates/fr/errors/0x2-beroot.txt new file mode 100755 index 0000000..22350f3 --- /dev/null +++ b/etc/templates/fr/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Error 0x2. + Vous devez être root pour exécuter ce script. + diff --git a/etc/templates/fr/errors/0x3-dependencies.txt b/etc/templates/fr/errors/0x3-dependencies.txt new file mode 100755 index 0000000..7efa98f --- /dev/null +++ b/etc/templates/fr/errors/0x3-dependencies.txt @@ -0,0 +1,4 @@ + + Error 0x3. + Vous devez avoir un compilateur (gcc ou cc) pour continuer l'installation. + diff --git a/etc/templates/fr/errors/0x4-installtype.txt b/etc/templates/fr/errors/0x4-installtype.txt new file mode 100755 index 0000000..12b5aed --- /dev/null +++ b/etc/templates/fr/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Error 0x4. + Mauvais type d'installation. Cela ne peut être que agent, serveur ou local. + diff --git a/etc/templates/fr/errors/0x5-build.txt b/etc/templates/fr/errors/0x5-build.txt new file mode 100755 index 0000000..712e20b --- /dev/null +++ b/etc/templates/fr/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Error 0x5. + Erreur de compilation. Impossible de finir l'installation. + diff --git a/etc/templates/fr/language.txt b/etc/templates/fr/language.txt new file mode 100755 index 0000000..b3a9c82 --- /dev/null +++ b/etc/templates/fr/language.txt @@ -0,0 +1 @@ + ** Pour une installation en français, choisissez [fr] diff --git a/etc/templates/fr/messages.txt b/etc/templates/fr/messages.txt new file mode 100755 index 0000000..9f5cc09 --- /dev/null +++ b/etc/templates/fr/messages.txt @@ -0,0 +1,107 @@ +# Configuration +yes="o" +no="n" +yesmatch="o" +nomatch="n" +agent="agent" +local="local" +server="serveur" +help="aide" + +# Global +moreinfo="Plus d'information sur: " +starting="Démarrage de OSSEC HIDS" +systemis="Le Système est" +modifiedinit="Script d'initialisation modifié pour démarrer OSSEC HIDS pendant le boot." +noboot="Système inconnu. Aucun script d'initialisation ajouté." + +# Part 1 +installscript="Script d'installation" +system="Système" +user="Utilisateur" +host="Hôte" +hitanyorabort="Appuyez sur Entrée pour continuer ou Ctrl-C pour annuler." +whattoinstall="Quel type d'installation voulez-vous (serveur, agent, local ou aide) ?" +serverchose="Installation du serveur choisie" +clientchose="Installation de l'agent (client) choisie" +localchose="Installation en local choisie" + +# Part 2 +settingupenv="Définition de l'environnement d'installation" +wheretoinstall="Choisissez votre répertoire d'installation de OSSEC HIDS" +installat="L'installation sera faite sur " +deletedir="Le répertoire d'installation existe déjà. Doit-on le supprimer ?" + +# Part 3 +configuring="Configuration de" +mailnotify="Voulez-vous une alerte par email ?" +nomail="Alerte par email désactivée" +whatsemail="Quel est votre adresse email ?" +yoursmtp="Nous trouvons votre serveur SMTP sur" +usesmtp="Voulez-vous l'utiliser ?" +usingsmtp="Serveur SMTP utilisé : " +whatsmtp="Quel est l'adresse IP ou le nom d'hôte de votre serveur SMTP ?" + +# Part 3.1/agent +serverip="Quelle est l'adresse IP de votre serveur OSSEC HIDS ?" +addingip="Ajout de l'IP du Serveur" + + +# Part 3.2 +runsyscheck="Voulez-vous démarrer le démon de vérification d'intégrité ?" +nosyscheck="Syscheck non lancé (démon de vérification d'intégrité)" +yessyscheck="Lancement de syscheck (démon de vérification d'intégrité)" + +# Part 3.3 +runrootcheck="Voulez-vous démarrer le moteur de détection de rootkit ?" +norootcheck="Rootcheck non lancé (détection de rootkit)" +yesrootcheck="Lancement de rootcheck (détection de rootkit)" + +# Part 3.4/server/local +enable_ar="voulez-vous démarrer la réponse active ?" +noactive="Réponse active désactivée" +nohosts="contrôle d'hôte (host-deny) désactivé" +yeshosts="contrôle d'hôte (host-deny) activé (local) pour les levels >= 6" +firewallar="Voulez-vous activer la réponse pare-feu (firewall-drop) ?" +nofirewall="pare-feu (firewall-drop) désactivé." +yesfirewall="pare-feu (firewall-drop) activé (local) pour les levels >= 6" +defaultwhitelist="liste blanche (white list) par défaut pour la réponse active :" +addwhite="Voulez-vous d'autres adresses IP dans votre liste (white list) ?" +ipswhite="IPs (séparées par des espaces) : " + +# Part 3.5/server/local +syslog="Voulez-vous activer fonctionnalité syslog (port udp 514) ?" +nosyslog="Fonctionnalité syslog désactivé" +yessyslog="Fonctionnalité syslog activé" + +# Part 3.4/3.5 +readlogs="Mise en place de la configuration pour analyser les logs suivants :" + +# Part 5 +installing="Installation du système" +runningmake="Exécution du Makefile" + +# Final +configurationdone="Configuration correctement terminée" +tostart="Pour démarrer OSSEC HIDS" +tostop="Pour arrêter OSSEC HIDS" +configat="La configuration peut être visualisée ou modifiée dans" +addserveragent="Vous devez ajouter le(s) agent(s) avant qu'ils aient un accés autorisé." +runma="Lancez 'manage_agent' pour les ajouter ou les supprimer" +presskey="Appuyez sur Entrée pour continuer" + +# Update +wanttoupdate="Vous avez déjà installé OSSEC. Voulez-vous le mettre à jour ?" +unabletoupdate="Impossible de mettre à jour. Une nouvelle installation est nécessaire." +updatecompleted="Mise à jour complète." +updatefailed="Echec de la mise à jour." +updaterules="Voulez-vous mettre à jour les règles ?" +updatingrules="Mise à jour des règles." +notupdatingrules="Règles non mises à jour." + +# Pf support +pfenable="Voulez-vous utiliser le firewall PF dans la réponse active ?" +nopf="Réponse par PF désactivée." +pftablename="Nom de la table PF à utiliser ?" +pfmessage="Ajouter les lignes suivantes au début de vos règles" + diff --git a/etc/templates/fr/messages/0x101-initial.txt b/etc/templates/fr/messages/0x101-initial.txt new file mode 100755 index 0000000..b21f882 --- /dev/null +++ b/etc/templates/fr/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + Vous êtes sur le point d'installer OSSEC HIDS. + Vous devez avoir une compilateur C préinstallé sur votre système. + Si vous avez des questions ou des commentaires, envoyez un email + à dcid@ossec.net (ou daniel.cid@gmail.com). + diff --git a/etc/templates/fr/messages/0x102-installhelp.txt b/etc/templates/fr/messages/0x102-installhelp.txt new file mode 100755 index 0000000..f282d68 --- /dev/null +++ b/etc/templates/fr/messages/0x102-installhelp.txt @@ -0,0 +1,29 @@ + + - Vous avez 3 installations possibles : server, agent ou local. + + - Si vous choisissez 'serveur', vous pourrez analyser tous + les logs, créer des alertes par email et leurs réponses, + et aussi recevoir les logs depuis les machines syslog + distantes et depuis les systèmes utilisant les 'agents' + (le tranfert étant codé et envoyé jusqu'au server). + + - Si vous choisissez 'agent'(client), vous pourrez lire les + fichiers locaux (de syslog, snort, apache, etc) et les + envoyer (codés) au serveur pour les analyser. + + - Si vous choisissez 'local', vous pourrez faire tout ce + que le serveur fait, à l'exception de la réception des + messages des agents ou de machines syslog externes. + + - Choisissez 'serveur' si vous installez un serveur de log ou un analyseur. + + - Choisissez 'agent' si vous avez une autre machine lancée en tant + que serveur de log et que vous voulez lui envoyer les logs pour analyse. + (idéal pour les serveurs web, de base de données, etc) + + - choisissez 'local' si vous n'avez qu'une machine à surveiller. + + - Plus d'information sur : + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/fr/messages/0x103-thanksforusing.txt b/etc/templates/fr/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..f2f4df1 --- /dev/null +++ b/etc/templates/fr/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Merci d'utiliser OSSEC HIDS. + Si vous avez des questions, suggestions ou si vous trouvez + un bug, contactez nous sur contact@ossec.net ou en utilisant la + liste de diffusion publique sur ossec-list@ossec.net + ( http://www.ossec.net/en/mailing_lists.html ). + + Plus d'information peut être trouver sur http://www.ossec.net + + --- Appuyez sur Entrée pour finir (peut-être plus d'info plus bas). --- + diff --git a/etc/templates/fr/messages/0x104-client.txt b/etc/templates/fr/messages/0x104-client.txt new file mode 100755 index 0000000..9219455 --- /dev/null +++ b/etc/templates/fr/messages/0x104-client.txt @@ -0,0 +1,6 @@ + + - Vous devez d'abord ajouter cet agent sur le serveur pour + qu'ils communiquent entre eux. Quand cela sera fait, + vous pourrez lancer l'outil 'manage_agents' pour + importer la clef d'authentification depuis le serveur. + diff --git a/etc/templates/fr/messages/0x105-noboot.txt b/etc/templates/fr/messages/0x105-noboot.txt new file mode 100755 index 0000000..86e5c0c --- /dev/null +++ b/etc/templates/fr/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - Aucune action n'a été faite pour configurer OSSEC HIDS pour + démarrer lors du boot. Ajoutez la ligne suivante à votre script + d'initialisation : + diff --git a/etc/templates/fr/messages/0x106-logs.txt b/etc/templates/fr/messages/0x106-logs.txt new file mode 100755 index 0000000..2a48f67 --- /dev/null +++ b/etc/templates/fr/messages/0x106-logs.txt @@ -0,0 +1,9 @@ + - Si vous voulez surveiller d'autres fichiers, changez + le fichier ossec.conf en ajoutant une nouvelle valeur + de nom de fichier local. + Pour toutes vos questions sur la configuration, + consultez notre site web http://www.ossec.net . + + + --- Appuyez sur Entrée pour continuer --- + diff --git a/etc/templates/fr/messages/0x107-ar.txt b/etc/templates/fr/messages/0x107-ar.txt new file mode 100755 index 0000000..7d5e4b7 --- /dev/null +++ b/etc/templates/fr/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- La réponse active vous permet d'éxécuter des commandes + spécifiques en fonction d'évènement. Par exemple, + vous pouvez bloquer une adresse IP ou interdire + l'accès à un utilisateur spécifique. + Plus d'information sur : + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/fr/messages/0x108-ar-enabled.txt b/etc/templates/fr/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..d17ad2c --- /dev/null +++ b/etc/templates/fr/messages/0x108-ar-enabled.txt @@ -0,0 +1,11 @@ + - Réponse active activée. + + - Par défaut, nous pouvons activer le contrôle d'hôte + et le pare-feu (firewall-drop). Le premier ajoute + un hôte dans /etc/hosts.deny et le second bloquera + l'hôte dans iptables (sous linux) ou dans ipfilter + (sous Solaris, FreeBSD ou NetSBD). + - Ils peuvent aussi être utilisés pour arrêter les scans + en force brute de SSHD, les scans de ports ou d'autres + formes d'attaques. Vous pouvez aussi les bloquer par + rapport à des évènements snort, par exemple. diff --git a/etc/templates/it/errors/0x1-location.txt b/etc/templates/it/errors/0x1-location.txt new file mode 100755 index 0000000..345e5a7 --- /dev/null +++ b/etc/templates/it/errors/0x1-location.txt @@ -0,0 +1,7 @@ + + Error 0x1. + Questo script deve essere eseguito a partire dalla directory in cui + si trova. + Prima di eseguire questo script entra nella directory in cui si trova. + Per eseguire lo script scrivi "./install.sh" + diff --git a/etc/templates/it/errors/0x2-beroot.txt b/etc/templates/it/errors/0x2-beroot.txt new file mode 100755 index 0000000..ae7b96e --- /dev/null +++ b/etc/templates/it/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Error 0x2. + Devi essere root per eseguire questo script. + diff --git a/etc/templates/it/errors/0x3-dependencies.txt b/etc/templates/it/errors/0x3-dependencies.txt new file mode 100755 index 0000000..d1475d5 --- /dev/null +++ b/etc/templates/it/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Error 0x3. + E' necessario avere un compilatore installato (come gcc o cc) per proseguire + con l'installazione. + diff --git a/etc/templates/it/errors/0x4-installtype.txt b/etc/templates/it/errors/0x4-installtype.txt new file mode 100755 index 0000000..69c1835 --- /dev/null +++ b/etc/templates/it/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Error 0x4. + Tipo di installazione errata. Può essere solamente Server, Agent o Local. + diff --git a/etc/templates/it/errors/0x5-build.txt b/etc/templates/it/errors/0x5-build.txt new file mode 100755 index 0000000..2381f39 --- /dev/null +++ b/etc/templates/it/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Error 0x5. + Errore di compilazione. Impossibile terminare l'installazione. + diff --git a/etc/templates/it/language.txt b/etc/templates/it/language.txt new file mode 100755 index 0000000..c5a3774 --- /dev/null +++ b/etc/templates/it/language.txt @@ -0,0 +1 @@ + ** Per l'installazione in Italiano, scegli [it]. diff --git a/etc/templates/it/messages.txt b/etc/templates/it/messages.txt new file mode 100755 index 0000000..33f01fa --- /dev/null +++ b/etc/templates/it/messages.txt @@ -0,0 +1,107 @@ +# Configuration +yes="s" +no="n" +yesmatch="s" +nomatch="n" +agent="agent" +local="local" +server="server" +help="help" + +# Global +moreinfo="Maggiori informazioni su: " +starting="Avvio OSSEC HIDS" +systemis="Il Sistema è" +modifiedinit="Script di Init modificato per eseguire OSSEC HIDS in fase di boot." +noboot="Sistema sconosciuto. Nessuno script di init aggiunto." + +# Part 1 +installscript="Script di installazione" +system="Sistema" +user="User" +host="Host" +hitanyorabort="Premi ENTER per continuare o Ctrl-C per abbandonare." +whattoinstall="Che tipo di installazione vuoi fare (server, agent, local o help)?" +serverchose="Scelta installazione Server" +clientchose="Scelta installazione Agent(client)" +localchose="Scelta installazione Local" + +# Part 2 +settingupenv="Configurazione dell'ambiente di installazione" +wheretoinstall="Scegli dove installare OSSEC HIDS" +installat="L'installazione verrà effettuata in " +deletedir="La directory di installazione è già presente. La devo cancellare?" + +# Part 3 +configuring="Configuro " +mailnotify="Vuoi attivare l'e-mail di notifica?" +nomail="E-mail di notifica disattivata" +whatsemail="Qual'è il tuo indirizzo e-mail?" +yoursmtp="Il tuo server SMTP è" +usesmtp="Vuoi utilizzarlo?" +usingsmtp="Utilizzo il server SMTP: " +whatsmtp="Qual'è l'ip/host del tuo server SMTP?" + +# Part 3.1/agent +serverip="Qual'è l'indirizzo IP del server OSSEC HIDS?" +addingip="Aggiungo l'IP del Server" + + +# Part 3.2 +runsyscheck="Vuoi attivare il demone di controllo dell'integrità?" +nosyscheck="Syscheck (demone di controllo dell'integrità) disattivato" +yessyscheck="Syscheck (demone di controllo dell'integrità) attivato" + +# Part 3.3 +runrootcheck="Vuoi attivare il sistema di rilevamento dei rootkit?" +norootcheck="Rootcheck (Sistema di rilevamento dei rootkit) disattivato" +yesrootcheck="Rootcheck (Sistema di rilevamento dei rootkit) attivato" + +# Part 3.4/server/local +enable_ar="Vuoi abilitare la risposta attiva?" +noactive="Risposta attiva disabilitata" +nohosts="host-deny disattivato" +yeshosts="host-deny attivato (local) per i livelli >= 6" +firewallar="Vuoi attivare la risposta firewall-drop?" +nofirewall="firewall-drop disattivata." +yesfirewall="firewall-drop attivata (local) per i livelli >= 6" +defaultwhitelist="White list di default per la risposta attiva:" +addwhite="Vuoi aggiungere altri indirizzi IP alla white list?" +ipswhite="Indirizzi IP (separati da uno spazio): " + +# Part 3.5/server/local +syslog="Vuoi attivare il syslog remoto (porta 514 udp)?" +nosyslog="Syslog remoto disattivato" +yessyslog="Syslog remoto attivato" + +# Part 3.4/3.5 +readlogs="Imposto la configurazione per l'analisi dei seguenti logs:" + +# Part 5 +installing="Installo il sistema" +runningmake="Eseguo il Makefile" + +# Final +configurationdone="Configurazione terminata correttamente" +tostart="Per avviare OSSEC HIDS" +tostop="Per arrestare OSSEC HIDS" +configat="La configurazione può essere vista o modificata in" +addserveragent="E' necessario aggiungere gli agent(s) prima che siano autorizzati ad accedere al server." +runma="Utilizza 'manage_agents' per aggiungerli o rimuoverli" +presskey="Premi ENTER per continuare." + +# update +wanttoupdate="OSSEC è già stato installato. Vuoi aggiornarlo ?" +unabletoupdate="Impossibile eseguire l'aggiornamento. E' necessaria un'installazione completa." +updatecompleted="Aggiornamento completato." +updatefailed="Aggiornamento fallito." +updaterules="Si desidera aggiornare le regole ?" +updatingrules="Aggiornamento delle regole in corso." +notupdatingrules="Nessun aggiornamento delle regole in corso." + +# Pf support +pfenable="Do you want to use the PF firewall in the active response?" +nopf="PF response disabled." +pftablename="Name of the PF table to use?" +pfmessage="Add the following lines to the beginning of your rules" + diff --git a/etc/templates/it/messages/0x101-initial.txt b/etc/templates/it/messages/0x101-initial.txt new file mode 100755 index 0000000..b0efc38 --- /dev/null +++ b/etc/templates/it/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + Stai per iniziare il processo di installazione di OSSEC HIDS. + Devi avere un compilatore C pre-installato sul tuo sistema. + Per qualsiasi domanda o commento, per favore invia una e-mail + a dcid@ossec.net (or daniel.cid@gmail.com). + diff --git a/etc/templates/it/messages/0x102-installhelp.txt b/etc/templates/it/messages/0x102-installhelp.txt new file mode 100755 index 0000000..1a9ee3e --- /dev/null +++ b/etc/templates/it/messages/0x102-installhelp.txt @@ -0,0 +1,27 @@ + - Hai tre tipi di installazione possibili: server, agent o local. + + - Se scegli 'server', sarai in grado di analizzare tutti i logs, + creare e-mail di notifica e risopsta, e ricevere i logs da + server syslog remoti e dai sistemi che eseguono gli 'agents' + (da dove il traffico viene inviato crittografato al server). + + - Se scegli 'agent' (client), sarai in grado di leggere i files + locali (di syslog, snort, apache, etc..) e inoltrarli (crittografati) + al server per l'analisi. + + - Se scegli 'local', sarai in grado di fare tutto quello che fa il + server, eccetto la ricezione di messaggi da parte degli agents + o dei sistemi di syslog remoti. + + - Scegli 'server' se desideri configurare un server di log/analisi + + - Scegli 'agent' se hai già un'altra macchina che faccia da log server + e vuoi inoltrarle i log da analizzare (ideale per webservers, + database servers, etc) + + - Scegli 'local' se hai un solo sistema da monitorare. + + - Ulteriori informazioni su: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/it/messages/0x103-thanksforusing.txt b/etc/templates/it/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..6cdd28f --- /dev/null +++ b/etc/templates/it/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Grazie per aver scelto OSSEC HIDS. + Per qualsiasi domanda, suggerimento o se hai trovato qualche bug, + contattaci all'indirizzo contact@ossec.net o utlizza la nostra + mailinglist pubblica: + ( http://www.ossec.net/en/mailing_lists.html ). + + Puoi trovare ulteriori informazioni all'indirizzo http://www.ossec.net + + --- Premi ENTER per terminare --- + diff --git a/etc/templates/it/messages/0x104-client.txt b/etc/templates/it/messages/0x104-client.txt new file mode 100755 index 0000000..cfc5a61 --- /dev/null +++ b/etc/templates/it/messages/0x104-client.txt @@ -0,0 +1,5 @@ + + - Come prima cosa devi aggiungere questo agent al server affinchè possano comunicare + tra di loro. Una volta fatto questo, potrai utilizzare il comando 'manage_agents' + per importare la chiave di autenticazione dal server. + diff --git a/etc/templates/it/messages/0x105-noboot.txt b/etc/templates/it/messages/0x105-noboot.txt new file mode 100755 index 0000000..2f16cd2 --- /dev/null +++ b/etc/templates/it/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - Non è stata effettuata alcuna modifica per avviare OSSEC HIDS + in fase di boot. + Aggiungi la seguente riga al tuo script di init: + diff --git a/etc/templates/it/messages/0x106-logs.txt b/etc/templates/it/messages/0x106-logs.txt new file mode 100755 index 0000000..11f1805 --- /dev/null +++ b/etc/templates/it/messages/0x106-logs.txt @@ -0,0 +1,8 @@ + - Se desideri monitorare qualsiasi altro file, modifica ossec.conf + e aggiungi una nuova, specifica, sezione. + Per qualsiasi dubbio sulla configurazione visita il sito del progetto + all'indirizzo http://www.ossec.net . + + + --- Premi ENTER per continuare --- + diff --git a/etc/templates/it/messages/0x107-ar.txt b/etc/templates/it/messages/0x107-ar.txt new file mode 100755 index 0000000..c28a4bf --- /dev/null +++ b/etc/templates/it/messages/0x107-ar.txt @@ -0,0 +1,7 @@ + + 3.4- La risposta attiva consente di eseguire uno specifico comando in + conseguenza di un evento. Ad esempio, puoi bloccare un indrizzo IP o + disabilitare l'accesso ad uno specifico user. + Ulteriori informazioni su: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/it/messages/0x108-ar-enabled.txt b/etc/templates/it/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..8ac99cd --- /dev/null +++ b/etc/templates/it/messages/0x108-ar-enabled.txt @@ -0,0 +1,8 @@ + - Risposta attiva abilitata. + + - Per default, si possono abilitare le risposte di + tipo host-deny e firewall-drop. La prima aggiunge + un host a /etc/host.deny e la seconda blocca l'host + con iptables (Linux) o con ipfilter (Solaris, FreeBSD o NetBSD). + - Possono essere utilizzate per interrompere attacchi brute-force + a SSHD, portscans e diverse altre forme di attacchi. diff --git a/etc/templates/jp/errors/0x1-location.txt b/etc/templates/jp/errors/0x1-location.txt new file mode 100755 index 0000000..534241a --- /dev/null +++ b/etc/templates/jp/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + エラー 0x1. + このスクリプトは同じディレクトリからのみ実行できます. + スクリプトを実行させる前にディレクトリを変更してください. + そして,./install.sh として実行してください." + diff --git a/etc/templates/jp/errors/0x2-beroot.txt b/etc/templates/jp/errors/0x2-beroot.txt new file mode 100755 index 0000000..5012a67 --- /dev/null +++ b/etc/templates/jp/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + エラー 0x2. + このスクリプトはルート権限で動作させてください. + diff --git a/etc/templates/jp/errors/0x3-dependencies.txt b/etc/templates/jp/errors/0x3-dependencies.txt new file mode 100755 index 0000000..625c2ac --- /dev/null +++ b/etc/templates/jp/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + エラー 0x3. + インストールを続けるにはコンパイラ(gcc または cc 等)が + 必要です. + diff --git a/etc/templates/jp/errors/0x4-installtype.txt b/etc/templates/jp/errors/0x4-installtype.txt new file mode 100755 index 0000000..881612c --- /dev/null +++ b/etc/templates/jp/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + エラー 0x4. + インストールに選んだ種類が間違っています. + agent,server あるいは local のみです. diff --git a/etc/templates/jp/errors/0x5-build.txt b/etc/templates/jp/errors/0x5-build.txt new file mode 100755 index 0000000..6683d63 --- /dev/null +++ b/etc/templates/jp/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + エラー 0x5. + 構築エラー.インストールを完了できませんでした. + diff --git a/etc/templates/jp/language.txt b/etc/templates/jp/language.txt new file mode 100755 index 0000000..ad74c8a --- /dev/null +++ b/etc/templates/jp/language.txt @@ -0,0 +1 @@ + ** 日本語でインストールします.選択して下さい.[jp]. diff --git a/etc/templates/jp/messages.txt b/etc/templates/jp/messages.txt new file mode 100755 index 0000000..bb52b64 --- /dev/null +++ b/etc/templates/jp/messages.txt @@ -0,0 +1,113 @@ +# Configuration +yes="y" +no="n" +yesmatch="y" +nomatch="n" +agent="agent" +local="local" +server="server" +help="help" + + +# Global +moreinfo="詳細な情報は以下にあります: " +starting="OSSEC HIDS を起動します" +systemis="システムは" +modifiedinit="Init script modified to start OSSEC HIDS during boot." +modifiedinit="初期スクリプトはブート中に OSSEC HIDS を起動するよう修正しました." +noboot="不明なシステムです.初期スクリプトは追加されません." + +# Part 1 +installscript="インストールスクリプト" +system="システム" +user="ユーザ" +host="ホスト" +hitanyorabort="続けるには ENTER を押してください.また,Ctrl-C で中止します." +whattoinstall="どの種類のインストールを選択しますか (server,agent,local または help)?" +serverchose="Server インストールを選択しました" +clientchose="Agent(client) インストールを選択しました" +localchose="Local インストールを選択しました" + +# Part 2 +settingupenv="インストール環境を設定しています" +wheretoinstall="Choose where to install the OSSEC HIDS" +wheretoinstall="OSSEC HIDS のインストール先を選択してください" +installat="インストール先を以下に作成します " +deletedir="インストール先のディレクトリが既に存在します.削除してよろしいですか?" + +# Part 3 +configuring="設定" +mailnotify="メール通知を希望しますか?" +nomail="メール通知を無効にしました" +whatsemail="メールアドレスは何ですか?" +yoursmtp="あなたの SMTP サーバを発見しました" +usesmtp="このサーバを使用しますか?" +usingsmtp="この SMTP サーバを使用します: " +whatsmtp="使用する SMTP サーバの ip/host は何ですか?" + +# Part 3.1/agent +serverip="OSSEC HIDS サーバの IP アドレスは何ですか?" +addingip="サーバの IP を加えています" + + +# Part 3.2 +runsyscheck="整合性検査を行うデーモンを実行させますか?" +nosyscheck="syscheck (整合性検査デーモン) は実行させません" +yessyscheck="syscheck (整合性検査デーモン) を実行させます" + +# Part 3.3 +runrootcheck="rootkit 検知エンジンを実行させますか?" +norootcheck="rootcheck (rootkit 検知) は実行させません" +yesrootcheck="rootcheck (rootkit 検知) を実行させます" + +# Part 3.4/server/local +enable_ar="アクティブレスポンスを有効にしますか?" +noactive="アクティブレスポンスを無効にしました" +nohosts="host-deny を無効にしました" +yeshosts="host-deny enabled (local) for levels >= 6" +yeshosts="local での levels >= に対する host-deny を有効にしました" +firewallar="firewall-drop レスポンスを有効にしますか?" +nofirewall="firewall-drop を無効にしました." +yesfirewall="local での levels >= 6 に対する firewall-drop を有効にしました" +defaultwhitelist="アクティブレスポンスでの初期ホワイトリスト:" +addwhite="ホワイトリストへ IP を追加しますか?" +ipswhite="IP を入力してください (スペース区切り): " + +# Part 3.5/server/local +syslog="Do you want to enable remote syslog (port 514 udp)?" +syslog="リモート syslog (port 514 udp) を有効にしますか?" +nosyslog="リモート syslog を無効にしました" +yessyslog="リモート syslog を有効にしました" + +# Part 3.4/3.5 +readlogs="以下のログを解析するための設定を準備しています:" + +# Part 5 +installing="システムをインストールします" +runningmake="Makefile を実行します" + + +# Final +configurationdone="設定が完全に終了しました" +tostart="OSSEC HIDS を開始させます" +tostop="OSSEC HIDS を停止させます" +configat="以下のファイルで設定についての確認と変更ができます" +addserveragent="エージェントを追加する前にアクセスするための認証が必要になります." +runma="エージェントを追加するか削除する際は 'manage_agents' を実行してください" +presskey="続けるには ENTER を押してください" + +# Update +wanttoupdate="既に OSSEC がインストールされています.アップデートしますか?" +unabletoupdate="アップデート作業を行えません.新しくインストールする必要があります." +updatecompleted="アップデートは完了しました." +updatefailed="アップデートは失敗しました." +updaterules="ルールをアップデートしますか?" +updatingrules="ルールをアップデートしています" +notupdatingrules="ルールはアップデートしません." + + +# Pf support +pfenable="アクティブレスポンスを PF ファイヤーウォールで使用しますか?" +nopf="PF レスポンスを無効にしました." +pftablename="使用する PF テーブル名は?" +pfmessage="以下にあなたのルールを最初から追加してください." diff --git a/etc/templates/jp/messages/0x101-initial.txt b/etc/templates/jp/messages/0x101-initial.txt new file mode 100755 index 0000000..aa953ac --- /dev/null +++ b/etc/templates/jp/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + OSSEC HIDS のインストール作業を始めます. + 事前に C コンパイラがシステムにインストールされてる必要があります. + 質問やコメントがあれば,dcid@ossec.net (または daniel.cid@gmail.com) に + メールを下さい. + diff --git a/etc/templates/jp/messages/0x102-installhelp.txt b/etc/templates/jp/messages/0x102-installhelp.txt new file mode 100755 index 0000000..2088e38 --- /dev/null +++ b/etc/templates/jp/messages/0x102-installhelp.txt @@ -0,0 +1,28 @@ + + - 三種類のインストールオプションがあります.: server,agent または local. + + - 'server' を選択した場合,全てのログ解析,通知メールの作成, + 対応,遠隔の syslog 計算機と 'agents' が動作しているシステム + からのログ受信(トラフィックは暗号化されてサーバに送られます) + ができます. + + - 'agents' を選択した場合,計算機上のファイル(syslog,snort, + apache,等)を読みこみ,それらを解析のために暗号化してサーバ + に送ることができます. + + - 'local' を選択した場合,agents や外部の syslog デバイスから + 遠隔メッセージを受信することを除き, サーバの機能を全て使用 + できます. + + - log/analysis サーバを設定するなら 'server' を選択してください. + + - 他の計算機でログサーバを実行しており,解析のためにログをサーバに + 転送したいなら 'agent' を選択してください. + (ウェブサーバやデータベースサーバ等に適しています) + + - 単一システムを監視するためならば 'local' を選択してください. + + - 詳細な情報は以下のサイトから得られます: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/jp/messages/0x103-thanksforusing.txt b/etc/templates/jp/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..89d3d0f --- /dev/null +++ b/etc/templates/jp/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + OSSEC HIDS の使用に感謝します. + あなたが何らかの質問,提案したいときや,バグを発見したときは, + contact@ossec.net まで連絡するか ossec-list@ossec.net にある + 我々の公開メーリングリストを使ってください. + (http://www.ossec.net/main/support/). + + 詳細な情報は http://www.ossec.net にあります. + + --- ENTER を押すと終了します (以下,詳細な情報が続きます).--- + diff --git a/etc/templates/jp/messages/0x104-client.txt b/etc/templates/jp/messages/0x104-client.txt new file mode 100755 index 0000000..6c206aa --- /dev/null +++ b/etc/templates/jp/messages/0x104-client.txt @@ -0,0 +1,5 @@ + + - 最初に,このエージェントをサーバに追加する必要があります. + それにより互いに通信が可能となります.その後,サーバから + の認証鍵を取り入れるために 'manage_agents' ツールを実行 + することができます. diff --git a/etc/templates/jp/messages/0x105-noboot.txt b/etc/templates/jp/messages/0x105-noboot.txt new file mode 100755 index 0000000..02eb5a0 --- /dev/null +++ b/etc/templates/jp/messages/0x105-noboot.txt @@ -0,0 +1,6 @@ + + - 起動中において,OSSEC HIDS を開始し設定する動作が行われませんでした. + 以下のラインをあなたの初期スクリプトに加えてください: + + + diff --git a/etc/templates/jp/messages/0x106-logs.txt b/etc/templates/jp/messages/0x106-logs.txt new file mode 100755 index 0000000..fab0a64 --- /dev/null +++ b/etc/templates/jp/messages/0x106-logs.txt @@ -0,0 +1,7 @@ + - 他のファイルを監視したい場合は,ossec.conf を変更し + 新しいエントリーを追加してください. + 設定に関するどんな質問にも我々の Web サイト http://www.ossec.net + を訪れることで答えることができます. + + + --- 続けるには ENTER を押してください --- diff --git a/etc/templates/jp/messages/0x107-ar.txt b/etc/templates/jp/messages/0x107-ar.txt new file mode 100755 index 0000000..fc63918 --- /dev/null +++ b/etc/templates/jp/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- アクティブレスポンスによりイベントが発生した際に特定の + コマンドを実行することができます. + 例えば,ある IP アドレスを遮断することや特定のユーザ + に対してアクセスを無効にすることができます. + 詳細な情報は以下にあります: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/jp/messages/0x108-ar-enabled.txt b/etc/templates/jp/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..0ef29ab --- /dev/null +++ b/etc/templates/jp/messages/0x108-ar-enabled.txt @@ -0,0 +1,12 @@ + - アクティブレスポンスを有効にしました. + + - デフォルトでは,host-deny と firewall-drop レスポンス + が有効化することができます.一つ目は /etc/hosts.deny + にホストを加えます.二つ目は iptable (linux) か + ipfilter (Solaris, FreeBSD または NetBSD) によりホストを + 遮断します. + + - SSHD への総当たりスキャン,ポートスキャンや他の何らかの + 攻撃手法を停止することに使うことができます. + また,例えば,snort のイベントに基づいてそれらを遮断する + こともできます. diff --git a/etc/templates/nl/errors/0x1-location.txt b/etc/templates/nl/errors/0x1-location.txt new file mode 100755 index 0000000..f25f980 --- /dev/null +++ b/etc/templates/nl/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Fout 0x1. + Dit script kan enkel uit dezelfde map worden uitgevoerd. + Wijzig de map naar de scriptmap alvorens u de installatie uitvoert. + U dient het script zo aan te roepen ./install.sh ." + diff --git a/etc/templates/nl/errors/0x2-beroot.txt b/etc/templates/nl/errors/0x2-beroot.txt new file mode 100755 index 0000000..bed7fa9 --- /dev/null +++ b/etc/templates/nl/errors/0x2-beroot.txt @@ -0,0 +1,5 @@ + + Fout 0x2. + Je moet administratie rechten bekeomen om dit script + uit te voeren. + diff --git a/etc/templates/nl/errors/0x3-dependencies.txt b/etc/templates/nl/errors/0x3-dependencies.txt new file mode 100755 index 0000000..821b664 --- /dev/null +++ b/etc/templates/nl/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Fout 0x3. + U heeft een compiler (zoals gcc of cc) nodig om door + te kunnen gaan met de installatie. + diff --git a/etc/templates/nl/errors/0x4-installtype.txt b/etc/templates/nl/errors/0x4-installtype.txt new file mode 100755 index 0000000..3b00507 --- /dev/null +++ b/etc/templates/nl/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Fout 0x4. + Onjuist installatie type. Het kan enkel agent, server of local zijn. + diff --git a/etc/templates/nl/errors/0x5-build.txt b/etc/templates/nl/errors/0x5-build.txt new file mode 100755 index 0000000..bf22e22 --- /dev/null +++ b/etc/templates/nl/errors/0x5-build.txt @@ -0,0 +1,5 @@ + + Fout 0x5. + Tijdens het bouwen trad er een fout op. Kan de installatie niet + voortzetten. + diff --git a/etc/templates/nl/language.txt b/etc/templates/nl/language.txt new file mode 100755 index 0000000..12f9f15 --- /dev/null +++ b/etc/templates/nl/language.txt @@ -0,0 +1 @@ + ** Voor installatie in het Nederlands, kies [nl]. diff --git a/etc/templates/nl/messages.txt b/etc/templates/nl/messages.txt new file mode 100755 index 0000000..6dbc90d --- /dev/null +++ b/etc/templates/nl/messages.txt @@ -0,0 +1,106 @@ +# Configuration +yes="j" +no="n" +yesmatch="j" +nomatch="n" +agent="agent" +local="local" +server="server" +help="help" + +# Global +moreinfo="Meer informatie op: " +starting="Bezig met starten van OSSEC HIDS" +systemis="Systeem is" +modifiedinit="Init script aangepast om OSSEC HIDS te laden tijdens opstarten." +noboot="Onbekend systeem. Geen init script toegevoegd." + +# Part 1 +installscript="Installatie Script" +system="Systeem" +user="Gebruiker" +host="Host" +hitanyorabort="Druk op ENTER om door te gaan of Ctrl-C om af te breken." +whattoinstall="Wat voor soort installatie wilt u doen (server, agent, local of help)?" +serverchose="Gekozen voor server installatie" +clientchose="Gekozen voor agent(client) installatie" +localchose="Gekozen voor lokale installatie" + +# Part 2 +settingupenv="Opzetten van installatie omgeving" +wheretoinstall="Waar wilt u OSSEC HIDS installaren" +installat="Installatie word geplaatst in " +deletedir="De installatie map bestaat reeds. Zal ik deze verwijderen?" + +# Part 3 +configuring="Configureren van" +mailnotify="Wilt u email notificatie inschakelen?" +nomail="Email notificatie uitgeschakeld" +whatsemail="Wat is uw emailadres?" +yoursmtp="We hebben uw SMTP server gevonden als: " +usesmtp="Wilt u deze gebruiken ?" +usingsmtp="Gebruik maken van SMTP server: " +whatsmtp="Wat is uw SMTP server ip/host?" + +# Part 3.1/agent +serverip="Wat is het IP adres van uw OSSEC HIDS host?" +addingip="Toevoegen van server IP" + + +# Part 3.2 +runsyscheck="Wilt u de integriteits controle proces?" +nosyscheck="Geen syscheck (integriteits controle proces)" +yessyscheck="Starten van syscheck (integriteits controle proces)" + +# Part 3.3 +runrootcheck="Wilt u de rootkit detectie engine?" +norootcheck="Geen rootcheck (rootkit detectie)" +yesrootcheck="Starten van rootcheck (rootkit detectie)" + +# Part 3.4/server/local +enable_ar="Wilt u actief handelen?" +noactive="Actief handelen uitgeschakeld" +nohosts="host-deny uitgeschakeld" +yeshosts="host-deny ingeschakeld (lokaal) voor niveaus >= 6" +firewallar="Wilt u de firewall-drop handeling inschakelen?" +nofirewall="firewall-drop uitgeschakeld." +yesfirewall="firewall-drop ingeschakeld (lokaal) voor niveaus >= 6" +defaultwhitelist="Standaard witte lijst voor actief handelen:" +addwhite="Wilt u meer IPs toevoegen aan de witte lijst?" +ipswhite="IPs (spatie gescheiden): " + +# Part 3.5/server/local +syslog="Wilt u externe systeem logging (syslog) inschakelen (poort 514 udp)?" +nosyslog="Externe systeem logging uitgeschakeld" +yessyslog="Externe systeem logging ingeschakeld" + +# Part 3.4/3.5 +readlogs="Systeem instellen om de volgende logbestanden te controleren:" + +# Part 5 +installing="Bezig met installeren van het systeem" +runningmake="Uitvoeren van Makefile" + +# Final +configurationdone="Configuratie is succesvol afgesloten" +tostart="Om OSSEC HIDS te starten" +tostop="Om OSSEC HIDS te stoppen" +configat="De configuratie kan worden bekeken en gewijzigd in" +addserveragent="Om verbinding te maken tussen agent en server, moet je alle agenten aan de server toevoegen." +runma="Voer 'manage_agents' uit om ze toe te voegen of te verwijderen" +presskey="Druk op ENTER om door te gaan" + +# Update +wanttoupdate="U heeft OSSEC reeds geinstalleerd. Wilt u actualiseren?" +unabletoupdate="Kan geen actualisatie uitvoeren. Een volledig nieuwe installatie is vereist." +updatecompleted="Actualisatie succesvol uitgevoerd." +updatefailed="Actualisatie is gefaald." +updaterules="Wilt u de regels actualiseren?" +updatingrules="Actualiseren van regels." +notupdatingrules="Regels worden niet geactualiseerd." + +# Pf support +pfenable="Wilt u de PF firewall gebruiken bij actief handelen?" +nopf="PF respons is uitgeschakeld." +pftablename="Naam van de PF tabel om te gebruiken?" +pfmessage="Voeg de volgende regels toe aan het begin van uw PF regels" diff --git a/etc/templates/nl/messages/0x101-initial.txt b/etc/templates/nl/messages/0x101-initial.txt new file mode 100755 index 0000000..995bf5d --- /dev/null +++ b/etc/templates/nl/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + U staat op het punt om het installatie proces te starten van OSSEC HIDS. + U heeft een C compiler nodig voorgeinstalleerd op uw systeem. + Bij enige vragen of commentaar kunt u een email sturen naar + dcid@ossec.net (of daniel.cid@gmail.com). + diff --git a/etc/templates/nl/messages/0x102-installhelp.txt b/etc/templates/nl/messages/0x102-installhelp.txt new file mode 100755 index 0000000..7e001c6 --- /dev/null +++ b/etc/templates/nl/messages/0x102-installhelp.txt @@ -0,0 +1,31 @@ + + - U heeft 3 installatie typen: server, agent or local. + + - Als u kiest voor 'server', kunt u alle logs analyseren, + email notificaties en handelingen aanmaken en tevens + externe systeem logs ontvangen van externe machines + en systemen met 'agents' (waarweg gegevens beveiligd + worden verzonden). + + - Als u kiest voor 'agent'(client), kunt u alle lokale + bestanden lezen (van syslog, snort, apache, etc) en + deze (beveiligd) doorsturen naar de server voor + analyse. + + - Als u kiest voor 'local', kunt u alles doen wat de + server kan, behalve het ontvangen van externe berichten + vanaf agenten of externe systeemloggende apparaten. + + - Kies voor 'server' als u een log/analyze server opzet. + + - Kies voor 'agent' als u een andere machine als log server + heeft opgezet en hier naar toe voor analyze wilt doorsturen. + (ideaal voor webservers en database servers) + + - Kies voor 'local' als u een enkel systeem in de gaten + wilt houden. + + - Meer informatie vindt u op: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/nl/messages/0x103-thanksforusing.txt b/etc/templates/nl/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..c660bce --- /dev/null +++ b/etc/templates/nl/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Bedankt voor het gebruiken van OSSEC HIDS. + Heeft u een vraag of suggestie of een andere vorm van opmerking, + neem contact met ons op via contact@ossec.net of gebruik de mailinglijst + ossec-list@ossec.net + ( http://www.ossec.net/main/support/ ). + + Meer informatie vindt u op http://www.ossec.net + + --- Druk op ENTER om te finaliseren (wellicht meer informatie hieronder). --- + diff --git a/etc/templates/nl/messages/0x104-client.txt b/etc/templates/nl/messages/0x104-client.txt new file mode 100755 index 0000000..c166263 --- /dev/null +++ b/etc/templates/nl/messages/0x104-client.txt @@ -0,0 +1,7 @@ + + - U dient eerst deze agent aan de server toe te voegen + zodat ze met elkaar kunnen communiceren. Als u dit + gedaan heeft dan kunt u de 'manage_agents' tool ge- + bruiken om de authenticatiesleutel te importeren + vanaf de server. + diff --git a/etc/templates/nl/messages/0x105-noboot.txt b/etc/templates/nl/messages/0x105-noboot.txt new file mode 100755 index 0000000..07bf200 --- /dev/null +++ b/etc/templates/nl/messages/0x105-noboot.txt @@ -0,0 +1,4 @@ + + - Er is geen actie ondernomen om een opstart script te maken voor + OSSEC HIDS. U dient de volgede regel toe te voegen aan uw initscript: + diff --git a/etc/templates/nl/messages/0x106-logs.txt b/etc/templates/nl/messages/0x106-logs.txt new file mode 100755 index 0000000..a400d35 --- /dev/null +++ b/etc/templates/nl/messages/0x106-logs.txt @@ -0,0 +1,10 @@ + - Als u een ander bestand in de gaten wilt houden, + kunt u het bestand ossec.conf wijzigen door een + nieuwe localfile in te brengen. + Vragen over het configuratie bestand kunnen worden + beantwoord door ons online te bezoeken op + http://www.ossec.net . + + + --- Druk op ENTER om door te gaan --- + diff --git a/etc/templates/nl/messages/0x107-ar.txt b/etc/templates/nl/messages/0x107-ar.txt new file mode 100755 index 0000000..42f044e --- /dev/null +++ b/etc/templates/nl/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- Actief handelen stelt u in staat om een specifiek + commando uit te voeren op basis van de ontvangen + events. Bijvoorbeeld, u kunt een IP adres blokkeren + of de toegang ontzeggen voor een bepaalde gebruiker. + Meer informatie vindt u op: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/nl/messages/0x108-ar-enabled.txt b/etc/templates/nl/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..98d462c --- /dev/null +++ b/etc/templates/nl/messages/0x108-ar-enabled.txt @@ -0,0 +1,12 @@ + - Actief handelen is ingeschakeld. + + - Als standaard, kunnen we de host-deny en + firewall-drop handelingen inschakelen. De + eerste voegt een host toe aan /etc/hosts.deny + en de tweede zal de host blokkeren op iptables + (bij linux) of ipfilter (bij Solaris, FreeBSD + of NetBSD). + - Ze kunnen gebruikt worden om SSHD brute force scans, + portscans of andere vormen van aanvallen te stoppen. + U kunt deze ook gebruiken om blokkeren op basis van + bijvoorbeeld snort events. diff --git a/etc/templates/pl/errors/0x1-location.txt b/etc/templates/pl/errors/0x1-location.txt new file mode 100755 index 0000000..6ab6421 --- /dev/null +++ b/etc/templates/pl/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Błąd 0x1. + Skrypt może być tylko uruchamiany ze swojego katalogu. + Przejdź do katalogu w którym jest skrypt. + Następnie uruchom poprzez: ./install.sh ." + diff --git a/etc/templates/pl/errors/0x2-beroot.txt b/etc/templates/pl/errors/0x2-beroot.txt new file mode 100755 index 0000000..7337548 --- /dev/null +++ b/etc/templates/pl/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Błąd 0x2. + Skrypt należy uruchamiać na prawach root'a. + diff --git a/etc/templates/pl/errors/0x3-dependencies.txt b/etc/templates/pl/errors/0x3-dependencies.txt new file mode 100755 index 0000000..e3c3afd --- /dev/null +++ b/etc/templates/pl/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Błąd 0x3. + Potrzebujesz kompilatora (np. gcc lub cc) aby kontynuować + instalacje. + diff --git a/etc/templates/pl/errors/0x4-installtype.txt b/etc/templates/pl/errors/0x4-installtype.txt new file mode 100755 index 0000000..af86f0e --- /dev/null +++ b/etc/templates/pl/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Błąd 0x4. + Niewłaściwy typ instalacji. Wybierz spośród: agent, serwer, lokalna. + diff --git a/etc/templates/pl/errors/0x5-build.txt b/etc/templates/pl/errors/0x5-build.txt new file mode 100755 index 0000000..fb6b313 --- /dev/null +++ b/etc/templates/pl/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Błąd 0x5. + Błąd kompilacji. Nie można zakończyć instalacji. + diff --git a/etc/templates/pl/language.txt b/etc/templates/pl/language.txt new file mode 100755 index 0000000..4203bc6 --- /dev/null +++ b/etc/templates/pl/language.txt @@ -0,0 +1 @@ + ** Aby instalować w języku Polskim, wybierz [pl]. diff --git a/etc/templates/pl/messages.txt b/etc/templates/pl/messages.txt new file mode 100755 index 0000000..1703452 --- /dev/null +++ b/etc/templates/pl/messages.txt @@ -0,0 +1,107 @@ +# Konfiguracja +yes="y" +no="n" +yesmatch="y" +nomatch="n" +agent="agent" +local="lokalnie" +server="serwer" +help="pomoc" + +# Ogólne +moreinfo="Więcej informacji na: " +starting="Rozpoczynam OSSEC HIDS" +systemis="System " +modifiedinit="Init skrypt zmodyfikowany do uruchomiania OSSEC HIDS podczas bootowania." +noboot="Nieznany system. Skrypt init nie został dodany." + +# Część 1 +installscript="Skrypt instalacyjny" +system="System" +user="Użytkownik" +host="Host" +hitanyorabort="Wciśnij ENTER aby kontynuować lub Ctrl-C aby przerwać." +whattoinstall="Wybierz rodzaj instalacji (serwer, agent, lokalnie or pomoc)?" +serverchose="Wybrana instalacja: serwer" +clientchose="Wybrana instalacja: agent(klient)" +localchose="Wybrana instalacja: lokalnie" + +# Część 2 +settingupenv="Ustawianie środowiska instalacyjnego" +wheretoinstall="Wybierz katalog w którym zainstalować OSSEC HIDS" +installat="OSSEC HIDS zostanie zainstalowane w :" +deletedir="Wybrany katalog istnieje, skasować go?" + +# Część 3 +configuring="Konfiguracja " +mailnotify="Czy chcesz powiadomienie na e-mail?" +nomail="Powiadomienie e-mail wyłączone" +whatsemail="Podaj e-mail adres?" +yoursmtp="Znaleziony SMTP serwer: " +usesmtp="Czy chcesz go użyć?" +usingsmtp="Używam SMTP serwer: " +whatsmtp="Podaj SMTP serwer (ip/host)?" + +# Część 3.1/agent +serverip="Podaj adres IP serwera OSSEC HIDS." +addingip="Dodaje IP serwera" + + +# Część 3.2 +runsyscheck="Czy chcesz aby demon sprawdzania integralności systemu (syscheck) był uruchomiony?" +nosyscheck="Nie uruchomiony syscheck (demon sprawdzania integralności systemu)" +yessyscheck="Uruchomiony syscheck (demon sprawdzania integralności systemu)" + +# Część 3.3 +runrootcheck="Czy chcesz aby system detekcji rootkit'ów (rootcheck) był uruchomiony?" +norootcheck="Nie uruchomiony rootcheck (system detekcji rootkit'ów)" +yesrootcheck="Uruchomiony rootcheck (system detekcji rootkit'ów)" + +# Część 3.4/server/local +enable_ar="Czy chcesz uaktywnić aktywną ochrone?" +noactive="Aktywna ochrona wyłączona" +nohosts="host-deny wyłączone" +yeshosts="host-deny włączone (local) dla poziomów >= 6" +firewallar="Czy chcesz uaktywnić ochrone firewall-drop?" +nofirewall="firewall-drop wyłączone." +yesfirewall="firewall-drop włączone (local) dla poziomów >= 6" +defaultwhitelist="Domyślna biała lista dla aktywnej ochrony:" +addwhite="Czy chcesz dodać więcej adresów IP do białej listy?" +ipswhite="Adresy IP (część oddzielona): " + +# Część 3.5/server/local +syslog="Czy chcesz uaktywnić zdalnego syslog'a (port 514 udp)?" +nosyslog="Zdalny syslog wyłączony" +yessyslog="Zdalny syslog włączony" + +# Część 3.4/3.5 +readlogs="Ustawianie konfiguracji do analizy następujących logów:" + +# Część 5 +installing="Instaluje system" +runningmake="Uruchomiono Makefile" + +# Finał +configurationdone="Konfiguracja zakończona pomyślnie" +tostart="Aby wystartować OSSEC HIDS" +tostop="Aby zatrzymać OSSEC HIDS" +configat="Konfiguracja może być wyświetlona lub zmodyfikowana w" +addserveragent="Powinieneś dodać agent(a/ów) przed ich autoryzacją dostępu." +runma="Uruchom 'manage_agents' aby je dodać lub usunąć" +presskey="Wciśnij ENTER aby kontynuować" + +# Update +wanttoupdate="Masz już zainstalowany OSSEC. Czy chcesz dokonać aktualizacji?" +unabletoupdate="Nie można dokonać aktualizacji. Pełna nowa instalacja jest konieczna." +updatecompleted="Aktualizacja ukończona." +updatefailed="Aktualizacja ukończona niepowodzeniem." +updaterules="Czy chcesz zaktualizować reguły?" +updatingrules="Aktualizacja reguł." +notupdatingrules="Bez aktualizacji reguł." + +# Wsparcie dla Pf +pfenable="Chcesz uywa firewall'a PF jako aktywnej ochrony?" +nopf="ochrona PF wyczona." +pftablename="Podaj nazwe tabeli PF?" +pfmessage="Dodaj nastpujce linie na pocztku Twoich regu" + diff --git a/etc/templates/pl/messages/0x101-initial.txt b/etc/templates/pl/messages/0x101-initial.txt new file mode 100755 index 0000000..1ed9c2f --- /dev/null +++ b/etc/templates/pl/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + Rozpoczynasz proces instalacji programu OSSEC HIDS. + Aby kontynuować musisz mieć zainstalowany kompilator C. + Jeśli masz jakieś pytania albo komentarze, wyślij e-mail + do dcid@ossec.net (lub daniel.cid@gmail.com). + diff --git a/etc/templates/pl/messages/0x102-installhelp.txt b/etc/templates/pl/messages/0x102-installhelp.txt new file mode 100755 index 0000000..6377a64 --- /dev/null +++ b/etc/templates/pl/messages/0x102-installhelp.txt @@ -0,0 +1,30 @@ + + - Masz do wyboru trzy metody instalacji: serwer, agent oraz lokalna. + + - Jeśli wybierzesz 'serwer', bęziesz miał możliwość analizy + wszystkich logów, tworzenia powiadomienia e-mail, aktywnej + ochrony oraz także otrzymywania logów ze zdalnych maszyn z + syslog-iem i systemów działajcych jako 'agent' (skąd ruch + jest szyfrowany do serwera) + + - Jeśli wybierzesz 'agent'(klient), będziesz miał możliwość + czytania lokalnych plików (z syslog, apache, snort itp) + oraz przekazywania ich (zaszyfrowanych) do serwera w celu + analizy. + + - Jeśli wybierzesz 'lokalna', będziesz wstanie wykonywać + wszystkie operacje serwera za wyjątkiem odbierania zdalnych + wiadomości od klientów oraz zewnętrzych syslog-ów. + + - Wybierz 'serwer' jeśli chcesz ustawić serwer analizy logów. + + - Wybierz 'agent' jeśli masz inną maszynę działającą jako serwer i + chcesz przekazywać do niego logi w celu analizy. + (idealny dla serwerów http, bazodanowych, itp) + + - Wybierz 'lokalna' jeśli masz tylko jeden system do monitorowania. + + - Więcej informacji na: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/pl/messages/0x103-thanksforusing.txt b/etc/templates/pl/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..44efa0e --- /dev/null +++ b/etc/templates/pl/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + + Dziękujemy za użycie OSSEC HIDS. + Jeśli masz jakieś pytania, propozycje lub znalazłeś jakiś błąd, + skontaktuj się z nami poprzez contact@ossec.net lub publiczną + listę mailingową ossec-list@ossec.net + ( http://www.ossec.net/main/support/ ). + + Więcej informacji można znaleźć na http://www.ossec.net + + --- Wciśnij ENTER aby zakończyć (więcej informacji poniżej?). --- + diff --git a/etc/templates/pl/messages/0x104-client.txt b/etc/templates/pl/messages/0x104-client.txt new file mode 100755 index 0000000..d0f6808 --- /dev/null +++ b/etc/templates/pl/messages/0x104-client.txt @@ -0,0 +1,6 @@ + + - Najpierw musisz dodać tego agenta do serwera aby + umożliwić komunikację między nimi. Jeśli zakończyłeś + możesz uruchomić narzędzie 'manage_agents' aby + zaimportować klucz autoryzacyjny z serwera. + diff --git a/etc/templates/pl/messages/0x105-noboot.txt b/etc/templates/pl/messages/0x105-noboot.txt new file mode 100755 index 0000000..27dedbf --- /dev/null +++ b/etc/templates/pl/messages/0x105-noboot.txt @@ -0,0 +1,5 @@ + + - Nie została podjęta żadna akcja aby skonfigurować OSSEC HIDS + do startowania podczas bootowania. + Dodaj następującą linię do skryptu init: + diff --git a/etc/templates/pl/messages/0x106-logs.txt b/etc/templates/pl/messages/0x106-logs.txt new file mode 100755 index 0000000..74931b3 --- /dev/null +++ b/etc/templates/pl/messages/0x106-logs.txt @@ -0,0 +1,8 @@ + - Jeśli chcesz monitorować inne pliki, poprostu + zmień ossec.conf oraz dodaj nowy wpis localfile. + Wszystkie wyjaśnienia odnośnie konfiguracji + znajdziesz na http://www.ossec.net . + + + --- Wciśnij ENTER aby kontynuować --- + diff --git a/etc/templates/pl/messages/0x107-ar.txt b/etc/templates/pl/messages/0x107-ar.txt new file mode 100755 index 0000000..0b27443 --- /dev/null +++ b/etc/templates/pl/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- Aktywna ochrona pozwala na wykonywanie określonych + komend w zależności od otrzymanego sygnału. Np. + możesz zablokować adres IP lub dostęp dla wybranego + użytkownika. + Więcej informacji na: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/pl/messages/0x108-ar-enabled.txt b/etc/templates/pl/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..2af7b60 --- /dev/null +++ b/etc/templates/pl/messages/0x108-ar-enabled.txt @@ -0,0 +1,11 @@ + - Aktywna ochrona włączona. + + - Domyślnie, możemy włączyć ochronę host-deny oraz + firewall-drop. Pierwsze doda hosta do listy + /etc/hosts.deny, a drugie zablokuje hosta na + poziomie iptables (dla linuxa) lub ipfilter + (dla Solaris, FreeBSD oraz NetBSD). + - Przedstawione metody mogą zatrzymać ataki brute + force na ssh, skanowanie portów oraz pare innych. + Możesz również na przykład dodać blokowanie + korzystając ze zdarzeń snort'a. diff --git a/etc/templates/ru/errors/0x1-location.txt b/etc/templates/ru/errors/0x1-location.txt new file mode 100755 index 0000000..ff335b7 --- /dev/null +++ b/etc/templates/ru/errors/0x1-location.txt @@ -0,0 +1,4 @@ + Ошибка 0x1. Этот скрипт может быть запущен только из того же каталога + Сделайте каталог где находится скрипт текущей перед его зпуском + Вы должны запустить скрипт командой ./install.sh + diff --git a/etc/templates/ru/errors/0x2-beroot.txt b/etc/templates/ru/errors/0x2-beroot.txt new file mode 100755 index 0000000..95ba923 --- /dev/null +++ b/etc/templates/ru/errors/0x2-beroot.txt @@ -0,0 +1 @@ + Ошибка 0x2 .Вы должны иметь права root чтобы воспользоваться этим скриптом diff --git a/etc/templates/ru/errors/0x3-dependencies.txt b/etc/templates/ru/errors/0x3-dependencies.txt new file mode 100755 index 0000000..861e52e --- /dev/null +++ b/etc/templates/ru/errors/0x3-dependencies.txt @@ -0,0 +1,2 @@ + Ошибка 0x3. Вам нужен компиллятор (например gcc или cc) чтобы продолжить + далее. diff --git a/etc/templates/ru/errors/0x4-installtype.txt b/etc/templates/ru/errors/0x4-installtype.txt new file mode 100755 index 0000000..b9ca981 --- /dev/null +++ b/etc/templates/ru/errors/0x4-installtype.txt @@ -0,0 +1,2 @@ +Ошибка 0x4. Неправильный тип установки . Он должен быть :агент,сервер или локальный. + diff --git a/etc/templates/ru/errors/0x5-build.txt b/etc/templates/ru/errors/0x5-build.txt new file mode 100755 index 0000000..1638762 --- /dev/null +++ b/etc/templates/ru/errors/0x5-build.txt @@ -0,0 +1,2 @@ + Ошибка 0x5 .Ошибка компиляции. Невозможно завершить установку. + diff --git a/etc/templates/ru/language.txt b/etc/templates/ru/language.txt new file mode 100755 index 0000000..da65414 --- /dev/null +++ b/etc/templates/ru/language.txt @@ -0,0 +1 @@ + ** Для инструкций по установке на русском ,введите [ru]. diff --git a/etc/templates/ru/messages.txt b/etc/templates/ru/messages.txt new file mode 100755 index 0000000..3220658 --- /dev/null +++ b/etc/templates/ru/messages.txt @@ -0,0 +1,107 @@ +# Configuration +yes="д" +no="н" +yesmatch="д" +nomatch="н" +agent="агент" +local="локальный" +server="сервер" +help="помощь" + +# Global +moreinfo="Дополнительная информация: " +starting="Запуск OSSEC HIDS" +systemis="Система" +modifiedinit="Init скрипт модифицирован чтобы програма OSSEC HIDS запускалась при перезагрузке компьютера." +noboot="Система неизвестна. Никаких скриптов начала запуска не добавлено." + +# Part 1 +installscript="Скрипт установки программы" +system="Система" +user="Пользователь" +host="Хост" +hitanyorabort="Нажмите Ввод (ENTER) для продолжения или Ctrl-C для выхода." +whattoinstall="Какой тип установки Вы выбираете (сервер,агент,локальный или помощь)?" +serverchose="Выбран тип установки сервер" +clientchose="Выбран тип установки агент (клиент)" +localchose="Выбран локальный тип утановки" + +# Part 2 +settingupenv="Производится конфигурация параметров установки" +wheretoinstall="Укажите куда установить OSSEC HIDS" +installat="Программа будет установлена в " +deletedir="Указанный каталог уже существует. Удалить его?" + +# Part 3 +configuring="Конфигурация" +mailnotify="Активировать систему уведомления по электронной почте?" +nomail="Оповещение по электронной почте отменено" +whatsemail="Укажите адрес электронной почты:" +yoursmtp="Ваш сервер SMTP (для отправки электронной почты) определён как" +usesmtp="Хотите использовать его?" +usingsmtp="Испльзуется SMTP сервер: " +whatsmtp="Каков Ваш SMTP сервер ip/host?" + +# Part 3.1/agent +serverip="Какой IP адрес у Вашего OSSEC HIDS сервера?" +addingip="Добавляется IP адрес сервера" + + +# Part 3.2 +runsyscheck="Запустить сервис проверки целостности системы?" +nosyscheck="syscheck (сервис проверки целостности системы) не запущен" +yessyscheck="Запускается syscheck (сервис проверки целостности системы)" + +# Part 3.3 +runrootcheck="Активировать сервис обнаружения руткитов?" +norootcheck="Сервис обнаружения руткитов (rootcheck) не запущен " +yesrootcheck="Запускается rootcheck (обнаружение руткитов)" + +# Part 3.4/server/local +enable_ar="Включить систему активного реагирования?" +noactive="Система активного реагирования отключена" +nohosts="Блокирование хостов отключено " +yeshosts="Блокирование хостов включено (локально) для уровня >= 6" +firewallar="Включить блокирование файерволом?" +nofirewall="Блокирование файерволом отключено." +yesfirewall="Блокирование файерволом включено (локально) для уровня >= 6" +defaultwhitelist="Список разрешённых адресов по умолчанию для активного реагирования:" +addwhite="Вы хотите добавить ещё адресов IP в список разрешённых?" +ipswhite="Адреса IP (разделяйте пробелом): " + +# Part 3.5/server/local +syslog="Активировать сохранение логов на удаленном сервере syslog (порт 514 udp)?" +nosyslog="Удалённое сохранение логов отменено" +yessyslog="Удалённое сохранение логов включено" + +# Part 3.4/3.5 +readlogs="Устанавливается конфигурация для анализа следующих логов" + +# Part 5 +installing="Производится установка" +runningmake="Исполняется Makefile" + +# Final +configurationdone="Конфигурация произведена успешно" +tostart="Запустить OSSEC HIDS" +tostop="Завершить работу OSSEC HIDS" +configat="Вы можете прочитать и отредактировать конфигурацию здесь" +addserveragent="Вы должны добавить агентов прежде чем они получат права доступа" +runma="Запустите 'manage_agents' чтобы добавить или удалить их" +presskey="Нажмите Ввод (ENTER) чтобы продолжить" + +# Update +wanttoupdate="OSSEC уже установлен на этой машине. Хотите ли Вы обновить его?" +unabletoupdate="Невозможно произвести обновление. Потребуется полная установка заново" +updatecompleted="Обновление завершено успешно." +updatefailed="Произошел сбой и обновление не произведено ." +updaterules="Вы хотите обновить правила?" +updatingrules="Идет обновление правил ." +notupdatingrules="Обновление правил не производится ." + + +# Pf support +pfenable="Хотите ли Вы использовать PF файервол в активном реагировании?" +nopf="PF активное реагирование отключено" +pftablename="Имя таблицы PF ?" +pfmessage="Добавьте следующие строки в начало ваших правил" diff --git a/etc/templates/ru/messages/0x101-initial.txt b/etc/templates/ru/messages/0x101-initial.txt new file mode 100755 index 0000000..a96bf18 --- /dev/null +++ b/etc/templates/ru/messages/0x101-initial.txt @@ -0,0 +1,5 @@ +Вы готовы начать процесс установки OSSEC HIDS. Для следующего шага на Вашей +системе должен уже быть установлен компиллятор языка С. Со всеми вопросами +и замечаниями пожалуйста обращайтесь на + dcid@ossec.net (or daniel.cid@gmail.com). + diff --git a/etc/templates/ru/messages/0x102-installhelp.txt b/etc/templates/ru/messages/0x102-installhelp.txt new file mode 100755 index 0000000..0c1c0e6 --- /dev/null +++ b/etc/templates/ru/messages/0x102-installhelp.txt @@ -0,0 +1,17 @@ + - Есть 3 варианта установки: сервер,агент или локальный. + + - Если выбрать "сервер", Вы сможете анализировать логи, создавать уведомления + по e-mail и ответные действия, а также получать логи от удаленных syslog + серверов и машин с установленными агентами (откуда все данные посылаются +зашифрованными) .Если выбрать "агент" (клиент) Вы сможете читать локальные + файлы (от syslog, snort, apache, и так далее) и пересылать их (зашифрованным +и) на сервер для анализа. Если выбрать локальный то Вы сможете делать всё что + вариант "сервер" позволяет делать кроме принимать сообщения от агентлв на +удалённых машинах или внешних устройств syslog . + - Выберите "сервер" если хотите установить сервер обработки логов/анализа. + - Выберите "агент" если другая машина будет сервером обрабатывающим логи и туда + устанавливаемый агент будет посылать свои логи (идеально для веб серверов, + серверов баз данных ). + - Выберите "локальный" если у Вас всего лишь одна система . Более подробно +можно прочитать здесь: http://www.ossec.net/en/manual.html#starting + diff --git a/etc/templates/ru/messages/0x103-thanksforusing.txt b/etc/templates/ru/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..2303f01 --- /dev/null +++ b/etc/templates/ru/messages/0x103-thanksforusing.txt @@ -0,0 +1,8 @@ + Спасибо что воспользовались OSSEC HIDS . + Со всеми вопросами замечаниями или багами пожалуйста обращайтесь на + contact@ossec.net или в свободно доступную почтовую рассылку ossec-list@ossec.net + ( http://www.ossec.net/main/support/ ). + + Дополнительная информация доступна тут: http://www.ossec.net + + --- Нажмите Ввод для завершения (возможна дополнительная информация далее). diff --git a/etc/templates/ru/messages/0x104-client.txt b/etc/templates/ru/messages/0x104-client.txt new file mode 100755 index 0000000..53632ac --- /dev/null +++ b/etc/templates/ru/messages/0x104-client.txt @@ -0,0 +1,4 @@ + Сначала Вы должны добавить этого агента на +сервере, чтобы они смогли обмениваться информацией друг с +другом. После этого Вы можете ,командой 'manage_agents', +импортировать ключ идентификации с сервера. diff --git a/etc/templates/ru/messages/0x105-noboot.txt b/etc/templates/ru/messages/0x105-noboot.txt new file mode 100755 index 0000000..1072109 --- /dev/null +++ b/etc/templates/ru/messages/0x105-noboot.txt @@ -0,0 +1,4 @@ + - Никаких изменений с целью запускать OSSEC HIDS при перезагрузке системы +в конфигурации произведено не было. + Добавьте следующую строку в скрипт init: + diff --git a/etc/templates/ru/messages/0x106-logs.txt b/etc/templates/ru/messages/0x106-logs.txt new file mode 100755 index 0000000..dfd5d36 --- /dev/null +++ b/etc/templates/ru/messages/0x106-logs.txt @@ -0,0 +1,4 @@ +- Если Вы хотите отслеживать любой другой файл, просто + измените ossec.conf и добавьте новое значение в localfile. + Любые ответы по конфигурации могут быть найдены на сайте + http://www.ossec.net diff --git a/etc/templates/ru/messages/0x107-ar.txt b/etc/templates/ru/messages/0x107-ar.txt new file mode 100755 index 0000000..69f14c9 --- /dev/null +++ b/etc/templates/ru/messages/0x107-ar.txt @@ -0,0 +1,4 @@ + 3.4- Активное реагирование позволяет Вам выполнить выбранную команду в +зависимости от полученного события. Например, Вы можете блокировать адрес IP +или отказать в доступе определённому пользователю. Дополнительная информация + на сайте: http://www.ossec.net/en/manual.html#active-response diff --git a/etc/templates/ru/messages/0x108-ar-enabled.txt b/etc/templates/ru/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..c0af4d5 --- /dev/null +++ b/etc/templates/ru/messages/0x108-ar-enabled.txt @@ -0,0 +1,8 @@ +- Активное реагирование включено. + - По умолчанию, мы можем задействовать host-deny и firewall-drop ответные + реакции. Первая добавит хост в файл /etc/hosts.deny , а вторая заблокирует + хост через iptables (если Линукс) или через ipfilter (если Solaris, + FreeBSD или NetBSD). + - Они могут быть полезны для остановки сканирования методом перебора, + а также сканирования портов и некоторые другие формы атак. Также можно + добавить их для блокирования в связке с событиями snort. diff --git a/etc/templates/sr/errors/0x1-location.txt b/etc/templates/sr/errors/0x1-location.txt new file mode 100755 index 0000000..f60899d --- /dev/null +++ b/etc/templates/sr/errors/0x1-location.txt @@ -0,0 +1,5 @@ +GreÅ¡ka 0x1. +Ovaj skript može biti izveden jedino iz istog direktorijuma. +Prebaci direktorij tamo gde je ovaj skript pre nego Å¡to ga pustiÅ¡. +MoraÅ¡ ga pustiti kao ./install.sh ." + diff --git a/etc/templates/sr/errors/0x2-beroot.txt b/etc/templates/sr/errors/0x2-beroot.txt new file mode 100755 index 0000000..06ed265 --- /dev/null +++ b/etc/templates/sr/errors/0x2-beroot.txt @@ -0,0 +1,3 @@ +GreÅ¡ka 0x2. +MoraÅ¡ biti root da bi koristio ovaj skript. + diff --git a/etc/templates/sr/errors/0x3-dependencies.txt b/etc/templates/sr/errors/0x3-dependencies.txt new file mode 100755 index 0000000..3949c0e --- /dev/null +++ b/etc/templates/sr/errors/0x3-dependencies.txt @@ -0,0 +1,2 @@ +GreÅ¡ka 0x3. +Treba ti kompajler (kao gcc ili cc) da nastaviÅ¡ sa instalacijom. diff --git a/etc/templates/sr/errors/0x4-installtype.txt b/etc/templates/sr/errors/0x4-installtype.txt new file mode 100755 index 0000000..d44df78 --- /dev/null +++ b/etc/templates/sr/errors/0x4-installtype.txt @@ -0,0 +1,3 @@ +GreÅ¡ka 0x4. +PogreÅ¡an tip instalacije. Može biti jedino agent, server ili lokalna. + diff --git a/etc/templates/sr/errors/0x5-build.txt b/etc/templates/sr/errors/0x5-build.txt new file mode 100755 index 0000000..40ac745 --- /dev/null +++ b/etc/templates/sr/errors/0x5-build.txt @@ -0,0 +1,4 @@ + GreÅ¡ka 0x5. + GreÅ¡ka u gradnji. U nemogućnosti da zavrÅ¡i instalaciju. + + diff --git a/etc/templates/sr/language.txt b/etc/templates/sr/language.txt new file mode 100755 index 0000000..f9a0e95 --- /dev/null +++ b/etc/templates/sr/language.txt @@ -0,0 +1 @@ + ** Za instalaciju na srpskom, izaberi [sr]. diff --git a/etc/templates/sr/messages.txt b/etc/templates/sr/messages.txt new file mode 100755 index 0000000..f9d6580 --- /dev/null +++ b/etc/templates/sr/messages.txt @@ -0,0 +1,107 @@ +# Configuration +yes="d" +no="n" +yesmatch="d" +nomatch="n" +agent="agent" +local="lokalna" +server="server" +help="pomoć" + +# Global +moreinfo="Vise informacija na: " +starting="Zapocinje OSSEC HIDS" +systemis="Sistem je" +modifiedinit="Init skript je modifikovan da započne OSSEC HIDS za vreme startovanja ." +noboot="Nepoznat sistem. Init skript nije dodat." + +# Part 1 +installscript="Instalacioni Skript" +system="Sistem" +user="Korisnik" +host="Host" +hitanyorabort="Pritisni ENTER da nastavis ili Ctrl-C da poniÅ¡tiÅ¡." +whattoinstall="Koju vrstu instalacije želiÅ¡ (server, agent, lokalnu ili pomoć)?" +serverchose="Izabrana instalacija server" +clientchose="Izabrana instalacija agent (klijent)" +localchose="Izabrana lokalna instalacija" + +# Part 2 +settingupenv="Postavljanje instalacionog okruženja" +wheretoinstall="Izaberi gde želiÅ¡ da instaliraÅ¡ OSSEC HIDS" +installat="Instalacija će biti izvrÅ¡ena na " +deletedir="Instalacioni direktorij već postoji. Da li da ga obriÅ¡em?" + +# Part 3 +configuring="Trenutno vrÅ¡i konfiguraciju" +mailnotify="Da li želiÅ¡ email notifikaciju?" +nomail="Email notifikacija onesposobljena" +whatsemail="Koja je tvoja email adresa?" +yoursmtp="NaÅ¡li smo da je tvoj SMTP server" +usesmtp="Da li želiÅ¡ da ga koristiÅ¡?" +usingsmtp="Koristi SMTP server: " +whatsmtp="Koji je tvoj SMTP server IP/host?" + +# Part 3.1/agent +serverip="Koja je IP adresa OSSEC HIDS servera?" +addingip="Dodaje serverov IP" + + +# Part 3.2 +runsyscheck="Da li želiÅ¡ da pustiÅ¡ daemon provere integriteta?" +nosyscheck="Ne obavlja syscheck (daemon provere integriteta)" +yessyscheck="Obavlja syscheck (daemon provere integriteta)" + +# Part 3.3 +runrootcheck="Da li želiÅ¡ da pustiÅ¡ engine za otkrivanje rootkit-a?" +norootcheck="Ne obavlja rootcheck (otkrivanje rootkit-a )" +yesrootcheck="Obavlja rootcheck (otkrivanje rootkit-a)" + +# Part 3.4/server/local +enable_ar="Da li želiÅ¡ da osposobiÅ¡ aktivnu reakciju?" +noactive="Aktivna reakcija onesposobljena" +nohosts="host-deny onesposobljen" +yeshosts="host-deny osposobljen (lokalni) za nivoe >= 6" +firewallar="Da li želiÅ¡ da osposobiÅ¡ firewall-drop reakciju?" +nofirewall="firewall-drop onesposobljen." +yesfirewall="firewall-drop osposobljen (lokalni) za nivoe >= 6" +defaultwhitelist="Default bele liste za aktivnu reakciju:" +addwhite="Da li želiÅ¡ da dodaÅ¡ joÅ¡ IP-jeva beloj listi?" +ipswhite="IP-jevi (odvojen prostor): " + +# Part 3.5/server/local +syslog="Da li želiÅ¡ da osposobiÅ¡ udaljeni syslog (port 514 udp)?" +nosyslog="Udaljeni syslog onesposobljen" +yessyslog="Udaljeni syslog osposobljen" + +# Part 3.4/3.5 +readlogs="Postavlja konfiguraciju da analizira sledeće logove:" + +# Part 5 +installing="Instalira sistem" +runningmake="VrÅ¡i Makefile" + +# Final +configurationdone="Konfiguracija je dobro zavrÅ¡ena" +tostart="Da se započne OSSEC HIDS" +tostop="Da se zaustavi OSSEC HIDS" +configat="Konfiguracija se može videti ili modifikovati na" +addserveragent="Da bi se agent povezao sa serverom, treba da dodaÅ¡ svakog od tvojih agenata +serveru." +runma="Pusti 'manage_agents' da ih dodaje ili otklanja" +presskey="Pritisni ENTER da nastaviÅ¡" + +# Update +wanttoupdate="Već imaÅ¡ instaliran OSSEC. Da li želiÅ¡ da ga ažuriraÅ¡?" +unabletoupdate="U nemogućnosti da izvrÅ¡i ažuriranje. Potrebna je potpuna nova instalacija." +updatecompleted="Ažuriranje zavrÅ¡eno." +updatefailed="Ažuriranje nije uspelo." +updaterules="Da li želiÅ¡ da ažuriraÅ¡ pravila?" +updatingrules="Pravila ažuriranja." +notupdatingrules="Ne ažurira pravila." + +# Pf support +pfenable="Da li želiÅ¡ da koristiÅ¡ PF firewall u aktivnoj reakciji?" +nopf="PF reakcija onesposobljena." +pftablename="Ime PF table za korišćenje?" +pfmessage="Dodaj sledeće redove početku tvojih PF pravila" diff --git a/etc/templates/sr/messages/0x101-initial.txt b/etc/templates/sr/messages/0x101-initial.txt new file mode 100755 index 0000000..8fa8686 --- /dev/null +++ b/etc/templates/sr/messages/0x101-initial.txt @@ -0,0 +1,5 @@ + NalaziÅ¡ se pred početkom instalacionog proces OSSEC HIDS. + MoraÅ¡ imati c kompajler već instaliran u svoj sistem. + Ako imaÅ¡ bilo kakvih pitanja ili komentara molim te poÅ¡alji e-mail + na dcid@ossec.net (ili daniel.cid@gmail.com). + diff --git a/etc/templates/sr/messages/0x102-installhelp.txt b/etc/templates/sr/messages/0x102-installhelp.txt new file mode 100755 index 0000000..953b6e8 --- /dev/null +++ b/etc/templates/sr/messages/0x102-installhelp.txt @@ -0,0 +1,28 @@ + - ImaÅ¡ tri instalacione opcije: server, agent ili lokalnu. + + - Ako izabereÅ¡ 'server', moćićeÅ¡ da analiziraÅ¡ sve + logove, napraviÅ¡ e-mail notifikacije i reakcije, + kao i da primiÅ¡ logove sa udaljenih syslog maÅ¡ina i + sistema kojima su puÅ¡teni 'agenti' (iz kojih se saobraćaj + Å¡alje kriptovan u server). + + - Ako izabereÅ¡ 'agent' (klijent), moćićeÅ¡ da čitaÅ¡ + lokalne fajlove (iz syslog, snort. apache itd) i da ih proslediÅ¡ + (kriptovane) serveru na analizu. + + - Ako izabereÅ¡ 'lokalnu', moćićeÅ¡ da radiÅ¡ sve Å¡to radi server, + osim da primaÅ¡ udaljene poruke od agenata ili spoljaÅ¡njih + syslog maÅ¡ina. + + - Izaberi 'server' ako postavljaÅ¡ log/analysis server. + + - Izaberi 'agent' ako imaÅ¡ drugu maÅ¡inu koju možeÅ¡ da koristiÅ¡ kao + log server i hoćeÅ¡ da prosleđujeÅ¡ logove serveru na analizu. + (idealno za webservere, servere baze podataka, itd) + + - Izaberi 'lokalnu' ako pratiÅ¡ samo jedan sistem. + + - ViÅ¡e obaveÅ¡tenja na: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/sr/messages/0x103-thanksforusing.txt b/etc/templates/sr/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..5fb3f0a --- /dev/null +++ b/etc/templates/sr/messages/0x103-thanksforusing.txt @@ -0,0 +1,11 @@ + Hvala Å¡to koristiÅ¡ OSSEC HIDS. + Ako imaÅ¡ bilo kakvo pitanje, predlog ili ako nađeÅ¡ neki bag, + kontaktiraj nas na contact@ossec.net ili koristeći naÅ¡u javnu maillistu na + ossec-list@ossec.net + ( http://www.ossec.net/main/support/ ). + + ViÅ¡e informacija možeÅ¡ naći na http://www.ossec.net + + --- Pritisni ENTER da zavrÅ¡iÅ¡ (možda ima joÅ¡ informacije niže). --- + + diff --git a/etc/templates/sr/messages/0x104-client.txt b/etc/templates/sr/messages/0x104-client.txt new file mode 100755 index 0000000..3ed5a5e --- /dev/null +++ b/etc/templates/sr/messages/0x104-client.txt @@ -0,0 +1,5 @@ + - MoraÅ¡ prvo dodati ovog agenta serveru tako da + mogu da komuniciraju jedan sa drugim. Kada to uradiÅ¡ + možeÅ¡ da pustiÅ¡ 'manage_agents' pomagalo da preuzmeÅ¡ + ključ autentičnosti od servera. + diff --git a/etc/templates/sr/messages/0x105-noboot.txt b/etc/templates/sr/messages/0x105-noboot.txt new file mode 100755 index 0000000..15a8f85 --- /dev/null +++ b/etc/templates/sr/messages/0x105-noboot.txt @@ -0,0 +1,2 @@ + NiÅ¡ta nije preduzeto da konfiguriÅ¡e OSSEC HIDS da startuje + u toku buta. Dodaj sledeći red svom init skriptu: diff --git a/etc/templates/sr/messages/0x106-logs.txt b/etc/templates/sr/messages/0x106-logs.txt new file mode 100755 index 0000000..b7f061e --- /dev/null +++ b/etc/templates/sr/messages/0x106-logs.txt @@ -0,0 +1,9 @@ + - Ako želiÅ¡ da nadgledaÅ¡ neki drugi fajl, samo promeni + ossec.conf i dodaj novi localfile ulaz. + Sva pitanja vezana za konfiguraciju mogu biti odgovorena + ako nas posetiÅ¡ online na http://www.ossec.net . + + + --- Pritisni ENTER da nastaviÅ¡ --- + + diff --git a/etc/templates/sr/messages/0x107-ar.txt b/etc/templates/sr/messages/0x107-ar.txt new file mode 100755 index 0000000..c8bc97f --- /dev/null +++ b/etc/templates/sr/messages/0x107-ar.txt @@ -0,0 +1,7 @@ + 3.4- Aktivna reakcija ti omogućava da izvedeÅ¡ specifičnu + komandu na bazi primljenih događaja. Na primer, + možeÅ¡ da blokiraÅ¡ IP adresu ili onemogućiÅ¡ pristup + određenom korisniku. + ViÅ¡e obaveÅ¡tenja na: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/sr/messages/0x108-ar-enabled.txt b/etc/templates/sr/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..a8ead14 --- /dev/null +++ b/etc/templates/sr/messages/0x108-ar-enabled.txt @@ -0,0 +1,13 @@ + - Aktivirana aktivna reakcija. + + - Po default-u možemo osposobiti host-deny i + firewall-drop reakcije. Prvi će dodati host-a + na /etc/hosts.deny a drugi će blokirati host-a + na iptabeli (ako je u pitanju Linux) ili na + ipfilteru (Solaris, FreeBSD ili NetBSD). + - Oni se mogu koristiti da zaustave SSHD brute force skenove, + portskenove i neke druge vrste napada. Takođe ih možeÅ¡ + dodati za blokiranje u slučaju snort dojava, na primer. + + + diff --git a/etc/templates/tr/errors/0x1-location.txt b/etc/templates/tr/errors/0x1-location.txt new file mode 100755 index 0000000..4b6a52d --- /dev/null +++ b/etc/templates/tr/errors/0x1-location.txt @@ -0,0 +1,6 @@ + + Error 0x1. + Bu betik sadece aynı dizin içinden çalıştırılabilir. + Bu betiğin daha önce çalıştığı dizine geçin. + Betiği ./install.sh şeklinde çalıştırmalısınız. + diff --git a/etc/templates/tr/errors/0x2-beroot.txt b/etc/templates/tr/errors/0x2-beroot.txt new file mode 100755 index 0000000..0c43845 --- /dev/null +++ b/etc/templates/tr/errors/0x2-beroot.txt @@ -0,0 +1,4 @@ + + Error 0x2. + Bu betiği çalıştırabilmeniz için root olmalısınız. + diff --git a/etc/templates/tr/errors/0x3-dependencies.txt b/etc/templates/tr/errors/0x3-dependencies.txt new file mode 100755 index 0000000..a887507 --- /dev/null +++ b/etc/templates/tr/errors/0x3-dependencies.txt @@ -0,0 +1,5 @@ + + Error 0x3. + Kuruluma devam edebilmek için bir derleyiciye (gcc veya cc gibi) + ihtiyacınız var. + diff --git a/etc/templates/tr/errors/0x4-installtype.txt b/etc/templates/tr/errors/0x4-installtype.txt new file mode 100755 index 0000000..8e4c99c --- /dev/null +++ b/etc/templates/tr/errors/0x4-installtype.txt @@ -0,0 +1,4 @@ + + Error 0x4. + Yanlış kurulum türü. Sadece aracı, sunucu veya yerel olabilir. + diff --git a/etc/templates/tr/errors/0x5-build.txt b/etc/templates/tr/errors/0x5-build.txt new file mode 100755 index 0000000..7ad99ed --- /dev/null +++ b/etc/templates/tr/errors/0x5-build.txt @@ -0,0 +1,4 @@ + + Error 0x5. + Oluşturma hatası. Kurulum tamamlanamadı. + diff --git a/etc/templates/tr/language.txt b/etc/templates/tr/language.txt new file mode 100755 index 0000000..c3e1f3f --- /dev/null +++ b/etc/templates/tr/language.txt @@ -0,0 +1 @@ + ** Türkçe kurulum için seçin [tr]. diff --git a/etc/templates/tr/messages.txt b/etc/templates/tr/messages.txt new file mode 100755 index 0000000..e3800e6 --- /dev/null +++ b/etc/templates/tr/messages.txt @@ -0,0 +1,107 @@ +# Configuration +yes="e" +no="h" +yesmatch="e" +nomatch="h" +agent="aracı" +local="yerel" +server="sunucu" +help="yardım" + +# Global +moreinfo="Daha fazla bilgi: " +starting="OSSEC HIDS başlatılıyor" +systemis="Sistem" +modifiedinit="OSSEC HIDS'i önyüklemede başlatmak için başlangıç betiği değiştirildi." +noboot="Bilinmeyen sistem. Başlangıç betiği eklenmedi." + +# Part 1 +installscript="Kurulum Betiği" +system="Sistem" +user="Kullanıcı" +host="Bilgisayar" +hitanyorabort="Devam etmek için ENTER veya çıkmak için Ctrl-C ye basın" +whattoinstall="Ne tür kurulum yapmak istiyorsunuz (sunucu,aracı,yerel veya yardım)?" +serverchose="Sunucu kurulumu seçildi" +clientchose="Aracı(istemci) kurulumu seçildi" +localchose="Yerel kurulum seçildi" + +# Part 2 +settingupenv="Kurulum ortamı hazırlanıyor" +wheretoinstall="OSSEC HIDS kurulacak yeri seçin" +installat="Kurulum buraya yapılacak: " +deletedir="Kurulum dizini zaten var. Silinsin mi?" + +# Part 3 +configuring="yapılandırılıyor:" +mailnotify="E-posta ile bilgilendirilmek ister misiniz?" +nomail="E-posta ile bilgilendirme etkisiz kılındı" +whatsemail="E-posta adresiniz nedir?" +yoursmtp="SMTP sunucunuz olarak bunu bulduk" +usesmtp="Kullanmak ister misiniz?" +usingsmtp="SMTP sunucu kullanılıyor: " +whatsmtp="SMTP sunucunuzun IP adresi veya ismi nedir?" + +# Part 3.1/agent +serverip="OSSEC HIDS sunucusunun IP adresi nedir?" +addingip="Sunucu IP adresi ekleniyor" + + +# Part 3.2 +runsyscheck="Güvenilirlik/bütünlük kontrol programının çalıştırılmasını ister misiniz?" +nosyscheck="syscheck çalıştırılmıyor (güvenilirlik/bütünlük kontrol programı)" +yessyscheck="syscheck çalıştırılıyor (güvenilirlik/bütünlük kontrol programı)" + +# Part 3.3 +runrootcheck="rootkit tespit etme motorunun çalışmasını ister misiniz?" +norootcheck="rootcheck çalıştırılmıyor (rootkit tespit etme)" +yesrootcheck="rootcheck çalıştırılıyor (rootkit tespit etme)" + +# Part 3.4/server/local +enable_ar="Etkin yanıt üretmenin (Active response) etkin kılınmasını ister misiniz?" +noactive="Etkin yanıt üretme(Active response) etkisiz kılındı" +nohosts="host-deny etkin kılınmadı" +yeshosts="Uyarı seviyesi >= 6 için host-deny etkin kılındı (yerel)" +firewallar="firewall-drop yanıtının etkin kılınmasını ister misiniz?" +nofirewall="firewall-drop etkisiz kılındı." +yesfirewall="Uyarı seviyesi >= 6 için firewall-drop etkin kılındı (yerel)" +defaultwhitelist="Etkin yanıt üretme için öntanımlı beyaz liste:" +addwhite="Beyaz listeye başka IP adreslerini de eklemek ister misiniz?" +ipswhite="IPler (boşlukla ayrılmış): " + +# Part 3.5/server/local +syslog="Uzak syslog'un (514 udp) etkin kılınmasını ister misiniz?" +nosyslog="Uzak syslog etkisiz kılındı" +yessyslog="Uzak syslog etkin kılındı" + +# Part 3.4/3.5 +readlogs="Bu dosyaları incelemek için yapılandırma oluşturuluyor:" + +# Part 5 +installing="Sistem kuruluyor" +runningmake="Makefile çalıştırılıyor" + +# Final +configurationdone="Yapılandırma doğru olarak tamamlandı" +tostart="OSSEC HIDS'i başlatmak için" +tostop="OSSEC HIDS'i durdurmak için" +configat="Yapılandırma buradan görülebilir veya değiştirilebilir:" +addserveragent="Her bir aracıyı/istemciyi erişim için yetkilendirmeden önce eklemeniz gerekmektedir." +runma="Eklemek ve çıkarmak için 'manage_agents' komutunu kullanın." +presskey="Devam etmek için ENTER tuşuna basınız" + +# Update +wanttoupdate="Bir OSSEC kurulumu mevcut. Güncellemek ister misiniz?" +unabletoupdate="Güncelleme gerçekleştirilemedi. Yeni kurulum yapılması gerekiyor." +updatecompleted="Güncelleme tamamlandı." +updatefailed="Güncelleme başarısız oldu." +updaterules="Kuralları güncellemek ister misiniz?" +updatingrules="Kurallar güncelleniyor." +notupdatingrules="Kurallar güncellenmiyor." + +# Pf support +pfenable="Etkin yanıtlarda PF güvenlik duvarını kullanmak istiyor musunuz?" +nopf="PF yanıtları etkisiz kılındı." +pftablename="Kullanılacak PF tablosunun adı?" +pfmessage="Aşağıdaki satırları kurallarınızın başına ekleyin" + diff --git a/etc/templates/tr/messages/0x101-initial.txt b/etc/templates/tr/messages/0x101-initial.txt new file mode 100755 index 0000000..8b1487e --- /dev/null +++ b/etc/templates/tr/messages/0x101-initial.txt @@ -0,0 +1,6 @@ + + OSSEC HIDS kurulum sürecini başlatmak üzeresiniz. + Sisteminizde önceden kurulmuş bir C derleyicisi bulunmalıdır. + Her türlü soru, öneri ve yorumlarınız için lütfen dcid@ossec.net + (veya daniel.cid@gmail.com) adresine e-posta gönderiniz. + diff --git a/etc/templates/tr/messages/0x102-installhelp.txt b/etc/templates/tr/messages/0x102-installhelp.txt new file mode 100755 index 0000000..e43d504 --- /dev/null +++ b/etc/templates/tr/messages/0x102-installhelp.txt @@ -0,0 +1,30 @@ + + - Üç adet kurulum seçeneği bulunmaktadır: sunucu, aracı veya yerel. + + - Eğer sunucu seçerseniz, bütün günlük kayıtlarını inceleyebilir + e-posta ile bilgilendirilebilir, yanıt üretebilirsiniz. + Ayrıca uzak syslog bilgisayarlarından ve 'aracı' olarak + çalışan sistemlerden günlük kayıtlarını alabilirsiniz + (aradaki trafik şifrelenecektir). + + - Eğer 'aracı' (istemci) seçerseniz, syslog, snort, apache vb. + tarafından üretilen yerel dosyaları okuyabilir ve incelenmek üzere + şifreli bir şekilde sunucuya gönderebilirsiniz. + + - Eğer 'yerel' seçerseniz, aracılardan veya harici syslog + aygıtlarından gelen mesajları almak dışında sunucunun + yapabildiği herşeyi yapabilirsiniz. + + - Eğer günlük kaydı inceleme sunucusu oluşturuyorsanız 'sunucu' kullanın. + + - Eğer başka bir günlük kaydı sunucunuz varsa ve incelenmesi için + günlük kayıtlarınızı bu sunucuya yönlendirmek istiyorsanız + 'aracı' kullanın. (web sunucular, veritabanı sunucular vb. için + idealdir) + + - Eğer inceleme yapacağınız tek sisteminiz varsa 'yerel' kullanın. + + - Daha fazla bilgi: + http://www.ossec.net/en/manual.html#starting + + diff --git a/etc/templates/tr/messages/0x103-thanksforusing.txt b/etc/templates/tr/messages/0x103-thanksforusing.txt new file mode 100755 index 0000000..c02617b --- /dev/null +++ b/etc/templates/tr/messages/0x103-thanksforusing.txt @@ -0,0 +1,12 @@ + + OSSEC HIDS kullandığınız için teşekkürler. + Sorularınız, önerileriniz olursa veya her hangi bir yanlış + bulursanız contact@ossec.net adresi ile veya kamuya açık + e-posta listemiz ile ossec-list@ossec.net adresinden iletişime + geçiniz. + ( http://www.ossec.net/main/support/ ). + + http://www.ossec.net adresinde daha fazla bilgi bulunabilir. + + --- Bitirmek için ENTER tuşuna basın (aşağıda daha fazla bilgi olabilir). --- + diff --git a/etc/templates/tr/messages/0x104-client.txt b/etc/templates/tr/messages/0x104-client.txt new file mode 100755 index 0000000..92811da --- /dev/null +++ b/etc/templates/tr/messages/0x104-client.txt @@ -0,0 +1,6 @@ + + - Sunucu ile iletişimi sağlayabilmek için önce bu aracıyı + sunucuya eklemeniz gerekmektedir. Bunu yaptıktan sonra + sunucudan yetkilendirme anahtarını aktarmak için 'manage_agents' + komutunu çalıştırabilirsiniz. + diff --git a/etc/templates/tr/messages/0x105-noboot.txt b/etc/templates/tr/messages/0x105-noboot.txt new file mode 100755 index 0000000..765d575 --- /dev/null +++ b/etc/templates/tr/messages/0x105-noboot.txt @@ -0,0 +1,4 @@ + + - Önyükleme sırasında OSSEC HIDS'i başlatmak için hiç birşey yapılmadı. + Bu satırı başlangıç betiğine ekleyin: + diff --git a/etc/templates/tr/messages/0x106-logs.txt b/etc/templates/tr/messages/0x106-logs.txt new file mode 100755 index 0000000..c4a8f69 --- /dev/null +++ b/etc/templates/tr/messages/0x106-logs.txt @@ -0,0 +1,8 @@ + - Eğer başka bir dosyayı daha gözlemek isterseniz + ossec.conf dosyasına yeni bir localfile girdisi ekleyin. + Yapılandırma hakkındaki herhangi bir sorunuzu cevaplamak için + http://www.ossec.net adresini ziyaret edebilirsiniz. + + + --- Devam etmek için ENTER tuşuna basın --- + diff --git a/etc/templates/tr/messages/0x107-ar.txt b/etc/templates/tr/messages/0x107-ar.txt new file mode 100755 index 0000000..a94b9d4 --- /dev/null +++ b/etc/templates/tr/messages/0x107-ar.txt @@ -0,0 +1,8 @@ + + 3.4- Etkin yanıt üretme (Active response), edinilen olay + bilgilerine göre belirli bir komut çalıştırmanıza olanak + tanır. Örneğin bir IP adresinin engelleyebilir veya bir + kullanıcının erişimini kısıtlayabilirsiniz. + Daha fazla bilgi: + http://www.ossec.net/en/manual.html#active-response + diff --git a/etc/templates/tr/messages/0x108-ar-enabled.txt b/etc/templates/tr/messages/0x108-ar-enabled.txt new file mode 100755 index 0000000..dab0f59 --- /dev/null +++ b/etc/templates/tr/messages/0x108-ar-enabled.txt @@ -0,0 +1,11 @@ + - Etkin yanıt üretme (Active response) etkin kılındı. + + - Öntanımlı olarak host-deny ve firewall-drop etkin yanıt + mekanizmalarını etkin hale getirebiliriz. Bunlardan ilki + bir bilgisayarı /etc/hosts.deny dosyasına ekler, ikincisi + bilgisayarı iptables (linux) veya ipfilter (Solaris, + FreeBSD vb.) ile engeller. + - Bunlar, SSHD kaba güç saldırılarını, port taramalarını + ve diğer saldırı şekillerini durdurmak için kullanılabilir. + Ayrıca snort olaylarını değerlendirerek engelleme yapmak + için de ekleyebilirsiniz. diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..9fc0e94 --- /dev/null +++ b/install.sh @@ -0,0 +1,1184 @@ +#!/bin/sh +# Installation script for the OSSEC +# Author: Daniel B. Cid +# Last modification: Mar 02, 2006 + +# Changelog 19/03/2006 - Rafael M. Capovilla +# New function AddWhite to allow users to add more Ips in the white_list +# Minor *echos* modifications to better look +# Bug fix - When email address is blank +# Bug fix - delete INSTALLDIR - Default is yes but if the user just press enter the script wasn't deleting it as it should +# Changelog 15/07/2006 - Rafael M. Capovilla +# New function AddTable to add support for OpenBSD pf rules in firewall-drop active response + + + +### Looking up for the execution directory +cd `dirname $0` + + +### Looking for echo -n +ECHO="echo -n" +hs=`echo -n "a"` +if [ ! "X$hs" = "Xa" ]; then + ls "/usr/ucb/echo" > /dev/null 2>&1 + if [ $? = 0 ]; then + ECHO="/usr/ucb/echo -n" + else + ECHO=echo + fi +fi + +# For solaris +echo "xxxx" | grep -E "xxx" > /dev/null 2>&1 +if [ ! $? = 0 ]; then + ls "/usr/xpg4/bin/grep" > /dev/null 2>&1 + if [ $? = 0 ]; then + PATH=/usr/xpg4/bin:$PATH + fi +fi + +# Initializing vars +SET_DEBUG="" + +# Checking for command line arguments +for i in $*; do + if [ "X$i" = "Xdebug" ]; then + SET_DEBUG="debug" + elif [ "X$i" = "Xbinary-install" ]; then + USER_BINARYINSTALL="yes" + elif [ "X$i" = "Xhelp" ]; then + echo "$0 debug" + echo "$0 binary-install" + exit 1; + fi +done + + + +########## +# install() +########## +Install() +{ + echo "" + echo "5- ${installing}" + + echo "DIR=\"${INSTALLDIR}\"" > ${LOCATION} + echo "CC=${CC}" >> ${LOCATION} + + # Changing Config.OS with the new C flags + # Checking if debug is enabled + if [ "X${SET_DEBUG}" = "Xdebug" ]; then + CEXTRA="${CEXTRA} -DDEBUGAD" + fi + + echo "CEXTRA=${CEXTRA}" >> ./src/Config.OS + + # Makefile + echo " - ${runningmake}" + cd ./src + + # Binary install will use the previous generated code. + if [ "X${USER_BINARYINSTALL}" = "X" ]; then + make all + if [ $? != 0 ]; then + cd ../ + catError "0x5-build" + fi + + # Building everything + make build + if [ $? != 0 ]; then + cd ../ + catError "0x5-build" + fi + fi + + # If update, stop ossec + if [ "X${update_only}" = "Xyes" ]; then + UpdateStopOSSEC + fi + + # Making the right installation type + if [ "X$INSTYPE" = "Xserver" ]; then + ./InstallServer.sh + + elif [ "X$INSTYPE" = "Xagent" ]; then + ./InstallAgent.sh + + elif [ "X$INSTYPE" = "Xlocal" ]; then + ./InstallServer.sh local + fi + + cd ../ + + + # Generate the /etc/ossec-init.conf + VERSION_FILE="./src/VERSION" + VERSION=`cat ${VERSION_FILE}` + chmod 700 ${OSSEC_INIT} > /dev/null 2>&1 + echo "DIRECTORY=\"${INSTALLDIR}\"" > ${OSSEC_INIT} + echo "VERSION=\"${VERSION}\"" >> ${OSSEC_INIT} + echo "DATE=\"`date`\"" >> ${OSSEC_INIT} + echo "TYPE=\"${INSTYPE}\"" >> ${OSSEC_INIT} + chmod 600 ${OSSEC_INIT} + cp -pr ${OSSEC_INIT} ${INSTALLDIR}${OSSEC_INIT} + chmod 644 ${INSTALLDIR}${OSSEC_INIT} + + + # If update_rules is set, we need to tweak + # ossec.conf to read the new signatures. + if [ "X${update_rules}" = "Xyes" ]; then + UpdateOSSECRules + fi + + # If update, start OSSEC + if [ "X${update_only}" = "Xyes" ]; then + UpdateStartOSSEC + fi + + # Calling the init script to start ossec hids during boot + if [ "X${update_only}" = "X" ]; then + runInit + if [ $? = 1 ]; then + notmodified="yes" + fi + fi + +} + + + + +########## +# UseSyscheck() +########## +UseSyscheck() +{ + + # Integrity check config + echo "" + $ECHO " 3.2- ${runsyscheck} ($yes/$no) [$yes]: " + if [ "X${USER_ENABLE_SYSCHECK}" = "X" ]; then + read AS + else + AS=${USER_ENABLE_SYSCHECK} + fi + echo "" + case $AS in + $nomatch) + echo " - ${nosyscheck}." + ;; + *) + SYSCHECK="yes" + echo " - ${yessyscheck}." + ;; + esac + + # Adding to the config file + if [ "X$SYSCHECK" = "Xyes" ]; then + cat ${SYSCHECK_TEMPLATE} >> $NEWCONFIG + fi +} + + + + +########## +# UseRootcheck() +########## +UseRootcheck() +{ + + # Rootkit detection configuration + echo "" + $ECHO " 3.3- ${runrootcheck} ($yes/$no) [$yes]: " + + if [ "X${USER_ENABLE_ROOTCHECK}" = "X" ]; then + read ES + else + ES=${USER_ENABLE_ROOTCHECK} + fi + + echo "" + case $ES in + $nomatch) + echo " - ${norootcheck}." + ;; + *) + ROOTCHECK="yes" + echo " - ${yesrootcheck}." + ;; + esac + + + # Adding to the config file + if [ "X$ROOTCHECK" = "Xyes" ]; then + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " $INSTALLDIR/etc/shared/rootkit_files.txt" >> $NEWCONFIG + echo " $INSTALLDIR/etc/shared/rootkit_trojans.txt" >> $NEWCONFIG + echo " $INSTALLDIR/etc/shared/system_audit_rcl.txt" >> $NEWCONFIG + echo " $INSTALLDIR/etc/shared/cis_debian_linux_rcl.txt" >> $NEWCONFIG + echo " $INSTALLDIR/etc/shared/cis_rhel_linux_rcl.txt" >> $NEWCONFIG + echo " $INSTALLDIR/etc/shared/cis_rhel5_linux_rcl.txt" >> $NEWCONFIG + echo " " >> $NEWCONFIG + else + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " yes" >> $NEWCONFIG + echo " " >> $NEWCONFIG + fi +} + + + + +########## +# SetupLogs() +########## +SetupLogs() +{ + + NB=$1 + echo "" + echo " $NB- ${readlogs}" + + echo " " >> $NEWCONFIG + LOG_FILES=`cat ${SYSLOG_TEMPLATE}` + for i in ${LOG_FILES}; do + # If log file present, add it + ls $i > /dev/null 2>&1 + if [ $? = 0 ]; then + echo " -- $i" + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " syslog" >> $NEWCONFIG + echo " $i" >>$NEWCONFIG + echo " " >> $NEWCONFIG + fi + done + + # Getting snort files + SNORT_FILES=`cat ${SNORT_TEMPLATE}` + for i in ${SNORT_FILES}; do + ls $i > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + + head -n 1 $i|grep "\[**\] "|grep -v "Classification:" > /dev/null + if [ $? = 0 ]; then + echo " snort-full" >> $NEWCONFIG + echo " -- $i (snort-full file)" + else + echo " snort-fast" >> $NEWCONFIG + echo " -- $i (snort-fast file)" + fi + echo " $i" >>$NEWCONFIG + echo " " >> $NEWCONFIG + fi + done + + # Getting apache logs + APACHE_FILES=`cat ${APACHE_TEMPLATE}` + for i in ${APACHE_FILES}; do + ls $i > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " apache" >> $NEWCONFIG + echo " $i" >>$NEWCONFIG + echo " " >> $NEWCONFIG + + echo " -- $i (apache log)" + fi + done + + # Getting postgresql logs + PGSQL_FILES=`cat ${PGSQL_TEMPLATE}` + for i in ${PGSQL_FILES}; do + ls $i > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " postgresql_log" >> $NEWCONFIG + echo " $i" >>$NEWCONFIG + echo " " >> $NEWCONFIG + + echo " -- $i (postgresql log)" + fi + done + + + echo "" + catMsg "0x106-logs" + + + if [ "X$USER_NO_STOP" = "X" ]; then + read ANY + fi +} + + + + +########## +# ConfigureClient() +########## +ConfigureClient() +{ + echo "" + echo "3- ${configuring} $NAME." + echo "" + + if [ "X${USER_AGENT_SERVER_IP}" = "X" ]; then + # Looping and asking for server ip + while [ 1 ]; do + $ECHO " 3.1- ${serverip}: " + read IPANSWER + echo $IPANSWER | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "" + IP=$IPANSWER + echo " - ${addingip} $IP" + break; + fi + done + else + IP=${USER_AGENT_SERVER_IP} + fi + + echo "" > $NEWCONFIG + echo " " >> $NEWCONFIG + echo " $IP" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo "" >> $NEWCONFIG + + # Syscheck? + UseSyscheck + + # Rootcheck? + UseRootcheck + + echo "" + $ECHO " 3.4 - ${enable_ar} ($yes/$no) [$yes]: " + + if [ "X${USER_ENABLE_ACTIVE_RESPONSE}" = "X" ]; then + read ANY + else + ANY=${USER_ENABLE_ACTIVE_RESPONSE} + fi + + case $ANY in + $nomatch) + echo "" + echo " - ${noactive}." + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " yes" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo "" >> $NEWCONFIG + ;; + *) + ACTIVERESPONSE="yes" + echo "" + ;; + esac + + # Set up the log files + SetupLogs "3.5" + + echo "" >> $NEWCONFIG +} + + + + +########## +# ConfigureServer() +########## +ConfigureServer() +{ + echo "" + echo "3- ${configuring} $NAME." + + + # Configuring e-mail notification + echo "" + $ECHO " 3.1- ${mailnotify} ($yes/$no) [$yes]: " + + if [ "X${USER_ENABLE_EMAIL}" = "X" ]; then + read ANSWER + else + ANSWER=${USER_ENABLE_EMAIL} + fi + + case $ANSWER in + $nomatch) + echo "" + echo " --- ${nomail}." + EMAILNOTIFY="no" + ;; + *) + EMAILNOTIFY="yes" + $ECHO " - ${whatsemail} " + if [ "X${USER_EMAIL_ADDRESS}" = "X" ]; then + + read EMAIL + echo "${EMAIL}" | grep -E "^[a-zA-Z0-9_.-]{1,36}@[a-zA-Z0-9_.-]{1,54}$" > /dev/null 2>&1 ;RVAL=$?; + # Ugly e-mail validation + while [ "$EMAIL" = "" -o ! ${RVAL} = 0 ] ; do + $ECHO " - ${whatsemail} " + read EMAIL + echo "${EMAIL}" | grep -E "^[a-zA-Z0-9_.-]{1,36}@[a-zA-Z0-9_.-]{1,54}$" > /dev/null 2>&1 ;RVAL=$?; + done + else + EMAIL=${USER_EMAIL_ADDRESS} + fi + + ls ${HOST_CMD} > /dev/null 2>&1 + if [ $? = 0 ]; then + HOSTTMP=`${HOST_CMD} -W 5 -t mx devmail.ossec.net 2>/dev/null` + if [ $? = 1 ]; then + # Trying without the -W + HOSTTMP=`${HOST_CMD} -t mx devmail.ossec.net 2>/dev/null` + fi + if [ "X$HOSTTMP" = "X${OSSECMX}" -o "X$HOSTTMP" = "X${OSSECMX2}" -o "X$HOSTTMP" = "X${OSSECMX3}" ];then + # Breaking down the user e-mail + EMAILHOST=`echo ${EMAIL} | cut -d "@" -f 2` + if [ "X${EMAILHOST}" = "Xlocalhost" ]; then + SMTPHOST="127.0.0.1" + else + HOSTTMP=`${HOST_CMD} -W 5 -t mx ${EMAILHOST}` + SMTPHOST=`echo ${HOSTTMP} | cut -d " " -f 7` + fi + fi + fi + + if [ "X${USER_EMAIL_SMTP}" = "X" ]; then + if [ "X${SMTPHOST}" != "X" ]; then + echo "" + echo " - ${yoursmtp}: ${SMTPHOST}" + $ECHO " - ${usesmtp} ($yes/$no) [$yes]: " + read EMAIL2 + case ${EMAIL2} in + $nomatch) + echo "" + SMTP="" + ;; + *) + SMTP=${SMTPHOST} + echo "" + echo " --- ${usingsmtp} ${SMTP}" + ;; + esac + fi + + if [ "X${SMTP}" = "X" ]; then + $ECHO " - ${whatsmtp} " + read SMTP + fi + else + SMTP=${USER_EMAIL_SMTP} + fi + ;; + esac + + + # Writting global parameters + echo "" > $NEWCONFIG + echo " " >> $NEWCONFIG + if [ "$EMAILNOTIFY" = "yes" ]; then + echo " yes" >> $NEWCONFIG + echo " $EMAIL" >> $NEWCONFIG + echo " $SMTP" >> $NEWCONFIG + echo " ossecm@${HOST}" >> $NEWCONFIG + else + echo " no" >> $NEWCONFIG + fi + + echo " " >> $NEWCONFIG + echo "" >> $NEWCONFIG + + # Writting rules configuration + cat ${RULES_TEMPLATE} >> $NEWCONFIG + echo "" >> $NEWCONFIG + + + # Checking if syscheck should run + UseSyscheck + + # Checking if rootcheck should run + UseRootcheck + + + # Active response + catMsg "0x107-ar" + $ECHO " - ${enable_ar} ($yes/$no) [$yes]: " + + if [ "X${USER_ENABLE_ACTIVE_RESPONSE}" = "X" ]; then + read AR + else + AR=${USER_ENABLE_ACTIVE_RESPONSE} + fi + + case $AR in + $nomatch) + echo "" + echo " - ${noactive}." + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " yes" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo "" >> $NEWCONFIG + ;; + *) + ACTIVERESPONSE="yes" + echo "" + catMsg "0x108-ar-enabled" + + echo "" + $ECHO " - ${firewallar} ($yes/$no) [$yes]: " + + if [ "X${USER_ENABLE_FIREWALL_RESPONSE}" = "X" ]; then + read HD2 + else + HD2=${USER_ENABLE_FIREWALL_RESPONSE} + fi + + echo "" + case $HD2 in + $nomatch) + echo " - ${nofirewall}" + ;; + *) + echo " - ${yesfirewall}" + FIREWALLDROP="yes" + ;; + esac + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " 127.0.0.1" >> $NEWCONFIG + echo " ^localhost.localdomain$">>$NEWCONFIG + echo "" + echo " - ${defaultwhitelist}" + for ip in ${NAMESERVERS} ${NAMESERVERS2}; + do + if [ ! "X${ip}" = "X" ]; then + echo " - ${ip}" + echo " ${ip}" >>$NEWCONFIG + fi + done + AddWhite + + # If Openbsd or Freebsd with pf enable, ask about + # automatically setting it up. + # Commenting it out in case I change my mind about it + # later. + #if [ "X`sh ./src/init/fw-check.sh`" = "XPF" ]; then + # echo "" + # $ECHO " - ${pfenable} ($yes/$no) [$yes]: " + # if [ "X${USER_ENABLE_PF}" = "X" ]; then + # read PFENABLE + # else + # PFENABLE=${USER_ENABLE_PF} + # fi + # + # echo "" + # case $PFENABLE in + # $nomatch) + # echo " - ${nopf}" + # ;; + # *) + # AddPFTable + # ;; + # esac + #fi + + echo " " >> $NEWCONFIG + ;; + esac + + + if [ "X$INSTYPE" = "Xserver" ]; then + # Configuring remote syslog + echo "" + $ECHO " 3.5- ${syslog} ($yes/$no) [$yes]: " + + if [ "X${USER_ENABLE_SYSLOG}" = "X" ]; then + read ANSWER + else + ANSWER=${USER_ENABLE_SYSLOG} + fi + + echo "" + case $ANSWER in + $nomatch) + echo " --- ${nosyslog}." + ;; + *) + echo " - ${yessyslog}." + RLOG="yes" + ;; + esac + + # Configuring remote connections + SLOG="yes" + fi + + + + if [ "X$RLOG" = "Xyes" ]; then + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " syslog" >> $NEWCONFIG + echo " " >> $NEWCONFIG + fi + + if [ "X$SLOG" = "Xyes" ]; then + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " secure" >> $NEWCONFIG + echo " " >> $NEWCONFIG + fi + + + # Email/log alerts + echo "" >> $NEWCONFIG + echo " " >> $NEWCONFIG + echo " 1" >> $NEWCONFIG + if [ "$EMAILNOTIFY" = "yes" ]; then + echo " 7">> $NEWCONFIG + fi + echo " " >> $NEWCONFIG + + + if [ "X$ACTIVERESPONSE" = "Xyes" ]; then + # Add commands in here + echo "" >> $NEWCONFIG + cat ${HOST_DENY_TEMPLATE} >> $NEWCONFIG + echo "" >> $NEWCONFIG + cat ${FIREWALL_DROP_TEMPLATE} >> $NEWCONFIG + echo "" >> $NEWCONFIG + cat ${DISABLE_ACCOUNT_TEMPLATE} >> $NEWCONFIG + echo "" >> $NEWCONFIG + cat ${ROUTENULL_TEMPLATE} >> $NEWCONFIG + echo "" >> $NEWCONFIG + + if [ "X$FIREWALLDROP" = "Xyes" ]; then + echo "" >> $NEWCONFIG + cat ${ACTIVE_RESPONSE_TEMPLATE} >> $NEWCONFIG + echo "" >> $NEWCONFIG + fi + fi + + # Setting up the logs + SetupLogs "3.6" + echo "" >> $NEWCONFIG +} + + + + +########## +# setEnv() +########## +setEnv() +{ + echo "" + echo "2- ${settingupenv}." + + echo "" + if [ "X${USER_DIR}" = "X" ]; then + while [ 1 ]; do + $ECHO " - ${wheretoinstall} [$INSTALLDIR]: " + read ANSWER + if [ ! "X$ANSWER" = "X" ]; then + echo $ANSWER |grep -E "^/[a-zA-Z0-9./_-]{3,128}$">/dev/null 2>&1 + if [ $? = 0 ]; then + INSTALLDIR=$ANSWER; + break; + fi + else + break; + fi + done + else + INSTALLDIR=${USER_DIR} + fi + + + CEXTRA="$CEXTRA -DDEFAULTDIR=\\\"${INSTALLDIR}\\\"" + + echo "" + echo " - ${installat} ${INSTALLDIR} ." + + + if [ "X$INSTYPE" = "Xagent" ]; then + CEXTRA="$CEXTRA -DCLIENT" + elif [ "X$INSTYPE" = "Xlocal" ]; then + CEXTRA="$CEXTRA -DLOCAL" + fi + + ls $INSTALLDIR >/dev/null 2>&1 + if [ $? = 0 ]; then + if [ "X${USER_DELETE_DIR}" = "X" ]; then + echo "" + $ECHO " - ${deletedir} ($yes/$no) [$yes]: " + read ANSWER + else + ANSWER=${USER_DELETE_DIR} + fi + + case $ANSWER in + $yesmatch) + rm -rf $INSTALLDIR + if [ ! $? = 0 ]; then + exit 2; + fi + ;; + esac + fi +} + + + + +########## +# checkDependencies() +# Thanks to gabriel@macacos.org +########## +checkDependencies() +{ + echo "" + OLDOPATH=$PATH + if [ "X$NUNAME" = "XSunOS" ]; then + PATH=$PATH:/usr/ccs/bin:/usr/xpg4/bin:/opt/csw/gcc3/bin:/opt/csw/bin:/usr/sfw/bin + export PATH + elif [ "X$NUNAME" = "XAIX" ]; then + PATH=$PATH:/usr/vac/bin + export PATH + fi + + ls "`which gcc`" > /dev/null 2>&1 + if [ ! $? = 0 ]; then + ls "`which cc`" > /dev/null 2>&1 + if [ ! $? = 0 ]; then + if [ "X${USER_BINARYINSTALL}" = "X" ]; then + catError "0x3-dependencies" + fi + fi + CC="cc" + else + CC="gcc" + fi + + PATH=$OLDOPATH + export PATH +} + +########## +# AddWhite() +########## +AddWhite() +{ + while [ 1 ] + do + echo "" + $ECHO " - ${addwhite} ($yes/$no)? [$no]: " + + # If white list is set, we don't need to ask it here. + if [ "X${USER_WHITE_LIST}" = "X" ]; then + read ANSWER + else + ANSWER=$yes + fi + + if [ "X${ANSWER}" = "X" ] ; then + ANSWER=$no + fi + + case $ANSWER in + $no) + break; + ;; + *) + $ECHO " - ${ipswhite}" + if [ "X${USER_WHITE_LIST}" = "X" ]; then + read IPS + else + IPS=${USER_WHITE_LIST} + fi + + for ip in ${IPS}; + do + if [ ! "X${ip}" = "X" ]; then + echo $ip | grep -E "^[0-9./]{5,20}$" > /dev/null 2>&1 + if [ $? = 0 ]; then + echo " ${ip}" >>$NEWCONFIG + fi + fi + done + + break; + ;; + esac + done +} + + +########## +# AddPFTable() +########## +AddPFTable() +{ + #default pf rules + TABLE="ossec_fwtable" + + # Add table to the first line + echo "" + echo " - ${pfmessage}:" + echo " ${moreinfo}" + echo " http://www.ossec.net/en/manual.html#active-response-tools" + + echo "" + echo "" + echo " table <${TABLE}> persist #$TABLE " + echo " block in quick from <${TABLE}> to any" + echo " block out quick from any to <${TABLE}>" + echo "" + echo "" + +} + +########## +# main() +########## +main() +{ + LG="en" + LANGUAGE="en" + . ./src/init/shared.sh + . ./src/init/functions.sh + + # Reading pre-defined file + if [ ! `isFile ${PREDEF_FILE}` = "${FALSE}" ]; then + . ${PREDEF_FILE} + fi + + # If user language is not set + + if [ "X${USER_LANGUAGE}" = "X" ]; then + + # Choosing the language. + while [ 1 ]; do + echo "" + for i in `ls ${TEMPLATE}`; do + # ignore CVS (should not be there anyways and config) + if [ "$i" = "CVS" -o "$i" = "config" ]; then continue; fi + cat "${TEMPLATE}/$i/language.txt" + if [ ! "$i" = "en" ]; then + LG="${LG}/$i" + fi + done + $ECHO " (${LG}) [en]: " + read USER_LG; + + if [ "X${USER_LG}" = "X" ]; then + USER_LG="en" + fi + + ls "${TEMPLATE}/${USER_LG}" > /dev/null 2>&1 + if [ $? = 0 ]; then + break; + fi + done; + + LANGUAGE=${USER_LG} + + else + + # If provided language is not valid, default to english + ls "${TEMPLATE}/${USER_LANGUAGE}" > /dev/null 2>&1 + if [ $? = 0 ]; then + LANGUAGE=${USER_LANGUAGE} + else + LANGUAGE="en" + fi + + fi # for USER_LANGUAGE + + + . ./src/init/shared.sh + . ./src/init/language.sh + . ./src/init/functions.sh + . ./src/init/init.sh + . ${TEMPLATE}/${LANGUAGE}/messages.txt + + + # Must be executed as ./install.sh + if [ `isFile ${VERSION_FILE}` = "${FALSE}" ]; then + catError "0x1-location"; + fi + + # Must be root + if [ ! "X$ME" = "Xroot" ]; then + catError "0x2-beroot"; + fi + + # Checking dependencies + checkDependencies + + clear + + + # Initial message + echo " $NAME $VERSION ${installscript} - http://www.ossec.net" + + catMsg "0x101-initial" + + echo " - $system: $UNAME" + echo " - $user: $ME" + echo " - $host: $HOST" + echo "" + echo "" + echo " -- $hitanyorabort --" + + if [ "X$USER_NO_STOP" = "X" ]; then + read ANY + fi + + . ./src/init/update.sh + # Is this an update? + if [ "`isUpdate`" = "${TRUE}" ]; then + echo "" + ct="1" + while [ $ct = "1" ]; do + ct="0" + $ECHO " - ${wanttoupdate} ($yes/$no): " + if [ "X${USER_UPDATE}" = "X" ]; then + read ANY + else + ANY=$yes + fi + + case $ANY in + $yes) + update_only="yes" + break; + ;; + $no) + break; + ;; + *) + ct="1" + ;; + esac + done + + + # Do some of the update steps. + if [ "X${update_only}" = "Xyes" ]; then + . ./src/init/update.sh + + if [ "`doUpdatecleanup`" = "${FALSE}" ]; then + # Disabling update + echo "" + echo "${unabletoupdate}" + sleep 5; + update_only="" + else + # Get update + USER_INSTALL_TYPE=`getPreinstalled` + USER_DIR=`getPreinstalledDir` + USER_DELETE_DIR="$nomatch" + fi + + ct="1" + + # We dont need to update the rules on agent installs + if [ "X${USER_INSTALL_TYPE}" = "Xagent" ]; then + ct="0" + fi + + while [ $ct = "1" ]; do + ct="0" + $ECHO " - ${updaterules} ($yes/$no): " + if [ "X${USER_UPDATE_RULES}" = "X" ]; then + read ANY + else + ANY=$yes + fi + + case $ANY in + $yes) + update_rules="yes" + break; + ;; + $no) + break; + ;; + *) + ct="1" + ;; + esac + done + fi + echo "" + fi + + serverm=`echo ${server} | cut -b 1` + localm=`echo ${local} | cut -b 1` + agentm=`echo ${agent} | cut -b 1` + helpm=`echo ${help} | cut -b 1` + + # If user install type is not set, ask for it. + if [ "X${USER_INSTALL_TYPE}" = "X" ]; then + + # Loop for the installation options + while [ 1 ] + do + echo "" + $ECHO "1- ${whattoinstall} " + + read ANSWER + case $ANSWER in + + ${helpm}|${help}) + catMsg "0x102-installhelp" + ;; + + ${server}|${serverm}) + echo "" + echo " - ${serverchose}." + INSTYPE="server" + break; + ;; + + ${agent}|${agentm}) + echo "" + echo " - ${clientchose}." + INSTYPE="agent" + break; + ;; + + ${local}|${localm}) + echo "" + echo " - ${localchose}." + INSTYPE="local" + break; + ;; + esac + done + + else + INSTYPE=${USER_INSTALL_TYPE} + fi + + + # Setting up the environment + setEnv + + + # Configuring the system (based on the installation type) + if [ "X${update_only}" = "X" ]; then + if [ "X$INSTYPE" = "Xserver" ]; then + ConfigureServer + elif [ "X$INSTYPE" = "Xagent" ]; then + ConfigureClient + elif [ "X$INSTYPE" = "Xlocal" ]; then + ConfigureServer + else + catError "0x4-installtype" + fi + fi + + # Installing (calls the respective script + # -- InstallAgent.sh or InstallServer.sh + Install + + # User messages + echo "" + echo " - ${configurationdone}." + echo "" + echo " - ${tostart}:" + echo " $INSTALLDIR/bin/ossec-control start" + echo "" + echo " - ${tostop}:" + echo " $INSTALLDIR/bin/ossec-control stop" + echo "" + echo " - ${configat} $INSTALLDIR/etc/ossec.conf" + echo "" + + + catMsg "0x103-thanksforusing" + + + if [ "X${update_only}" = "Xyes" ]; then + # Message for the update + if [ "X`sh ./src/init/fw-check.sh`" = "XPF" -a "X${ACTIVERESPONSE}" = "Xyes" ]; then + if [ "X$USER_NO_STOP" = "X" ]; then + read ANY + fi + AddPFTable + fi + echo "" + echo " - ${updatecompleted}" + echo "" + exit 0; + fi + + + if [ "X$USER_NO_STOP" = "X" ]; then + read ANY + fi + + + # PF firewall message + if [ "X`sh ./src/init/fw-check.sh`" = "XPF" -a "X${ACTIVERESPONSE}" = "Xyes" ]; then + AddPFTable + fi + + + if [ "X$INSTYPE" = "Xserver" ]; then + echo "" + echo " - ${addserveragent}" + echo " ${runma}:" + echo "" + echo " $INSTALLDIR/bin/manage_agents" + echo "" + echo " ${moreinfo}" + echo " http://www.ossec.net/en/manual.html#ma" + echo "" + + elif [ "X$INSTYPE" = "Xagent" ]; then + catMsg "0x104-client" + echo " $INSTALLDIR/bin/manage_agents" + echo "" + echo " ${moreinfo}" + echo " http://www.ossec.net/en/manual.html#ma" + echo "" + fi + + if [ "X$notmodified" = "Xyes" ]; then + catMsg "0x105-noboot" + echo " $INSTALLDIR/bin/ossec-control start" + echo "" + fi +} + + + + +### Calling main function where everything happens +main + + +exit 0 + + + +## EOF ## + diff --git a/src/Config.Make b/src/Config.Make new file mode 100755 index 0000000..8fe97b7 --- /dev/null +++ b/src/Config.Make @@ -0,0 +1,26 @@ +# Config.Make +# Options for the Makefile +# Daniel B. Cid +# http://www.ossec.net + + +include ${PT}LOCATION +include ${PT}Config.OS + + +CFLAGS = -g -Wall -I${PT} -I${PT}headers ${CPATH} ${CEXTRA} ${DEXTRA} ${EEXTRA} ${FEXTRA} ${GEXTRA} ${HEXTRA} -DARGV0=\"${NAME}\" -DXML_VAR=\"var\" -DOSSECHIDS + +SOURCES = *.c +OBJECTS = *.o +CLEAN = rm -f -r ${OBJECTS} ${NAME} *.a core core.* *.core +BUILD = cp -pr ${NAME} ${PT}../bin + +OS_XML = ${PT}os_xml/os_xml.a +OS_REGEX = ${PT}os_regex/os_regex.a +OS_NET = ${PT}os_net/os_net.a +OS_CRYPTO = ${PT}os_crypto/os_crypto.a +OS_SHARED = ${PT}shared/lib_shared.a +OS_ROOTCHECK = ${PT}rootcheck/rootcheck_lib.a +OS_CONFIG = ${PT}config/lib_config.a +OS_ZLIB = ${PT}os_zlib/os_zlib.c ${PT}external/libz.a +OS_LINK = ${IEXTRA} diff --git a/src/InstallAgent.sh b/src/InstallAgent.sh new file mode 100755 index 0000000..6ee67e5 --- /dev/null +++ b/src/InstallAgent.sh @@ -0,0 +1,225 @@ +#!/bin/sh + + +# Checking if it is executed from the right place +LOCATION=./LOCATION + +ls ${LOCATION} > /dev/null 2>&1 +if [ $? != 0 ]; then + echo "Cannot execute. Wrong directory" + exit 1; +fi + +UNAME=`uname`; +# Getting default variables +DIR=`grep DIR ${LOCATION} | cut -f2 -d\"` +GROUP="ossec" +USER="ossec" +subdirs="logs bin queue queue/ossec queue/alerts queue/syscheck queue/rids var var/run etc etc/shared active-response active-response/bin agentless .ssh" + + +# ${DIR} must be set +if [ "X${DIR}" = "X" ]; then + echo "Error building OSSEC HIDS." + exit 1; +fi + + +# Creating root directory +ls ${DIR} > /dev/null 2>&1 +if [ $? != 0 ]; then mkdir -m 700 -p ${DIR}; fi +ls ${DIR} > /dev/null 2>&1 +if [ $? != 0 ]; then + echo "You do not have permissions to create ${DIR}. Exiting..." + exit 1; +fi + + +# Creating groups/users +if [ "$UNAME" = "FreeBSD" -o "$UNAME" = "DragonFly" ]; then + grep "^${USER}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/sbin/pw groupadd ${GROUP} + /usr/sbin/pw useradd ${USER} -d ${DIR} -s /sbin/nologin -g ${GROUP} + fi + +elif [ "$UNAME" = "SunOS" ]; then + grep "^${USER}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/sbin/groupadd ${GROUP} + /usr/sbin/useradd -d ${DIR} -s /bin/false -g ${GROUP} ${USER} + fi + +elif [ "$UNAME" = "AIX" ]; then + AIXSH="" + ls -la /bin/false > /dev/null 2>&1 + if [ $? = 0 ]; then + AIXSH="-s /bin/false" + fi + grep "^${USER}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/bin/mkgroup ${GROUP} + /usr/sbin/useradd -d ${DIR} ${AIXSH} -g ${GROUP} ${USER} + fi + +# Thanks Chuck L. for the mac addusers +elif [ "$UNAME" = "Darwin" ]; then + id -u ${USER} > /dev/null 2>&1 + if [ ! $? = 0 ]; then + + # Creating for 10.5 + /usr/bin/sw_vers 2>/dev/null| grep "ProductVersion" | grep -E "10.5.|10.6" > /dev/null 2>&1 + if [ $? = 0 ]; then + chmod +x ./init/osx105-addusers.sh + ./init/osx105-addusers.sh + else + chmod +x ./init/darwin-addusers.pl + ./init/darwin-addusers.pl + fi + fi +else + grep "^${USER}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/sbin/groupadd ${GROUP} + + # We first check if /sbin/nologin is present. If it is not, + # we look for bin/false. If none of them is present, we + # just stick with nologin (no need to fail the install for that). + OSMYSHELL="/sbin/nologin" + ls -la ${OSMYSHELL} > /dev/null 2>&1 + if [ ! $? = 0 ]; then + ls -la /bin/false > /dev/null 2>&1 + if [ $? = 0 ]; then + OSMYSHELL="/bin/false" + fi + fi + /usr/sbin/useradd -d ${DIR} -s ${OSMYSHELL} -g ${GROUP} ${USER} + fi +fi + + +# Creating sub dirs +for i in ${subdirs}; do + ls ${DIR}/${i} > /dev/null 2>&1 + if [ $? != 0 ]; then mkdir -m 700 ${DIR}/${i}; fi +done + +# Default for all directories +chmod -R 550 ${DIR} +chown -R root:${GROUP} ${DIR} + +# To the ossec queue (default for agentd to read) +chown -R ${USER}:${GROUP} ${DIR}/queue/ossec +chmod -R 770 ${DIR}/queue/ossec + +# For the logging user +chown -R ${USER}:${GROUP} ${DIR}/logs +chmod -R 750 ${DIR}/logs +chmod -R 775 ${DIR}/queue/rids +touch ${DIR}/logs/ossec.log +chown ${USER}:${GROUP} ${DIR}/logs/ossec.log +chmod 664 ${DIR}/logs/ossec.log + + + +# For the etc dir +chmod 550 ${DIR}/etc +chown -R root:${GROUP} ${DIR}/etc + +ls /etc/localtime > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -p /etc/localtime ${DIR}/etc/; +fi + +# Solaris Needs some extra files +if [ "$UNAME" = "SunOS" ]; then + mkdir -p ${DIR}/usr/share/lib/zoneinfo/ + chmod -R 555 ${DIR}/usr/ + cp -pr /usr/share/lib/zoneinfo/* ${DIR}/usr/share/lib/zoneinfo/ + chown -R root:${GROUP} ${DIR}/usr/ +fi + +ls /etc/TIMEZONE > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -p /etc/TIMEZONE ${DIR}/etc/; + chown root:${GROUP} ${DIR}/etc/TIMEZONE + chmod 555 ${DIR}/etc/TIMEZONE +fi + + + +# For the /etc/shared +cp -pr rootcheck/db/*.txt ${DIR}/etc/shared/ + +# Backup currently internal_options file. +ls ${DIR}/etc/internal_options.conf > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -pr ${DIR}/etc/internal_options.conf ${DIR}/etc/backup-internal_options.$$ +fi + +cp -pr ../etc/internal_options.conf ${DIR}/etc/ +cp -pr ../etc/local_internal_options.conf ${DIR}/etc/ > /dev/null 2>&1 +cp -pr ../etc/client.keys ${DIR}/etc/ > /dev/null 2>&1 +cp -pr agentlessd/scripts/* ${DIR}/agentless/ + +chown root:${GROUP} ${DIR}/etc/internal_options.conf +chown root:${GROUP} ${DIR}/etc/local_internal_options.conf > /dev/null 2>&1 +chown root:${GROUP} ${DIR}/etc/client.keys > /dev/null 2>&1 +chown root:${GROUP} ${DIR}/agentless/* +chown ${USER}:${GROUP} ${DIR}/.ssh +chown -R root:${GROUP} ${DIR}/etc/shared + +chmod 550 ${DIR}/etc +chmod 440 ${DIR}/etc/internal_options.conf +chmod 440 ${DIR}/etc/local_internal_options.conf > /dev/null 2>&1 +chmod 440 ${DIR}/etc/client.keys > /dev/null 2>&1 +chmod -R 770 ${DIR}/etc/shared # ossec must be able to write to it +chmod 550 ${DIR}/agentless/* +chmod 700 ${DIR}/.ssh + + +# For the /var/run +chmod 770 ${DIR}/var/run +chown root:${GROUP} ${DIR}/var/run + + +# Moving the binary files +cp -pr ../bin/ossec-agentd ${DIR}/bin/ +cp -pr ../bin/ossec-logcollector ${DIR}/bin/ +cp -pr ../bin/ossec-syscheckd ${DIR}/bin/ +cp -pr ../bin/ossec-execd ${DIR}/bin/ +cp -pr ./init/ossec-client.sh ${DIR}/bin/ossec-control +cp -pr ../bin/manage_agents ${DIR}/bin/ + +# Copying active response modules +sh ./init/fw-check.sh execute > /dev/null +cp -pr ../active-response/*.sh ${DIR}/active-response/bin/ +cp -pr ../active-response/firewalls/*.sh ${DIR}/active-response/bin/ +chmod 755 ${DIR}/active-response/bin/* +chown root:${GROUP} ${DIR}/active-response/bin/* + +chown root:${GROUP} ${DIR}/bin/* +chmod 550 ${DIR}/bin/* + + +# Moving the config file +ls ${DIR}/etc/ossec.conf > /dev/null 2>&1 +if [ $? = 0 ]; then + exit 0; +fi + + +ls ../etc/ossec.mc > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -pr ../etc/ossec.mc ${DIR}/etc/ossec.conf +else + cp -pr ../etc/ossec-agent.conf ${DIR}/etc/ossec.conf +fi +chown root:${GROUP} ${DIR}/etc/ossec.conf +chmod 440 ${DIR}/etc/ossec.conf + + + +exit 0; + +#EOF diff --git a/src/InstallServer.sh b/src/InstallServer.sh new file mode 100755 index 0000000..7393513 --- /dev/null +++ b/src/InstallServer.sh @@ -0,0 +1,320 @@ +#!/bin/sh + + +# Checking if it is executed from the right place +LOCATION=./LOCATION +ls ${LOCATION} > /dev/null 2>&1 +if [ $? != 0 ]; then + echo "Cannot execute. Wrong directory" + exit 1; +fi + +# Getting any argument +if [ "X$1" = "Xlocal" ]; then + # Setting local install + LOCAL="local" +fi + +UNAME=`uname`; + +# Getting default variables +DIR=`grep DIR ${LOCATION} | cut -f2 -d\"` +GROUP="ossec" +USER="ossec" +USER_MAIL="ossecm" +USER_REM="ossecr" +subdirs="logs logs/archives logs/alerts logs/firewall bin stats rules queue queue/alerts queue/ossec queue/fts queue/syscheck queue/rootcheck queue/diff queue/agent-info queue/agentless queue/rids tmp var var/run etc etc/shared active-response active-response/bin agentless .ssh" + +# ${DIR} must be set +if [ "X${DIR}" = "X" ]; then + echo "Error building OSSEC HIDS." + exit 1; +fi + + +# Creating root directory +ls ${DIR} > /dev/null 2>&1 +if [ $? != 0 ]; then mkdir -m 700 -p ${DIR}; fi +ls ${DIR} > /dev/null 2>&1 +if [ $? != 0 ]; then + echo "You do not have permissions to create ${DIR}. Exiting..." + exit 1; +fi + + +# Creating groups/users +if [ "$UNAME" = "FreeBSD" -o "$UNAME" = "DragonFly" ]; then + grep "^${USER_REM}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/sbin/pw groupadd ${GROUP} + /usr/sbin/pw useradd ${USER} -d ${DIR} -s /sbin/nologin -g ${GROUP} + /usr/sbin/pw useradd ${USER_MAIL} -d ${DIR} -s /sbin/nologin -g ${GROUP} + /usr/sbin/pw useradd ${USER_REM} -d ${DIR} -s /sbin/nologin -g ${GROUP} + fi + +elif [ "$UNAME" = "SunOS" ]; then + grep "^${USER_REM}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/sbin/groupadd ${GROUP} + /usr/sbin/useradd -d ${DIR} -s /bin/false -g ${GROUP} ${USER} + /usr/sbin/useradd -d ${DIR} -s /bin/false -g ${GROUP} ${USER_MAIL} + /usr/sbin/useradd -d ${DIR} -s /bin/false -g ${GROUP} ${USER_REM} + fi + +elif [ "$UNAME" = "AIX" ]; then + AIXSH="" + ls -la /bin/false > /dev/null 2>&1 + if [ $? = 0 ]; then + AIXSH="-s /bin/false" + fi + + grep "^${USER_REM}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/bin/mkgroup ${GROUP} + /usr/sbin/useradd -d ${DIR} ${AIXSH} -g ${GROUP} ${USER} + /usr/sbin/useradd -d ${DIR} ${AIXSH} -g ${GROUP} ${USER_MAIL} + /usr/sbin/useradd -d ${DIR} ${AIXSH} -g ${GROUP} ${USER_REM} + fi + +# Thanks Chuck L. for the mac addusers +elif [ "$UNAME" = "Darwin" ]; then + id -u ${USER} > /dev/null 2>&1 + if [ ! $? = 0 ]; then + + # Creating for 10.5 and 10.6 + /usr/bin/sw_vers 2>/dev/null| grep "ProductVersion" | grep -E "10.5.|10.6" > /dev/null 2>&1 + if [ $? = 0 ]; then + chmod +x ./init/osx105-addusers.sh + ./init/osx105-addusers.sh + else + chmod +x ./init/darwin-addusers.pl + ./init/darwin-addusers.pl + fi + fi +else + grep "^${USER_REM}" /etc/passwd > /dev/null 2>&1 + if [ ! $? = 0 ]; then + /usr/sbin/groupadd ${GROUP} + + # We first check if /sbin/nologin is present. If it is not, + # we look for bin/false. If none of them is present, we + # just stick with nologin (no need to fail the install for that). + OSMYSHELL="/sbin/nologin" + ls -la ${OSMYSHELL} > /dev/null 2>&1 + if [ ! $? = 0 ]; then + ls -la /bin/false > /dev/null 2>&1 + if [ $? = 0 ]; then + OSMYSHELL="/bin/false" + fi + fi + /usr/sbin/useradd -d ${DIR} -s ${OSMYSHELL} -g ${GROUP} ${USER} + /usr/sbin/useradd -d ${DIR} -s ${OSMYSHELL} -g ${GROUP} ${USER_MAIL} + /usr/sbin/useradd -d ${DIR} -s ${OSMYSHELL} -g ${GROUP} ${USER_REM} + fi +fi + + +# Creating sub directories +for i in ${subdirs}; do + ls ${DIR}/${i} > /dev/null 2>&1 + if [ $? != 0 ]; then mkdir -m 700 ${DIR}/${i}; fi +done + +# Default for all directories +chmod -R 550 ${DIR} +chown -R root:${GROUP} ${DIR} + +# AnalysisD needs to write to alerts: log, mail and cmds +chown -R ${USER}:${GROUP} ${DIR}/queue/alerts +chmod -R 770 ${DIR}/queue/alerts + +# To the ossec queue (default for analysisd to read) +chown -R ${USER}:${GROUP} ${DIR}/queue/ossec +chmod -R 770 ${DIR}/queue/ossec + +# To the ossec fts queue +chown -R ${USER}:${GROUP} ${DIR}/queue/fts +chmod -R 750 ${DIR}/queue/fts +chmod 740 ${DIR}/queue/fts/* > /dev/null 2>&1 + +# To the ossec syscheck/rootcheck queue +chown -R ${USER}:${GROUP} ${DIR}/queue/syscheck +chmod -R 750 ${DIR}/queue/syscheck +chmod 740 ${DIR}/queue/syscheck/* > /dev/null 2>&1 + +chown -R ${USER}:${GROUP} ${DIR}/queue/rootcheck +chmod -R 750 ${DIR}/queue/rootcheck +chmod 740 ${DIR}/queue/rootcheck/* > /dev/null 2>&1 + +chown -R ${USER}:${GROUP} ${DIR}/queue/diff +chmod -R 750 ${DIR}/queue/diff +chmod 740 ${DIR}/queue/diff/* > /dev/null 2>&1 + +chown -R ${USER_REM}:${GROUP} ${DIR}/queue/agent-info +chmod -R 755 ${DIR}/queue/agent-info +chmod 744 ${DIR}/queue/agent-info/* > /dev/null 2>&1 +chown -R ${USER_REM}:${GROUP} ${DIR}/queue/rids +chmod -R 755 ${DIR}/queue/rids +chmod 744 ${DIR}/queue/rids/* > /dev/null 2>&1 + +chown -R ${USER}:${GROUP} ${DIR}/queue/agentless +chmod -R 755 ${DIR}/queue/agentless +chmod 744 ${DIR}/queue/agentless/* > /dev/null 2>&1 + + +# For the stats directory +chown -R ${USER}:${GROUP} ${DIR}/stats +chmod -R 750 ${DIR}/stats + +# For the logging user +chown -R ${USER}:${GROUP} ${DIR}/logs +chmod -R 750 ${DIR}/logs +touch ${DIR}/logs/ossec.log +chown ${USER}:${GROUP} ${DIR}/logs/ossec.log +chmod 664 ${DIR}/logs/ossec.log + +# For the rules directory +ls ${DIR}/rules/*.xml > /dev/null 2>&1 + +# Backup previous rules +if [ $? = 0 ]; then + mkdir ${DIR}/rules/backup-rules.$$ + cp -pr ${DIR}/rules/*.xml ${DIR}/rules/backup-rules.$$/ + + # Checking for the local rules + ls ${DIR}/rules/local_rules.xml > /dev/null 2>&1 + if [ $? = 0 ]; then + cp -pr ${DIR}/rules/local_rules.xml ${DIR}/rules/saved_local_rules.xml.$$ + fi +fi + +cp -pr ../etc/rules/* ${DIR}/rules/ + +# If the local_rules is saved, moved it back +ls ${DIR}/rules/saved_local_rules.xml.$$ > /dev/null 2>&1 +if [ $? = 0 ]; then + mv ${DIR}/rules/saved_local_rules.xml.$$ ${DIR}/rules/local_rules.xml +fi + +chown -R root:${GROUP} ${DIR}/rules +chmod -R 550 ${DIR}/rules + + +# For the etc dir +chmod 550 ${DIR}/etc +chown -R root:${GROUP} ${DIR}/etc +ls /etc/localtime > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -pL /etc/localtime ${DIR}/etc/; + chmod 555 ${DIR}/etc/localtime + chown root:${GROUP} ${DIR}/etc/localtime +fi + +# Solaris Needs some extra files +if [ "$UNAME" = "SunOS" ]; then + mkdir -p ${DIR}/usr/share/lib/zoneinfo/ + chmod -R 555 ${DIR}/usr/ + cp -pr /usr/share/lib/zoneinfo/* ${DIR}/usr/share/lib/zoneinfo/ +fi + +ls /etc/TIMEZONE > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -p /etc/TIMEZONE ${DIR}/etc/; + chmod 555 ${DIR}/etc/TIMEZONE +fi + + +# For the /var/run +chmod 770 ${DIR}/var/run +chown root:${GROUP} ${DIR}/var/run + +# Moving the binary files +cp -pr ../bin/ossec* ${DIR}/bin/ +cp -pr ../bin/manage_agents ${DIR}/bin/ +cp -pr ../bin/syscheck_update ${DIR}/bin/ +cp -pr ../bin/clear_stats ${DIR}/bin/ +cp -pr ../bin/list_agents ${DIR}/bin/ +cp -pr ../bin/agent_control ${DIR}/bin/ +cp -pr ../bin/syscheck_control ${DIR}/bin/ +cp -pr ../bin/rootcheck_control ${DIR}/bin/ + +# Local install chosen +if [ "X$LOCAL" = "Xlocal" ]; then + cp -pr ./init/ossec-local.sh ${DIR}/bin/ossec-control +else + cp -pr ./init/ossec-server.sh ${DIR}/bin/ossec-control +fi + +# Moving the decoders/internal_conf file. +cp -pr ../etc/decoder.xml ${DIR}/etc/ + +# Copying local files. +cp -pr ../etc/local_decoder.xml ${DIR}/etc/ > /dev/null 2>&1 +cp -pr ../etc/local_internal_options.conf ${DIR}/etc/ > /dev/null 2>&1 +cp -pr ../etc/client.keys ${DIR}/etc/ > /dev/null 2>&1 + +# Copying agentless files. +cp -pr agentlessd/scripts/* ${DIR}/agentless/ + + +# Backup currently internal_options file. +ls ${DIR}/etc/internal_options.conf > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -pr ${DIR}/etc/internal_options.conf ${DIR}/etc/backup-internal_options.$$ +fi + +cp -pr ../etc/internal_options.conf ${DIR}/etc/ +cp -pr rootcheck/db/*.txt ${DIR}/etc/shared/ +chown root:${GROUP} ${DIR}/etc/decoder.xml +chown root:${GROUP} ${DIR}/etc/local_decoder.xml >/dev/null 2>&1 +chown root:${GROUP} ${DIR}/etc/internal_options.conf +chown root:${GROUP} ${DIR}/etc/local_internal_options.conf >/dev/null 2>&1 +chown root:${GROUP} ${DIR}/etc/client.keys >/dev/null 2>&1 +chown root:${GROUP} ${DIR}/etc/shared/* +chown root:${GROUP} ${DIR}/agentless/* +chown ${USER}:${GROUP} ${DIR}/.ssh +chmod 440 ${DIR}/etc/decoder.xml +chmod 440 ${DIR}/etc/local_decoder.xml >/dev/null 2>&1 +chmod 440 ${DIR}/etc/internal_options.conf +chmod 440 ${DIR}/etc/local_internal_options.conf >/dev/null 2>&1 +chmod 440 ${DIR}/etc/client.keys >/dev/null 2>&1 +chmod 550 ${DIR}/etc +chmod 770 ${DIR}/etc/shared +chmod 440 ${DIR}/etc/shared/* +chmod 550 ${DIR}/agentless/* +rm ${DIR}/etc/shared/merged.mg >/dev/null 2>&1 +chmod 700 ${DIR}/.ssh + + +# Copying active response modules +sh ./init/fw-check.sh execute > /dev/null +cp -p ../active-response/*.sh ${DIR}/active-response/bin/ +cp -p ../active-response/firewalls/*.sh ${DIR}/active-response/bin/ + +chmod 755 ${DIR}/active-response/bin/* +chown root:${GROUP} ${DIR}/active-response/bin/* + +chown root:${GROUP} ${DIR}/bin/* +chmod 550 ${DIR}/bin/* + + +# Moving the config file +ls ${DIR}/etc/ossec.conf > /dev/null 2>&1 +if [ $? = 0 ]; then + exit 0; +fi + +ls ../etc/ossec.mc > /dev/null 2>&1 +if [ $? = 0 ]; then + cp -pr ../etc/ossec.mc ${DIR}/etc/ossec.conf +else + cp -pr ../etc/ossec-server.conf ${DIR}/etc/ossec.conf +fi +chown root:${GROUP} ${DIR}/etc/ossec.conf +chmod 440 ${DIR}/etc/ossec.conf + + + +exit 0; + +#EOF diff --git a/src/LOCATION b/src/LOCATION new file mode 100755 index 0000000..4145da3 --- /dev/null +++ b/src/LOCATION @@ -0,0 +1,2 @@ +DIR="/var/ossec" +CC=gcc diff --git a/src/Makeall b/src/Makeall new file mode 100755 index 0000000..f129cb4 --- /dev/null +++ b/src/Makeall @@ -0,0 +1,232 @@ +#!/bin/sh + +# Make clean? +ARGV=$1 + +# Checking argument +if [ "X${ARGV}" = "X" ]; then + echo "" + echo "No argument. Available options are:" + echo " $0 clean" + echo " $0 all" + echo " $0 build" + echo " $0 libs" + echo " $0 rootcheck" + echo "" + exit 1; +fi + +# Increasing maximum number of agents +if [ "X$1" = "Xsetmaxagents" ]; then + echo -n "Specify maximum number of agents: "; + read AGMAX + echo "HEXTRA=-DMAX_AGENTS=$AGMAX" >> ./Config.OS + echo "Maximum number of agents set to $AGMAX." + exit 0; +fi + + +ZLIBV="external/zlib-1.2.3/" + +# CPU information +#CPU=`uname -p` +MACH=`uname -m` +OS=`uname` +VERSION=`cat ./VERSION` + +MSG="" +# Libraries. They need to be compiled before. +LIBS="os_xml os_regex os_net os_crypto" +# Shares sources +SOURCES="shared config" +# Binaries +BINARIES="os_maild os_dbd os_csyslogd agentlessd os_execd analysisd logcollector remoted client-agent addagent util rootcheck syscheckd monitord" +ROOTCHECKBIN="rootcheck" +DIRECTORIES="" # Directories to make + + +# Setting SunOS path +if [ "X$OS" = "XSunOS" ]; then + PATH=$PATH:/usr/ccs/bin:/usr/xpg4/bin:/opt/csw/gcc3/bin:/opt/csw/bin:/usr/sfw/bin + export PATH +fi + + +# Cleaning Config.OS +if [ "X${ARGV}" = "Xall" -o "X${ARGV}" = "Xrootcheck" -o "X${ARGV}" = "Xlibs" ]; then + ls ./Config.OS >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "" > Config.OS + fi + + # Checking for OpenSSLconf.h + ls /usr/include/openssl/opensslconf.h > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "DEXTRA=-DUSE_OPENSSL" >> Config.OS + fi + + # Checking for inotify + if [ "X$OS" = "XLinux" ]; then + ls /usr/include/sys/inotify.h > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "EEXTRA=-DUSEINOTIFY" >> Config.OS + fi + + fi + + if [ "X$OS" = "XAIX" ]; then + echo "EEXTRA=-DAIX -DHIGHFIRST" >> Config.OS + PATH=$PATH:/usr/vac/bin + export PATH + + elif [ "X$OS" = "XSunOS" ]; then + # Set CPU optimization for Sun UltraSparc + # by Eric Straavaldsen + # Disabled by default. To enable it, just uncomment the following + # lines and comment the EEXTRA below. + #PROC=`isainfo -n` + #if [ $PROC = sparcv9 ]; then + # echo "EEXTRA=-lsocket -lnsl -lresolv -DSOLARIS -DHIGHFIRST -O3 -mcpu=ultrasparc">>Config.OS + #fi + echo "EEXTRA=-DSOLARIS -DHIGHFIRST">>Config.OS + echo "IEXTRA=-lsocket -lnsl -lresolv" >> Config.OS + + elif [ "X$OS" = "XHP-UX" ]; then + echo "EEXTRA=-DHPUX -D_XOPEN_SOURCE_EXTENDED -DHIGHFIRST -D_REENTRANT" >> Config.OS + + elif [ "X$OS" = "XDarwin" ]; then + echo "EEXTRA=-DDarwin -DHIGHFIRST" >> Config.OS + + else + + echo 'int main() { short one = 1; char *cp = (char*)&one; if ( *cp == 0 ) return(1); else return(0); }' > isbigendian.c + gcc -o isbigendian isbigendian.c + ./isbigendian + if [ $? = 1 ]; then + echo "INFO: Big endian set." + echo "GEXTRA=-DHIGHFIRST" >> Config.OS + else + echo "INFO: Little endian set." + fi + fi + + + if [ "X$OS" = "XFreeBSD" -o "X$OS" = "XDragonFly" ]; then + echo "TEXTRA=-pthread" >> Config.OS + else + echo "TEXTRA=-lpthread" >> Config.OS + fi +fi + + +# Cleaning +if [ "X${ARGV}" = "Xclean" ]; then + echo "" > ./Config.OS +fi + + +# Getting values for each action +if [ "X${ARGV}" = "Xall" ]; then + DIRECTORIES="${LIBS} ${SOURCES} ${BINARIES}" + DOZLIB="x" +elif [ "X${ARGV}" = "Xlibs" ]; then + DIRECTORIES="${LIBS} ${SOURCES}" + DOZLIB="x" +elif [ "X${ARGV}" = "Xrootcheck" ]; then + DIRECTORIES="os_xml os_regex os_net ${SOURCES} ${ROOTCHECKBIN}" +elif [ "X${ARGV}" = "Xbuild" ]; then + DIRECTORIES="${BINARIES}" # Only binaries need to be built +else + DIRECTORIES="${LIBS} ${SOURCES} ${BINARIES}" +fi + + +if [ "X${DOZLIB}" = "Xx" ]; then + # Build zlib here + echo "" + echo " *** Making zlib (by Jean-loup Gailly and Mark Adler) *** " + cd ${ZLIBV}; make; make ossec; + cd ../../ + echo "" +fi + + +if [ "X${ARGV}" = "Xclean" ]; then + # Cleaning zlib + cd ${ZLIBV}; make clean; + cd ../../ +fi + + +# Checking if the bin directory is present +if [ ! "X${ARGV}" = "Xrootcheck" ]; then + ls ../bin >/dev/null 2>&1 + if [ $? != 0 ]; then + mkdir -p ../bin + fi +else + echo "Compiling Rootcheck..." + echo "" +fi + + + +# Making each directory +for i in ${DIRECTORIES}; do + cd $i + if [ $? != 0 ]; then + echo "" + echo "Error acessing directory $i" + exit 1; + fi + if [ "X${ARGV}" = "Xclean" ]; then + echo "Entering $i" + make clean + elif [ "X${ARGV}" = "Xbuild" ]; then + make build + if [ $? != 0 ]; then + echo "" + echo "Error Making the binaries" + exit 1; + fi + elif [ "X${ARGV}" = "Xrootcheck" ]; then + echo "Making $i" + if [ $i = "rootcheck" ]; then + make binary + else + make + fi + if [ $? != 0 ]; then + echo "" + echo "Error Making $i" + exit 1; + fi + else + echo "" + echo "" + echo " *** Making $i *** " + echo "" + make + if [ $? != 0 ]; then + echo "" + echo "Error Making $i" + exit 1; + fi + fi + cd ../ +done + + +if [ "X${ARGV}" = "Xrootcheck" ]; then + cp -pr ./rootcheck/ossec-rootcheck ../ + cp -pr ./rootcheck/db ../ + cp -pr ./rootcheck/rootcheck.conf ../ + echo "" + echo "Rootcheck compilation completed." + echo "Just run './ossec-rootcheck' to execute it." + echo "" +fi + + +exit 0; +# EOF # diff --git a/src/Makefile b/src/Makefile new file mode 100755 index 0000000..e971e17 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,58 @@ +# Makefile +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +none: + @echo "Nothing selected ..." + @echo "\"make all\" to compile everything." + @echo "\"make server\" to build the server." + @echo "\"make local\" to build the local." + @echo "\"make agent\" to build the agent." + @echo "\"make libs\" to build the libraries only." + @echo "\"make clean\" to clean anything built." + @echo "\"make setagent\" to set agent install." + @echo "\"make setlocal\" to set local install." + @echo "\"make setprelude\" to enable prelude output." + @echo "\"make setdb\" to enable database support." + @echo "\"make unsetdb\" to disable database support." + +clean: + @/bin/sh ./Makeall clean + rm -f ../bin/ossec* + rm -f ../bin/manage_agents + +all: + @/bin/sh ./Makeall all + +build: + @/bin/sh ./Makeall build + +libs: + @/bin/sh ./Makeall libs + +server: + @/bin/sh ./InstallServer.sh + +local: + @/bin/sh ./InstallServer.sh local + +agent: + @/bin/sh ./InstallAgent.sh + +setagent: + @echo "CEXTRA=-DCLIENT" >> ./Config.OS + +setprelude: + @echo "CPRELUDE=-DPRELUDE -lprelude `libprelude-config --pthread-cflags` `libprelude-config --libs`" >> ./Config.OS + +setdb: + @cd ./os_dbd; echo "CDB=`./dbmake.sh`" >> ../Config.OS; +setmaxagents: + @/bin/sh ./Makeall setmaxagents +unsetdb: + @echo "CDB=" >> ./Config.OS; +setlocal: + @echo "CEXTRA=-DLOCAL" >> ./Config.OS + +setfullsubject: + @echo "FEXTRA=-DCLEANFULL" >> ./Config.OS diff --git a/src/VERSION b/src/VERSION new file mode 100755 index 0000000..e70ef1d --- /dev/null +++ b/src/VERSION @@ -0,0 +1 @@ +v2.3 diff --git a/src/addagent/Makefile b/src/addagent/Makefile new file mode 100755 index 0000000..b5c7c00 --- /dev/null +++ b/src/addagent/Makefile @@ -0,0 +1,18 @@ +# Makefile for addagent /manage_agents +# Daniel B. Cid +# http://www.ossec.net + +NAME=manage_agents +PT=../ + +include $(PT)Config.Make + +OBJS = ${OS_SHARED} ${OS_REGEX} ${OS_ZLIB} ${OS_CRYPTO} ${OS_NET} + +handler: + $(CC) $(CFLAGS) ${OS_LINK} *.c $(OBJS) -o manage_agents +clean: + $(CLEAN) manage_agents +build: + ${BUILD} + cp -pr manage_agents ${PT}../bin diff --git a/src/addagent/b64.c b/src/addagent/b64.c new file mode 100755 index 0000000..754e891 --- /dev/null +++ b/src/addagent/b64.c @@ -0,0 +1,268 @@ +/* @(#) $Id: b64.c,v 1.2 2006/06/21 00:18:21 dcid Exp $ */ +/* + * Copyright (C), 2000-2004 by the monit project group. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +char *decode_base64(const char *src); +char *encode_base64(int size, char *src); + +/* Private prototypes */ +static int is_base64(char c); +static char encode(unsigned char u); +static unsigned char decode(char c); + + +/** + * Implementation of base64 encoding/decoding. + * + * @author Jan-Henrik Haukeland, + * + * @version \$Id: b64.c,v 1.2 2006/06/21 00:18:21 dcid Exp $ + * + * @file + */ + + + +/** + * Base64 encode and return size data in 'src'. The caller must free the + * returned string. + * @param size The size of the data in src + * @param src The data to be base64 encode + * @return encoded string otherwise NULL + */ +char *encode_base64(int size, char *src) { + + int i; + char *out, *p; + + if(!src) + return NULL; + + if(!size) + size= strlen((char *)src); + + out = (char *)calloc(sizeof(char), size*4/3+4); + if(!out) + return NULL; + + p = out; + + for(i = 0; i < size; i+=3) { + + unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0; + + b1 = src[i]; + + if(i+1>2; + b5= ((b1&0x3)<<4)|(b2>>4); + b6= ((b2&0xf)<<2)|(b3>>6); + b7= b3&0x3f; + + *p++= encode(b4); + *p++= encode(b5); + + if(i+1>4) ); + + if(c3 != '=') { + *p++=(((b2&0xf)<<4)|(b3>>2) ); + } + + if(c4 != '=') { + *p++=(((b3&0x3)<<6)|b4 ); + } + + } + + free(buf); + + /*return(p-dest); */ + return(dest); + + } + + return(NULL); + +} + + + /* ----------------------------------------------------------------- Private */ + +static char encode(unsigned char u) { + + if(u < 26) return 'A'+u; + if(u < 52) return 'a'+(u-26); + if(u < 62) return '0'+(u-52); + if(u == 62) return '+'; + + return '/'; + +} + + +/** + * Decode a base64 character + */ +static unsigned char decode(char c) { + + if(c >= 'A' && c <= 'Z') return(c - 'A'); + if(c >= 'a' && c <= 'z') return(c - 'a' + 26); + if(c >= '0' && c <= '9') return(c - '0' + 52); + if(c == '+') return 62; + + return 63; + +} + + +/** + * Return TRUE if 'c' is a valid base64 character, otherwise FALSE + */ +static int is_base64(char c) { + + if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || (c == '+') || + (c == '/') || (c == '=')) { + + return TRUE; + + } + + return FALSE; + +} + + +/* +int main(int argc, char **argv) +{ + char *s; + char *d; + + if(argc < 2) + { + printf("%s string\n",argv[0]); + exit(1); + } + s = encode_base64(strlen(argv[1]), argv[1]); + + printf("b64:\n%s\n",s); + + + d = decode_base64(s); + printf("decode:%s\n",d); + + exit(0); +} + +*/ + + +/* EOF */ diff --git a/src/addagent/main.c b/src/addagent/main.c new file mode 100755 index 0000000..334932d --- /dev/null +++ b/src/addagent/main.c @@ -0,0 +1,246 @@ +/* @(#) $Id: main.c,v 1.15 2009/08/05 18:02:13 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "manage_agents.h" + + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: Manage agents.\n", ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-V Display OSSEC version.\n"); + printf("\t-l List available agents.\n"); + printf("\t-e Extracts key for an agent (Manager only).\n"); + printf("\t-i Import authentication key (Agent only).\n\n"); + exit(1); +} + + +/* print banner */ +void print_banner() +{ + printf("\n"); + printf(BANNER, __name, __version); + + #ifdef CLIENT + printf(BANNER_CLIENT); + #else + printf(BANNER_OPT); + #endif + + return; +} + + +/* Clean shutdown on kill */ +void manage_shutdown() +{ + /* Checking if restart message is necessary */ + if(restart_necessary) + { + printf(MUST_RESTART); + } + else + { + printf("\n"); + } + printf(EXIT); + + exit(0); +} + + +/** main **/ +int main(int argc, char **argv) +{ + char *user_msg; + + int c = 0, cmdlist = 0; + char *cmdexport = NULL; + char *cmdimport = NULL; + + #ifndef WIN32 + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + int gid; + #endif + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vhle:i:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + helpmsg(); + break; + case 'd': + nowDebug(); + break; + case 'e': + #ifdef CLIENT + ErrorExit("%s: You can't export keys on an agent", ARGV0); + #endif + if(!optarg) + ErrorExit("%s: -e needs an argument",ARGV0); + cmdexport = optarg; + break; + case 'i': + #ifndef CLIENT + ErrorExit("%s: You can't import keys on the manager.", ARGV0); + #endif + if(!optarg) + ErrorExit("%s: -i needs an argument",ARGV0); + cmdimport = optarg; + break; + case 'l': + cmdlist = 1; + break; + default: + helpmsg(); + break; + } + + } + + + + /* Getting currently time */ + time1 = time(0); + restart_necessary = 0; + + + #ifndef WIN32 + /* Getting the group name */ + gid = Privsep_GetGroup(group); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, "", group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR, ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Starting signal handler */ + StartSIG2(ARGV0, manage_shutdown); + #endif + + + if(cmdlist == 1) + { + list_agents(cmdlist); + exit(0); + } + else if(cmdimport) + { + k_import(cmdimport); + exit(0); + } + else if(cmdexport) + { + k_extract(cmdexport); + exit(0); + } + + + + /* Little shell */ + while(1) + { + int leave_s = 0; + print_banner(); + + user_msg = read_from_user(); + + /* All the allowed actions */ + switch(user_msg[0]) + { + case 'A': + case 'a': + add_agent(); + break; + case 'e': + case 'E': + k_extract(NULL); + break; + case 'i': + case 'I': + k_import(NULL); + break; + case 'l': + case 'L': + list_agents(0); + break; + case 'r': + case 'R': + remove_agent(); + break; + case 'q': + case 'Q': + leave_s = 1; + break; + case 'V': + print_version(); + break; + default: + printf("\n ** Invalid Action ** \n\n"); + break; + } + + if(leave_s) + { + break; + } + + continue; + + } + + /* Checking if restart message is necessary */ + if(restart_necessary) + { + printf(MUST_RESTART); + } + else + { + printf("\n"); + } + printf(EXIT); + + return(0); +} + + +/* EOF */ diff --git a/src/addagent/manage_agents.c b/src/addagent/manage_agents.c new file mode 100755 index 0000000..f9b7ba9 --- /dev/null +++ b/src/addagent/manage_agents.c @@ -0,0 +1,405 @@ +/* @(#) $Id: manage_agents.c,v 1.33 2009/08/19 18:35:57 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Manage agents tool + * Add/extract and remove agents from a server. + */ + + +#include "manage_agents.h" +#include "os_crypto/md5/md5_op.h" + + + +/* Global internal variables */ + + + +/* chomp: remove spaces, new lines, etc from a string */ +char *chomp(char *str) +{ + char *tmp_str; + int size = 0; + + /* Removing spaces from the beginning */ + while(*str == ' ' || *str == '\t') + str++; + + + /* Removing any trailing new lines or \r */ + do + { + tmp_str = strchr(str, '\n'); + if(tmp_str) + { + *tmp_str = '\0'; + continue; + } + + tmp_str = strchr(str, '\r'); + if(tmp_str) + { + *tmp_str = '\0'; + } + }while(tmp_str != NULL); + + + /* Removing spaces at the end of the string */ + tmp_str = str; + size = strlen(str)-1; + + while((size >= 0) && (tmp_str[size] == ' ' || tmp_str[size] == '\t')) + { + tmp_str[size] = '\0'; + size--; + } + + return(str); +} + + + +/* Add an agent */ +int add_agent() +{ + int i = 1; + FILE *fp; + char str1[STR_SIZE +1]; + char str2[STR_SIZE +1]; + + os_md5 md1; + os_md5 md2; + + char *user_input; + char *_name; + char *_id; + char *_ip; + + char name[FILE_SIZE +1]; + char id[FILE_SIZE +1]; + char ip[FILE_SIZE +1]; + os_ip *c_ip; + + + /* Checking if we can open the auth_file */ + fp = fopen(AUTH_FILE,"a"); + if(!fp) + { + ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE); + } + fclose(fp); + + + /* Allocating for c_ip */ + os_calloc(1, sizeof(os_ip), c_ip); + + + #ifndef WIN32 + chmod(AUTH_FILE, 0440); + #endif + + /* Setting time 2 */ + time2 = time(0); + + + /* Source is time1+ time2 +pid + ppid */ + #ifndef WIN32 + #ifdef __OpenBSD__ + srandomdev(); + #else + srandom(time2 + time1 + getpid() + getppid()); + #endif + #else + srandom(time2 + time1 + getpid()); + #endif + + rand1 = random(); + + + /* Zeroing strings */ + memset(str1,'\0', STR_SIZE +1); + memset(str2,'\0', STR_SIZE +1); + + + printf(ADD_NEW); + + + /* Getting the name */ + memset(name, '\0', FILE_SIZE +1); + + do + { + printf(ADD_NAME); + fflush(stdout); + _name = read_from_user(); + + if(strcmp(_name, QUIT) == 0) + return(0); + + strncpy(name, _name, FILE_SIZE -1); + + /* check the name */ + if(!OS_IsValidName(name)) + printf(INVALID_NAME,name); + + /* Search for name -- no duplicates */ + if(NameExist(name)) + printf(ADD_ERROR_NAME, name); + + } while(NameExist(name) || !OS_IsValidName(name)); + + + /* Getting IP */ + memset(ip, '\0', FILE_SIZE +1); + + do + { + printf(ADD_IP); + fflush(stdout); + + _ip = read_from_user(); + + /* quit */ + if(strcmp(_ip, QUIT) == 0) + return(0); + + strncpy(ip, _ip, FILE_SIZE -1); + + if(!OS_IsValidIP(ip, c_ip)) + { + printf(IP_ERROR, ip); + _ip = NULL; + } + + } while(!_ip); + + + do + { + /* Default ID */ + i = 1024; + snprintf(id, 8, "%03d", i); + while(!IDExist(id)) + { + i--; + snprintf(id, 8, "%03d", i); + + /* No key present, use id 0 */ + if(i <= 0) + { + i = 0; + break; + } + } + snprintf(id, 8, "%03d", i+1); + + /* Getting ID */ + printf(ADD_ID, id); + fflush(stdout); + + _id = read_from_user(); + + + + /* quit */ + if(strcmp(_id, QUIT) == 0) + return(0); + + + if(_id[0] != '\0') + { + strncpy(id, _id, FILE_SIZE -1); + } + + if(!OS_IsValidID(id)) + printf(INVALID_ID, id); + + /* Search for ID KEY -- no duplicates */ + if(IDExist(id)) + printf(ADD_ERROR_ID, id); + + } while(IDExist(id) || !OS_IsValidID(id)); + + + + printf(AGENT_INFO, id, name, ip); + fflush(stdout); + + do + { + printf(ADD_CONFIRM); + user_input = read_from_user(); + + /* If user accepts to add */ + if(user_input[0] == 'y' || user_input[0] == 'Y') + { + time3 = time(0); + rand2 = random(); + + fp = fopen(AUTH_FILE,"a"); + if(!fp) + { + ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE); + } + #ifndef WIN32 + chmod(AUTH_FILE, 0440); + #endif + + + /* Random 1: Time took to write the agent information. + * Random 2: Time took to choose the action. + * Random 3: All of this + time + pid + * Random 4: Md5 all of this + the name, key and ip + * Random 5: Final key + */ + + snprintf(str1, STR_SIZE, "%d%s%d",time3-time2, name, rand1); + snprintf(str2, STR_SIZE, "%d%s%s%d", time2-time1, ip, id, rand2); + + OS_MD5_Str(str1, md1); + OS_MD5_Str(str2, md2); + + snprintf(str1, STR_SIZE, "%s%d%d%d",md1,(int)getpid(), (int)random(), + time3); + OS_MD5_Str(str1, md1); + + fprintf(fp,"%s %s %s %s%s\n",id, name, c_ip->ip, md1,md2); + + fclose(fp); + + printf(AGENT_ADD); + restart_necessary = 1; + break; + } + else if(user_input[0] == 'n' || user_input[0] == 'N') + { + printf(ADD_NOT); + break; + } + + } while(1); + + return(0); +} + + +/* remove an agent */ +int remove_agent() +{ + FILE *fp; + char *user_input; + char u_id[FILE_SIZE +1]; + + u_id[FILE_SIZE] = '\0'; + + if(!print_agents(0, 0, 0)) + { + printf(NO_AGENT); + return(0); + } + + do + { + printf(REMOVE_ID); + fflush(stdout); + + user_input = read_from_user(); + + if(strcmp(user_input, QUIT) == 0) + return(0); + + strncpy(u_id, user_input, FILE_SIZE); + + if(!IDExist(user_input)) + { + printf(NO_ID, user_input); + } + } while(!IDExist(user_input)); + + do + { + printf(REMOVE_CONFIRM); + fflush(stdout); + + user_input = read_from_user(); + + /* If user confirm */ + if(user_input[0] == 'y' || user_input[0] == 'Y') + { + /* Getting full agent name */ + char *full_name = getFullnameById(u_id); + if(!full_name) + { + ErrorExit(MEM_ERROR, ARGV0); + } + + fp = fopen(AUTH_FILE, "r+"); + if(!fp) + { + free(full_name); + ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE); + } + #ifndef WIN32 + chmod(AUTH_FILE, 0440); + #endif + + + /* Removing the agent, but keeping the id. */ + fsetpos(fp, &fp_pos); + fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id); + + fclose(fp); + + + /* Remove counter for id */ + delete_agentinfo(full_name); + OS_RemoveCounter(u_id); + free(full_name); + full_name = NULL; + + + printf(REMOVE_DONE, u_id); + restart_necessary = 1; + break; + } + else if(user_input[0] == 'n' || user_input[0] == 'N') + { + printf(REMOVE_NOT); + break; + } + + } while(1); + + return(0); +} + + +int list_agents(int cmdlist) +{ + if(!print_agents(0, 0, 0)) + printf(NO_AGENT); + + printf("\n"); + if(!cmdlist) + { + printf(PRESS_ENTER); + read_from_user(); + } + + return(0); + +} + +/* EOF */ diff --git a/src/addagent/manage_agents.h b/src/addagent/manage_agents.h new file mode 100755 index 0000000..54e9e97 --- /dev/null +++ b/src/addagent/manage_agents.h @@ -0,0 +1,140 @@ +/* @(#) $Id: manage_agents.h,v 1.20 2009/08/05 18:02:13 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "sec.h" + + +/** Prototypes **/ + +/* Read any input from the user (stdin) */ +char *read_from_user(); + +/* Add or remove an agent */ +int add_agent(); +int remove_agent(); + +/* Extract or import a key */ +int k_extract(char *cmdextract); +int k_import(char *cmdimport); + +/* Validation functions */ +int OS_IsValidName(char *u_name); +int OS_IsValidID(char *id); +int IDExist(char *id); +int NameExist(char *u_name); +char *getFullnameById(char *id); + + +/* Print available agents */ +int print_agents(int print_status, int active_only, int csv_output); +int list_agents(int cmdlist); + +/* clear a line */ +char *chomp(char *str); + + +/* Shared variables */ +int restart_necessary; +int time1; +int time2; +int time3; +int rand1; +int rand2; +fpos_t fp_pos; + + +/* Internal defines */ +#define USER_SIZE 514 +#define FILE_SIZE 257 +#define STR_SIZE 66 + +/* Internal strings */ +#define QUIT "\\q" + +/* Print agents */ +#define PRINT_AVAILABLE "\nAvailable agents: \n" +#define PRINT_AGENT " ID: %s, Name: %s, IP: %s\n" +#define PRINT_AGENT_STATUS " ID: %s, Name: %s, IP: %s, %s\n" + + +/* Add new agent */ +#define ADD_NEW "\n- Adding a new agent"\ + " (use '\\q' to return to the main menu).\n"\ + " Please provide the following:\n" +#define ADD_NAME " * A name for the new agent: " +#define ADD_IP " * The IP Address of the new agent: " +#define ADD_ID " * An ID for the new agent[%s]: " +#define AGENT_INFO "Agent information:\n ID:%s\n Name:%s\n " \ + "IP Address:%s\n\n" +#define ADD_CONFIRM "Confirm adding it?(y/n): " +#define AGENT_ADD "Agent added.\n" +#define ADDED "Added.\n" +#define ADD_NOT "Not Adding ..\n" +#define PRESS_ENTER "** Press ENTER to return to the main menu.\n" +#define MUST_RESTART "\n** You must restart the server for your changes" \ + " to have effect.\n\n" + +/* Add errors */ +#define ADD_ERROR_ID "\n** ID '%s' already present. They must be unique.\n\n" +#define ADD_ERROR_NAME "\n** Name '%s' already present. Please enter a new name.\n\n" +#define IP_ERROR "\n** Invalid IP '%s'. Please enter a valid IP Address.\n\n" +#define NO_AGENT "\n** No agent available. You need to add one first.\n" +#define NO_ID "\n** Invalid ID '%s' given. ID is not present.\n" +#define NO_KEY "\n** Invalid authentication key. Starting over again.\n" +#define INVALID_ID "\n** Invalid ID '%s' given. ID must be numeric (max 5 digits).\n\n" +#define INVALID_NAME "\n** Invalid name '%s' given. Name must contain only alphanumeric characters (min=2, max=32).\n\n" + +/* Remove agent */ +#define REMOVE_ID "Provide the ID of the agent to be removed (or '\\q' to quit): " +#define REMOVE_CONFIRM "Confirm deleting it?(y/n): " +#define REMOVE_DONE "Agent '%s' removed.\n" +#define REMOVE_NOT "Not removing ..\n" + +/* Import agent */ +#define IMPORT_KEY "\n* Provide the Key generated by the server.\n" \ + "* The best approach is to cut and paste it.\n" \ + "*** OBS: Do not include spaces or new lines.\n\n" \ + "Paste it here (or '\\q' to quit): " + +/* extract key */ +#define EXTRACT_KEY "Provide the ID of the agent to extract " \ + "the key (or '\\q' to quit): " +#define EXTRACT_MSG "\nAgent key information for '%s' is: \n%s\n" + + +/* Commom errors */ +#define ERROR_KEYS "Unable to handle keys file. Exiting.\n" +#define EXTRACT_ERROR "Unable to extract agent key.\n" +#define INPUT_LARGE ARGV0 ": Input too large. Not adding it.\n" +#define EXIT ARGV0 ": Exiting ..\n" + +#define BANNER "\n****************************************" \ + "\n* %s %s Agent manager. *" \ + "\n* The following options are available: *" \ + "\n****************************************\n" + +#define BANNER_OPT " (A)dd an agent (A).\n" \ + " (E)xtract key for an agent (E).\n" \ + " (L)ist already added agents (L).\n" \ + " (R)emove an agent (R).\n" \ + " (Q)uit.\n" \ + "Choose your action: A,E,L,R or Q: " + +#define BANNER_CLIENT " (I)mport key from the server (I).\n" \ + " (Q)uit.\n" \ + "Choose your action: I or Q: " + +/* EOF */ diff --git a/src/addagent/manage_keys.c b/src/addagent/manage_keys.c new file mode 100755 index 0000000..bc2bb02 --- /dev/null +++ b/src/addagent/manage_keys.c @@ -0,0 +1,227 @@ +/* @(#) $Id: manage_keys.c,v 1.20 2009/08/05 18:02:13 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "manage_agents.h" + + +/* b64 function prototypes */ +char *decode_base64(const char *src); +char *encode_base64(int size, char *src); + + +/* Import a key */ +int k_import(char *cmdimport) +{ + FILE *fp; + char *user_input; + char *b64_dec; + + char *name; char *ip; char *tmp_key; + + char line_read[FILE_SIZE +1]; + + + /* Parsing user argument. */ + if(cmdimport) + { + user_input = cmdimport; + } + else + { + printf(IMPORT_KEY); + + user_input = read_from_user(); + } + + + /* quit */ + if(strcmp(user_input, QUIT) == 0) + return(0); + + b64_dec = decode_base64(user_input); + if(b64_dec == NULL) + { + printf(NO_KEY); + printf(PRESS_ENTER); + read_from_user(); + return(0); + } + + + memset(line_read, '\0', FILE_SIZE +1); + strncpy(line_read, b64_dec, FILE_SIZE); + + + name = strchr(b64_dec, ' '); + if(name && strlen(line_read) < FILE_SIZE) + { + *name = '\0'; + name++; + ip = strchr(name, ' '); + if(ip) + { + *ip = '\0'; + ip++; + + tmp_key = strchr(ip, ' '); + if(!tmp_key) + { + printf(NO_KEY); + return(0); + } + *tmp_key = '\0'; + + printf("\n"); + printf(AGENT_INFO, b64_dec, name, ip); + + while(1) + { + printf(ADD_CONFIRM); + fflush(stdout); + + user_input = read_from_user(); + + if(user_input[0] == 'y' || user_input[0] == 'Y') + { + fp = fopen(KEYS_FILE,"w"); + if(!fp) + { + ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE); + } + fprintf(fp,"%s\n",line_read); + fclose(fp); + #ifndef WIN32 + chmod(KEYS_FILE, 0440); + #endif + + /* Removing sender counter. */ + OS_RemoveCounter("sender"); + + printf(ADDED); + printf(PRESS_ENTER); + read_from_user(); + restart_necessary = 1; + return(1); + } + else if(user_input[0] == 'n' || user_input[0] == 'N') + { + printf("%s", ADD_NOT); + return(0); + } + } + } + } + + printf(NO_KEY); + printf(PRESS_ENTER); + read_from_user(); + return(0); + +} + + +/* extract base64 for a specific agent */ +int k_extract(char *cmdextract) +{ + FILE *fp; + char *user_input; + char *b64_enc; + char line_read[FILE_SIZE +1]; + char n_id[USER_SIZE +1]; + + + if(cmdextract) + { + user_input = cmdextract; + + if(!IDExist(user_input)) + { + printf(NO_ID, user_input); + exit(1); + } + } + + else + { + if(!print_agents(0, 0, 0)) + { + printf(NO_AGENT); + printf(PRESS_ENTER); + read_from_user(); + return(0); + } + + do + { + printf(EXTRACT_KEY); + fflush(stdout); + user_input = read_from_user(); + + /* quit */ + if(strcmp(user_input, QUIT) == 0) + return(0); + + if(!IDExist(user_input)) + printf(NO_ID, user_input); + + } while(!IDExist(user_input)); + } + + + /* Trying to open the auth file */ + fp = fopen(AUTH_FILE, "r"); + if(!fp) + { + ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE); + } + + fsetpos(fp, &fp_pos); + + memset(n_id, '\0', USER_SIZE +1); + strncpy(n_id, user_input, USER_SIZE -1); + + + if(fgets(line_read, FILE_SIZE, fp) == NULL) + { + printf(ERROR_KEYS); + fclose(fp); + exit(1); + } + chomp(line_read); + + + b64_enc = encode_base64(strlen(line_read),line_read); + if(b64_enc == NULL) + { + printf(EXTRACT_ERROR); + fclose(fp); + exit(1); + } + + printf(EXTRACT_MSG, n_id, b64_enc); + if(!cmdextract) + { + printf("\n" PRESS_ENTER); + read_from_user(); + } + + free(b64_enc); + fclose(fp); + + return(0); +} + + +/* EOF */ diff --git a/src/addagent/read_from_user.c b/src/addagent/read_from_user.c new file mode 100755 index 0000000..9b84c76 --- /dev/null +++ b/src/addagent/read_from_user.c @@ -0,0 +1,38 @@ +/* @(#) $Id: read_from_user.c,v 1.6 2009/06/24 17:06:20 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "manage_agents.h" + +char __user_buffer[USER_SIZE +1]; +char *__user_buffer_pt; + + +/** read_from_user **/ +char *read_from_user() +{ + memset(__user_buffer, '\0', USER_SIZE +1); + + if((fgets(__user_buffer, USER_SIZE -1, stdin) == NULL) || + (strlen(__user_buffer) >= (USER_SIZE -2))) + { + printf(INPUT_LARGE); + exit(1); + } + + __user_buffer_pt = chomp(__user_buffer); + + return(__user_buffer_pt); +} + + +/* EOF */ diff --git a/src/addagent/validate.c b/src/addagent/validate.c new file mode 100755 index 0000000..91c48f6 --- /dev/null +++ b/src/addagent/validate.c @@ -0,0 +1,387 @@ +/* @(#) $Id: validate.c,v 1.19 2009/06/24 17:06:20 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "manage_agents.h" + + +int OS_IsValidID(char *id) +{ + int id_len = 0; + int i = 0; + + /* ID must not be null */ + if(!id) + return(0); + + id_len = strlen(id); + + /* Check ID length, it should contain max. 5 characters */ + if (id_len > 8) + return(0); + + /* Check ID if it contains only numeric characters [0-9] */ + for(i = 0; i < id_len; i++) + { + if(!(isdigit((int)id[i]))) + return(0); + } + + return(1); +} + + +/* Get full agent name (name + ip) of ID. + */ +char *getFullnameById(char *id) +{ + FILE *fp; + char line_read[FILE_SIZE +1]; + line_read[FILE_SIZE] = '\0'; + + /* ID must not be null */ + if(!id) + return(NULL); + + fp = fopen(AUTH_FILE, "r"); + if(!fp) + return(NULL); + + + while(fgets(line_read, FILE_SIZE -1, fp) != NULL) + { + char *name; + char *ip; + char *tmp_str; + + if(line_read[0] == '#') + { + continue; + } + + name = strchr(line_read, ' '); + if(name) + { + *name = '\0'; + /* Didn't match */ + if(strcmp(line_read,id) != 0) + { + continue; + } + + name++; + + /* Removed entry */ + if(*name == '#') + { + continue; + } + + ip = strchr(name, ' '); + if(ip) + { + *ip = '\0'; + ip++; + + /* Cleaning up ip */ + tmp_str = strchr(ip, ' '); + if(tmp_str) + { + char *final_str; + *tmp_str = '\0'; + tmp_str = strchr(ip, '/'); + if(tmp_str) + *tmp_str = '\0'; + + /* If we reached here, we found the IP and name */ + os_calloc(1, FILE_SIZE, final_str); + snprintf(final_str, FILE_SIZE -1, "%s-%s", name, ip); + + fclose(fp); + return(final_str); + } + } + } + } + + fclose(fp); + return(NULL); +} + + +/* ID Search (is valid ID) */ +int IDExist(char *id) +{ + FILE *fp; + char line_read[FILE_SIZE +1]; + line_read[FILE_SIZE] = '\0'; + + /* ID must not be null */ + if(!id) + return(0); + + fp = fopen(AUTH_FILE, "r"); + if(!fp) + return(0); + + fseek(fp, 0, SEEK_SET); + fgetpos(fp, &fp_pos); + + while(fgets(line_read,FILE_SIZE -1, fp) != NULL) + { + char *name; + + if(line_read[0] == '#') + { + fgetpos(fp, &fp_pos); + continue; + } + + name = strchr(line_read, ' '); + if(name) + { + *name = '\0'; + name++; + + if(strcmp(line_read,id) == 0) + { + fclose(fp); + return (1); /*(fp_pos);*/ + } + } + + fgetpos(fp, &fp_pos); + } + + fclose(fp); + return(0); +} + + +/* Validate agent name. + */ +int OS_IsValidName(char *u_name) +{ + int i = 0; + + /* We must have something in the name */ + if(strlen(u_name) < 2 || strlen(u_name) > 128) + return(0); + + /* check if it contains any non-alphanumeric characters */ + for(i = 0; i < strlen(u_name); i++) + { + if(!isalnum((int)u_name[i]) && (u_name[i] != '-') && + (u_name[i] != '_') && (u_name[i] != '.')) + return(0); + } + + return(1); +} + + +/* Is_Name (is valid name) */ +int NameExist(char *u_name) +{ + FILE *fp; + char line_read[FILE_SIZE +1]; + line_read[FILE_SIZE] = '\0'; + + if((!u_name)|| + (*u_name == '\0')|| + (*u_name == '\r')|| + (*u_name == '\n')) + return(0); + + fp = fopen(AUTH_FILE, "r"); + if(!fp) + return(0); + + + fseek(fp, 0, SEEK_SET); + fgetpos(fp, &fp_pos); + + + while(fgets(line_read, FILE_SIZE-1, fp) != NULL) + { + char *name; + + if(line_read[0] == '#') + continue; + + name = strchr(line_read, ' '); + if(name) + { + char *ip; + name++; + + if(*name == '#') + { + continue; + } + + ip = strchr(name, ' '); + if(ip) + { + *ip = '\0'; + if(strcmp(u_name, name) == 0) + { + fclose(fp); + return(1); + } + } + } + fgetpos(fp, &fp_pos); + } + + fclose(fp); + return(0); +} + + +/* print available agents */ +int print_agents(int print_status, int active_only, int csv_output) +{ + int total = 0; + FILE *fp; + char line_read[FILE_SIZE +1]; + line_read[FILE_SIZE] = '\0'; + + fp = fopen(AUTH_FILE, "r"); + if(!fp) + return(0); + + fseek(fp, 0, SEEK_SET); + + memset(line_read,'\0',FILE_SIZE); + + while(fgets(line_read, FILE_SIZE -1, fp) != NULL) + { + char *name; + + if(line_read[0] == '#') + continue; + + name = strchr(line_read, ' '); + if(name) + { + char *ip; + *name = '\0'; + name++; + + + /* Removed agent. */ + if(*name == '#') + { + continue; + } + + ip = strchr(name, ' '); + if(ip) + { + char *key; + *ip = '\0'; + ip++; + key = strchr(ip, ' '); + if(key) + { + *key = '\0'; + if(!total && !print_status) + printf(PRINT_AVAILABLE); + total++; + + + if(print_status) + { + int agt_status = get_agent_status(name, ip); + if(active_only && (agt_status != GA_STATUS_ACTIVE)) + { + continue; + } + + if(csv_output) + { + printf("%s,%s,%s,%s,\n", line_read, name, ip, + print_agent_status(agt_status)); + } + else + { + printf(PRINT_AGENT_STATUS, line_read, name, ip, + print_agent_status(agt_status)); + } + } + else + { + printf(PRINT_AGENT, line_read, name, ip); + } + } + + } + } + } + + + /* Only print agentless for non-active only searches */ + if(!active_only && print_status) + { + char *aip = NULL; + DIR *dirp; + struct dirent *dp; + + if(!csv_output) + { + printf("\nList of agentless devices:\n"); + } + + dirp = opendir(AGENTLESS_ENTRYDIR); + if(dirp) + { + while ((dp = readdir(dirp)) != NULL) + { + if(strncmp(dp->d_name, ".", 1) == 0) + { + continue; + } + + aip = strchr(dp->d_name, '@'); + if(aip) + { + aip++; + } + else + { + aip = ""; + } + + if(csv_output) + { + printf("na,%s,%s,agentless,\n", dp->d_name, aip); + } + else + { + printf(" ID: na, Name: %s, IP: %s, agentless\n", + dp->d_name, aip); + } + } + closedir(dirp); + } + } + + fclose(fp); + if(total) + return(1); + + return(0); +} + + +/* EOF */ diff --git a/src/agentlessd/Makefile b/src/agentlessd/Makefile new file mode 100755 index 0000000..ec4ced7 --- /dev/null +++ b/src/agentlessd/Makefile @@ -0,0 +1,18 @@ +# Makefile for agentlessd +# Daniel B. Cid + +PT=../ +NAME=ossec-agentlessd + +include ../Config.Make + +LOCAL = *.c + +OBJS = ${OS_CONFIG} ${OS_SHARED} ${OS_NET} ${OS_REGEX} ${OS_XML} ${OS_CRYPTO} + +magentless: + ${CC} ${CFLAGS} ${OS_LINK} ${LOCAL} ${OBJS} -o ${NAME} +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/agentlessd/README b/src/agentlessd/README new file mode 100644 index 0000000..463ef24 --- /dev/null +++ b/src/agentlessd/README @@ -0,0 +1,26 @@ +Agentless Daemon. + +It will use the connection type specified in the configuration to access +a remote box and do integrity checking or log analysis. + +The connection types are specified at /var/ossec/agentless . + +Example of config: + + + + + ssh_integrity_check_bsd + 3600 + dcid@127.0.0.1 + periodic + /bin /etc/ /sbin + + + + ssh_integrity_check_linux + 3600 + dcid@192.168.2.15 + periodic + /bin /etc/ /sbin + diff --git a/src/agentlessd/agentlessd.c b/src/agentlessd/agentlessd.c new file mode 100755 index 0000000..6e6bd2e --- /dev/null +++ b/src/agentlessd/agentlessd.c @@ -0,0 +1,538 @@ +/* @(#) $Id: agentlessd.c,v 1.13 2009/06/24 17:06:20 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "os_crypto/md5/md5_op.h" +#include "agentlessd.h" + + + +/* Saves agentless entry for the control tools to gather. */ +int save_agentless_entry(char *host, char *script, char *agttype) +{ + FILE *fp; + char sys_location[1024 +1]; + + sys_location[1024] = '\0'; + snprintf(sys_location, 1024, "%s/(%s) %s", + AGENTLESS_ENTRYDIRPATH, script, host); + + fp = fopen(sys_location, "w"); + if(fp) + { + fprintf(fp, "type: %s\n", agttype); + fclose(fp); + } + else + { + merror(FOPEN_ERROR, ARGV0, sys_location); + } + + return(0); +} + + + +/* send integrity checking message. */ +int send_intcheck_msg(char *script, char *host, char *msg) +{ + char sys_location[1024 +1]; + + sys_location[1024] = '\0'; + snprintf(sys_location, 1024, "(%s) %s->%s", script, host, SYSCHECK); + + if(SendMSG(lessdc.queue, msg, sys_location, SYSCHECK_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + + if((lessdc.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + + /* If we reach here, we can try to send it again */ + SendMSG(lessdc.queue, msg, sys_location, SYSCHECK_MQ); + } + + return(0); +} + + + +/* Generate diffs alerts. */ +int gen_diff_alert(char *host, char *script, int alert_diff_time) +{ + int n = 0; + FILE *fp; + char *tmp_str; + char buf[2048 +1]; + char diff_alert[4096 +1]; + + buf[2048] = '\0'; + diff_alert[4096] = '\0'; + + snprintf(buf, 2048, "%s/%s->%s/diff.%d", + DIFF_DIR_PATH, host, script, alert_diff_time); + + fp = fopen(buf, "r"); + if(!fp) + { + merror("%s: ERROR: Unable to generate diff alert.", ARGV0); + return(0); + } + + n = fread(buf, 1, 2048 -1, fp); + if(n <= 0) + { + merror("%s: ERROR: Unable to generate diff alert (fread).", ARGV0); + fclose(fp); + return(0); + } + else if(n >= 2040) + { + /* We need to clear the last new line. */ + buf[n] = '\0'; + tmp_str = strrchr(buf, '\n'); + if(tmp_str) + *tmp_str = '\0'; + else + { + /* Weird diff with only one large line. */ + buf[256] = '\0'; + } + } + else + { + buf[n] = '\0'; + } + + n = 0; + + + /* Getting up to 8 line changes. */ + tmp_str = buf; + + while(tmp_str && (*tmp_str != '\0')) + { + tmp_str = strchr(tmp_str, '\n'); + if(!tmp_str) + break; + else if(n >= 7) + { + *tmp_str = '\0'; + break; + } + n++; + tmp_str++; + } + + + /* Creating alert. */ + snprintf(diff_alert, 4096 -1, "ossec: agentless: Change detected:\n%s%s", + buf, n>=7? + "\nMore changes..": + ""); + + + snprintf(buf, 1024, "(%s) %s->agentless", script, host); + + if(SendMSG(lessdc.queue, diff_alert, buf, LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + + if((lessdc.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + + /* If we reach here, we can try to send it again */ + SendMSG(lessdc.queue, diff_alert, buf, LOCALFILE_MQ); + } + + save_agentless_entry(host, script, "diff"); + + fclose(fp); + return(0); +} + + + +/* Checks if the file has changed */ +int check_diff_file(char *host, char *script) +{ + int date_of_change; + char old_location[1024 +1]; + char new_location[1024 +1]; + char tmp_location[1024 +1]; + char diff_cmd[2048 +1]; + + os_md5 md5sum_old; + os_md5 md5sum_new; + + old_location[1024] = '\0'; + new_location[1024] = '\0'; + tmp_location[1024] = '\0'; + diff_cmd[2048] = '\0'; + + snprintf(new_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, script, + DIFF_NEW_FILE); + snprintf(old_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, script, + DIFF_LAST_FILE); + + + /* If the file is not there, rename new location to last location. */ + if(OS_MD5_File(old_location, md5sum_old) != 0) + { + if(rename(new_location, old_location) != 0) + { + merror(RENAME_ERROR, ARGV0, new_location); + } + return(0); + } + + /* Get md5sum of the new file. */ + if(OS_MD5_File(new_location, md5sum_new) != 0) + { + merror("%s: ERROR: Invalid internal state (missing '%s').", + ARGV0, new_location); + return(0); + } + + /* If they match, keep the old file and remove the new. */ + if(strcmp(md5sum_new, md5sum_old) == 0) + { + unlink(new_location); + return(0); + } + + + /* Saving the old file at timestamp and renaming new to last. */ + date_of_change = File_DateofChange(old_location); + snprintf(tmp_location, 1024, "%s/%s->%s/state.%d", DIFF_DIR_PATH, host, script, + date_of_change); + rename(old_location, tmp_location); + rename(new_location, old_location); + + + /* Run diff. */ + date_of_change = File_DateofChange(old_location); + snprintf(diff_cmd, 2048, "diff \"%s\" \"%s\" > \"%s/%s->%s/diff.%d\" " + "2>/dev/null", + tmp_location, old_location, + DIFF_DIR_PATH, host, script, date_of_change); + if(system(diff_cmd) != 256) + { + merror("%s: ERROR: Unable to run diff for %s->%s", + ARGV0, host, script); + return(0); + } + + + /* Generate alert. */ + gen_diff_alert(host, script, date_of_change); + + + return(0); +} + + + +/* get the diff file. */ +FILE *open_diff_file(char *host, char *script) +{ + FILE *fp = NULL; + char sys_location[1024 +1]; + + sys_location[1024] = '\0'; + snprintf(sys_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, script, + DIFF_NEW_FILE); + + + fp = fopen(sys_location, "w"); + + /* If we can't open, try creating the directory. */ + if(!fp) + { + snprintf(sys_location, 1024, "%s/%s->%s", DIFF_DIR_PATH, host, script); + if(IsDir(sys_location) == -1) + { + if(mkdir(sys_location, 0770) == -1) + { + merror(MKDIR_ERROR, ARGV0, sys_location); + return(NULL); + } + } + + snprintf(sys_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, + script, DIFF_NEW_FILE); + fp = fopen(sys_location, "w"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, sys_location); + return(NULL); + } + } + + return(fp); +} + + + +/* Run periodic commands. */ +int run_periodic_cmd(agentlessd_entries *entry, int test_it) +{ + int i = 0; + char *tmp_str; + char buf[OS_SIZE_2048 +1]; + char command[OS_SIZE_1024 +1]; + FILE *fp; + FILE *fp_store = NULL; + + + buf[0] = '\0'; + command[0] = '\0'; + command[OS_SIZE_1024] = '\0'; + + + while(entry->server[i]) + { + /* Ignored entry. */ + if(entry->server[i][0] == '\0') + { + i++; + continue; + } + + + /* We only test for the first server entry. */ + else if(test_it) + { + int ret_code = 0; + snprintf(command, OS_SIZE_1024, + "%s/%s test test >/dev/null 2>&1", + AGENTLESSDIRPATH, entry->type); + ret_code = system(command); + + /* Checking if the test worked. */ + if(ret_code != 0) + { + if(ret_code == 32512) + { + merror("%s: ERROR: Expect command not found (or bad " + "arguments) for '%s'.", + ARGV0, entry->type); + } + merror("%s: ERROR: Test failed for '%s' (%d). Ignoring.", + ARGV0, entry->type, ret_code/256); + entry->error_flag = 99; + return(-1); + } + + verbose("%s: INFO: Test passed for '%s'.", ARGV0, entry->type); + return(0); + } + + if(entry->server[i][0] == 's') + { + snprintf(command, OS_SIZE_1024, "%s/%s \"use_su\" \"%s\" %s 2>&1", + AGENTLESSDIRPATH, entry->type, entry->server[i] +1, + entry->options); + } + else if(entry->server[i][0] == 'o') + { + snprintf(command, OS_SIZE_1024, "%s/%s \"use_sudo\" \"%s\" %s 2>&1", + AGENTLESSDIRPATH, entry->type, entry->server[i] +1, + entry->options); + } + else + { + snprintf(command, OS_SIZE_1024, "%s/%s \"%s\" %s 2>&1", + AGENTLESSDIRPATH, entry->type, entry->server[i] +1, + entry->options); + } + + fp = popen(command, "r"); + if(fp) + { + while(fgets(buf, OS_SIZE_2048, fp) != NULL) + { + /* Removing new lines or carriage returns. */ + tmp_str = strchr(buf, '\r'); + if(tmp_str) + *tmp_str = '\0'; + tmp_str = strchr(buf, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + if(strncmp(buf, "ERROR: ", 7) == 0) + { + merror("%s: ERROR: %s: %s: %s", ARGV0, + entry->type, entry->server[i] +1, buf +7); + entry->error_flag++; + break; + } + else if(strncmp(buf, "INFO: ", 6) == 0) + { + verbose("%s: INFO: %s: %s: %s", ARGV0, + entry->type, entry->server[i] +1, buf +6); + } + else if(strncmp(buf, "FWD: ", 4) == 0) + { + tmp_str = buf + 5; + send_intcheck_msg(entry->type, entry->server[i]+1, + tmp_str); + } + else if((entry->state & LESSD_STATE_DIFF) && + (strncmp(buf, "STORE: ", 7) == 0)) + { + fp_store = open_diff_file(entry->server[i]+1, + entry->type); + } + else if(fp_store) + { + fprintf(fp_store, "%s\n", buf); + } + else + { + debug1("%s: DEBUG: buffer: %s", ARGV0, buf); + } + } + + if(fp_store) + { + fclose(fp_store); + fp_store = NULL; + + check_diff_file(entry->server[i] +1, entry->type); + } + else + { + save_agentless_entry(entry->server[i] +1, + entry->type, "syscheck"); + } + pclose(fp); + } + else + { + merror("%s: ERROR: popen failed on '%s' for '%s'.", ARGV0, + entry->type, entry->server[i] +1); + entry->error_flag++; + } + + i++; + } + + if(fp_store) + { + fclose(fp_store); + } + + return(0); +} + + + +/* Main agentlessd */ +void Agentlessd() +{ + time_t tm; + struct tm *p; + + int today = 0; + int thismonth = 0; + int thisyear = 0; + int test_it = 1; + + char str[OS_SIZE_1024 +1]; + + + /* Waiting a few seconds to settle */ + sleep(2); + memset(str, '\0', OS_SIZE_1024 +1); + + + /* Getting currently time before starting */ + tm = time(NULL); + p = localtime(&tm); + + today = p->tm_mday; + thismonth = p->tm_mon; + thisyear = p->tm_year+1900; + + + /* Connecting to the message queue + * Exit if it fails. + */ + if((lessdc.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); + } + + + + /* Main monitor loop */ + while(1) + { + int i = 0; + tm = time(NULL); + p = localtime(&tm); + + + /* Day changed, deal with log files */ + if(today != p->tm_mday) + { + today = p->tm_mday; + thismonth = p->tm_mon; + thisyear = p->tm_year+1900; + } + + + while(lessdc.entries[i]) + { + if(lessdc.entries[i]->error_flag >= 10) + { + if(lessdc.entries[i]->error_flag != 99) + { + merror("%s: ERROR: Too many failures for '%s'. Ignoring it.", + ARGV0, lessdc.entries[i]->type); + lessdc.entries[i]->error_flag = 99; + } + + i++; + sleep(i); + continue; + } + + + /* Run the check again if the frequency has elapsed. */ + if((lessdc.entries[i]->state & LESSD_STATE_PERIODIC) && + ((lessdc.entries[i]->current_state + + lessdc.entries[i]->frequency) < tm)) + { + run_periodic_cmd(lessdc.entries[i], test_it); + if(!test_it) + lessdc.entries[i]->current_state = tm; + } + + i++; + + sleep(i); + } + + /* We only check every minute */ + test_it = 0; + sleep(60); + } +} + +/* EOF */ diff --git a/src/agentlessd/agentlessd.h b/src/agentlessd/agentlessd.h new file mode 100755 index 0000000..3f75bb0 --- /dev/null +++ b/src/agentlessd/agentlessd.h @@ -0,0 +1,32 @@ +/* @(#) $Id: agentlessd.h,v 1.2 2009/06/24 17:06:21 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _AGENTLESSD_H +#define _AGENTLESSD_H + +#include "config/agentlessd-config.h" + +#ifndef ARGV0 + #define ARGV0 "ossec-agentlessd" +#endif + + + +/** Prototypes **/ + +/* Main monitord */ +void Agentlessd(); + + +agentlessd_config lessdc; + +#endif diff --git a/src/agentlessd/main.c b/src/agentlessd/main.c new file mode 100755 index 0000000..71a3daf --- /dev/null +++ b/src/agentlessd/main.c @@ -0,0 +1,156 @@ +/* @(#) $Id: main.c,v 1.3 2009/11/18 19:07:39 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "agentlessd.h" +#include "config/config.h" + + + +int main(int argc, char **argv) +{ + int c, test_config = 0, run_foreground = 0; + int uid=0,gid=0; + char *dir = DEFAULTDIR; + char *user = USER; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTCPATH; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user=optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group=optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir=optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + + /* Starting daemon */ + debug1(STARTED_MSG,ARGV0); + + + /* Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + ErrorExit(USER_ERROR,ARGV0,user,group); + + + /* Reading config. */ + c = 0; + c|= CAGENTLESS; + lessdc.entries = NULL; + lessdc.queue = 0; + + if(ReadConfig(c, cfg, &lessdc, NULL) < 0) + { + ErrorExit(XML_INV_AGENTLESS, ARGV0); + } + + + /* Exit here if test config is set */ + if(test_config) + exit(0); + + + /* Going on daemon mode */ + if(!run_foreground) + { + nowDaemon(); + goDaemonLight(); + } + chdir(dir); + + + /* Exiting if not configured. */ + if(!lessdc.entries) + { + verbose("%s: INFO: Not configured. Exiting.", ARGV0); + exit(0); + } + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* Changing user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + debug1(PRIVSEP_MSG,ARGV0,dir,user); + + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + + /* Creating PID files */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR,ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* the real daemon now */ + Agentlessd(); + exit(0); +} + + +/* EOF */ diff --git a/src/agentlessd/scripts/main.exp b/src/agentlessd/scripts/main.exp new file mode 100755 index 0000000..b7ea020 --- /dev/null +++ b/src/agentlessd/scripts/main.exp @@ -0,0 +1,101 @@ +#!/usr/bin/env expect + +# @(#) $Id: main.exp,v 1.5 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +if {$argc <= 1} { + send_user "\nERROR: ssh_integrity_check \n"; + exit 1; +} + + +# NOTE: this script must be called from within /var/ossec for it to work. +set passlist "agentless/.passlist" +set sshsrc "agentless/ssh.exp" +set susrc "agentless/su.exp" +set sshloginsrc "agentless/sshlogin.exp" +set sshnopasssrc "agentless/ssh_nopass.exp" +set hostname [lindex $argv 0] +set args [lrange $argv 1 end] +set pass "x" +set use_su " " +set use_sudo " " +set addpass "x" +set timeout 20 + + +# Doing script test +if {[string compare $hostname "test"] == 0} { + if {[string compare $args "test"] == 0} { + exit 0; + } +} + +# Checking if the hostname (first argument) is an option. +if {[string compare $hostname "use_su"] == 0} { + set use_su "su;" + set hostname [lindex $argv 1] + set args [lrange $argv 2 end] +} +# Checking if the hostname (first argument) is an option. +if {[string compare $hostname "use_sudo"] == 0} { + set use_sudo "sudo sh;" + set hostname [lindex $argv 1] + set args [lrange $argv 2 end] +} + + +# Reading the password list. +if [catch { + set in [open "$passlist" r] +} loc_error] { + send_user "\nERROR: Password list not present (use \"register_host\" first).\n" + exit 1; +} + +while {[gets $in line] != -1} { + set me [string first "|" $line] + set me2 [string last "|" $line] + set length [string length $line] + + if {$me == -1} { + continue; + } + if {$me2 == -1} { + continue; + } + if {$me == $me2} { + continue; + } + + set me [expr $me-1] + set me2 [expr $me2-1] + + set host_list [string range $line 0 $me] + set me [expr $me+2] + set pass_list [string range $line $me $me2] + set me2 [expr $me2+2] + set addpass_list [string range $line $me2 $length] + + if {[string compare $host_list $hostname] == 0} { + set pass "$pass_list" + set addpass "$addpass_list" + break + } +} +close $in + + +if {[string compare $pass "x"] == 0} { + send_user "\nERROR: Password for '$hostname' not found.\n" + exit 1; +} diff --git a/src/agentlessd/scripts/register_host.sh b/src/agentlessd/scripts/register_host.sh new file mode 100755 index 0000000..0984e76 --- /dev/null +++ b/src/agentlessd/scripts/register_host.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +# @(#) $Id: register_host.sh,v 1.5 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +MYNAME="register_host.sh" +MYPASS=".passlist" + + +# Checking the location. +ls -la $MYNAME > /dev/null 2>&1 +if [ ! $? = 0 ]; then + LOCALDIR=`dirname $0`; + cd ${LOCALDIR} + + ls -la $MYNAME > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: You must run this script from the same directory." + exit 1; + fi +fi + + + +# Arguments +if [ "x$1" = "x" -o "x$1" = "xhelp" -o "x$1" = "x-h" ]; then + echo "$0 options:" + echo " add [] ()" + echo " list (passwords)" + exit 0; +fi + + +if [ "x$1" = "xlist" ]; then + echo "*Available hosts: " + if [ "x$2" = "xpasswords" ]; then + cat $MYPASS | sort | uniq; + else + cat $MYPASS | cut -d "|" -f 1 | sort | uniq; + fi + exit 0; + + + +elif [ "x$1" = "xadd" ]; then + if [ "x$2" = "x" ]; then + echo "ERROR: Missing hostname name."; + echo "ex: $0 add [] ()"; + exit 1; + fi + + grep "$2|" $MYPASS > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "ERROR: Host '$2' already added."; + exit 1; + fi + + + # Checking if the password was supplied. + if [ "x$3" = "x" ]; then + echo "Please provide password for host $2." + echo -n "Password: "; + stty -echo + read INPASS + stty echo + + echo "Please provide additional password for host $2 ( for empty)." + echo -n "Password: "; + stty -echo + read ADDPASS + stty echo + else + INPASS=$3 + ADDPASS=$4 + fi + + echo "$2|$INPASS|$ADDPASS" >> $MYPASS; + if [ ! $? = 0 ]; then + echo "ERROR: Unable to creating entry (echo failed)." + exit 1; + fi + echo "*Host $2 added." + +else + + echo "ERROR: Invalid argument."; + exit 1; + +fi + + +# EOF + diff --git a/src/agentlessd/scripts/ssh.exp b/src/agentlessd/scripts/ssh.exp new file mode 100755 index 0000000..238e373 --- /dev/null +++ b/src/agentlessd/scripts/ssh.exp @@ -0,0 +1,57 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh.exp,v 1.4 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +if {[string compare $pass "NOPASS"] == 0} { + source $sshnopasssrc + return +} + + +expect { + "WARNING: REMOTE HOST" { + send_user "\nERROR: RSA host key for '$hostname' has changed. Unable to access.\n" + exit 1; + } + "*sure you want to continue connecting*" { + send "yes\r" + expect "* password:*" { + send "$pass\r" + source $sshloginsrc + } + } + "ssh: connect to host*" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "no address associated with name" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection refused*" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection closed by remote host*" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "* password:*" { + send "$pass\r" + source $sshloginsrc + } + timeout { + send_user "\nERROR: Timeout while connecting to host: $hostname . \n" + exit 1; + } +} diff --git a/src/agentlessd/scripts/ssh_asa-fwsmconfig_diff b/src/agentlessd/scripts/ssh_asa-fwsmconfig_diff new file mode 100755 index 0000000..3d661c2 --- /dev/null +++ b/src/agentlessd/scripts/ssh_asa-fwsmconfig_diff @@ -0,0 +1,210 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_asa-fwsmconfig_diff,v 1.2 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +if {$argc < 1} { + send_user "ERROR: ssh_pixconfig_diff \n"; + exit 1; +} + + +# NOTE: this script must be called from within /var/ossec for it to work. +set passlist "agentless/.passlist" +set hostname [lindex $argv 0] +set commands [lrange $argv 1 end] +set pass "x" +set addpass "x" +set timeout 20 + +if {[string compare $hostname "test"] == 0} { + if {[string compare $commands "test"] == 0} { + exit 0; + } +} + +# Reading the password list. +if [catch { + set in [open "$passlist" r] +} loc_error] { + send_user "ERROR: Password list not present (use \"register_host\" first).\n" + exit 1; +} + +while {[gets $in line] != -1} { + set me [string first "|" $line] + set me2 [string last "|" $line] + set length [string length $line] + + if {$me == -1} { + continue; + } + if {$me2 == -1} { + continue; + } + if {$me == $me2} { + continue; + } + + set me [expr $me-1] + set me2 [expr $me2-1] + + set host_list [string range $line 0 $me] + set me [expr $me+2] + set pass_list [string range $line $me $me2] + set me2 [expr $me2+2] + set addpass_list [string range $line $me2 $length] + + if {[string compare $host_list $hostname] == 0} { + set pass "$pass_list" + set addpass "$addpass_list" + break + } +} +close $in + + +if {[string compare $pass "x"] == 0} { + send_user "ERROR: Password for '$hostname' not found.\n" + exit 1; +} + + +# SSHing to the box and passing the directories to check. +if [catch { + spawn ssh -c des $hostname +} loc_error] { + send_user "ERROR: Opening connection: $loc_error.\n" + exit 1; +} + +expect { + "WARNING: REMOTE HOST" { + send_user "ERROR: RSA host key for '$hostname' has changed. Unable to access.\n" + exit 1; + } + "*sure you want to continue connecting*" { + send "yes\r" + expect "* password:*" { + send "$pass\r" + + expect { + "Permission denied" { + send_user "ERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while running on host (too long to finish): $hostname .\n" + exit 1; + } + "*>" { + send_user "\nINFO: Starting.\n" + } + } + } + } + "ssh: connect to host*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "no address associated with name" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection refused*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection closed by remote host*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "* password:*" { + send "$pass\r" + + expect { + "Permission denied" { + send_user "ERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while running on host (too long to finish): $hostname .\n" + exit 1; + } + "*>" { + send_user "INFO: Starting.\n" + } + } + } + timeout { + send_user "ERROR: Timeout while connecting to host: $hostname . \n" + exit 1; + } +} + +# Going into enable mode. +send "enable\r" +expect { + "Password:" { + send "$addpass\r" + + expect { + "*asswor*" { + send_user "ERROR: Incorrect enable password to remote host: $hostname .\n" + exit 1; + } + "*rror in authenticatio*" { + send_user "ERROR: Incorrect enable password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while going to enable mode on host: $hostname .\n" + exit 1; + } + "*#" { + send_user "ok on enable pass\n" + } + } + } + timeout { + send_user "ERROR: Timeout while running enable on host: $hostname .\n" + exit 1; + } +} + + + +# Sending commands +set timeout 60 +send_user "\nSTORE: now\n" + +send "term pager 0\r" + +# Excluding uptime from the output +send "show version | grep -v Configuration last| up\r" +send "show running-config\r" +send "$commands\r" +send "exit\r" + +expect { + timeout { + send_user "ERROR: Timeout while running commands on host: $hostname .\n" + exit 1; + } + eof { + send_user "\nINFO: Finished.\n" + exit 0; + } +} + +send_user "ERROR: Unable to finish properly.\n" +exit 1; diff --git a/src/agentlessd/scripts/ssh_foundry_diff b/src/agentlessd/scripts/ssh_foundry_diff new file mode 100755 index 0000000..ece1288 --- /dev/null +++ b/src/agentlessd/scripts/ssh_foundry_diff @@ -0,0 +1,212 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_foundry_diff,v 1.2 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +if {$argc < 1} { + send_user "ERROR: ssh_pixconfig_diff \n"; + exit 1; +} + + +# NOTE: this script must be called from within /var/ossec for it to work. +set passlist "agentless/.passlist" +set hostname [lindex $argv 0] +set commands [lrange $argv 1 end] +set pass "x" +set addpass "x" +set timeout 20 + +if {[string compare $hostname "test"] == 0} { + if {[string compare $commands "test"] == 0} { + exit 0; + } +} + +# Reading the password list. +if [catch { + set in [open "$passlist" r] +} loc_error] { + send_user "ERROR: Password list not present (use \"register_host\" first).\n" + exit 1; +} + +while {[gets $in line] != -1} { + set me [string first "|" $line] + set me2 [string last "|" $line] + set length [string length $line] + + if {$me == -1} { + continue; + } + if {$me2 == -1} { + continue; + } + if {$me == $me2} { + continue; + } + + set me [expr $me-1] + set me2 [expr $me2-1] + + set host_list [string range $line 0 $me] + set me [expr $me+2] + set pass_list [string range $line $me $me2] + set me2 [expr $me2+2] + set addpass_list [string range $line $me2 $length] + + if {[string compare $host_list $hostname] == 0} { + set pass "$pass_list" + set addpass "$addpass_list" + break + } +} +close $in + + +if {[string compare $pass "x"] == 0} { + send_user "ERROR: Password for '$hostname' not found.\n" + exit 1; +} + + +# SSHing to the box and passing the directories to check. +if [catch { + spawn ssh $hostname +} loc_error] { + send_user "ERROR: Opening connection: $loc_error.\n" + exit 1; +} + +expect { + "WARNING: REMOTE HOST" { + send_user "ERROR: RSA host key for '$hostname' has changed. Unable to access.\n" + exit 1; + } + "*sure you want to continue connecting*" { + send "yes\r" + expect "* password:*" { + send "$pass\r" + + expect { + "Permission denied" { + send_user "ERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while running on host (too long to finish): $hostname .\n" + exit 1; + } + "*>" { + send_user "\nINFO: Starting.\n" + } + } + } + } + "ssh: connect to host*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "no address associated with name" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection refused*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection closed by remote host*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "* password:*" { + send "$pass\r" + + expect { + "Permission denied" { + send_user "ERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while running on host (too long to finish): $hostname .\n" + exit 1; + } + "*>" { + send_user "INFO: Starting.\n" + } + } + } + timeout { + send_user "ERROR: Timeout while connecting to host: $hostname . \n" + exit 1; + } +} + + +if {[string compare $addpass ""] != 0} { + # Going into enable mode. + send "enable\r" + expect { + "Password:" { + send "$addpass\r" + + expect { + "*asswor*" { + send_user "ERROR: Incorrect enable password to remote host: $hostname .\n" + exit 1; + } + "*rror - incorrect password*" { + send_user "ERROR: Incorrect enable password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while going to enable mode on host: $hostname .\n" + exit 1; + } + "*#" { + send_user "ok on enable pass\n" + } + } + } + timeout { + send_user "ERROR: Timeout while running enable on host: $hostname .\n" + exit 1; + } + } +} + + +# Sending commands +set timeout 60 +send_user "\nSTORE: now\n" + +send "skip-page-display\r" + + +# Excluding uptime from the output +send "sh run\r" +send "$commands\r" +send "exit\rexit\r" + +expect { + timeout { + send_user "ERROR: Timeout while running commands on host: $hostname .\n" + exit 1; + } + eof { + send_user "\nINFO: Finished.\n" + exit 0; + } +} + +send_user "ERROR: Unable to finish properly.\n" +exit 1; diff --git a/src/agentlessd/scripts/ssh_generic_diff b/src/agentlessd/scripts/ssh_generic_diff new file mode 100755 index 0000000..d63a9af --- /dev/null +++ b/src/agentlessd/scripts/ssh_generic_diff @@ -0,0 +1,49 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_generic_diff,v 1.10 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +# Main script. +source "agentless/main.exp" + + +# SSHing to the box and passing the directories to check. +if [catch { + spawn ssh $hostname +} loc_error] { + send_user "ERROR: Opening connection: $loc_error.\n" + exit 1; +} + + +source $sshsrc +source $susrc + + +set timeout 600 +send_user "INFO: Starting.\n" +send_user "\nSTORE: now\n" +send "$args\r" +send "exit\r" + +expect { + timeout { + send_user "ERROR: Timeout while running commands on host: $hostname .\n" + exit 1; + } + eof { + send_user "\nINFO: Finished.\n" + exit 0; + } +} + +exit 0; diff --git a/src/agentlessd/scripts/ssh_integrity_check_bsd b/src/agentlessd/scripts/ssh_integrity_check_bsd new file mode 100755 index 0000000..cbda255 --- /dev/null +++ b/src/agentlessd/scripts/ssh_integrity_check_bsd @@ -0,0 +1,46 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_integrity_check_bsd,v 1.10 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +# Main script. +source "agentless/main.exp" + + +# SSHing to the box and passing the directories to check. +if [catch { + spawn ssh $hostname +} loc_error] { + send_user "\nERROR: Opening connection: $loc_error.\n" + exit 1; +} + + +source $sshsrc +source $susrc + +set timeout 600 +send "for i in `find $args 2>/dev/null`;do tail \$i >/dev/null 2>&1 && md5=`md5 \$i | cut -d \"=\" -f 2|cut -d \" \" -f 2` && sha1=`sha1 \$i | cut -d \"=\" -f 2|cut -d \" \" -f 2` && echo FWD: `stat -f \"%Dz:%Dp:%Du:%Dg\" \$i`:\$md5:\$sha1 \$i; done; exit\r" +send "exit\r" + +expect { + timeout { + send_user "\nERROR: Timeout while running commands on host: $hostname .\n" + exit 1; + } + eof { + send_user "\nINFO: Finished.\n" + exit 0; + } +} + +exit 0; diff --git a/src/agentlessd/scripts/ssh_integrity_check_linux b/src/agentlessd/scripts/ssh_integrity_check_linux new file mode 100755 index 0000000..df69215 --- /dev/null +++ b/src/agentlessd/scripts/ssh_integrity_check_linux @@ -0,0 +1,46 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_integrity_check_linux,v 1.11 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +# Main script. +source "agentless/main.exp" + + +# SSHing to the box and passing the directories to check. +if [catch { + spawn ssh $hostname +} loc_error] { + send_user "ERROR: Opening connection: $loc_error.\n" + exit 1; +} + + +source $sshsrc +source $susrc + +set timeout 600 +send "echo \"INFO: Starting.\"; for i in `find $args 2>/dev/null`;do tail \$i >/dev/null 2>&1 && md5=`md5sum \$i | cut -d \" \" -f 1` && sha1=`sha1sum \$i | cut -d \" \" -f 1` && echo FWD: `stat --printf \"%s:%a:%u:%g\" \$i`:\$md5:\$sha1 \$i; done; exit\r" +send "exit\r" + +expect { + timeout { + send_user "ERROR: Timeout while running commands on host: $hostname .\n" + exit 1; + } + eof { + send_user "\nINFO: Finished.\n" + exit 0; + } +} + +exit 0; diff --git a/src/agentlessd/scripts/ssh_nopass.exp b/src/agentlessd/scripts/ssh_nopass.exp new file mode 100755 index 0000000..62b7b6f --- /dev/null +++ b/src/agentlessd/scripts/ssh_nopass.exp @@ -0,0 +1,54 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_nopass.exp,v 1.3 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + +expect { + "WARNING: REMOTE HOST" { + send_user "\nERROR: RSA host key for '$hostname' has changed. Unable to access.\n" + exit 1; + } + "*sure you want to continue connecting*" { + send "yes\r" + source $sshnopasssrc + return + } + "ssh: connect to host*" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "no address associated with name" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection refused*" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection closed by remote host*" { + send_user "\nERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "* password:*" { + send_user "\nERROR: Public key authentication failed to host: $hostname .\n" + exit 1 + } + "*\\\$" { + send_user "\nINFO: Started.\n" + } + "*#" { + send_user "\nINFO: Started.\n" + } + timeout { + send_user "\nERROR: Timeout while connecting to host: $hostname . \n" + exit 1; + } +} diff --git a/src/agentlessd/scripts/ssh_pixconfig_diff b/src/agentlessd/scripts/ssh_pixconfig_diff new file mode 100755 index 0000000..9968432 --- /dev/null +++ b/src/agentlessd/scripts/ssh_pixconfig_diff @@ -0,0 +1,211 @@ +#!/usr/bin/env expect + +# @(#) $Id: ssh_pixconfig_diff,v 1.6 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +if {$argc < 1} { + send_user "ERROR: ssh_pixconfig_diff \n"; + exit 1; +} + + +# NOTE: this script must be called from within /var/ossec for it to work. +set passlist "agentless/.passlist" +set hostname [lindex $argv 0] +set commands [lrange $argv 1 end] +set pass "x" +set addpass "x" +set timeout 20 + +if {[string compare $hostname "test"] == 0} { + if {[string compare $commands "test"] == 0} { + exit 0; + } +} + +# Reading the password list. +if [catch { + set in [open "$passlist" r] +} loc_error] { + send_user "ERROR: Password list not present (use \"register_host\" first).\n" + exit 1; +} + +while {[gets $in line] != -1} { + set me [string first "|" $line] + set me2 [string last "|" $line] + set length [string length $line] + + if {$me == -1} { + continue; + } + if {$me2 == -1} { + continue; + } + if {$me == $me2} { + continue; + } + + set me [expr $me-1] + set me2 [expr $me2-1] + + set host_list [string range $line 0 $me] + set me [expr $me+2] + set pass_list [string range $line $me $me2] + set me2 [expr $me2+2] + set addpass_list [string range $line $me2 $length] + + if {[string compare $host_list $hostname] == 0} { + set pass "$pass_list" + set addpass "$addpass_list" + break + } +} +close $in + + +if {[string compare $pass "x"] == 0} { + send_user "ERROR: Password for '$hostname' not found.\n" + exit 1; +} + + +# SSHing to the box and passing the directories to check. +if [catch { + spawn ssh -c des $hostname +} loc_error] { + send_user "ERROR: Opening connection: $loc_error.\n" + exit 1; +} + +expect { + "WARNING: REMOTE HOST" { + send_user "ERROR: RSA host key for '$hostname' has changed. Unable to access.\n" + exit 1; + } + "*sure you want to continue connecting*" { + send "yes\r" + expect "* password:*" { + send "$pass\r" + + expect { + "Permission denied" { + send_user "ERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while running on host (too long to finish): $hostname .\n" + exit 1; + } + "*>" { + send_user "\nINFO: Starting.\n" + } + } + } + } + "ssh: connect to host*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "no address associated with name" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection refused*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "*Connection closed by remote host*" { + send_user "ERROR: Unable to connect to remote host: $hostname .\n" + exit 1; + } + "* password:*" { + send "$pass\r" + + expect { + "Permission denied" { + send_user "ERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while running on host (too long to finish): $hostname .\n" + exit 1; + } + "*>" { + send_user "INFO: Starting.\n" + } + } + } + timeout { + send_user "ERROR: Timeout while connecting to host: $hostname . \n" + exit 1; + } +} + +# Going into enable mode. +send "enable\r" +expect { + "Password:" { + send "$addpass\r" + + expect { + "*asswor*" { + send_user "ERROR: Incorrect enable password to remote host: $hostname .\n" + exit 1; + } + "*rror in authenticatio*" { + send_user "ERROR: Incorrect enable password to remote host: $hostname .\n" + exit 1; + } + timeout { + send_user "ERROR: Timeout while going to enable mode on host: $hostname .\n" + exit 1; + } + "*#" { + send_user "ok on enable pass\n" + } + } + } + timeout { + send_user "ERROR: Timeout while running enable on host: $hostname .\n" + exit 1; + } +} + + +# Sending commands +set timeout 60 +send_user "\nSTORE: now\n" + +send "no pager\r" +send "term len 0\r" +send "terminal pager 0\r" + +# Excluding uptime from the output +send "show version | grep -v Configuration last| up\r" +send "show running-config\r" +send "$commands\r" +send "exit\r" + +expect { + timeout { + send_user "ERROR: Timeout while running commands on host: $hostname .\n" + exit 1; + } + eof { + send_user "\nINFO: Finished.\n" + exit 0; + } +} + +send_user "ERROR: Unable to finish properly.\n" +exit 1; diff --git a/src/agentlessd/scripts/sshlogin.exp b/src/agentlessd/scripts/sshlogin.exp new file mode 100755 index 0000000..6335e27 --- /dev/null +++ b/src/agentlessd/scripts/sshlogin.exp @@ -0,0 +1,34 @@ +#!/usr/bin/env expect + +# @(#) $Id: sshlogin.exp,v 1.5 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +expect { + "Permission denied" { + send_user "\nERROR: Incorrect password to remote host: $hostname .\n" + exit 1; + } + eof { + send_user "\nERROR: EOF while logging to host: $hostname .\n" + exit 0; + } + timeout { + send_user "\nERROR: Timeout while running on host: $hostname .\n" + exit 1; + } + "*\\\$" { + send_user "\nINFO: Started.\n" + } + "*#" { + send_user "\nINFO: Started.\n" + } +} diff --git a/src/agentlessd/scripts/su.exp b/src/agentlessd/scripts/su.exp new file mode 100755 index 0000000..7f9c0cf --- /dev/null +++ b/src/agentlessd/scripts/su.exp @@ -0,0 +1,58 @@ +#!/usr/bin/env expect + +# @(#) $Id: su.exp,v 1.5 2009/06/24 17:06:21 dcid Exp $ +# Agentless monitoring +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. + + +# If su was chosen +set timeout 10 +if {[string compare $use_su "su;"] == 0} { + + # Run su command + send "\rsu\r" + + expect { + "Password:" { + send "$addpass\r" + } + timeout { + send_user "\nERROR: Unable to run su.\n" + exit 1; + } + } + + + expect { + "Permission denied" { + send_user "\nERROR: Incorrect su password to host: $hostname .\n" + exit 1; + } + "Password:" { + send_user "\nERROR: Incorrect su password to host: $hostname .\n" + exit 1; + } + "Sorry" { + send_user "\nERROR: Incorrect su password to remote host: $hostname .\n" + exit 1; + } + eof { + send_user "\nERROR: EOF while running su on host: $hostname .\n" + exit 1; + } + timeout { + send_user "\nERROR: Timeout while running on host: $hostname .\n" + exit 1; + } + "*#" { + send_user "\nINFO: su accepted.\n" + } + } +} diff --git a/src/analysisd/Makefile b/src/analysisd/Makefile new file mode 100755 index 0000000..c5a7c3f --- /dev/null +++ b/src/analysisd/Makefile @@ -0,0 +1,37 @@ +# Makefile for analysisd +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +PT=../ +NAME=ossec-analysisd + +include ../Config.Make + +LOCAL= analysisd.c stats.c rules.c rules_list.c config.c fts.c eventinfo.c eventinfo_list.c cleanevent.c active-response.c picviz.c prelude.c compiled_rules/*.o ${OS_CONFIG} +PLUGINS = decoders/decoders.a +ALERTS = alerts/alerts.a + +loga_OBJS = ${LOCAL} ${PLUGINS} ${ALERTS} ${OS_XML} ${OS_REGEX} ${OS_NET} ${OS_SHARED} ${OS_ZLIB} ${CPRELUDE} + + +logaudit: + cd ./alerts; make + cd ./decoders; make + cd ./compiled_rules; make; + $(CC) $(CFLAGS) ${OS_LINK} -I./ ${loga_OBJS} -o ${NAME} + make logtest + +logtest: + cd ./decoders; make logtest + cd ./compiled_rules; make; + $(CC) $(CFLAGS) ${OS_LINK} -DTESTRULE -I./ testrule.c ${loga_OBJS} -o ossec-logtest + +clean: + cd ./alerts; make clean + cd ./decoders; make clean + cd ./compiled_rules; make clean + ${CLEAN} + +build: + ${BUILD} + cp -pr ossec-logtest ${PT}../bin diff --git a/src/analysisd/active-response.c b/src/analysisd/active-response.c new file mode 100755 index 0000000..5827ad9 --- /dev/null +++ b/src/analysisd/active-response.c @@ -0,0 +1,71 @@ +/* @(#) $Id: active-response.c,v 1.26 2009/06/24 17:06:21 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "active-response.h" + + +/** void AR_Init() + * Initializing active response. + */ +void AR_Init() +{ + ar_commands = OSList_Create(); + active_responses = OSList_Create(); + ar_flag = 0; + + if(!ar_commands || !active_responses) + { + ErrorExit(LIST_ERROR, ARGV0); + } +} + + +/** int AR_ReadConfig(int test_config, char *cfgfile) + * Reads active response configuration and write them + * to the appropriate lists. + */ +int AR_ReadConfig(int test_config, char *cfgfile) +{ + FILE *fp; + int modules = 0; + + modules|= CAR; + + + /* Cleaning ar file */ + fp = fopen(DEFAULTARPATH, "w"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, DEFAULTARPATH); + return(OS_INVALID); + } + fprintf(fp, "restart-ossec0 - restart-ossec.sh - 0\n"); + fprintf(fp, "restart-ossec0 - restart-ossec.cmd - 0\n"); + fclose(fp); + + + /* Setting right permission */ + chmod(DEFAULTARPATH, 0444); + + + /* Reading configuration */ + if(ReadConfig(modules, cfgfile, ar_commands, active_responses) < 0) + { + return(OS_INVALID); + } + + + return(0); +} + +/* EOF */ diff --git a/src/analysisd/active-response.h b/src/analysisd/active-response.h new file mode 100755 index 0000000..0bbb1e6 --- /dev/null +++ b/src/analysisd/active-response.h @@ -0,0 +1,40 @@ +/* @(#) $Id: active-response.h,v 1.13 2009/06/24 17:06:21 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _AR__H +#define _AR__H + +#include "config/config.h" +#include "config/active-response.h" +#include "list_op.h" + + +/** void AR_Init() + * Initializing active response. + */ +void AR_Init(); + +/** int AR_ReadConfig(int test_config, char *cfgfile) + * Reads active response configuration and write them + * to the appropriate lists. + */ +int AR_ReadConfig(int test_config, char *cfgfile); + + +/* Active response commands */ +OSList *ar_commands; + +/* Active response information */ +OSList *active_responses; + + +#endif diff --git a/src/analysisd/alerts/Makefile b/src/analysisd/alerts/Makefile new file mode 100755 index 0000000..3534d89 --- /dev/null +++ b/src/analysisd/alerts/Makefile @@ -0,0 +1,20 @@ +# Makefile for analysisd alerts +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +PT=../../ +NAME=alerts + +include ../../Config.Make + +SRCS = mail.c log.c exec.c getloglocation.c +OBJS = mail.o log.o exec.o getloglocation.o + + +response: + $(CC) -I../ $(CFLAGS) -c $(SRCS) + ar cru alerts.a $(OBJS) + ranlib alerts.a + +clean: + ${CLEAN} diff --git a/src/analysisd/alerts/alerts.h b/src/analysisd/alerts/alerts.h new file mode 100755 index 0000000..8c99c6f --- /dev/null +++ b/src/analysisd/alerts/alerts.h @@ -0,0 +1,22 @@ +/* @(#) $Id: alerts.h,v 1.6 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Global alert header */ + +#ifndef _ALERT__H + +#define _ALERT__H + +#include "log.h" +#include "exec.h" +#include "getloglocation.h" + +#endif diff --git a/src/analysisd/alerts/exec.c b/src/analysisd/alerts/exec.c new file mode 100755 index 0000000..a5c07ce --- /dev/null +++ b/src/analysisd/alerts/exec.c @@ -0,0 +1,158 @@ +/* @(#) $Id: exec.c,v 1.39 2009/11/20 15:38:28 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Basic e-mailing operations */ + + +#include "shared.h" +#include "rules.h" +#include "alerts.h" +#include "config.h" +#include "active-response.h" + +#include "os_net/os_net.h" +#include "os_regex/os_regex.h" +#include "os_execd/execd.h" + +#include "eventinfo.h" + + +/* OS_Exec v0.1 + */ +void OS_Exec(int *execq, int *arq, Eventinfo *lf, active_response *ar) +{ + char exec_msg[OS_SIZE_1024 +1]; + char *ip; + char *user; + + + /* Cleaning the IP */ + if(lf->srcip && (ar->ar_cmd->expect & SRCIP)) + { + ip = strrchr(lf->srcip, ':'); + if(ip) + { + ip++; + } + else + { + ip = lf->srcip; + } + + + /* Checking if IP is to ignored */ + if(Config.white_list) + { + if(OS_IPFoundList(ip, Config.white_list)) + { + return; + } + } + + /* Checking if it is a hostname */ + if(Config.hostname_white_list) + { + int srcip_size; + OSMatch **wl; + + srcip_size = strlen(ip); + + wl = Config.hostname_white_list; + while(*wl) + { + if(OSMatch_Execute(ip, srcip_size, *wl)) + return; + wl++; + } + } + } + else + { + ip = "-"; + } + + + /* Getting username */ + if(lf->dstuser && (ar->ar_cmd->expect & USERNAME)) + { + user = lf->dstuser; + } + else + { + user = "-"; + } + + + /* active response on the server. + * The response must be here if the ar->location is set to AS + * or the ar->location is set to local (REMOTE_AGENT) and the + * event location is from here. + */ + if((ar->location & AS_ONLY) || + ((ar->location & REMOTE_AGENT) && (lf->location[0] != '(')) ) + { + if(!(Config.ar & LOCAL_AR)) + return; + + snprintf(exec_msg, OS_SIZE_1024, + "%s %s %s %d.%ld %d %s", + ar->name, + user, + ip, + lf->time, + __crt_ftell, + lf->generated_rule->sigid, + lf->location); + + if(OS_SendUnix(*execq, exec_msg, 0) < 0) + { + merror("%s: Error communicating with execd.", ARGV0); + } + } + + + /* Active response to the forwarder */ + else if((Config.ar & REMOTE_AR) && (lf->location[0] == '(')) + { + int rc; + snprintf(exec_msg, OS_SIZE_1024, + "%s %c%c%c %s %s %s %s %d.%ld %d %s", + lf->location, + (ar->location & ALL_AGENTS)?ALL_AGENTS_C:NONE_C, + (ar->location & REMOTE_AGENT)?REMOTE_AGENT_C:NONE_C, + (ar->location & SPECIFIC_AGENT)?SPECIFIC_AGENT_C:NONE_C, + ar->agent_id != NULL? ar->agent_id: "(null)", + ar->name, + user, + ip, + lf->time, + __crt_ftell, + lf->generated_rule->sigid, + lf->location); + + if((rc = OS_SendUnix(*arq, exec_msg, 0)) < 0) + { + if(rc == OS_SOCKBUSY) + { + merror("%s: AR socket busy.", ARGV0); + } + else + { + merror("%s: AR socket error (shutdown?).", ARGV0); + } + merror("%s: Error communicating with ar queue (%d).", ARGV0, rc); + } + } + + return; +} + +/* EOF */ diff --git a/src/analysisd/alerts/exec.h b/src/analysisd/alerts/exec.h new file mode 100755 index 0000000..09577db --- /dev/null +++ b/src/analysisd/alerts/exec.h @@ -0,0 +1,22 @@ +/* @(#) $Id: exec.h,v 1.7 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _EXEC__H + +#define _EXEC__H + +#include "eventinfo.h" +#include "active-response.h" + +void OS_Exec(int *execq, int *arq, Eventinfo *lf, active_response *ar); + +#endif diff --git a/src/analysisd/alerts/getloglocation.c b/src/analysisd/alerts/getloglocation.c new file mode 100755 index 0000000..2f12488 --- /dev/null +++ b/src/analysisd/alerts/getloglocation.c @@ -0,0 +1,198 @@ +/* @(#) $Id: getloglocation.c,v 1.14 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Get the log directory/file based on the day/month/year */ + + +/* analysisd headers */ +#include "getloglocation.h" + +int __crt_day; +char __elogfile[OS_FLSIZE+1]; +char __alogfile[OS_FLSIZE+1]; +char __flogfile[OS_FLSIZE+1]; + +/* OS_InitLog */ +void OS_InitLog() +{ + OS_InitFwLog(); + + __crt_day = 0; + + /* alerts and events log file */ + memset(__alogfile,'\0',OS_FLSIZE +1); + memset(__elogfile,'\0',OS_FLSIZE +1); + memset(__flogfile,'\0',OS_FLSIZE +1); + + _eflog = NULL; + _aflog = NULL; + _fflog = NULL; + + /* Setting the umask */ + umask(0027); +} + + +/* gzips a log file +int OS_CompressLog(int yesterday, char *prev_month, int prev_year) + + -- moved to monitord. +*/ + + + + +/* OS_GetLogLocation: v0.1, 2005/04/25 */ +int OS_GetLogLocation(Eventinfo *lf) +{ + /* Checking what directories to create + * Checking if the year directory is there. + * If not, create it. Same for the month directory. + */ + + /* For the events */ + if(_eflog) + { + if(ftell(_eflog) == 0) + unlink(__elogfile); + fclose(_eflog); + _eflog = NULL; + } + + snprintf(__elogfile,OS_FLSIZE,"%s/%d/", EVENTS, lf->year); + if(IsDir(__elogfile) == -1) + if(mkdir(__elogfile,0770) == -1) + { + ErrorExit(MKDIR_ERROR,ARGV0,__elogfile); + } + + snprintf(__elogfile,OS_FLSIZE,"%s/%d/%s", EVENTS, lf->year,lf->mon); + + if(IsDir(__elogfile) == -1) + if(mkdir(__elogfile,0770) == -1) + { + ErrorExit(MKDIR_ERROR,ARGV0,__elogfile); + } + + + /* Creating the logfile name */ + snprintf(__elogfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log", + EVENTS, + lf->year, + lf->mon, + "archive", + lf->day); + + + _eflog = fopen(__elogfile,"a"); + if(!_eflog) + ErrorExit("%s: Error opening logfile: '%s'",ARGV0,__elogfile); + + /* Creating a symlink */ + unlink(EVENTS_DAILY); + link(__elogfile, EVENTS_DAILY); + + + /* for the alerts logs */ + if(_aflog) + { + if(ftell(_aflog) == 0) + unlink(__alogfile); + fclose(_aflog); + _aflog = NULL; + } + + snprintf(__alogfile,OS_FLSIZE,"%s/%d/", ALERTS, lf->year); + if(IsDir(__alogfile) == -1) + if(mkdir(__alogfile,0770) == -1) + { + ErrorExit(MKDIR_ERROR,ARGV0,__alogfile); + } + + snprintf(__alogfile,OS_FLSIZE,"%s/%d/%s", ALERTS, lf->year,lf->mon); + + if(IsDir(__alogfile) == -1) + if(mkdir(__alogfile,0770) == -1) + { + ErrorExit(MKDIR_ERROR,ARGV0,__alogfile); + } + + + /* Creating the logfile name */ + snprintf(__alogfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log", + ALERTS, + lf->year, + lf->mon, + "alerts", + lf->day); + + _aflog = fopen(__alogfile,"a"); + + if(!_aflog) + ErrorExit("%s: Error opening logfile: '%s'",ARGV0,__alogfile); + + /* Creating a symlink */ + unlink(ALERTS_DAILY); + link(__alogfile, ALERTS_DAILY); + + + /* For the firewall events */ + if(_fflog) + { + if(ftell(_fflog) == 0) + unlink(__flogfile); + fclose(_fflog); + _fflog = NULL; + } + + snprintf(__flogfile,OS_FLSIZE,"%s/%d/", FWLOGS, lf->year); + if(IsDir(__flogfile) == -1) + if(mkdir(__flogfile,0770) == -1) + { + ErrorExit(MKDIR_ERROR,ARGV0,__flogfile); + } + + snprintf(__flogfile,OS_FLSIZE,"%s/%d/%s", FWLOGS, lf->year,lf->mon); + + if(IsDir(__flogfile) == -1) + if(mkdir(__flogfile,0770) == -1) + { + ErrorExit(MKDIR_ERROR,ARGV0,__flogfile); + } + + + /* Creating the logfile name */ + snprintf(__flogfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log", + FWLOGS, + lf->year, + lf->mon, + "firewall", + lf->day); + + _fflog = fopen(__flogfile,"a"); + + if(!_fflog) + ErrorExit("%s: Error opening logfile: '%s'",ARGV0,__flogfile); + + + /* Creating a symlink */ + unlink(FWLOGS_DAILY); + link(__flogfile, FWLOGS_DAILY); + + + /* Setting the new day */ + __crt_day = lf->day; + + return(0); +} + +/* EOF */ diff --git a/src/analysisd/alerts/getloglocation.h b/src/analysisd/alerts/getloglocation.h new file mode 100755 index 0000000..3b431c4 --- /dev/null +++ b/src/analysisd/alerts/getloglocation.h @@ -0,0 +1,42 @@ +/* @(#) $Id: getloglocation.h,v 1.10 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __GETLL_H + +#define __GETLL_H + +#include "eventinfo.h" + +/* + * Start the log location (need to be called before getlog) + * + */ +void OS_InitLog(); + +void OS_InitFwLog(); + +/* + * Get the log file based on the date/logtype/ + * + * @param lf Event structure + * + * @retval 0 success + * -1 error + */ +int OS_GetLogLocation(Eventinfo *lf); + + +FILE *_eflog; +FILE *_aflog; +FILE *_fflog; + +#endif /* GETLL_H */ diff --git a/src/analysisd/alerts/log.c b/src/analysisd/alerts/log.c new file mode 100755 index 0000000..2686620 --- /dev/null +++ b/src/analysisd/alerts/log.c @@ -0,0 +1,208 @@ +/* @(#) $Id: log.c,v 1.33 2009/11/20 15:38:28 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "log.h" +#include "alerts.h" +#include "getloglocation.h" +#include "rules.h" +#include "eventinfo.h" +#include "config.h" + + +/* Drop/allow patterns */ +OSMatch FWDROPpm; +OSMatch FWALLOWpm; + + +/* OS_Store: v0.2, 2005/02/10 */ +/* Will store the events in a file + * The string must be null terminated and contain + * any necessary new lines, tabs, etc. + * + */ +void OS_Store(Eventinfo *lf) +{ + fprintf(_eflog, + "%d %s %02d %s %s%s%s %s\n", + lf->year, + lf->mon, + lf->day, + lf->hour, + lf->hostname != lf->location?lf->hostname:"", + lf->hostname != lf->location?"->":"", + lf->location, + lf->full_log); + + fflush(_eflog); + return; +} + + +/* OS_Log: v0.3, 2006/03/04 */ +/* _writefile: v0.2, 2005/02/09 */ +void OS_Log(Eventinfo *lf) +{ + /* Writting to the alert log file */ + fprintf(_aflog, + "** Alert %d.%ld:%s - %s\n" + "%d %s %02d %s %s%s%s\nRule: %d (level %d) -> '%s'\n" + "Src IP: %s\nUser: %s\n%.1256s\n", + lf->time, + __crt_ftell, + lf->generated_rule->alert_opts & DO_MAILALERT?" mail ":"", + lf->generated_rule->group, + lf->year, + lf->mon, + lf->day, + lf->hour, + lf->hostname != lf->location?lf->hostname:"", + lf->hostname != lf->location?"->":"", + lf->location, + lf->generated_rule->sigid, + lf->generated_rule->level, + lf->generated_rule->comment, + lf->srcip == NULL?"(none)":lf->srcip, + lf->dstuser == NULL?"(none)":lf->dstuser, + lf->full_log); + + + /* Printing the last events if present */ + if(lf->generated_rule->last_events) + { + char **lasts = lf->generated_rule->last_events; + while(*lasts) + { + fprintf(_aflog,"%.1256s\n",*lasts); + lasts++; + } + lf->generated_rule->last_events[0] = NULL; + } + + fprintf(_aflog,"\n"); + + fflush(_aflog); + return; +} + + + +void OS_InitFwLog() +{ + /* Initializing fw log regexes */ + if(!OSMatch_Compile(FWDROP, &FWDROPpm, 0)) + { + ErrorExit(REGEX_COMPILE, ARGV0, FWDROP, + FWDROPpm.error); + } + + if(!OSMatch_Compile(FWALLOW, &FWALLOWpm, 0)) + { + ErrorExit(REGEX_COMPILE, ARGV0, FWALLOW, + FWALLOWpm.error); + } + +} + + +/* FW_Log: v0.1, 2005/12/30 */ +int FW_Log(Eventinfo *lf) +{ + /* If we don't have the srcip or the + * action, there is no point in going + * forward over here + */ + if(!lf->action || !lf->srcip) + { + return(0); + } + + + /* Setting the actions */ + switch(*lf->action) + { + /* discard, drop, deny, */ + case 'd': + case 'D': + /* reject, */ + case 'r': + case 'R': + /* block */ + case 'b': + case 'B': + os_free(lf->action); + os_strdup("DROP", lf->action); + break; + /* Closed */ + case 'c': + case 'C': + /* Teardown */ + case 't': + case 'T': + os_free(lf->action); + os_strdup("CLOSED", lf->action); + break; + /* allow, accept, */ + case 'a': + case 'A': + /* pass/permitted */ + case 'p': + case 'P': + /* open */ + case 'o': + case 'O': + os_free(lf->action); + os_strdup("ALLOW", lf->action); + break; + default: + if(OSMatch_Execute(lf->action,strlen(lf->action),&FWDROPpm)) + { + os_free(lf->action); + os_strdup("DROP", lf->action); + } + if(OSMatch_Execute(lf->action,strlen(lf->action),&FWALLOWpm)) + { + os_free(lf->action); + os_strdup("ALLOW", lf->action); + } + else + { + os_free(lf->action); + os_strdup("UNKNOWN", lf->action); + } + break; + } + + + /* log to file */ + fprintf(_fflog, + "%d %s %02d %s %s%s%s %s %s %s:%s->%s:%s\n", + lf->year, + lf->mon, + lf->day, + lf->hour, + lf->hostname != lf->location?lf->hostname:"", + lf->hostname != lf->location?"->":"", + lf->location, + lf->action, + lf->protocol, + lf->srcip, + lf->srcport, + lf->dstip, + lf->dstport); + + fflush(_fflog); + + return(1); +} + +/* EOF */ diff --git a/src/analysisd/alerts/log.h b/src/analysisd/alerts/log.h new file mode 100755 index 0000000..78b7e82 --- /dev/null +++ b/src/analysisd/alerts/log.h @@ -0,0 +1,28 @@ +/* @(#) $Id: log.h,v 1.8 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Basic logging operations */ + +#ifndef __LOG_H +#define __LOG_H + +#include "eventinfo.h" + +#define FWDROP "drop" +#define FWALLOW "accept" + +void OS_Log(Eventinfo *lf); +void OS_Store(Eventinfo *lf); +int FW_Log(Eventinfo *lf); + +#endif + + diff --git a/src/analysisd/alerts/mail.c b/src/analysisd/alerts/mail.c new file mode 100755 index 0000000..a198c02 --- /dev/null +++ b/src/analysisd/alerts/mail.c @@ -0,0 +1,14 @@ +/* $OSSEC, mail.c, v0.2, 2005/02/10, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Basic e-mailing operations */ + +/* EOF */ diff --git a/src/analysisd/analysisd.c b/src/analysisd/analysisd.c new file mode 100755 index 0000000..25f8e18 --- /dev/null +++ b/src/analysisd/analysisd.c @@ -0,0 +1,1541 @@ +/* @(#) $Id: analysisd.c,v 1.149 2009/11/20 16:11:46 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Part of the OSSEC + * Available at http://www.ossec.net + */ + + +/* ossec-analysisd. + * Responsible for correlation and log decoding. + */ + +#ifndef ARGV0 + #define ARGV0 "ossec-analysisd" +#endif + +#include "shared.h" + +#include "alerts/alerts.h" +#include "alerts/getloglocation.h" +#include "os_execd/execd.h" + +#include "os_regex/os_regex.h" +#include "os_net/os_net.h" + + +/** Local headers **/ +#include "active-response.h" +#include "config.h" +#include "rules.h" +#include "stats.h" +#include "eventinfo.h" +#include "analysisd.h" + +#include "picviz.h" + +#ifdef PRELUDE +#include "prelude.h" +#endif + + +/** Global data **/ + +/* execd queue */ +int execdq = 0; + +/* active response queue */ +int arq = 0; + + +/** Internal Functions **/ +void OS_ReadMSG(int m_queue); +RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node); + + +/** External functions prototypes (only called here) **/ + +/* For config */ +int GlobalConf(char * cfgfile); + + +/* For rules */ +void Rules_OP_CreateRules(); +int Rules_OP_ReadRules(char * cfgfile); +int _setlevels(RuleNode *node, int nnode); +int AddHash_Rule(RuleNode *node); + + +/* For cleanmsg */ +int OS_CleanMSG(char *msg, Eventinfo *lf); + + +/* for FTS */ +int FTS_Init(); +int FTS(Eventinfo *lf); +int AddtoIGnore(Eventinfo *lf); +int IGnore(Eventinfo *lf); + + +/* For decoders */ +void DecodeEvent(Eventinfo *lf); +int DecodeSyscheck(Eventinfo *lf); +int DecodeRootcheck(Eventinfo *lf); +int DecodeHostinfo(Eventinfo *lf); + + +/* For Decoders */ +int ReadDecodeXML(char *file); +int SetDecodeXML(); + + +/* For syscheckd (integrity checking) */ +void SyscheckInit(); +void RootcheckInit(); +void HostinfoInit(); + + +/* For stats */ +int Start_Hour(); +int Check_Hour(Eventinfo *lf); +void Update_Hour(); +void DumpLogstats(); + +/* Hourly alerts */ +int hourly_alerts; +int hourly_events; +int hourly_syscheck; +int hourly_firewall; + + +/** int main(int argc, char **argv) + */ +#ifndef TESTRULE +int main(int argc, char **argv) +#else +int main_analysisd(int argc, char **argv) +#endif +{ + int c = 0, m_queue = 0, test_config = 0,run_foreground = 0; + char *dir = DEFAULTDIR; + char *user = USER; + char *group = GROUPGLOBAL; + int uid = 0,gid = 0; + + char *cfg = DEFAULTCPATH; + + /* Setting the name */ + OS_SetName(ARGV0); + + thishour = 0; + today = 0; + prev_year = 0; + memset(prev_month, '\0', 4); + hourly_alerts = 0; + hourly_events = 0; + hourly_syscheck = 0; + hourly_firewall = 0; + + while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user = optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group = optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir = optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + + /* Starting daemon */ + debug1(STARTED_MSG,ARGV0); + DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0)); + + + /*Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + ErrorExit(USER_ERROR,ARGV0,user,group); + + + /* Found user */ + debug1(FOUND_USER, ARGV0); + + + /* Initializing Active response */ + AR_Init(); + if(AR_ReadConfig(test_config, cfg) < 0) + { + ErrorExit(CONFIG_ERROR,ARGV0, cfg); + } + debug1(ASINIT, ARGV0); + + + /* Reading configuration file */ + if(GlobalConf(cfg) < 0) + { + ErrorExit(CONFIG_ERROR,ARGV0, cfg); + } + + debug1(READ_CONFIG, ARGV0); + + + /* Fixing Config.ar */ + Config.ar = ar_flag; + if(Config.ar == -1) + Config.ar = 0; + + + /* Getting servers hostname */ + memset(__shost, '\0', 512); + if(gethostname(__shost, 512 -1) != 0) + { + strncpy(__shost, OSSEC_SERVER, 512 -1); + } + else + { + char *_ltmp; + + /* Remove domain part if available */ + _ltmp = strchr(__shost, '.'); + if(_ltmp) + *_ltmp = '\0'; + } + + /* going on Daemon mode */ + if(!test_config || !run_foreground) + { + nowDaemon(); + goDaemon(); + } + + + /* Starting prelude */ + #ifdef PRELUDE + if(Config.prelude) + { + prelude_start(Config.prelude_profile, argc, argv); + } + #endif + + + /* Opening the Picviz socket */ + if(Config.picviz) + { + OS_PicvizOpen(Config.picviz_socket); + chown(Config.picviz_socket, uid, gid); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + /* Chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + + nowChroot(); + + + + /* Initializing the list */ + OS_CreateOSDecoderList(); + + + /* Reading decoders */ + if(!ReadDecodeXML(XML_DECODER)) + { + ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER); + } + + /* Reading local ones. */ + c = ReadDecodeXML(XML_LDECODER); + if(!c) + { + if((c != -2)) + ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER); + } + else + { + if(!test_config) + verbose("%s: INFO: Reading local decoder file.", ARGV0); + } + SetDecodeXML(); + + + /* Creating the rules list */ + Rules_OP_CreateRules(); + + + /* Reading the rules */ + { + char **rulesfiles; + rulesfiles = Config.includes; + while(rulesfiles && *rulesfiles) + { + if(!test_config) + verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles); + if(Rules_OP_ReadRules(*rulesfiles) < 0) + ErrorExit(RULES_ERROR, ARGV0, *rulesfiles); + + free(*rulesfiles); + rulesfiles++; + } + + free(Config.includes); + Config.includes = NULL; + } + + + /* Fixing the levels/accuracy */ + { + int total_rules; + RuleNode *tmp_node = OS_GetFirstRule(); + + total_rules = _setlevels(tmp_node, 0); + if(!test_config) + verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules); + } + + + + /* Creating a rules hash (for reading alerts from other servers). */ + { + RuleNode *tmp_node = OS_GetFirstRule(); + Config.g_rules_hash = OSHash_Create(); + if(!Config.g_rules_hash) + { + ErrorExit(MEM_ERROR, ARGV0); + } + AddHash_Rule(tmp_node); + } + + + + /* Ignored files on syscheck */ + { + char **files; + files = Config.syscheck_ignore; + while(files && *files) + { + if(!test_config) + verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files); + files++; + } + } + + + /* Checking if log_fw is enabled. */ + Config.logfw = getDefine_Int("analysisd", + "log_fw", + 0, 1); + + + /* Success on the configuration test */ + if(test_config) + exit(0); + + + /* Verbose message */ + debug1(PRIVSEP_MSG, ARGV0, dir, user); + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + /* Creating the PID file */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR,ARGV0); + + + /* Setting the queue */ + if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0) + ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); + + + /* White list */ + if(Config.white_list == NULL) + { + if(Config.ar) + verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0); + } + else + { + if(Config.ar) + { + os_ip **wl; + int wlc = 0; + wl = Config.white_list; + while(*wl) + { + verbose("%s: INFO: White listing IP: '%s'",ARGV0, (*wl)->ip); + wl++;wlc++; + } + verbose("%s: INFO: %d IPs in the white list for active response.", + ARGV0, wlc); + } + } + + /* Hostname White list */ + if(Config.hostname_white_list == NULL) + { + if(Config.ar) + verbose("%s: INFO: No Hostname in the white list for active reponse.", + ARGV0); + } + else + { + if(Config.ar) + { + int wlc = 0; + OSMatch **wl; + + wl = Config.hostname_white_list; + while(*wl) + { + char **tmp_pts = (*wl)->patterns; + while(*tmp_pts) + { + verbose("%s: INFO: White listing Hostname: '%s'",ARGV0,*tmp_pts); + wlc++; + tmp_pts++; + } + wl++; + } + verbose("%s: INFO: %d Hostname(s) in the white list for active response.", + ARGV0, wlc); + } + } + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* Going to main loop */ + OS_ReadMSG(m_queue); + + if (Config.picviz) + { + OS_PicvizClose(); + } + + exit(0); + +} + + + +/* OS_ReadMSG. + * Main function. Receives the messages(events) + * and analyze them all. + */ +#ifndef TESTRULE +void OS_ReadMSG(int m_queue) +#else +void OS_ReadMSG_analysisd(int m_queue) +#endif +{ + int i; + char msg[OS_MAXSTR +1]; + Eventinfo *lf; + + RuleInfo *stats_rule; + + + /* Null to global currently pointers */ + currently_rule = NULL; + + /* Initiating the logs */ + OS_InitLog(); + + + /* Initiating the integrity database */ + SyscheckInit(); + + + /* Initializing Rootcheck */ + RootcheckInit(); + + + /* Initializing host info */ + HostinfoInit(); + + + /* Creating the event list */ + OS_CreateEventList(Config.memorysize); + + + /* Initiating the FTS list */ + if(!FTS_Init()) + { + ErrorExit(FTS_LIST_ERROR, ARGV0); + } + + + /* Starting the active response queues */ + if(Config.ar) + { + /* Waiting the ARQ to settle .. */ + sleep(3); + + + #ifndef LOCAL + if(Config.ar & REMOTE_AR) + { + if((arq = StartMQ(ARQUEUE, WRITE)) < 0) + { + merror(ARQ_ERROR, ARGV0); + + /* If LOCAL_AR is set, keep it there */ + if(Config.ar & LOCAL_AR) + { + Config.ar = 0; + Config.ar|=LOCAL_AR; + } + else + { + Config.ar = 0; + } + } + else + { + verbose(CONN_TO, ARGV0, ARQUEUE, "active-response"); + } + } + + #else + /* Only for LOCAL_ONLY installs */ + if(Config.ar & REMOTE_AR) + { + if(Config.ar & LOCAL_AR) + { + Config.ar = 0; + Config.ar|=LOCAL_AR; + } + else + { + Config.ar = 0; + } + } + #endif + + if(Config.ar & LOCAL_AR) + { + if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0) + { + merror(ARQ_ERROR, ARGV0); + + /* If REMOTE_AR is set, keep it there */ + if(Config.ar & REMOTE_AR) + { + Config.ar = 0; + Config.ar|=REMOTE_AR; + } + else + { + Config.ar = 0; + } + } + else + { + verbose(CONN_TO, ARGV0, EXECQUEUE, "exec"); + } + } + } + debug1("%s: DEBUG: Active response Init completed.", ARGV0); + + + /* Getting currently time before starting */ + c_time = time(NULL); + + + /* Starting the hourly/weekly stats */ + if(Start_Hour() < 0) + Config.stats = 0; + else + { + /* Initializing stats rules */ + stats_rule = zerorulemember( + STATS_MODULE, + Config.stats, + 0,0,0,0,0,0); + + if(!stats_rule) + { + ErrorExit(MEM_ERROR, ARGV0); + } + stats_rule->group = "stats,"; + stats_rule->comment = "Excessive number of events (above normal)."; + } + + + /* Doing some cleanup */ + memset(msg, '\0', OS_MAXSTR +1); + + + /* Initializing the logs */ + { + lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); + if(!lf) + ErrorExit(MEM_ERROR, ARGV0); + lf->year = prev_year; + strncpy(lf->mon, prev_month, 3); + lf->day = today; + + if(OS_GetLogLocation(lf) < 0) + { + ErrorExit("%s: Error allocating log files", ARGV0); + } + + Free_Eventinfo(lf); + } + + + debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0); + + + /* Daemon loop */ + while(1) + { + lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); + + /* This shouldn't happen .. */ + if(lf == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0)); + + + /* Receive message from queue */ + if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg))) + { + RuleNode *rulenode_pt; + + /* Getting the time we received the event */ + c_time = time(NULL); + + + /* Default values for the log info */ + Zero_Eventinfo(lf); + + + /* Checking for a valid message. */ + if(i < 4) + { + merror(IMSG_ERROR, ARGV0, msg); + Free_Eventinfo(lf); + continue; + } + + + /* Message before extracting header */ + DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg); + + + /* Clean the msg appropriately */ + if(OS_CleanMSG(msg, lf) < 0) + { + merror(IMSG_ERROR,ARGV0, msg); + Free_Eventinfo(lf); + continue; + } + + + /* Msg cleaned */ + DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log); + + + /* Currently rule must be null in here */ + currently_rule = NULL; + + + /** Checking the date/hour changes **/ + + /* Update the hour */ + if(thishour != __crt_hour) + { + /* Search all the rules and print the number + * of alerts that each one fired. + */ + DumpLogstats(); + thishour = __crt_hour; + + /* Check if the date has changed */ + if(today != lf->day) + { + if(Config.stats) + { + /* Update the hourly stats (done daily) */ + Update_Hour(); + } + + if(OS_GetLogLocation(lf) < 0) + { + ErrorExit("%s: Error allocating log files", ARGV0); + } + + today = lf->day; + strncpy(prev_month, lf->mon, 3); + prev_year = lf->year; + } + } + + + /* Incrementing number of events received */ + hourly_events++; + + + /*** Running decoders ***/ + + /* Integrity check from syscheck */ + if(msg[0] == SYSCHECK_MQ) + { + hourly_syscheck++; + + if(!DecodeSyscheck(lf)) + { + /* We don't process syscheck events further */ + goto CLMEM; + } + + /* Getting log size */ + lf->size = strlen(lf->log); + } + + /* Rootcheck decoding */ + else if(msg[0] == ROOTCHECK_MQ) + { + if(!DecodeRootcheck(lf)) + { + /* We don't process rootcheck events further */ + goto CLMEM; + } + lf->size = strlen(lf->log); + } + + /* Host information special decoder */ + else if(msg[0] == HOSTINFO_MQ) + { + if(!DecodeHostinfo(lf)) + { + /* We don't process hostinfo events further */ + goto CLMEM; + } + lf->size = strlen(lf->log); + } + + /* Run the general Decoders */ + else + { + /* Getting log size */ + lf->size = strlen(lf->log); + + DecodeEvent(lf); + } + + + /* Firewall event */ + if(lf->decoder_info->type == FIREWALL) + { + /* If we could not get any information from + * the log, just ignore it + */ + hourly_firewall++; + if(Config.logfw) + { + if(!FW_Log(lf)) + { + goto CLMEM; + } + } + } + + + /* We only check if the last message is + * duplicated on syslog. + */ + else if(lf->decoder_info->type == SYSLOG) + { + /* Checking if the message is duplicated */ + if(LastMsg_Stats(lf->full_log) == 1) + goto CLMEM; + else + LastMsg_Change(lf->full_log); + } + + + /* Stats checking */ + if(Config.stats) + { + if(Check_Hour(lf) == 1) + { + void *saved_rule = lf->generated_rule; + char *saved_log; + + /* Saving previous log */ + saved_log = lf->full_log; + + lf->generated_rule = stats_rule; + lf->full_log = __stats_comment; + + + /* alert for statistical analysis */ + if(stats_rule->alert_opts & DO_LOGALERT) + { + __crt_ftell = ftell(_aflog); + OS_Log(lf); + } + + + /* Set lf to the old values */ + lf->generated_rule = saved_rule; + lf->full_log = saved_log; + } + } + + + /* Checking the rules */ + DEBUG_MSG("%s: DEBUG: Checking the rules - %d ", + ARGV0, lf->decoder_info->type); + + + /* Looping all the rules */ + rulenode_pt = OS_GetFirstRule(); + if(!rulenode_pt) + { + ErrorExit("%s: Rules in an inconsistent state. Exiting.", + ARGV0); + } + + + do + { + if(lf->decoder_info->type == OSSEC_ALERT) + { + if(!lf->generated_rule) + { + goto CLMEM; + } + + /* We go ahead in here and process the alert. */ + currently_rule = lf->generated_rule; + } + + /* The categories must match */ + else if(rulenode_pt->ruleinfo->category != + lf->decoder_info->type) + { + continue; + } + + /* Checking each rule. */ + else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt)) + == NULL) + { + continue; + } + + + /* Ignore level 0 */ + if(currently_rule->level == 0) + { + break; + } + + + /* Checking ignore time */ + if(currently_rule->ignore_time) + { + if(currently_rule->time_ignored == 0) + { + currently_rule->time_ignored = lf->time; + } + /* If the currently time - the time the rule was ignored + * is less than the time it should be ignored, + * leave (do not alert again). + */ + else if((lf->time - currently_rule->time_ignored) + < currently_rule->ignore_time) + { + break; + } + else + { + currently_rule->time_ignored = lf->time; + } + } + + + /* Pointer to the rule that generated it */ + lf->generated_rule = currently_rule; + + + /* Checking if we should ignore it */ + if(currently_rule->ckignore && IGnore(lf)) + { + /* Ignoring rule */ + lf->generated_rule = NULL; + break; + } + + + /* Checking if we need to add to ignore list */ + if(currently_rule->ignore) + { + AddtoIGnore(lf); + } + + + /* Log the alert if configured to ... */ + if(currently_rule->alert_opts & DO_LOGALERT) + { + __crt_ftell = ftell(_aflog); + OS_Log(lf); + } + + + /* Log to prelude */ + #ifdef PRELUDE + if(Config.prelude) + { + if(Config.prelude_log_level <= currently_rule->level) + { + OS_PreludeLog(lf); + } + } + #endif + + + /* Log to Picviz */ + if (Config.picviz) + { + OS_PicvizLog(lf); + } + + + /* Execute an active response */ + if(currently_rule->ar) + { + int do_ar; + active_response **rule_ar; + + rule_ar = currently_rule->ar; + + while(*rule_ar) + { + do_ar = 1; + if((*rule_ar)->ar_cmd->expect & USERNAME) + { + if(!lf->dstuser || + !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$")) + { + if(lf->dstuser) + merror(CRAFTED_USER, ARGV0, lf->dstuser); + do_ar = 0; + } + } + if((*rule_ar)->ar_cmd->expect & SRCIP) + { + if(!lf->srcip || + !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$")) + { + if(lf->srcip) + merror(CRAFTED_IP, ARGV0, lf->srcip); + do_ar = 0; + } + } + + if(do_ar) + { + OS_Exec(&execdq, &arq, lf, *rule_ar); + } + rule_ar++; + } + } + + + /* Copy the structure to the state memory of if_matched_sid */ + if(currently_rule->sid_prev_matched) + { + if(!OSList_AddData(currently_rule->sid_prev_matched, lf)) + { + merror("%s: Unable to add data to sig list.", ARGV0); + } + else + { + lf->sid_node_to_delete = + currently_rule->sid_prev_matched->last_node; + } + } + /* Group list */ + else if(currently_rule->group_prev_matched) + { + i = 0; + + while(i < currently_rule->group_prev_matched_sz) + { + if(!OSList_AddData( + currently_rule->group_prev_matched[i], + lf)) + { + merror("%s: Unable to add data to grp list.",ARGV0); + } + i++; + } + } + + OS_AddEvent(lf); + + break; + + }while((rulenode_pt = rulenode_pt->next) != NULL); + + + /* If configured to log all, do it */ + if(Config.logall) + OS_Store(lf); + + + /* Cleaning the memory */ + CLMEM: + + + /* Only clear the memory if the eventinfo was not + * added to the stateful memory + * -- message is free inside clean event -- + */ + if(lf->generated_rule == NULL) + Free_Eventinfo(lf); + + } + else + { + free(lf); + } + } + return; +} + + +/* CheckIfRuleMatch v0.1 + * Will check if the currently_rule matches the event information + */ +RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node) +{ + /* We check for: + * decoded_as, + * fts, + * word match (fast regex), + * regex, + * url, + * id, + * user, + * maxsize, + * protocol, + * srcip, + * dstip, + * srcport, + * dstport, + * time, + * weekday, + * status, + */ + RuleInfo *currently_rule = curr_node->ruleinfo; + + + /* Can't be null */ + if(!currently_rule) + { + merror("%s: Inconsistent state. currently rule NULL", ARGV0); + return(NULL); + } + + + #ifdef TESTRULE + if(full_output) + print_out(" Trying rule: %d - %s", currently_rule->sigid, + currently_rule->comment); + #endif + + + /* Checking if any decoder pre-matched here */ + if(currently_rule->decoded_as && + currently_rule->decoded_as != lf->decoder_info->id) + { + return(NULL); + } + + + + /* Checking program name */ + if(currently_rule->program_name) + { + if(!lf->program_name) + return(NULL); + + if(!OSMatch_Execute(lf->program_name, + lf->p_name_size, + currently_rule->program_name)) + return(NULL); + } + + + /* Checking for the id */ + if(currently_rule->id) + { + if(!lf->id) + { + return(NULL); + } + + if(!OSMatch_Execute(lf->id, + strlen(lf->id), + currently_rule->id)) + return(NULL); + } + + + /* Checking if any word to match exists */ + if(currently_rule->match) + { + if(!OSMatch_Execute(lf->log, lf->size, currently_rule->match)) + return(NULL); + } + + + + /* Checking if exist any regex for this rule */ + if(currently_rule->regex) + { + if(!OSRegex_Execute(lf->log, currently_rule->regex)) + return(NULL); + } + + + /* Checking for actions */ + if(currently_rule->action) + { + if(!lf->action) + return(NULL); + + if(strcmp(currently_rule->action,lf->action) != 0) + return(NULL); + } + + + /* Checking for the url */ + if(currently_rule->url) + { + if(!lf->url) + { + return(NULL); + } + + if(!OSMatch_Execute(lf->url, strlen(lf->url), currently_rule->url)) + { + return(NULL); + } + } + + + + /* Getting tcp/ip packet information */ + if(currently_rule->alert_opts & DO_PACKETINFO) + { + /* Checking for the srcip */ + if(currently_rule->srcip) + { + if(!lf->srcip) + { + return(NULL); + } + + if(!OS_IPFoundList(lf->srcip, currently_rule->srcip)) + { + return(NULL); + } + } + + /* Checking for the dstip */ + if(currently_rule->dstip) + { + if(!lf->dstip) + { + return(NULL); + } + + if(!OS_IPFoundList(lf->dstip, currently_rule->dstip)) + { + return(NULL); + } + } + + if(currently_rule->srcport) + { + if(!lf->srcport) + { + return(NULL); + } + + if(!OSMatch_Execute(lf->srcport, + strlen(lf->srcport), + currently_rule->srcport)) + { + return(NULL); + } + } + if(currently_rule->dstport) + { + if(!lf->dstport) + { + return(NULL); + } + + if(!OSMatch_Execute(lf->dstport, + strlen(lf->dstport), + currently_rule->dstport)) + { + return(NULL); + } + } + } /* END PACKET_INFO */ + + + /* Extra information from event */ + if(currently_rule->alert_opts & DO_EXTRAINFO) + { + /* Checking compiled rule. */ + if(currently_rule->compiled_rule) + { + if(!currently_rule->compiled_rule(lf)) + { + return(NULL); + } + } + + + /* Checking if exist any user to match */ + if(currently_rule->user) + { + if(lf->dstuser) + { + if(!OSMatch_Execute(lf->dstuser, + strlen(lf->dstuser), + currently_rule->user)) + return(NULL); + } + else if(lf->srcuser) + { + if(!OSMatch_Execute(lf->srcuser, + strlen(lf->srcuser), + currently_rule->user)) + return(NULL); + } + else + { + /* no user set */ + return(NULL); + } + } + + + /* Checking if any rule related to the size exist */ + if(currently_rule->maxsize) + { + if(lf->size < currently_rule->maxsize) + return(NULL); + } + + + /* Checking if we are in the right time */ + if(currently_rule->day_time) + { + if(!OS_IsonTime(lf->hour, currently_rule->day_time)) + { + return(NULL); + } + } + + + /* Checking week day */ + if(currently_rule->week_day) + { + if(!OS_IsonDay(__crt_wday, currently_rule->week_day)) + { + return(NULL); + } + } + + + /* Getting extra data */ + if(currently_rule->extra_data) + { + if(!lf->data) + return(NULL); + + if(!OSMatch_Execute(lf->data, + strlen(lf->data), + currently_rule->extra_data)) + return(NULL); + } + + + /* Checking hostname */ + if(currently_rule->hostname) + { + if(!lf->hostname) + return(NULL); + + if(!OSMatch_Execute(lf->hostname, + strlen(lf->hostname), + currently_rule->hostname)) + return(NULL); + } + + + /* Checking for status */ + if(currently_rule->status) + { + if(!lf->status) + return(NULL); + + if(!OSMatch_Execute(lf->status, + strlen(lf->status), + currently_rule->status)) + return(NULL); + } + } + + + /* Checking for the FTS flag */ + if(currently_rule->alert_opts & DO_FTS) + { + /** FTS CHECKS **/ + if(lf->decoder_info->fts) + { + if(lf->decoder_info->fts & FTS_DONE) + { + /* We already did the fts in here. */ + } + else if(!FTS(lf)) + { + return(NULL); + } + } + else + { + return(NULL); + } + } + + + /* If it is a context rule, search for it */ + if(currently_rule->context == 1) + { + if(!currently_rule->event_search(lf, currently_rule)) + return(NULL); + } + + #ifdef TESTRULE + if(full_output) + print_out(" *Rule %d matched.", currently_rule->sigid); + #endif + + + /* Search for dependent rules */ + if(curr_node->child) + { + RuleNode *child_node = curr_node->child; + RuleInfo *child_rule = NULL; + + #ifdef TESTRULE + if(full_output) + print_out(" *Trying child rules."); + #endif + + while(child_node) + { + child_rule = OS_CheckIfRuleMatch(lf, child_node); + if(child_rule != NULL) + { + return(child_rule); + } + + child_node = child_node->next; + } + } + + + /* If we are set to no alert, keep going */ + if(currently_rule->alert_opts & NO_ALERT) + { + return(NULL); + } + + + hourly_alerts++; + currently_rule->firedtimes++; + + return(currently_rule); /* Matched */ +} + + +/** void LoopRule(RuleNode *curr_node); + * Update each rule and print it to the logs. + */ +void LoopRule(RuleNode *curr_node, FILE *flog) +{ + if(curr_node->ruleinfo->firedtimes) + { + fprintf(flog, "%d-%d-%d-%d\n", + thishour, + curr_node->ruleinfo->sigid, + curr_node->ruleinfo->level, + curr_node->ruleinfo->firedtimes); + curr_node->ruleinfo->firedtimes = 0; + } + + if(curr_node->child) + { + RuleNode *child_node = curr_node->child; + + while(child_node) + { + LoopRule(child_node, flog); + child_node = child_node->next; + } + } + return; +} + + +/** void DumpLogstats(); + * Dump the hourly stats about each rule. + */ +void DumpLogstats() +{ + RuleNode *rulenode_pt; + char logfile[OS_FLSIZE +1]; + FILE *flog; + + /* Opening log file */ + snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year); + if(IsDir(logfile) == -1) + if(mkdir(logfile,0770) == -1) + { + merror(MKDIR_ERROR, ARGV0, logfile); + return; + } + + snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year,prev_month); + + if(IsDir(logfile) == -1) + if(mkdir(logfile,0770) == -1) + { + merror(MKDIR_ERROR,ARGV0,logfile); + return; + } + + + /* Creating the logfile name */ + snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log", + STATSAVED, + prev_year, + prev_month, + "totals", + today); + + flog = fopen(logfile, "a"); + if(!flog) + { + merror(FOPEN_ERROR, ARGV0, logfile); + return; + } + + rulenode_pt = OS_GetFirstRule(); + + if(!rulenode_pt) + { + ErrorExit("%s: Rules in an inconsistent state. Exiting.", + ARGV0); + } + + /* Looping on all the rules and printing the stats from them */ + do + { + LoopRule(rulenode_pt, flog); + }while((rulenode_pt = rulenode_pt->next) != NULL); + + + /* Print total for the hour */ + fprintf(flog, "%d--%d--%d--%d--%d\n\n", + thishour, + hourly_alerts, hourly_events, hourly_syscheck,hourly_firewall); + hourly_alerts = 0; + hourly_events = 0; + hourly_syscheck = 0; + hourly_firewall = 0; + + fclose(flog); +} + + + +/* EOF */ diff --git a/src/analysisd/analysisd.h b/src/analysisd/analysisd.h new file mode 100755 index 0000000..6175ebf --- /dev/null +++ b/src/analysisd/analysisd.h @@ -0,0 +1,50 @@ +/* @(#) $Id: analysisd.h,v 1.10 2009/06/24 17:06:21 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* v0.4(2005/09/08): Multiple additions. + * v0.1: + */ + + + +#ifndef _LOGAUDIT__H + +#define _LOGAUDIT__H + +#include + +/* Time structures */ +int today; +int thishour; + +int prev_year; +char prev_month[4]; + +int __crt_hour; +int __crt_wday; + + +/* For test rule only. */ +#ifdef TESTRULE +int full_output; +#endif + + +time_t c_time; /* Current time of event. Used everywhere */ + +/* Local host name */ +char __shost[512]; + +void *NULL_Decoder; + + +#define OSSEC_SERVER "ossec-server" +#endif diff --git a/src/analysisd/cleanevent.c b/src/analysisd/cleanevent.c new file mode 100755 index 0000000..6bfef2f --- /dev/null +++ b/src/analysisd/cleanevent.c @@ -0,0 +1,562 @@ +/* @(#) $Id: cleanevent.c,v 1.42 2009/06/24 17:06:21 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "os_regex/os_regex.h" + + +/* local headers */ +#include "eventinfo.h" +#include "analysisd.h" +#include "fts.h" +#include "config.h" + + +/* To translante between month (int) to month (char) */ +char *(month[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", + "Sep","Oct","Nov","Dec"}; + + + + +/* OS_CleanMSG v0.3: 2006/03/04 + * Format a received message in the + * Eventinfo structure. + */ +int OS_CleanMSG(char *msg, Eventinfo *lf) +{ + int loglen; + char *pieces; + struct tm *p; + + /* The message is formated in the following way: + * id:location:message. + */ + + + /* Ignoring the id of the message in here */ + msg+=2; + + + + /* Setting pieces as the message */ + pieces = strchr(msg, ':'); + if(!pieces) + { + merror(FORMAT_ERROR, ARGV0); + return(-1); + } + + *pieces = '\0'; + pieces++; + + + os_strdup(msg, lf->location); + + + /* Getting the log length */ + loglen = strlen(pieces) + 1; + + + /* Assigning the values in the strucuture (lf->full_log) */ + os_malloc((2*loglen) +1, lf->full_log); + + + /* Setting the whole message at full_log */ + strncpy(lf->full_log, pieces, loglen); + + + /* Log is the one used for parsing in the decoders and rules */ + lf->log = lf->full_log+loglen; + strncpy(lf->log, pieces, loglen); + + + + /* Checking for the syslog date format. + * ( ex: Dec 29 10:00:01 + * or 2007-06-14T15:48:55-04:00 for syslog-ng isodate + * or 2009-05-22T09:36:46.214994-07:00 for rsyslog ) + */ + if( + ( + (loglen > 17) && + (pieces[3] == ' ') && + (pieces[6] == ' ') && + (pieces[9] == ':') && + (pieces[12] == ':') && + (pieces[15] == ' ') && (lf->log+=16) + ) + || + ( + (loglen > 33) && + (pieces[4] == '-') && + (pieces[7] == '-') && + (pieces[10] == 'T') && + (pieces[13] == ':') && + (pieces[16] == ':') && + + ( + ((pieces[22] == ':') && + (pieces[25] == ' ') && (lf->log+=26)) || + + ((pieces[19] == '.') && + (pieces[29] == ':') && (lf->log+=32)) + ) + + ) + ) + { + /* Checking for an extra space in here */ + if(*lf->log == ' ') + lf->log++; + + + /* Hostname */ + pieces = lf->hostname = lf->log; + + + /* Checking for a valid hostname */ + while(isValidChar(*pieces) == 1) + { + pieces++; + } + + + /* Checking if it is a syslog without hostname (common on Solaris. */ + if(*pieces == ':' && pieces[1] == ' ') + { + /* Getting solaris 8/9 messages without hostname. + * In these cases, the process_name should be there. + * http://www.ossec.net/wiki/index.php/Log_Samples_Solaris + */ + lf->program_name = lf->hostname; + lf->hostname = NULL; + + /* Ending the program name string. */ + *pieces = '\0'; + + pieces+=2; + lf->log = pieces; + } + + + /* Extracting the hostname */ + else if(*pieces != ' ') + { + /* Invalid hostname */ + lf->hostname = NULL; + pieces = NULL; + } + else + { + /* Ending the hostname string */ + *pieces = '\0'; + + + /* Moving pieces to the beginning of the log message */ + pieces++; + lf->log = pieces; + + + /* Getting program_name */ + lf->program_name = pieces; + + + /* Extracting program_name */ + /* Valid names: + * p_name: + * p_name[pid]: + * p_name[pid]: [ID xx facility.severity] + * auth|security:info p_name: + * + */ + while(isValidChar(*pieces) == 1) + { + pieces++; + } + + + /* Checking for the first format: p_name: */ + if((*pieces == ':') && (pieces[1] == ' ')) + { + *pieces = '\0'; + pieces+=2; + } + + /* Checking for the second format: p_name[pid]: */ + else if((*pieces == '[') && (isdigit((int)pieces[1]))) + { + *pieces = '\0'; + pieces+=2; + while(isdigit((int)*pieces)) + pieces++; + + if((*pieces == ']')&& (pieces[1] == ':')&& (pieces[2] == ' ')) + { + pieces+=3; + } + /* Some systems are not terminating the program name with + * the ':'. Working around this in here.. + */ + else if((*pieces == ']') && (pieces[1] == ' ')) + { + pieces+=2; + } + else + { + /* Fixing for some weird log formats. */ + pieces--; + while(isdigit((int)*pieces)) + { + pieces--; + } + + if(*pieces == '\0') + *pieces = '['; + pieces = NULL; + lf->program_name = NULL; + } + } + /* AIX syslog. */ + else if((*pieces == '|') && islower((int)pieces[1])) + { + pieces+=2; + + /* Removing facility */ + while(isalnum((int)*pieces)) + pieces++; + + + if(*pieces == ':') + { + /* Removing severity. */ + pieces++; + while(isalnum((int)*pieces)) + pieces++; + + if(*pieces == ' ') + { + pieces++; + lf->program_name = pieces; + + + /* Getting program name again. */ + while(isValidChar(*pieces) == 1) + pieces++; + + /* Checking for the first format: p_name: */ + if((*pieces == ':') && (pieces[1] == ' ')) + { + *pieces = '\0'; + pieces+=2; + } + + /* Checking for the second format: p_name[pid]: */ + else if((*pieces == '[') && (isdigit((int)pieces[1]))) + { + *pieces = '\0'; + pieces+=2; + while(isdigit((int)*pieces)) + pieces++; + + if((*pieces == ']') && (pieces[1] == ':') && + (pieces[2] == ' ')) + { + pieces+=3; + } + else + { + pieces = NULL; + } + } + } + else + { + pieces = NULL; + lf->program_name = NULL; + } + } + /* Invalid AIX. */ + else + { + pieces = NULL; + lf->program_name = NULL; + } + } + else + { + pieces = NULL; + lf->program_name = NULL; + } + } + + + /* Removing [ID xx facility.severity] */ + if(pieces) + { + /* Setting log after program name */ + lf->log = pieces; + + if((pieces[0] == '[') && + (pieces[1] == 'I') && + (pieces[2] == 'D') && + (pieces[3] == ' ')) + { + pieces+=4; + + /* Going after the ] */ + pieces = strchr(pieces, ']'); + if(pieces) + { + pieces+=2; + lf->log = pieces; + } + } + } + + /* Getting program name size */ + if(lf->program_name) + { + lf->p_name_size = strlen(lf->program_name); + } + } + + /* xferlog date format + * Mon Apr 17 18:27:14 2006 1 64.160.42.130 + */ + else if((loglen > 28) && + (pieces[3] == ' ')&& + (pieces[7] == ' ')&& + (pieces[10] == ' ')&& + (pieces[13] == ':')&& + (pieces[16] == ':')&& + (pieces[19] == ' ')&& + (pieces[24] == ' ')&& + (pieces[26] == ' ')) + { + /* Moving log to the beginning of the message */ + lf->log+=24; + } + + + /* Checking for snort date format + * ex: 01/28-09:13:16.240702 [**] + */ + else if( (loglen > 24) && + (pieces[2] == '/') && + (pieces[5] == '-') && + (pieces[8] == ':') && + (pieces[11]== ':') && + (pieces[14]== '.') && + (pieces[21] == ' ') ) + { + lf->log+=23; + } + + /* Checking for apache log format */ + /* [Fri Feb 11 18:06:35 2004] [warn] */ + else if( (loglen > 27) && + (pieces[0] == '[') && + (pieces[4] == ' ') && + (pieces[8] == ' ') && + (pieces[11]== ' ') && + (pieces[14]== ':') && + (pieces[17]== ':') && + (pieces[20]== ' ') && + (pieces[25]== ']') ) + { + lf->log+=27; + } + + /* Checking for the osx asl log format. + * Examples: + * [Time 2006.12.28 15:53:55 UTC] [Facility auth] [Sender sshd] [PID 483] [Message error: PAM: Authentication failure for username from 192.168.0.2] [Level 3] [UID -2] [GID -2] [Host Hostname] + * [Time 2006.11.02 14:02:11 UTC] [Facility auth] [Sender sshd] [PID 856] + [Message refused connect from 59.124.44.34] [Level 4] [UID -2] [GID -2] + [Host robert-wyatts-emac] + */ + else if((loglen > 26) && + (pieces[0] == '[') && + (pieces[1] == 'T') && + (pieces[5] == ' ') && + (pieces[10] == '.') && + (pieces[13] == '.') && + (pieces[16] == ' ') && + (pieces[19] == ':')) + { + /* Do not read more than 1 message entry -> log tampering */ + short unsigned int done_message = 0; + + + /* Removing the date */ + lf->log+=25; + + /* Getting the desired values */ + pieces = strchr(lf->log, '['); + while(pieces) + { + pieces++; + + /* Getting the sender (set to program name) */ + if((strncmp(pieces, "Sender ", 7) == 0) && + (lf->program_name == NULL)) + { + pieces+=7; + lf->program_name = pieces; + + /* Getting the closing brackets */ + pieces = strchr(pieces, ']'); + if(pieces) + { + *pieces = '\0'; + + /* Setting program_name size */ + lf->p_name_size = strlen(lf->program_name); + + pieces++; + } + /* Invalid program name */ + else + { + lf->program_name = NULL; + break; + } + } + + /* Getting message */ + else if((strncmp(pieces, "Message ", 8) == 0) && + (done_message == 0)) + { + pieces+=8; + done_message = 1; + + lf->log = pieces; + + /* Getting the closing brackets */ + pieces = strchr(pieces, ']'); + if(pieces) + { + *pieces = '\0'; + pieces++; + } + /* Invalid log closure */ + else + { + break; + } + } + + /* Getting hostname */ + else if(strncmp(pieces, "Host ", 5) == 0) + { + pieces+=5; + lf->hostname = pieces; + + /* Getting the closing brackets */ + pieces = strchr(pieces, ']'); + if(pieces) + { + *pieces = '\0'; + pieces++; + } + + /* Invalid hostname */ + else + { + lf->hostname = NULL; + } + break; + } + + /* Getting next entry */ + pieces = strchr(pieces, '['); + } + } + + /* Checking for squid date format + * 1140804070.368 11623 + * seconds from 00:00:00 1970-01-01 UTC + */ + else if((loglen > 32) && + (pieces[0] == '1') && + (pieces[10] == '.') && + (pieces[14] == ' ') && + (isdigit((int)pieces[13])) && + (isdigit((int)pieces[1])) && + ((pieces[21] == ' ')||(pieces[22] == ' '))) + { + lf->log+=14; + + /* We need to start at the size of the event */ + while(*lf->log == ' ') + { + lf->log++; + } + } + + + /* Every message must be in the format + * hostname->location or + * (agent) ip->location. + */ + + + /* Setting hostname for local messages */ + if(lf->location[0] == '(') + { + /* Messages from an agent */ + lf->hostname = lf->location; + } + else if(lf->hostname == NULL) + { + lf->hostname = __shost; + } + + + /* Setting up the event data */ + lf->time = c_time; + p = localtime(&c_time); + + + + /* Assign hour, day, year and month values */ + lf->day = p->tm_mday; + lf->year = p->tm_year+1900; + strncpy(lf->mon,month[p->tm_mon],3); + snprintf(lf->hour, 9, "%02d:%02d:%02d", + p->tm_hour, + p->tm_min, + p->tm_sec); + + + + /* Setting the global hour/weekday */ + __crt_hour = p->tm_hour; + __crt_wday = p->tm_wday; + + + + #ifdef TESTRULE + print_out("**Phase 1: Completed pre-decoding."); + print_out(" full event: '%s'", lf->full_log); + print_out(" hostname: '%s'", lf->hostname); + print_out(" program_name: '%s'", lf->program_name); + print_out(" log: '%s'", lf->log); + #endif + return(0); + +} + +/* EOF */ diff --git a/src/analysisd/compiled_rules/.function_list b/src/analysisd/compiled_rules/.function_list new file mode 100644 index 0000000..3bd3d7d --- /dev/null +++ b/src/analysisd/compiled_rules/.function_list @@ -0,0 +1,3 @@ +check_id_size +comp_srcuser_dstuser +comp_mswin_targetuser_calleruser_diff diff --git a/src/analysisd/compiled_rules/Makefile b/src/analysisd/compiled_rules/Makefile new file mode 100755 index 0000000..f2a5873 --- /dev/null +++ b/src/analysisd/compiled_rules/Makefile @@ -0,0 +1,16 @@ +# Makefile for the compiled rules +# Daniel B. Cid +# http://www.ossec.net + +PT=../../ +NAME=ossec-analysisd + +include ../../Config.Make + + +plugins: + ./register_rule.sh build + $(CC) $(CFLAGS) -I../ -c $(SOURCES) + +clean: + -${CLEAN} diff --git a/src/analysisd/compiled_rules/generic_samples.c b/src/analysisd/compiled_rules/generic_samples.c new file mode 100644 index 0000000..8e05341 --- /dev/null +++ b/src/analysisd/compiled_rules/generic_samples.c @@ -0,0 +1,133 @@ +/* @(#) $Id: generic_samples.c,v 1.2 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "eventinfo.h" +#include "config.h" + + + +/** Note: If the rule fails to match it should return NULL. + * If you want processing to continue, return lf (the eventinfo structure). + */ + + + +/* Example 1: + * Comparing if the srcuser and dstuser are the same. If they are the same, + * return true. + * If any of them is not set, return true too. + */ +void *comp_srcuser_dstuser(Eventinfo *lf) +{ + if(!lf->srcuser || !lf->dstuser) + { + return(lf); + } + + if(strcmp(lf->srcuser, lf->dstuser) == 0) + { + return(lf); + } + + + /* In here, srcuser and dstuser are present and are different. */ + return(NULL); +} + + + +/* Example 2: + * Checking if the size of the id field is larger than 10. + */ +void *check_id_size(Eventinfo *lf) +{ + if(!lf->id) + { + return(NULL); + } + + if(strlen(lf->id) >= 10) + { + return(lf); + } + + return(NULL); +} + + + +/* Example 3: + * Comparing the Target Account Name and Caller User Name + * on Windows logs. + * It will return NULL (not match) if any of these values + * are not present or if they are the same. + * This function will return TRUE if they are NOT the same. + */ +void *comp_mswin_targetuser_calleruser_diff(Eventinfo *lf) +{ + char *target_user; + char *caller_user; + + + target_user = strstr(lf->log, "Target Account Name"); + caller_user = strstr(lf->log, "Caller User Name"); + + if(!target_user || !caller_user) + { + return(NULL); + } + + + /* We need to clear each user type and finish the string. + * It looks like: + * Target Account Name: account\t + * Caller User Name: account\t + */ + target_user = strchr(target_user, ':'); + caller_user = strchr(caller_user, ':'); + + if(!target_user || !caller_user) + { + return(NULL); + } + + + target_user++; + caller_user++; + + + while(*target_user != '\0') + { + if(*target_user != *caller_user) + return(lf); + + if(*target_user == '\t' || + (*target_user == ' ' && target_user[1] == ' ')) + break; + + target_user++;caller_user++; + } + + + /* If we got in here, the accounts are the same. + * So, we return NULL since we only want to alert if they are different. + */ + return(NULL); +} + + +/* END generic samples. */ + diff --git a/src/analysisd/compiled_rules/register_rule.sh b/src/analysisd/compiled_rules/register_rule.sh new file mode 100755 index 0000000..4ca0771 --- /dev/null +++ b/src/analysisd/compiled_rules/register_rule.sh @@ -0,0 +1,197 @@ +#!/bin/sh + + +# Variables - do not modify them. +CHF="compiled_rules.h" + + + +# Checking the location. +ls -la register_rule.sh > /dev/null 2>&1 +if [ ! $? = 0 ]; then + LOCALDIR=`dirname $0`; + cd ${LOCALDIR} + + ls -la register_rule.sh > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: You must run this script from the same directory." + exit 1; + fi +fi + + + +# Arguments +if [ "x$1" = "x" -o "x$1" = "xhelp" -o "x$1" = "x-h" ]; then + echo "$0 add " + echo "$0 list" + echo "$0 build" + echo "$0 save" + echo "$0 restore" + exit 0; +fi + + +if [ "x$1" = "xlist" ]; then + echo "*Available functions: " + cat .function_list | sort | uniq; + exit 0; + + +elif [ "x$1" = "xsave" ]; then + + ls -la /etc/ossec-init.conf > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to save rules. You must have OSSEC installed to do so." + exit 1; + fi + + cat /etc/ossec-init.conf > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to save rules. You must be root to do so." + exit 1; + fi + + + . /etc/ossec-init.conf + + + ls ${DIRECTORY}/compiled_rules > /dev/null 2>&1 + if [ ! $? = 0 ]; then + mkdir ${DIRECTORY}/compiled_rules > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to save rules. You must be root to do so." + exit 1; + fi + fi + + cp .function_list ${DIRECTORY}/compiled_rules/function_list > /dev/nulll 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to save rules. You must be root to do so." + exit 1; + fi + + for i in `ls *.c`; do + if [ ! "x$i" = "xgeneric_samples.c" ]; then + cp $i ${DIRECTORY}/compiled_rules/ > /dev/nulll 2>&1 + fi + done + echo "*Save completed at ${DIRECTORY}/compiled_rules/"; + exit 0; + + +elif [ "x$1" = "xrestore" ]; then + + ls -la /etc/ossec-init.conf > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to restore rules. You must have OSSEC installed to do so." + exit 1; + fi + + cat /etc/ossec-init.conf > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to restore rules. You must be root to do so." + exit 1; + fi + + + . /etc/ossec-init.conf + + + ls ${DIRECTORY}/compiled_rules/function_list > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "*No local compiled rules available to restore." + exit 0; + fi + + cat ${DIRECTORY}/compiled_rules/function_list >> .function_list + if [ ! $? = 0 ]; then + echo "ERROR: Unable to restore rules. Function list not present." + exit 1; + fi + + for i in `ls ${DIRECTORY}/compiled_rules/*.c`; do + if [ ! "x$i" = "xgeneric_samples.c" ]; then + cp $i ./ > /dev/nulll 2>&1 + fi + done + echo "*Restore completed from ${DIRECTORY}/compiled_rules/"; + exit 0; + + +elif [ "x$1" = "xbuild" ]; then + + ls -la .function_list > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Unable to build. No function is registered." + exit 1; + fi + + # Auto generating the file. + echo "/* This file is auto generated by $0. Do not touch it. */" > ${CHF} + echo "" >> ${CHF}; + + echo "/* Adding the function definitions. */" >> ${CHF}; + for i in `cat .function_list | sort| uniq`; do + echo "void *$i(Eventinfo *lf);" >> ${CHF}; + done + echo "" >> ${CHF}; + + echo "/* Adding the rules list. */" >> ${CHF}; + echo "void *(compiled_rules_list[]) = " >> ${CHF}; + echo "{" >> ${CHF}; + for i in `cat .function_list | sort| uniq`; do + echo " $i," >> ${CHF}; + done + echo " NULL" >> ${CHF}; + echo "};" >> ${CHF}; + echo "" >> ${CHF}; + + + echo "/* Adding the rules list names. */" >> ${CHF}; + echo "char *(compiled_rules_name[]) = " >> ${CHF}; + echo "{" >> ${CHF}; + for i in `cat .function_list |sort | uniq`; do + echo " \"$i\"," >> ${CHF}; + done + echo " NULL" >> ${CHF}; + echo "};" >> ${CHF}; + echo "" >> ${CHF}; + echo "/* EOF */" >> ${CHF}; + + + echo "*Build completed." + + +elif [ "x$1" = "xadd" ]; then + if [ "x$2" = "x" ]; then + echo "ERROR: Missing function name."; + echo "ex: $0 add "; + exit 1; + fi + + grep $2 ./*.c > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "ERROR: Function '$2' not found."; + exit 1; + fi + + grep $2 .function_list > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "ERROR: Function '$2' already added."; + exit 1; + fi + + echo $2 >> .function_list; + echo "*Function $2 added." + +else + + echo "ERROR: Invalid argument."; + exit 1; + +fi + + +# EOF + diff --git a/src/analysisd/config.c b/src/analysisd/config.c new file mode 100755 index 0000000..b833278 --- /dev/null +++ b/src/analysisd/config.c @@ -0,0 +1,83 @@ +/* @(#) $Id: config.c,v 1.32 2009/11/04 15:18:59 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Functions to handle the configuration files + */ + + +#include "shared.h" + +#include "os_xml/os_xml.h" +#include "os_regex/os_regex.h" + +#include "analysisd.h" +#include "config.h" + + +/* GlobalConf vv0.2: 2005/03/03 + * v0.2: Changing to support the new OS_XML + */ +int GlobalConf(char * cfgfile) +{ + int modules = 0; + + + /* Default values */ + Config.logall = 0; + Config.stats = 4; + Config.integrity = 8; + Config.rootcheck = 8; + Config.hostinfo = 8; + Config.picviz = 0; + Config.prelude = 0; + Config.memorysize = 1024; + Config.mailnotify = -1; + Config.keeplogdate = 0; + Config.syscheck_alert_new = 0; + Config.syscheck_auto_ignore = 1; + Config.ar = 0; + + Config.syscheck_ignore = NULL; + Config.white_list = NULL; + Config.hostname_white_list = NULL; + + /* Default actions -- only log above level 1 */ + Config.mailbylevel = 7; + Config.logbylevel = 1; + + Config.includes = NULL; + + modules|= CGLOBAL; + modules|= CRULES; + modules|= CALERTS; + + + /* Reading config */ + if(ReadConfig(modules, cfgfile, &Config, NULL)< 0) + { + return(OS_INVALID); + } + + /* Minimum memory size */ + if(Config.memorysize < 64) + Config.memorysize = 64; + + + return(0); +} + + + +/* EOF */ diff --git a/src/analysisd/config.h b/src/analysisd/config.h new file mode 100755 index 0000000..da73d3a --- /dev/null +++ b/src/analysisd/config.h @@ -0,0 +1,26 @@ +/* @(#) $Id: config.h,v 1.19 2009/11/20 15:38:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef _CONFIG__H + +#define _CONFIG__H + +#include "config/config.h" +#include "config/global-config.h" + +long int __crt_ftell; /* Global ftell pointer. */ +_Config Config; /* Global Config structure */ + + + +#endif diff --git a/src/analysisd/decoders/Makefile b/src/analysisd/decoders/Makefile new file mode 100755 index 0000000..3f59aca --- /dev/null +++ b/src/analysisd/decoders/Makefile @@ -0,0 +1,25 @@ +# Makefile for the decoders +# Daniel B. Cid +# http://www.ossec.net + +PT=../../ +NAME=ossec-analysisd + +include ../../Config.Make + + +dc: + cd plugins; make; + $(CC) $(CFLAGS) -I../ -c $(SOURCES) + ar cru decoders.a $(OBJECTS) plugins/*.o + ranlib decoders.a + +logtest: + cd plugins; make; + $(CC) $(CFLAGS) -DTESTRULE -I../ -c $(SOURCES) + ar cru decoders.a $(OBJECTS) plugins/*.o + ranlib decoders.a + +clean: + cd plugins; make clean; + -${CLEAN} diff --git a/src/analysisd/decoders/decode-xml.c b/src/analysisd/decoders/decode-xml.c new file mode 100755 index 0000000..bbb5e13 --- /dev/null +++ b/src/analysisd/decoders/decode-xml.c @@ -0,0 +1,954 @@ +/* @(#) $Id: decode-xml.c,v 1.47 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "os_regex/os_regex.h" +#include "os_xml/os_xml.h" + + +#include "analysisd.h" +#include "eventinfo.h" +#include "decoder.h" +#include "plugin_decoders.h" + + +#ifdef TESTRULE + #undef XML_LDECODER + #define XML_LDECODER "etc/local_decoder.xml" +#endif + + +/* Internal functions */ +char *_loadmemory(char *at, char *str); +OSStore *os_decoder_store = NULL; + + +/* Gets decoder id */ +int getDecoderfromlist(char *name) +{ + if(os_decoder_store) + { + return(OSStore_GetPosition(os_decoder_store, name)); + } + + return(0); +} + + +/* Adds decoder id */ +int addDecoder2list(char *name) +{ + if(os_decoder_store == NULL) + { + os_decoder_store = OSStore_Create(); + if(os_decoder_store == NULL) + { + merror(LIST_ERROR, ARGV0); + return(0); + } + } + + /* Storing data */ + if(!OSStore_Put(os_decoder_store, name, NULL)) + { + merror(LIST_ADD_ERROR, ARGV0); + return(0); + } + + return(1); +} + + +/* Set decoder ids */ +int os_setdecoderids(char *p_name) +{ + OSDecoderNode *node; + OSDecoderNode *child_node; + OSDecoderInfo *nnode; + + + node = OS_GetFirstOSDecoder(p_name); + + + /* Return if no node... + * This shouldn't happen here anyways. + */ + if(!node) + return(0); + + do + { + int p_id = 0; + char *p_name; + + nnode = node->osdecoder; + nnode->id = getDecoderfromlist(nnode->name); + + /* Id can noit be 0 */ + if(nnode->id == 0) + { + return(0); + } + + child_node = node->child; + + if(!child_node) + { + continue; + } + + + /* Setting parent id */ + p_id = nnode->id; + p_name = nnode->name; + + + /* Also setting on the child nodes */ + while(child_node) + { + nnode = child_node->osdecoder; + + if(nnode->use_own_name) + { + nnode->id = getDecoderfromlist(nnode->name); + } + else + { + nnode->id = p_id; + + /* Setting parent name */ + nnode->name = p_name; + } + + + /* Id can noit be 0 */ + if(nnode->id == 0) + { + return(0); + } + child_node = child_node->next; + } + }while((node=node->next) != NULL); + + return(1); +} + + +/* Read attributes */ +int ReadDecodeAttrs(char **names, char **values) +{ + if(!names || !values) + return(0); + + if(!names[0] || !values[0]) + { + return(0); + } + + if(strcmp(names[0], "offset") == 0) + { + int offset = 0; + + /* Offsets can be: after_parent, after_prematch + * or after_regex. + */ + if(strcmp(values[0],"after_parent") == 0) + { + offset |= AFTER_PARENT; + } + else if(strcmp(values[0],"after_prematch") == 0) + { + offset |= AFTER_PREMATCH; + } + else if(strcmp(values[0],"after_regex") == 0) + { + offset |= AFTER_PREVREGEX; + } + else + { + merror(INV_OFFSET, ARGV0, values[0]); + offset |= AFTER_ERROR; + } + + return(offset); + } + + /* Invalid attribute */ + merror(INV_ATTR, ARGV0, names[0]); + return(AFTER_ERROR); +} + + +/* ReaddecodeXML */ +int ReadDecodeXML(char *file) +{ + + OS_XML xml; + XML_NODE node = NULL; + + /* XML variables */ + /* These are the available options for the rule configuration */ + + char *xml_plugindecoder = "plugin_decoder"; + char *xml_decoder = "decoder"; + char *xml_decoder_name = "name"; + char *xml_decoder_status = "status"; + char *xml_usename = "use_own_name"; + char *xml_parent = "parent"; + char *xml_program_name = "program_name"; + char *xml_prematch = "prematch"; + char *xml_regex = "regex"; + char *xml_order = "order"; + char *xml_type = "type"; + char *xml_fts = "fts"; + char *xml_ftscomment = "ftscomment"; + + int i = 0; + OSDecoderInfo *NULL_Decoder_tmp = NULL; + + + /* Reading the XML */ + if((i = OS_ReadXML(file,&xml)) < 0) + { + if((i == -2) && (strcmp(file, XML_LDECODER) == 0)) + { + return(-2); + } + + merror(XML_ERROR, ARGV0, file, xml.err, xml.err_line); + return(0); + } + + + /* Applying any variable found */ + if(OS_ApplyVariables(&xml) != 0) + { + merror(XML_ERROR_VAR, ARGV0, file, xml.err); + return(0); + } + + + /* Getting the root elements */ + node = OS_GetElementsbyNode(&xml, NULL); + if(!node) + { + if(strcmp(file, XML_LDECODER) != 0) + { + merror(XML_ELEMNULL, ARGV0); + return(0); + } + + return(-2); + } + + + /* Zeroing NULL_decoder */ + os_calloc(1, sizeof(OSDecoderInfo), NULL_Decoder_tmp); + NULL_Decoder_tmp->id = 0; + NULL_Decoder_tmp->type = SYSLOG; + NULL_Decoder_tmp->name = NULL; + NULL_Decoder_tmp->fts = 0; + NULL_Decoder = (void *)NULL_Decoder_tmp; + + + + i = 0; + while(node[i]) + { + XML_NODE elements = NULL; + OSDecoderInfo *pi; + + int j = 0; + char *regex; + char *prematch; + char *p_name; + + + if(!node[i]->element || + strcasecmp(node[i]->element, xml_decoder) != 0) + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(0); + } + + + /* Getting name */ + if((!node[i]->attributes) || (!node[i]->values)|| + (!node[i]->values[0]) || (!node[i]->attributes[0])|| + (strcasecmp(node[i]->attributes[0],xml_decoder_name)!= 0)) + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(0); + } + + + /* Checking for additional entries */ + if(node[i]->attributes[1] && node[i]->values[1]) + { + if(strcasecmp(node[i]->attributes[0],xml_decoder_status)!= 0) + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(0); + } + + if(node[i]->attributes[2]) + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(0); + } + } + + + /* Getting decoder options */ + elements = OS_GetElementsbyNode(&xml,node[i]); + if(elements == NULL) + { + merror(XML_ELEMNULL, ARGV0); + return(0); + } + + /* Creating the OSDecoderInfo */ + pi = (OSDecoderInfo *)calloc(1,sizeof(OSDecoderInfo)); + if(pi == NULL) + { + merror(MEM_ERROR,ARGV0); + return(0); + } + + + /* Default values to the list */ + pi->parent = NULL; + pi->id = 0; + pi->name = strdup(node[i]->values[0]); + pi->order = NULL; + pi->plugindecoder = NULL; + pi->fts = 0; + pi->type = SYSLOG; + pi->prematch = NULL; + pi->program_name = NULL; + pi->regex = NULL; + pi->use_own_name = 0; + pi->get_next = 0; + pi->regex_offset = 0; + pi->prematch_offset = 0; + + regex = NULL; + prematch = NULL; + p_name = NULL; + + + /* Checking if strdup worked */ + if(!pi->name) + { + merror(MEM_ERROR, ARGV0); + return(0); + } + + /* Add decoder */ + if(!addDecoder2list(pi->name)) + { + merror(MEM_ERROR, ARGV0); + return(0); + } + + /* Looping on all the elements */ + while(elements[j]) + { + if(!elements[j]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(0); + } + else if(!elements[j]->content) + { + merror(XML_VALUENULL, ARGV0, elements[j]->element); + return(0); + } + + /* Checking if it is a child of a rule */ + else if(strcasecmp(elements[j]->element, xml_parent) == 0) + { + pi->parent = _loadmemory(pi->parent, elements[j]->content); + } + + /* Getting the regex */ + else if(strcasecmp(elements[j]->element,xml_regex) == 0) + { + int r_offset; + r_offset = ReadDecodeAttrs(elements[j]->attributes, + elements[j]->values); + + if(r_offset & AFTER_ERROR) + { + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + + /* Only the first regex entry may have an offset */ + if(regex && r_offset) + { + merror(DUP_REGEX, ARGV0, pi->name); + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + + /* regex offset */ + if(r_offset) + { + pi->regex_offset = r_offset; + } + + /* Assign regex */ + regex = + _loadmemory(regex, + elements[j]->content); + } + + /* Getting the pre match */ + else if(strcasecmp(elements[j]->element,xml_prematch)==0) + { + int r_offset; + + r_offset = ReadDecodeAttrs( + elements[j]->attributes, + elements[j]->values); + + if(r_offset & AFTER_ERROR) + { + ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name); + } + + + /* Only the first prematch entry may have an offset */ + if(prematch && r_offset) + { + merror(DUP_REGEX, ARGV0, pi->name); + ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name); + } + + if(r_offset) + { + pi->prematch_offset = r_offset; + } + + prematch = + _loadmemory(prematch, + elements[j]->content); + } + + /* Getting program name */ + else if(strcasecmp(elements[j]->element,xml_program_name) == 0) + { + p_name = _loadmemory(p_name, elements[j]->content); + } + + /* Getting the fts comment */ + else if(strcasecmp(elements[j]->element,xml_ftscomment)==0) + { + } + + else if(strcasecmp(elements[j]->element,xml_usename)==0) + { + if(strcmp(elements[j]->content,"true") == 0) + pi->use_own_name = 1; + } + + else if(strcasecmp(elements[j]->element, xml_plugindecoder) == 0) + { + int ed_c = 0; + for(ed_c = 0; plugin_decoders[ed_c] != NULL; ed_c++) + { + if(strcmp(plugin_decoders[ed_c], + elements[j]->content) == 0) + { + /* Initializing plugin */ + void (*dec_init)() = plugin_decoders_init[ed_c]; + + dec_init(); + pi->plugindecoder = plugin_decoders_exec[ed_c]; + break; + } + } + + /* Decoder not found */ + if(pi->plugindecoder == NULL) + { + merror(INV_DECOPTION, ARGV0, elements[j]->element, + elements[j]->content); + return(0); + } + } + + + /* Getting the type */ + else if(strcmp(elements[j]->element, xml_type) == 0) + { + if(strcmp(elements[j]->content, "firewall") == 0) + pi->type = FIREWALL; + else if(strcmp(elements[j]->content, "ids") == 0) + pi->type = IDS; + else if(strcmp(elements[j]->content, "web-log") == 0) + pi->type = WEBLOG; + else if(strcmp(elements[j]->content, "syslog") == 0) + pi->type = SYSLOG; + else if(strcmp(elements[j]->content, "squid") == 0) + pi->type = SQUID; + else if(strcmp(elements[j]->content, "windows") == 0) + pi->type = WINDOWS; + else if(strcmp(elements[j]->content, "host-information") == 0) + pi->type = HOST_INFO; + else if(strcmp(elements[j]->content, "ossec") == 0) + pi->type = OSSEC_RL; + else + { + merror("%s: Invalid decoder type '%s'.", + ARGV0, elements[j]->content); + return(0); + } + } + + /* Getting the order */ + else if(strcasecmp(elements[j]->element,xml_order)==0) + { + char **norder, **s_norder; + int order_int = 0; + + /* Maximum number is 8 for the order */ + norder = OS_StrBreak(',',elements[j]->content, 8); + s_norder = norder; + os_calloc(8, sizeof(void *), pi->order); + + + /* Initializing the function pointers */ + while(order_int < 8) + { + pi->order[order_int] = NULL; + order_int++; + } + order_int = 0; + + + /* Checking the values from the order */ + while(*norder) + { + if(strstr(*norder, "dstuser") != NULL) + { + pi->order[order_int] = (void *)DstUser_FP; + } + else if(strstr(*norder, "srcuser") != NULL) + { + pi->order[order_int] = (void *)SrcUser_FP; + } + /* User is an alias to dstuser */ + else if(strstr(*norder, "user") != NULL) + { + pi->order[order_int] = (void *)DstUser_FP; + } + else if(strstr(*norder, "srcip") != NULL) + { + pi->order[order_int] = (void *)SrcIP_FP; + } + else if(strstr(*norder, "dstip") != NULL) + { + pi->order[order_int] = (void *)DstIP_FP; + } + else if(strstr(*norder, "srcport") != NULL) + { + pi->order[order_int] = (void *)SrcPort_FP; + } + else if(strstr(*norder, "dstport") != NULL) + { + pi->order[order_int] = (void *)DstPort_FP; + } + else if(strstr(*norder, "protocol") != NULL) + { + pi->order[order_int] = (void *)Protocol_FP; + } + else if(strstr(*norder, "action") != NULL) + { + pi->order[order_int] = (void *)Action_FP; + } + else if(strstr(*norder, "id") != NULL) + { + pi->order[order_int] = (void *)ID_FP; + } + else if(strstr(*norder, "url") != NULL) + { + pi->order[order_int] = (void *)Url_FP; + } + else if(strstr(*norder, "data") != NULL) + { + pi->order[order_int] = (void *)Data_FP; + } + else if(strstr(*norder, "extra_data") != NULL) + { + pi->order[order_int] = (void *)Data_FP; + } + else if(strstr(*norder, "status") != NULL) + { + pi->order[order_int] = (void *)Status_FP; + } + else if(strstr(*norder, "system_name") != NULL) + { + pi->order[order_int] = (void *)SystemName_FP; + } + else + { + ErrorExit("decode-xml: Wrong field '%s' in the order" + " of decoder '%s'",*norder,pi->name); + } + + free(*norder); + norder++; + + order_int++; + } + + free(s_norder); + } + + /* Getting the fts order */ + else if(strcasecmp(elements[j]->element,xml_fts)==0) + { + char **norder; + char **s_norder; + + /* Maximum number is 8 for the fts */ + norder = OS_StrBreak(',',elements[j]->content, 8); + if(norder == NULL) + ErrorExit(MEM_ERROR,ARGV0); + + + /* Saving the initial point to free later */ + s_norder = norder; + + + /* Checking the values from the fts */ + while(*norder) + { + if(strstr(*norder, "dstuser") != NULL) + { + pi->fts|=FTS_DSTUSER; + } + if(strstr(*norder, "user") != NULL) + { + pi->fts|=FTS_DSTUSER; + } + else if(strstr(*norder, "srcuser") != NULL) + { + pi->fts|=FTS_SRCUSER; + } + else if(strstr(*norder, "srcip") != NULL) + { + pi->fts|=FTS_SRCIP; + } + else if(strstr(*norder, "dstip") != NULL) + { + pi->fts|=FTS_DSTIP; + } + else if(strstr(*norder, "id") != NULL) + { + pi->fts|=FTS_ID; + } + else if(strstr(*norder, "location") != NULL) + { + pi->fts|=FTS_LOCATION; + } + else if(strstr(*norder, "data") != NULL) + { + pi->fts|=FTS_DATA; + } + else if(strstr(*norder, "extra_data") != NULL) + { + pi->fts|=FTS_DATA; + } + else if(strstr(*norder, "system_name") != NULL) + { + pi->fts|=FTS_SYSTEMNAME; + } + else if(strstr(*norder, "name") != NULL) + { + pi->fts|=FTS_NAME; + } + else + { + ErrorExit("decode-xml: Wrong field '%s' in the fts" + " decoder '%s'",*norder, pi->name); + } + + free(*norder); + norder++; + } + + /* Clearing the memory here */ + free(s_norder); + } + else + { + merror("%s: Invalid element '%s' for " + "decoder '%s'", + ARGV0, + elements[j]->element, + node[i]->element); + return(0); + } + + /* NEXT */ + j++; + + } /* while(elements[j]) */ + + OS_ClearNode(elements); + + + /* Prematch must be set */ + if(!prematch && !pi->parent && !p_name) + { + merror(DECODE_NOPRE, ARGV0, pi->name); + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + + /* If pi->regex is not set, fts must not be set too */ + if((!regex && (pi->fts || pi->order)) || (regex && !pi->order)) + { + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + + + /* For the offsets */ + if(pi->regex_offset & AFTER_PARENT && !pi->parent) + { + merror(INV_OFFSET, ARGV0, "after_parent"); + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + + if(pi->regex_offset & AFTER_PREMATCH) + { + /* If after_prematch is set, but rule have + * no parent, set AFTER_PARENT and unset + * pre_match. + */ + if(!pi->parent) + { + pi->regex_offset = 0; + pi->regex_offset|= AFTER_PARENT; + } + else if(!prematch) + { + merror(INV_OFFSET, ARGV0, "after_prematch"); + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + } + + /* For the after_regex offset */ + if(pi->regex_offset & AFTER_PREVREGEX) + { + if(!pi->parent || !regex) + { + merror(INV_OFFSET, ARGV0, "after_regex"); + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + } + + + /* Checking the prematch offset */ + if(pi->prematch_offset) + { + /* Only the after parent is allowed */ + if(pi->prematch_offset & AFTER_PARENT) + { + if(!pi->parent) + { + merror(INV_OFFSET, ARGV0, "after_parent"); + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + } + else + { + merror(DEC_REGEX_ERROR, ARGV0, pi->name); + return(0); + } + } + + + /* Compiling the regex/prematch */ + if(prematch) + { + os_calloc(1, sizeof(OSRegex), pi->prematch); + if(!OSRegex_Compile(prematch, pi->prematch, 0)) + { + merror(REGEX_COMPILE, ARGV0, prematch, pi->prematch->error); + return(0); + } + + free(prematch); + } + + /* Compiling the p_name */ + if(p_name) + { + os_calloc(1, sizeof(OSMatch), pi->program_name); + if(!OSMatch_Compile(p_name, pi->program_name, 0)) + { + merror(REGEX_COMPILE, ARGV0, p_name, pi->program_name->error); + return(0); + } + + free(p_name); + } + + /* We may not have the pi->regex */ + if(regex) + { + os_calloc(1, sizeof(OSRegex), pi->regex); + if(!OSRegex_Compile(regex, pi->regex, OS_RETURN_SUBSTRING)) + { + merror(REGEX_COMPILE, ARGV0, regex, pi->regex->error); + return(0); + } + + /* We must have the sub_strings to retrieve the nodes */ + if(!pi->regex->sub_strings) + { + merror(REGEX_SUBS, ARGV0, regex); + return(0); + } + + free(regex); + } + + + /* Validating arguments */ + if(pi->plugindecoder && (pi->regex || pi->order)) + { + merror(DECODE_ADD, ARGV0, pi->name); + return(0); + } + + /* Adding osdecoder to the list */ + if(!OS_AddOSDecoder(pi)) + { + merror(DECODER_ERROR, ARGV0); + return(0); + } + + i++; + } /* while (node[i]) */ + + + /* Cleaning node and XML structures */ + OS_ClearNode(node); + + + OS_ClearXML(&xml); + + + /* Done over here */ + return(1); +} + + + +int SetDecodeXML() +{ + /* Adding rootcheck decoder to list */ + addDecoder2list(ROOTCHECK_MOD); + addDecoder2list(SYSCHECK_MOD); + addDecoder2list(SYSCHECK_MOD2); + addDecoder2list(SYSCHECK_MOD3); + addDecoder2list(SYSCHECK_NEW); + addDecoder2list(SYSCHECK_DEL); + addDecoder2list(HOSTINFO_NEW); + addDecoder2list(HOSTINFO_MOD); + + + /* Setting ids - for our two lists */ + if(!os_setdecoderids(NULL)) + { + merror(DECODER_ERROR, ARGV0); + return(0); + } + if(!os_setdecoderids(ARGV0)) + { + merror(DECODER_ERROR, ARGV0); + return(0); + } + + + /* Done over here */ + return(1); +} + + +/* _loadmemory: v0.1 + * Allocate memory at "*at" and copy *str to it. + * If *at already exist, realloc the memory and cat str + * on it. + * It will return the new string + */ +char *_loadmemory(char *at, char *str) +{ + if(at == NULL) + { + int strsize = 0; + if((strsize = strlen(str)) < OS_SIZE_1024) + { + at = calloc(strsize+1,sizeof(char)); + if(at == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + strncpy(at,str,strsize); + return(at); + } + else + { + merror(SIZE_ERROR,ARGV0,str); + return(NULL); + } + } + /* At is not null. Need to reallocat its memory and copy str to it */ + else + { + int strsize = strlen(str); + int atsize = strlen(at); + int finalsize = atsize+strsize+1; + if(finalsize > OS_SIZE_1024) + { + merror(SIZE_ERROR,ARGV0,str); + return(NULL); + } + at = realloc(at, (finalsize +1)*sizeof(char)); + if(at == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + strncat(at,str,strsize); + at[finalsize - 1] = '\0'; + + return(at); + } + return(NULL); +} + +/* EOF */ diff --git a/src/analysisd/decoders/decoder.c b/src/analysisd/decoders/decoder.c new file mode 100755 index 0000000..6587817 --- /dev/null +++ b/src/analysisd/decoders/decoder.c @@ -0,0 +1,407 @@ +/* @(#) $Id: decoder.c,v 1.42 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "os_regex/os_regex.h" +#include "os_xml/os_xml.h" + + +#include "eventinfo.h" +#include "decoder.h" + + + +/* DecodeEvent. + * Will use the osdecoders to decode the received event. + */ +void DecodeEvent(Eventinfo *lf) +{ + OSDecoderNode *node; + OSDecoderNode *child_node; + OSDecoderInfo *nnode; + + char *llog; + char *pmatch; + char *cmatch; + char *regex_prev = NULL; + + + node = OS_GetFirstOSDecoder(lf->program_name); + + + /* Return if no node... + * This shouldn't happen here anyways. + */ + if(!node) + return; + + + #ifdef TESTRULE + print_out("\n**Phase 2: Completed decoding."); + #endif + + do + { + nnode = node->osdecoder; + + + /* First checking program name */ + if(lf->program_name) + { + if(!OSMatch_Execute(lf->program_name, lf->p_name_size, + nnode->program_name)) + { + continue; + } + pmatch = lf->log; + } + + + /* If prematch fails, go to the next osdecoder in the list */ + if(nnode->prematch) + { + if(!(pmatch = OSRegex_Execute(lf->log, nnode->prematch))) + { + continue; + } + + /* Next character */ + if(*pmatch != '\0') + pmatch++; + } + + + #ifdef TESTRULE + print_out(" decoder: '%s'", nnode->name); + #endif + + + lf->decoder_info = nnode; + + + child_node = node->child; + + + /* If no child node is set, set the child node + * as if it were the child (ugh) + */ + if(!child_node) + { + child_node = node; + } + + else + { + /* Check if we have any child osdecoder */ + while(child_node) + { + nnode = child_node->osdecoder; + + + /* If we have a pre match and it matches, keep + * going. If we don't have a prematch, stop + * and go for the regexes. + */ + if(nnode->prematch) + { + char *llog; + + /* If we have an offset set, use it */ + if(nnode->prematch_offset & AFTER_PARENT) + { + llog = pmatch; + } + else + { + llog = lf->log; + } + + if((cmatch = OSRegex_Execute(llog, nnode->prematch))) + { + if(*cmatch != '\0') + cmatch++; + + lf->decoder_info = nnode; + + break; + } + } + else + { + cmatch = pmatch; + break; + } + + + /* If we have multiple regex-only childs, + * do not attempt to go any further with them. + */ + if(child_node->osdecoder->get_next) + { + do + { + child_node = child_node->next; + }while(child_node && child_node->osdecoder->get_next); + + if(!child_node) + return; + + child_node = child_node->next; + nnode = NULL; + } + else + { + child_node = child_node->next; + nnode = NULL; + } + } + } + + + /* Nothing matched */ + if(!nnode) + return; + + + /* If we have a external decoder, execute it */ + if(nnode->plugindecoder) + { + nnode->plugindecoder(lf); + return; + } + + + /* Getting the regex */ + while(child_node) + { + if(nnode->regex) + { + int i = 0; + + /* With regex we have multiple options + * regarding the offset: + * after the prematch, + * after the parent, + * after some previous regex, + * or any offset + */ + if(nnode->regex_offset) + { + if(nnode->regex_offset & AFTER_PARENT) + { + llog = pmatch; + } + else if(nnode->regex_offset & AFTER_PREMATCH) + { + llog = cmatch; + } + else if(nnode->regex_offset & AFTER_PREVREGEX) + { + if(!regex_prev) + llog = cmatch; + else + llog = regex_prev; + } + } + else + { + llog = lf->log; + } + + /* If Regex does not match, return */ + if(!(regex_prev = OSRegex_Execute(llog, nnode->regex))) + { + if(nnode->get_next) + { + child_node = child_node->next; + nnode = child_node->osdecoder; + continue; + } + return; + } + + + /* Fixing next pointer */ + if(*regex_prev != '\0') + regex_prev++; + + while(nnode->regex->sub_strings[i]) + { + if(nnode->order[i]) + { + nnode->order[i](lf, nnode->regex->sub_strings[i]); + nnode->regex->sub_strings[i] = NULL; + i++; + continue; + } + + /* We do not free any memory used above */ + os_free(nnode->regex->sub_strings[i]); + nnode->regex->sub_strings[i] = NULL; + i++; + } + + /* If we have a next regex, try getting it */ + if(nnode->get_next) + { + child_node = child_node->next; + nnode = child_node->osdecoder; + continue; + } + + break; + } + + /* If we don't have a regex, we may leave now */ + return; + } + + /* ok to return */ + return; + }while((node=node->next) != NULL); + + #ifdef TESTRULE + print_out(" No decoder matched."); + #endif + +} + + +/*** Event decoders ****/ +void *DstUser_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" dstuser: '%s'", field); + #endif + + lf->dstuser = field; + return(NULL); +} +void *SrcUser_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" srcuser: '%s'", field); + #endif + + lf->srcuser = field; + return(NULL); +} +void *SrcIP_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" srcip: '%s'", field); + #endif + + lf->srcip = field; + return(NULL); +} +void *DstIP_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" dstip: '%s'", field); + #endif + + lf->dstip = field; + return(NULL); +} +void *SrcPort_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" srcport: '%s'", field); + #endif + + lf->srcport = field; + return(NULL); +} +void *DstPort_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" dstport: '%s'", field); + #endif + + lf->dstport = field; + return(NULL); +} +void *Protocol_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" proto: '%s'", field); + #endif + + lf->protocol = field; + return(NULL); +} +void *Action_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" action: '%s'", field); + #endif + + lf->action = field; + return(NULL); +} +void *ID_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" id: '%s'", field); + #endif + + lf->id = field; + return(NULL); +} +void *Url_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" url: '%s'", field); + #endif + + lf->url = field; + return(NULL); +} +void *Data_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" extra_data: '%s'", field); + #endif + + lf->data = field; + return(NULL); +} +void *Status_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" status: '%s'", field); + #endif + + lf->status = field; + return(NULL); +} +void *SystemName_FP(Eventinfo *lf, char *field) +{ + #ifdef TESTRULE + print_out(" system_name: '%s'", field); + #endif + + lf->systemname = field; + return(NULL); +} +void *None_FP(Eventinfo *lf, char *field) +{ + free(field); + return(NULL); +} + + +/* EOF */ diff --git a/src/analysisd/decoders/decoder.h b/src/analysisd/decoders/decoder.h new file mode 100755 index 0000000..68a3339 --- /dev/null +++ b/src/analysisd/decoders/decoder.h @@ -0,0 +1,77 @@ +/* @(#) $Id: decoder.h,v 1.20 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef __DECODER_H + +#define __DECODER_H + + +/* We need the eventinfo and os_regex in here */ +#include "shared.h" +#include "os_regex/os_regex.h" + +#define AFTER_PARENT 0x001 /* 1 */ +#define AFTER_PREMATCH 0x002 /* 2 */ +#define AFTER_PREVREGEX 0x004 /* 4 */ +#define AFTER_ERROR 0x010 + + + +/* Decoder structure */ +typedef struct +{ + u_int8_t get_next; + u_int8_t type; + u_int8_t use_own_name; + + u_int16_t id; + u_int16_t regex_offset; + u_int16_t prematch_offset; + + int fts; + char *parent; + char *name; + char *ftscomment; + + OSRegex *regex; + OSRegex *prematch; + OSMatch *program_name; + + void (*plugindecoder)(void *lf); + void (**order)(void *lf, char *field); +}OSDecoderInfo; + +/* List structure */ +typedef struct _OSDecoderNode +{ + struct _OSDecoderNode *next; + struct _OSDecoderNode *child; + OSDecoderInfo *osdecoder; +}OSDecoderNode; + + + +/* Functions to Create the list, Add a osdecoder to the + * list and to get the first osdecoder. + */ +void OS_CreateOSDecoderList(); +int OS_AddOSDecoder(OSDecoderInfo *pi); +OSDecoderNode *OS_GetFirstOSDecoder(char *pname); +int getDecoderfromlist(char *name); + + +#endif + +/* EOF */ diff --git a/src/analysisd/decoders/decoders_list.c b/src/analysisd/decoders/decoders_list.c new file mode 100755 index 0000000..7fe23b6 --- /dev/null +++ b/src/analysisd/decoders/decoders_list.c @@ -0,0 +1,247 @@ +/* @(#) $Id: decoders_list.c,v 1.7 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include +#include +#include + +#include "headers/debug_op.h" +#include "decoder.h" + +#include "error_messages/error_messages.h" + + +/* We have two internal lists. One with the program_name + * and one without. This is going to improve greatly the + * performance of our decoder matching. + */ +OSDecoderNode *osdecodernode_forpname; +OSDecoderNode *osdecodernode_nopname; + + +/* Create the Event List */ +void OS_CreateOSDecoderList() +{ + osdecodernode_forpname = NULL; + osdecodernode_nopname = NULL; + + return; +} + + +/* Get first osdecoder */ +OSDecoderNode *OS_GetFirstOSDecoder(char *p_name) +{ + /* If program name is set, we return the forpname list. + */ + if(p_name) + { + return(osdecodernode_forpname); + } + + return(osdecodernode_nopname); +} + + +/* Add a osdecoder to the list */ +OSDecoderNode *_OS_AddOSDecoder(OSDecoderNode *s_node, OSDecoderInfo *pi) +{ + OSDecoderNode *tmp_node = s_node; + int rm_f = 0; + + if(tmp_node) + { + OSDecoderNode *new_node; + + new_node = (OSDecoderNode *)calloc(1,sizeof(OSDecoderNode)); + if(new_node == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + + /* Going to the last node */ + do + { + /* Checking for common names */ + if((strcmp(tmp_node->osdecoder->name,pi->name) == 0) && + (pi->parent != NULL)) + { + if((tmp_node->osdecoder->prematch || + tmp_node->osdecoder->regex) && pi->regex_offset) + { + rm_f = 1; + } + + /* Multi-regexes patterns cannot have prematch */ + if(pi->prematch) + { + merror(PDUP_INV, ARGV0,pi->name); + return(NULL); + } + + /* Multi-regex patterns cannot have fts set */ + if(pi->fts) + { + merror(PDUPFTS_INV, ARGV0,pi->name); + return(NULL); + } + + if(tmp_node->osdecoder->regex && pi->regex) + { + tmp_node->osdecoder->get_next = 1; + } + else + { + merror(DUP_INV, ARGV0,pi->name); + return(NULL); + } + } + + }while(tmp_node->next && (tmp_node = tmp_node->next)); + + + /* Must have a prematch set */ + if(!rm_f && (pi->regex_offset & AFTER_PREVREGEX)) + { + merror(INV_OFFSET, ARGV0, pi->name); + return(NULL); + } + + tmp_node->next = new_node; + + new_node->next = NULL; + new_node->osdecoder = pi; + new_node->child = NULL; + } + + else + { + /* Must not have a previous regex set */ + if(pi->regex_offset & AFTER_PREVREGEX) + { + merror(INV_OFFSET, ARGV0, pi->name); + return(NULL); + } + + tmp_node = (OSDecoderNode *)calloc(1, sizeof(OSDecoderNode)); + + if(tmp_node == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + tmp_node->child = NULL; + tmp_node->next = NULL; + tmp_node->osdecoder = pi; + + s_node = tmp_node; + } + + return (s_node); +} + + +int OS_AddOSDecoder(OSDecoderInfo *pi) +{ + int added = 0; + OSDecoderNode *osdecodernode; + + + /* We can actually have two lists. One with program + * name and the other without. + */ + if(pi->program_name) + { + osdecodernode = osdecodernode_forpname; + } + else + { + osdecodernode = osdecodernode_nopname; + } + + + /* Search for parent on both lists */ + if(pi->parent) + { + OSDecoderNode *tmp_node = osdecodernode_forpname; + + /* List with p_name */ + while(tmp_node) + { + if(strcmp(tmp_node->osdecoder->name, pi->parent) == 0) + { + tmp_node->child = _OS_AddOSDecoder(tmp_node->child, pi); + if(!tmp_node->child) + { + merror(DEC_PLUGIN_ERR, ARGV0); + return(0); + } + added = 1; + } + tmp_node = tmp_node->next; + } + + + /* List without p name */ + tmp_node = osdecodernode_nopname; + while(tmp_node) + { + if(strcmp(tmp_node->osdecoder->name, pi->parent) == 0) + { + tmp_node->child = _OS_AddOSDecoder(tmp_node->child, pi); + if(!tmp_node->child) + { + merror(DEC_PLUGIN_ERR, ARGV0); + return(0); + } + added = 1; + } + tmp_node = tmp_node->next; + } + + + /* OSDecoder was added correctly */ + if(added == 1) + { + return(1); + } + + merror(PPLUGIN_INV, ARGV0, pi->parent); + return(0); + } + else + { + osdecodernode = _OS_AddOSDecoder(osdecodernode, pi); + if(!osdecodernode) + { + merror(DEC_PLUGIN_ERR, ARGV0); + return(0); + } + + /* Updating global decoders pointers */ + if(pi->program_name) + { + osdecodernode_forpname = osdecodernode; + } + else + { + osdecodernode_nopname = osdecodernode; + } + } + return(1); +} + +/* EOF */ diff --git a/src/analysisd/decoders/hostinfo.c b/src/analysisd/decoders/hostinfo.c new file mode 100755 index 0000000..dccee36 --- /dev/null +++ b/src/analysisd/decoders/hostinfo.c @@ -0,0 +1,284 @@ +/* @(#) $Id: hostinfo.c,v 1.14 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Hostinfo decoder */ + + +#include "config.h" +#include "os_regex/os_regex.h" +#include "eventinfo.h" +#include "alerts/alerts.h" + + +#define HOSTINFO_FILE "/queue/fts/hostinfo" +#define HOST_HOST "Host: " +#define HOST_PORT " open ports: " + +#define HOST_CHANGED "Host information changed." +#define HOST_NEW "New host information added." +#define PREV_OPEN "Previously" + + +/** Global variables **/ +int hi_err = 0; +int id_new = 0; +int id_mod = 0; +char _hi_buf[OS_MAXSTR +1]; +FILE *_hi_fp = NULL; + + +/* Hostinfo decoder */ +OSDecoderInfo *hostinfo_dec = NULL; + + + +/* Check if the string matches. + */ +static char *__go_after(char *x, char *y) +{ + int x_s; + int y_s; + + /* X and Y must be not null */ + if(!x || !y) + return(NULL); + + x_s = strlen(x); + y_s = strlen(y); + + if(x_s <= y_s) + { + return(NULL); + } + + /* String does not match */ + if(strncmp(x,y,y_s) != 0) + { + return(NULL); + } + + x+=y_s; + + return(x); +} + + + +/* HostinfoInit + * Initialize the necessary information to process the host information + */ +void HostinfoInit() +{ + hi_err = 0; + + + /* Zeroing decoder */ + os_calloc(1, sizeof(OSDecoderInfo), hostinfo_dec); + hostinfo_dec->id = getDecoderfromlist(HOSTINFO_MOD); + hostinfo_dec->type = OSSEC_RL; + hostinfo_dec->name = HOSTINFO_MOD; + hostinfo_dec->fts = 0; + id_new = getDecoderfromlist(HOSTINFO_NEW); + id_mod = getDecoderfromlist(HOSTINFO_MOD); + + + + /* Opening HOSTINFO_FILE */ + snprintf(_hi_buf,OS_SIZE_1024, "%s", HOSTINFO_FILE); + + + /* r+ to read and write. Do not truncate */ + _hi_fp = fopen(_hi_buf,"r+"); + if(!_hi_fp) + { + /* try opening with a w flag, file probably does not exist */ + _hi_fp = fopen(_hi_buf, "w"); + if(_hi_fp) + { + fclose(_hi_fp); + _hi_fp = fopen(_hi_buf, "r+"); + } + } + if(!_hi_fp) + { + merror(FOPEN_ERROR, ARGV0, _hi_buf); + return; + } + + + /* clearing the buffer */ + memset(_hi_buf, '\0', OS_MAXSTR +1); + + return; +} + + + +/* HI_File + * Return the file pointer to be used + */ +FILE *HI_File() +{ + if(_hi_fp) + { + fseek(_hi_fp, 0, SEEK_SET); + return(_hi_fp); + } + + return(NULL); +} + + + +/* Special decoder for Hostinformation + * Not using the default rendering tools for simplicity + * and to be less resource intensive. + */ +int DecodeHostinfo(Eventinfo *lf) +{ + int changed = 0; + int bf_size; + + char *ip; + char *portss; + char *tmpstr; + + char buffer[OS_MAXSTR + 1]; + char opened[OS_MAXSTR + 1]; + FILE *fp; + + + /* Checking maximum number of errors */ + if(hi_err > 30) + { + merror("%s: Too many errors handling host information db. " + "Ignoring it.", ARGV0); + return(0); + } + + + /* Zeroing buffers */ + buffer[OS_MAXSTR] = '\0'; + opened[OS_MAXSTR] = '\0'; + fp = HI_File(); + if(!fp) + { + merror("%s: Error handling host information database.",ARGV0); + hi_err++; /* Increment hi error */ + + return(0); + } + + + /* Copying log to buffer */ + strncpy(buffer,lf->log, OS_MAXSTR); + + + /* Getting ip */ + tmpstr = __go_after(buffer, HOST_HOST); + if(!tmpstr) + { + merror("%s: Error handling host information database.",ARGV0); + hi_err++; + + return(0); + } + + + /* Setting ip */ + ip = tmpstr; + tmpstr = strchr(tmpstr, ','); + if(!tmpstr) + { + merror("%s: Error handling host information database.",ARGV0); + hi_err++; + + return(0); + } + *tmpstr = '\0'; + tmpstr++; + portss = tmpstr; + + + /* Getting ip only information -- to store */ + tmpstr = strchr(ip, ' '); + if(tmpstr) + { + *tmpstr = '\0'; + } + bf_size = strlen(ip); + + + /* Reads the file and search for a possible + * entry + */ + while(fgets(_hi_buf, OS_MAXSTR -1, fp) != NULL) + { + /* Ignore blank lines and lines with a comment */ + if(_hi_buf[0] == '\n' || _hi_buf[0] == '#') + { + continue; + } + + /* Removing new line */ + tmpstr = strchr(_hi_buf, '\n'); + if(tmpstr) + *tmpstr = '\0'; + + + /* Checking for ip */ + if(strncmp(ip, _hi_buf, bf_size) == 0) + { + /* Cannot use strncmp to avoid errors with crafted files */ + if(strcmp(portss, _hi_buf + bf_size) == 0) + { + return(0); + } + else + { + char *tmp_ports; + + tmp_ports = _hi_buf + (bf_size +1); + snprintf(opened, OS_MAXSTR, "%s %s", PREV_OPEN, tmp_ports); + changed = 1; + } + } + } + + + /* Adding the new entry at the end of the file */ + fseek(fp, 0, SEEK_END); + fprintf(fp,"%s%s\n", ip, portss); + + + /* Setting decoder */ + lf->decoder_info = hostinfo_dec; + + + /* Setting comment */ + if(changed == 1) + { + hostinfo_dec->id = id_mod; + //lf->generated_rule->last_events[0] = opened; + } + else + { + hostinfo_dec->id = id_new; + } + + + return(1); +} + + + +/* EOF */ diff --git a/src/analysisd/decoders/plugin_decoders.h b/src/analysisd/decoders/plugin_decoders.h new file mode 100755 index 0000000..dea9161 --- /dev/null +++ b/src/analysisd/decoders/plugin_decoders.h @@ -0,0 +1,59 @@ +/* @(#) $Id: plugin_decoders.h,v 1.7 2009/06/24 17:06:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef __PLUGINDECODER_H +#define __PLUGINDECODER_H + + +/* Plugin decoder for OpenBSD PF */ +void *PF_Decoder_Init(char *p_name); +void *PF_Decoder_Exec(void *lf); + +/* Plugin for Symantec Web Security */ +void *SymantecWS_Decoder_Init(char *p_name); +void *SymantecWS_Decoder_Exec(void *lf); + +/* Plugin for Sonicwall */ +void *SonicWall_Decoder_Init(char *p_name); +void *SonicWall_Decoder_Exec(void *lf); + +/* Plugin for OSSEC alert */ +void *OSSECAlert_Decoder_Init(char *p_name); +void *OSSECAlert_Decoder_Exec(void *lf); + + +/* List of plugins. All three lists must be in the same order */ +char *(plugin_decoders[])={"PF_Decoder", + "SymantecWS_Decoder", + "SonicWall_Decoder", + "OSSECAlert_Decoder", + NULL}; +void *(plugin_decoders_init[]) = {PF_Decoder_Init, + SymantecWS_Decoder_Init, + SonicWall_Decoder_Init, + OSSECAlert_Decoder_Init, + NULL}; +void *(plugin_decoders_exec[]) = {PF_Decoder_Exec, + SymantecWS_Decoder_Exec, + SonicWall_Decoder_Exec, + OSSECAlert_Decoder_Exec, + NULL}; + + + + +#endif + +/* EOF */ diff --git a/src/analysisd/decoders/plugins/Makefile b/src/analysisd/decoders/plugins/Makefile new file mode 100755 index 0000000..718d586 --- /dev/null +++ b/src/analysisd/decoders/plugins/Makefile @@ -0,0 +1,15 @@ +# Makefile for the decoders +# Daniel B. Cid +# http://www.ossec.net + +PT=../../../ +NAME=ossec-analysisd + +include ../../../Config.Make + + +plugins: + $(CC) $(CFLAGS) -I../../ -c $(SOURCES) + +clean: + -${CLEAN} diff --git a/src/analysisd/decoders/plugins/ossecalert_decoder.c b/src/analysisd/decoders/plugins/ossecalert_decoder.c new file mode 100644 index 0000000..2514d48 --- /dev/null +++ b/src/analysisd/decoders/plugins/ossecalert_decoder.c @@ -0,0 +1,181 @@ +/* @(#) $Id: ossecalert_decoder.c,v 1.3 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "eventinfo.h" +#include "config.h" + + + + +/* OSSECAlert decoder init */ +void *OSSECAlert_Decoder_Init() +{ + debug1("%s: Initializing OSSECAlert decoder.", ARGV0); + + + /* There is nothing else to do over here */ + return(NULL); +} + + + +#define oa_strchr(x,y,z) z = strchr(x,y); if(!z){ return(NULL); } + +/* OSSECAlert decoder + * Will extract the rule_id and point back to the original rule. + * Will also extract srcip and username if available. + * Examples: + * + */ +void *OSSECAlert_Decoder_Exec(Eventinfo *lf) +{ + char *oa_id = 0; + char *oa_location; + char *oa_val; + char oa_newlocation[256]; + char *tmp_str = NULL; + void *rule_pointer; + + + lf->decoder_info->type = OSSEC_ALERT; + + + /* Checking the alert level. */ + if(strncmp("Alert Level: ", lf->log, 12) != 0) + { + return(NULL); + } + + + /* Going past the level. */ + oa_strchr(lf->log, ';', tmp_str); + tmp_str++; + + + /* Getting rule id. */ + oa_strchr(tmp_str, ':', tmp_str); + tmp_str++; + if(*tmp_str != ' ') + { + return(NULL); + } + tmp_str++; + + + /* Getting id. */ + oa_id = tmp_str; + oa_strchr(tmp_str, ' ', tmp_str); + *tmp_str = '\0'; + + + /* Getting rule structure. */ + rule_pointer = OSHash_Get(Config.g_rules_hash, oa_id); + if(!rule_pointer) + { + merror("%s: WARN: Rule id '%s' not found internally.", ARGV0, oa_id); + *tmp_str = ' '; + return(NULL); + } + *tmp_str = ' '; + oa_strchr(tmp_str, ';', tmp_str); + tmp_str++; + + + /* Checking location. */ + if(strncmp(" Location: ", tmp_str, 11) != 0) + { + return(NULL); + } + tmp_str+=11; + + + /* Setting location; */ + oa_location = tmp_str; + + + oa_strchr(tmp_str, ';', tmp_str); + *tmp_str = '\0'; + + + /* Setting new location. */ + oa_newlocation[255] = '\0'; + + if(lf->hostname == lf->location) + { + snprintf(oa_newlocation, 255, "%s|%s", lf->location, oa_location); + free(lf->location); + os_strdup(oa_newlocation, lf->location); + lf->hostname = lf->location; + } + else + { + snprintf(oa_newlocation, 255, "%s->%s|%s", lf->hostname, + lf->location, oa_location); + free(lf->location); + os_strdup(oa_newlocation, lf->location); + lf->hostname = lf->location; + } + + *tmp_str = ';'; + tmp_str++; + + + /* Getting additional fields. */ + while((*tmp_str == ' ') && (tmp_str[1] != ' ')) + { + tmp_str++; + oa_val = tmp_str; + + tmp_str = strchr(tmp_str, ';'); + if(!tmp_str) + { + return(NULL); + } + *tmp_str = '\0'; + + if(strncmp(oa_val, "srcip: ", 7) == 0) + { + os_strdup(oa_val + 7, lf->srcip); + } + if(strncmp(oa_val, "user: ", 6) == 0) + { + os_strdup(oa_val + 6, lf->dstuser); + } + + *tmp_str = ';'; + tmp_str++; + } + + + /* Removing space. */ + while(*tmp_str == ' ') + tmp_str++; + + + /* Creating new full log. */ + free(lf->full_log); + os_strdup(tmp_str, lf->full_log); + lf->log = lf->full_log; + + + /* Rule that generated. */ + lf->generated_rule = rule_pointer; + + + return(NULL); +} + +/* END Decoder */ diff --git a/src/analysisd/decoders/plugins/pf_decoder.c b/src/analysisd/decoders/plugins/pf_decoder.c new file mode 100644 index 0000000..9457ae3 --- /dev/null +++ b/src/analysisd/decoders/plugins/pf_decoder.c @@ -0,0 +1,216 @@ +/* @(#) $Id: pf_decoder.c,v 1.5 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "eventinfo.h" + + +/* OpenBSD PF decoder init */ +void *PF_Decoder_Init() +{ + debug1("%s: Initializing PF decoder..", ARGV0); + + /* There is nothing to do over here */ + return(NULL); +} + + +/* OpenBSD PF decoder + * Will extract the action,srcip,dstip,protocol,srcport,dstport + * + * Examples: + * Mar 30 15:33:26 enigma pf: Mar 30 15:32:33.483712 rule 2/(match) pass in on xl0: 140.211.166.3.6667 > 192.168.2.10.16290: P 7408:7677(269) ack 1773 win 2520 (DF) + * Mar 30 15:47:05.522341 rule 4/(match) block in on lo0: 127.0.0.1.48784 > 127.0.0.1.23: S 1381529123:1381529123(0) win 16384 (DF) [tos 0x10] + * Mar 30 15:54:22.171929 rule 3/(match) pass out on xl0: 192.168.2.10.1514 > 192.168.2.190.1030: udp 73 + * Mar 30 15:54:22.174412 rule 3/(match) pass out on xl0: 192.168.2.10.1514 > 192.168.2.190.1030: udp 89 + * Mar 30 17:47:40.390143 rule 2/(match) pass in on lo0: 127.0.0.1 > 127.0.0.1: icmp: echo reply + * Mar 30 17:47:41.400075 rule 3/(match) pass out on lo0: 127.0.0.1 > 127.0.0.1: icmp: echo request + */ +void *PF_Decoder_Exec(Eventinfo *lf) +{ + int port_count = 0; + char *tmp_str; + char *aux_str; + + + /* tmp_str should be: Mar 30 15:54:22.171929 rule 3/(match) pass out .. */ + tmp_str = strchr(lf->log, ')'); + + + /* Didn't match */ + if(!tmp_str) + { + return(NULL); + } + + /* Going to the action entry */ + tmp_str++; + if(*tmp_str != ' ') + { + return(NULL); + } + tmp_str++; + + + /* tmp_str should be: pass out on xl0: 192.168.2.10.1514 .. */ + + + /* Getting action */ + if(*tmp_str == 'p') + { + os_strdup("pass", lf->action); + } + else if(*tmp_str == 'b') + { + os_strdup("block", lf->action); + } + else + { + /* Unknown action */ + return(NULL); + } + + + /* Jumping to the src ip */ + tmp_str = strchr(tmp_str, ':'); + if(!tmp_str) + { + return(NULL); + } + tmp_str++; + if(*tmp_str != ' ') + { + return(NULL); + } + tmp_str++; + + + + /* tmp_str should be: 192.168.2.10.1514 > .. */ + aux_str = strchr(tmp_str, ' '); + if(!aux_str) + return(NULL); + + + /* Setting aux_str to 0 for strdup */ + *aux_str = '\0'; + + os_strdup(tmp_str, lf->srcip); + + /* Aux str has a valid pointer to lf->log now */ + *aux_str = ' '; + aux_str++; + + + + /* Setting the source port if present */ + tmp_str = lf->srcip; + while(*tmp_str != '\0') + { + if(*tmp_str == '.') + port_count++; + + + /* Found port */ + if(port_count == 4) + { + *tmp_str = '\0'; + tmp_str++; + os_strdup(tmp_str, lf->srcport); + break; + } + + tmp_str++; + } + + + /* Invalid rest of log */ + if(*aux_str != '>') + return(NULL); + + + aux_str++; + if(*aux_str != ' ') + return(NULL); + aux_str++; + + + /* tmp_str should be: 192.168.2.10.1514: .. .. */ + tmp_str = strchr(aux_str, ':'); + if(!tmp_str) + return(NULL); + + + /* Setting aux_str to 0 for strdup */ + *tmp_str = '\0'; + + os_strdup(aux_str, lf->dstip); + + + /* tmp str has a valid pointer to lf->log now */ + *tmp_str = ':'; + tmp_str++; + + + /* Getting destination port */ + aux_str = lf->dstip; + port_count = 0; + while(*aux_str != '\0') + { + if(*aux_str == '.') + port_count++; + + + /* Found port */ + if(port_count == 4) + { + *aux_str = '\0'; + aux_str++; + os_strdup(aux_str, lf->dstport); + break; + } + + aux_str++; + } + + + /* Getting protocol */ + while(*tmp_str != '\0') + { + if(*tmp_str == ' ') + { + tmp_str++; + continue; + } + else if(*tmp_str == 'u') + { + os_strdup("UDP", lf->protocol); + } + else if(*tmp_str == 'i') + { + os_strdup("ICMP", lf->protocol); + } + else + { + os_strdup("TCP", lf->protocol); + } + + break; + } + + return(NULL); +} + +/* END Decoder */ diff --git a/src/analysisd/decoders/plugins/sonicwall_decoder.c b/src/analysisd/decoders/plugins/sonicwall_decoder.c new file mode 100644 index 0000000..d513c29 --- /dev/null +++ b/src/analysisd/decoders/plugins/sonicwall_decoder.c @@ -0,0 +1,330 @@ +/* @(#) $Id: sonicwall_decoder.c,v 1.5 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "eventinfo.h" + + +/* Regex to extract the priority and event id */ +#define SONICWALL_REGID "pri=(\\d) c=(\\d+) m=(\\d+) " + +/* Regex to extract the srcip and dst ip */ +#define SONICWALL_REGEX "src=(\\d+.\\d+.\\d+.\\d+):(\\d+):\\S+ " \ + "dst=(\\d+.\\d+.\\d+.\\d+):(\\d+):" + +/* Regex for the web proxy messages */ +#define SONICWALL_PROXY "result=(\\d+) dstname=(\\S+) arg=(\\S+)$" + + + +/** Global variables -- not thread safe. If we ever multi thread + * analysisd, these will need to be changed. + */ +OSRegex *__sonic_regex_prid = NULL; +OSRegex *__sonic_regex_sdip = NULL; +OSRegex *__sonic_regex_prox = NULL; + + + +/* SonicWall decoder init */ +void *SonicWall_Decoder_Init() +{ + debug1("%s: Initializing SonicWall decoder..", ARGV0); + + + /* Allocating memory */ + os_calloc(1, sizeof(OSRegex), __sonic_regex_sdip); + os_calloc(1, sizeof(OSRegex), __sonic_regex_prid); + os_calloc(1, sizeof(OSRegex), __sonic_regex_prox); + + /* Compiling our regexes */ + if(!OSRegex_Compile(SONICWALL_REGEX, __sonic_regex_sdip, OS_RETURN_SUBSTRING)) + { + merror(REGEX_COMPILE, ARGV0, SONICWALL_REGEX, __sonic_regex_sdip->error); + return(0); + } + if(!OSRegex_Compile(SONICWALL_REGID, __sonic_regex_prid, OS_RETURN_SUBSTRING)) + { + merror(REGEX_COMPILE, ARGV0, SONICWALL_REGID, __sonic_regex_prid->error); + return(0); + } + if(!OSRegex_Compile(SONICWALL_PROXY, __sonic_regex_prox, OS_RETURN_SUBSTRING)) + { + merror(REGEX_COMPILE, ARGV0, SONICWALL_PROXY, __sonic_regex_prox->error); + return(0); + } + + /* We must have the sub_strings to retrieve the nodes */ + if(!__sonic_regex_sdip->sub_strings) + { + merror(REGEX_SUBS, ARGV0, SONICWALL_REGEX); + return(0); + } + if(!__sonic_regex_prid->sub_strings) + { + merror(REGEX_SUBS, ARGV0, SONICWALL_REGID); + return(0); + } + if(!__sonic_regex_prox->sub_strings) + { + merror(REGEX_SUBS, ARGV0, SONICWALL_PROXY); + return(0); + } + + /* There is nothing else to do over here */ + return(NULL); +} + + + +/* SonicWall decoder + * Will extract the id, severity, action, srcip, dstip, protocol,srcport,dstport + * severity will be extracted as status. + * Examples: + * Jan 3 13:45:36 192.168.5.1 id=firewall sn=000SERIAL time="2007-01-03 14:48:06" fw=1.1.1.1 pri=6 c=262144 m=98 msg="Connection Opened" n=23419 src=2.2.2.2:36701:WAN dst=1.1.1.1:50000:WAN proto=tcp/50000 + * Jan 3 13:45:36 192.168.5.1 id=firewall sn=000SERIAL time="2007-01-03 14:48:07" fw=1.1.1.1 pri=1 c=32 m=30 msg="Administrator login denied due to bad credentials" n=7 src=2.2.2.2:36701:WAN dst=1.1.1.1:50000:WAN + */ +void *SonicWall_Decoder_Exec(Eventinfo *lf) +{ + int i = 0; + char category[8]; + char *tmp_str = NULL; + + + /* Zeroing category */ + category[0] = '\0'; + lf->decoder_info->type = SYSLOG; + + + + /** We first run our regex to extract the severity, cat and id. **/ + if(!(tmp_str = OSRegex_Execute(lf->log, __sonic_regex_prid))) + { + return(NULL); + } + + /* Getting severity, id and category */ + if(__sonic_regex_prid->sub_strings[0] && + __sonic_regex_prid->sub_strings[1] && + __sonic_regex_prid->sub_strings[2]) + { + lf->status = __sonic_regex_prid->sub_strings[0]; + lf->id = __sonic_regex_prid->sub_strings[2]; + + + /* Getting category */ + strncpy(category, __sonic_regex_prid->sub_strings[1], 7); + + + /* Clearing all substrings */ + __sonic_regex_prid->sub_strings[0] = NULL; + __sonic_regex_prid->sub_strings[2] = NULL; + + free(__sonic_regex_prid->sub_strings[1]); + __sonic_regex_prid->sub_strings[1] = NULL; + } + else + { + i = 0; + while(__sonic_regex_prid->sub_strings[i]) + { + free(__sonic_regex_prid->sub_strings[i]); + __sonic_regex_prid->sub_strings[i] = NULL; + i++; + } + + return(NULL); + } + + + + + /** Getting ips and ports **/ + if(!(tmp_str = OSRegex_Execute(tmp_str, __sonic_regex_sdip))) + { + return(NULL); + } + if(__sonic_regex_sdip->sub_strings[0] && + __sonic_regex_sdip->sub_strings[1] && + __sonic_regex_sdip->sub_strings[2] && + __sonic_regex_sdip->sub_strings[3]) + { + /* Setting all the values */ + lf->srcip = __sonic_regex_sdip->sub_strings[0]; + lf->srcport = __sonic_regex_sdip->sub_strings[1]; + lf->dstip = __sonic_regex_sdip->sub_strings[2]; + lf->dstport = __sonic_regex_sdip->sub_strings[3]; + + + /* Clearing substrings */ + __sonic_regex_sdip->sub_strings[0] = NULL; + __sonic_regex_sdip->sub_strings[1] = NULL; + __sonic_regex_sdip->sub_strings[2] = NULL; + __sonic_regex_sdip->sub_strings[3] = NULL; + + + /* Looking for protocol */ + tmp_str = strchr(tmp_str, ' '); + if(tmp_str) + { + tmp_str++; + if(strncmp(tmp_str, "proto=", 6) == 0) + { + char *proto = NULL; + + i = 0; + tmp_str += 6; + + + /* Allocating memory for the protocol */ + os_calloc(8, sizeof(char), proto); + while(isValidChar(*tmp_str) && (*tmp_str != '/')) + { + proto[i] = *tmp_str; + i++; + tmp_str++; + + if(i >= 6) + { + break; + } + } + + /* Setting protocol to event info structure */ + lf->protocol = proto; + } + } + } + else + { + i = 0; + while(__sonic_regex_sdip->sub_strings[i]) + { + free(__sonic_regex_sdip->sub_strings[i]); + __sonic_regex_sdip->sub_strings[i] = 0; + i++; + } + + return(NULL); + } + + + + + /** Setting the category/action based on the id. **/ + + /* IDS event */ + if(strcmp(category, "32") == 0) + { + lf->decoder_info->type = IDS; + } + + /* Firewall connection opened */ + else if((strcmp(lf->id, "98") == 0) || + (strcmp(lf->id, "597") == 0) || + (strcmp(lf->id, "598") == 0)) + { + lf->decoder_info->type = FIREWALL; + os_strdup("pass", lf->action); + } + + /* Firewall connection dropped */ + else if((strcmp(lf->id, "38") == 0) || + (strcmp(lf->id, "36") == 0) || + (strcmp(lf->id, "173") == 0) || + (strcmp(lf->id, "174") == 0) || + (strcmp(lf->id, "37") == 0)) + { + lf->decoder_info->type = FIREWALL; + os_strdup("drop", lf->action); + } + + /* Firewall connection closed */ + else if(strcmp(lf->id, "537") == 0) + { + lf->decoder_info->type = FIREWALL; + os_strdup("close", lf->action); + } + + /* Proxy msg */ + else if(strcmp(lf->id, "97") == 0) + { + lf->decoder_info->type = SQUID; + + + /* Checking if tmp_str is valid */ + if(!tmp_str) + { + return(NULL); + } + + + /* We first run our regex to extract the severity and id. */ + if(!OSRegex_Execute(tmp_str, __sonic_regex_prox)) + { + return(NULL); + } + + + /* Getting HTTP responde code as id */ + if(__sonic_regex_prox->sub_strings[0]) + { + free(lf->id); + lf->id = __sonic_regex_prox->sub_strings[0]; + __sonic_regex_prox->sub_strings[0] = NULL; + } + else + { + return(NULL); + } + + + /* Getting HTTP page */ + if(__sonic_regex_prox->sub_strings[1] && + __sonic_regex_prox->sub_strings[2]) + { + char *final_url; + int url_size = strlen(__sonic_regex_prox->sub_strings[1]) + + strlen(__sonic_regex_prox->sub_strings[2]) + 2; + + os_calloc(url_size +1, sizeof(char), final_url); + snprintf(final_url, url_size, "%s%s", + __sonic_regex_prox->sub_strings[1], + __sonic_regex_prox->sub_strings[2]); + + + /* Clearing the memory */ + free(__sonic_regex_prox->sub_strings[1]); + free(__sonic_regex_prox->sub_strings[2]); + __sonic_regex_prox->sub_strings[1] = NULL; + __sonic_regex_prox->sub_strings[2] = NULL; + + + /* Setting the url */ + lf->url = final_url; + } + else + { + merror("%s: Error getting regex - SonicWall." , ARGV0); + } + + return(NULL); + } + + + return(NULL); +} + +/* END Decoder */ diff --git a/src/analysisd/decoders/plugins/symantecws_decoder.c b/src/analysisd/decoders/plugins/symantecws_decoder.c new file mode 100644 index 0000000..cfb99a8 --- /dev/null +++ b/src/analysisd/decoders/plugins/symantecws_decoder.c @@ -0,0 +1,149 @@ +/* @(#) $Id: symantecws_decoder.c,v 1.5 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +#include "shared.h" +#include "eventinfo.h" + + +/* Symantec Web Security decoder init */ +void *SymantecWS_Decoder_Init() +{ + debug1("%s: Initializing SymantecWS decoder..", ARGV0); + + /* There is nothing to do over here */ + return(NULL); +} + + +/* Symantec Web Security decoder + * Will extract the action, srcip, id, url and username. + * + * Examples (also online at + * http://www.ossec.net/wiki/index.php/Symantec_WebSecurity ). + * 20070717,73613,1=5,11=10.1.1.3,10=userc,3=1,2=1 + * 20070717,73614,1=5,11=1.2.3.4,1106=News,60=http://news.bbc.co.uk/,10=userX,1000=212.58.240.42,2=27 + */ +void *SymantecWS_Decoder_Exec(Eventinfo *lf) +{ + int count = 0; + char buf_str[OS_SIZE_1024 +1]; + char *tmp_str = NULL; + + /* Initializing buffer */ + buf_str[0] = '\0'; + buf_str[OS_SIZE_1024] = '\0'; + + + /* Removing date and time */ + if(!(tmp_str = strchr(lf->log, ','))) + { + return(NULL); + } + if(!(tmp_str = strchr(tmp_str, ','))) + { + return(NULL); + } + tmp_str++; + + + /* Getting all the values */ + while(tmp_str != NULL) + { + /* Checking if we have the username */ + if(strncmp(tmp_str, "10=", 3) == 0) + { + count = 0; + tmp_str+=3; + while(*tmp_str != '\0' && count < 128 && *tmp_str != ',') + { + buf_str[count] = *tmp_str; + count++; tmp_str++; + } + buf_str[count] = '\0'; + + if(!lf->dstuser) + { + os_strdup(buf_str, lf->dstuser); + } + } + + /* Checking the ip address */ + else if(strncmp(tmp_str, "11=", 3) == 0) + { + count = 0; + tmp_str+=3; + while(*tmp_str != '\0' && count < 128 && *tmp_str != ',') + { + buf_str[count] = *tmp_str; + count++; tmp_str++; + } + buf_str[count] = '\0'; + + /* Avoiding memory leaks -- only adding the first one */ + if(!lf->srcip) + { + os_strdup(buf_str, lf->srcip); + } + } + + /* Getting the URL */ + else if(strncmp(tmp_str, "60=", 3) == 0) + { + count = 0; + tmp_str+=3; + while(*tmp_str != '\0' && count < OS_SIZE_1024 && *tmp_str != ',') + { + buf_str[count] = *tmp_str; + count++; tmp_str++; + } + buf_str[count] = '\0'; + + /* Avoiding memory leaks -- only adding the first one */ + if(!lf->url) + { + os_strdup(buf_str, lf->url); + } + } + + /* Getting ID */ + else if((strncmp(tmp_str, "3=", 2) == 0) || + (strncmp(tmp_str, "2=", 2) == 0)) + { + count = 0; + while(*tmp_str != '\0' && count < 9) + { + buf_str[count] = *tmp_str; + count++; tmp_str++; + } + buf_str[count] = '\0'; + + /* Avoiding memory leaks -- only adding the first one */ + if(!lf->id) + { + os_strdup(buf_str, lf->id); + } + } + + /* Getting next entry */ + tmp_str = strchr(tmp_str, ','); + if(tmp_str) + { + tmp_str++; + } + } + + return(NULL); +} + +/* END Decoder */ diff --git a/src/analysisd/decoders/rootcheck.c b/src/analysisd/decoders/rootcheck.c new file mode 100755 index 0000000..d134ae2 --- /dev/null +++ b/src/analysisd/decoders/rootcheck.c @@ -0,0 +1,242 @@ +/* @(#) $Id: rootcheck.c,v 1.26 2009/07/24 18:34:11 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Rootcheck decoder */ + + +#include "config.h" +#include "os_regex/os_regex.h" +#include "eventinfo.h" +#include "alerts/alerts.h" +#include "decoder.h" + + +#define ROOTCHECK_DIR "/queue/rootcheck" + + +/** Global variables **/ +char *rk_agent_ips[MAX_AGENTS]; +FILE *rk_agent_fps[MAX_AGENTS]; + +int rk_err; + +/* Rootcheck decoder */ +OSDecoderInfo *rootcheck_dec = NULL; + + +/* SyscheckInit + * Initialize the necessary information to process the syscheck information + */ +void RootcheckInit() +{ + int i = 0; + + rk_err = 0; + + for(;iid = getDecoderfromlist(ROOTCHECK_MOD); + rootcheck_dec->type = OSSEC_RL; + rootcheck_dec->name = ROOTCHECK_MOD; + rootcheck_dec->fts = 0; + + debug1("%s: RootcheckInit completed.", ARGV0); + + return; +} + + +/* RK_File + * Return the file pointer to be used + */ +FILE *RK_File(char *agent, int *agent_id) +{ + int i = 0; + char rk_buf[OS_SIZE_1024 +1]; + + while(rk_agent_ips[i] != NULL) + { + if(strcmp(rk_agent_ips[i],agent) == 0) + { + /* pointing to the beginning of the file */ + fseek(rk_agent_fps[i],0, SEEK_SET); + *agent_id = i; + return(rk_agent_fps[i]); + } + + i++; + } + + /* If here, our agent wasn't found */ + rk_agent_ips[i] = strdup(agent); + + if(rk_agent_ips[i] != NULL) + { + snprintf(rk_buf,OS_SIZE_1024, "%s/%s", ROOTCHECK_DIR,agent); + + /* r+ to read and write. Do not truncate */ + rk_agent_fps[i] = fopen(rk_buf,"r+"); + if(!rk_agent_fps[i]) + { + /* try opening with a w flag, file probably does not exist */ + rk_agent_fps[i] = fopen(rk_buf, "w"); + if(rk_agent_fps[i]) + { + fclose(rk_agent_fps[i]); + rk_agent_fps[i] = fopen(rk_buf, "r+"); + } + } + if(!rk_agent_fps[i]) + { + merror(FOPEN_ERROR, ARGV0, rk_buf); + + free(rk_agent_ips[i]); + rk_agent_ips[i] = NULL; + + return(NULL); + } + + /* Returning the opened pointer (the beginning of it) */ + fseek(rk_agent_fps[i],0, SEEK_SET); + *agent_id = i; + return(rk_agent_fps[i]); + } + + else + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + + return(NULL); +} + + +/* Special decoder for rootcheck + * Not using the default rendering tools for simplicity + * and to be less resource intensive + */ +int DecodeRootcheck(Eventinfo *lf) +{ + int agent_id; + + char *tmpstr; + char rk_buf[OS_SIZE_2048 +1]; + + FILE *fp; + + fpos_t fp_pos; + + /* Zeroing rk_buf */ + rk_buf[0] = '\0'; + rk_buf[OS_SIZE_2048] = '\0'; + + fp = RK_File(lf->location, &agent_id); + + if(!fp) + { + merror("%s: Error handling rootcheck database.",ARGV0); + rk_err++; /* Increment rk error */ + + return(0); + } + + /* Getting initial position */ + if(fgetpos(fp, &fp_pos) == -1) + { + merror("%s: Error handling rootcheck database (fgetpos).",ARGV0); + return(0); + } + + + /* Reads the file and search for a possible + * entry + */ + while(fgets(rk_buf, OS_SIZE_2048 -1, fp) != NULL) + { + /* Ignore blank lines and lines with a comment */ + if(rk_buf[0] == '\n' || rk_buf[0] == '#') + { + if(fgetpos(fp, &fp_pos) == -1) + { + merror("%s: Error handling rootcheck database " + "(fgetpos2).",ARGV0); + return(0); + } + continue; + } + + /* Removing new line */ + tmpstr = strchr(rk_buf, '\n'); + if(tmpstr) + { + *tmpstr = '\0'; + } + + + /* Old format without the time stampts */ + if(rk_buf[0] != '!') + { + /* Cannot use strncmp to avoid errors with crafted files */ + if(strcmp(lf->log, rk_buf) == 0) + { + rootcheck_dec->fts = 0; + lf->decoder_info = rootcheck_dec; + return(1); + } + } + /* New format */ + else + { + /* Going past time: !1183431603!1183431603 (last, first saw) */ + tmpstr = rk_buf + 23; + + /* Matches, we need to upgrade last time saw */ + if(strcmp(lf->log, tmpstr) == 0) + { + fsetpos(fp, &fp_pos); + fprintf(fp, "!%d", lf->time); + rootcheck_dec->fts = 0; + lf->decoder_info = rootcheck_dec; + return(1); + } + } + + /* Getting current position */ + if(fgetpos(fp, &fp_pos) == -1) + { + merror("%s: Error handling rootcheck database (fgetpos3).",ARGV0); + return(0); + } + } + + + /* Adding the new entry at the end of the file */ + fseek(fp, 0, SEEK_END); + fprintf(fp,"!%d!%d %s\n",lf->time, lf->time, lf->log); + fflush(fp); + + rootcheck_dec->fts = 0; + rootcheck_dec->fts |= FTS_DONE; + lf->decoder_info = rootcheck_dec; + return(1); +} + + +/* EOF */ diff --git a/src/analysisd/decoders/syscheck.c b/src/analysisd/decoders/syscheck.c new file mode 100755 index 0000000..b8c4a89 --- /dev/null +++ b/src/analysisd/decoders/syscheck.c @@ -0,0 +1,750 @@ +/* @(#) $Id: syscheck.c,v 1.53 2009/11/04 18:45:38 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Syscheck decoder */ + +#include "eventinfo.h" +#include "os_regex/os_regex.h" +#include "config.h" +#include "alerts/alerts.h" +#include "decoder.h" + + +typedef struct __sdb +{ + char buf[OS_MAXSTR + 1]; + char comment[OS_MAXSTR +1]; + + char size[OS_FLSIZE +1]; + char perm[OS_FLSIZE +1]; + char owner[OS_FLSIZE +1]; + char gowner[OS_FLSIZE +1]; + char md5[OS_FLSIZE +1]; + char sha1[OS_FLSIZE +1]; + + char agent_cp[MAX_AGENTS +1][1]; + char *agent_ips[MAX_AGENTS +1]; + FILE *agent_fps[MAX_AGENTS +1]; + + int db_err; + + + /* Ids for decoder */ + int id1; + int id2; + int id3; + int idn; + int idd; + + + /* Syscheck rule */ + OSDecoderInfo *syscheck_dec; + + + /* File search variables */ + fpos_t init_pos; + +}_sdb; /* syscheck db information */ + + +/* Global variable */ +_sdb sdb; + + + +/* SyscheckInit + * Initialize the necessary information to process the syscheck information + */ +void SyscheckInit() +{ + int i = 0; + + sdb.db_err = 0; + + for(;i <= MAX_AGENTS;i++) + { + sdb.agent_ips[i] = NULL; + sdb.agent_fps[i] = NULL; + sdb.agent_cp[i][0] = '0'; + } + + /* Clearing db memory */ + memset(sdb.buf, '\0', OS_MAXSTR +1); + memset(sdb.comment, '\0', OS_MAXSTR +1); + + memset(sdb.size, '\0', OS_FLSIZE +1); + memset(sdb.perm, '\0', OS_FLSIZE +1); + memset(sdb.owner, '\0', OS_FLSIZE +1); + memset(sdb.gowner, '\0', OS_FLSIZE +1); + memset(sdb.md5, '\0', OS_FLSIZE +1); + memset(sdb.sha1, '\0', OS_FLSIZE +1); + + + /* Creating decoder */ + os_calloc(1, sizeof(OSDecoderInfo), sdb.syscheck_dec); + sdb.syscheck_dec->id = getDecoderfromlist(SYSCHECK_MOD); + sdb.syscheck_dec->name = SYSCHECK_MOD; + sdb.syscheck_dec->type = OSSEC_RL; + sdb.syscheck_dec->fts = 0; + + sdb.id1 = getDecoderfromlist(SYSCHECK_MOD); + sdb.id2 = getDecoderfromlist(SYSCHECK_MOD2); + sdb.id3 = getDecoderfromlist(SYSCHECK_MOD3); + sdb.idn = getDecoderfromlist(SYSCHECK_NEW); + sdb.idd = getDecoderfromlist(SYSCHECK_DEL); + + debug1("%s: SyscheckInit completed.", ARGV0); + return; +} + +/* DB_IsCompleted + * Checks if the db is completed for that specific agent. + */ +#define DB_IsCompleted(x) (sdb.agent_cp[x][0] == '1')?1:0 + + +void __setcompleted(char *agent) +{ + FILE *fp; + + /* Getting agent file */ + snprintf(sdb.buf, OS_FLSIZE , "%s/.%s.cpt", SYSCHECK_DIR, agent); + + fp = fopen(sdb.buf,"w"); + if(fp) + { + fprintf(fp, "#!X"); + fclose(fp); + } +} + + +int __iscompleted(char *agent) +{ + FILE *fp; + + /* Getting agent file */ + snprintf(sdb.buf, OS_FLSIZE , "%s/.%s.cpt", SYSCHECK_DIR, agent); + + fp = fopen(sdb.buf,"r"); + if(fp) + { + fclose(fp); + return(1); + } + return(0); +} + + +/* void DB_SetCompleted(Eventinfo *lf). + * Set the database of a specific agent as completed. + */ +void DB_SetCompleted(Eventinfo *lf) +{ + int i = 0; + + /* Finding file pointer */ + while(sdb.agent_ips[i] != NULL) + { + if(strcmp(sdb.agent_ips[i], lf->location) == 0) + { + /* Return if already set as completed. */ + if(DB_IsCompleted(i)) + { + return; + } + + __setcompleted(lf->location); + + + /* Setting as completed in memory */ + sdb.agent_cp[i][0] = '1'; + return; + } + + i++; + } +} + + +/* DB_File + * Return the file pointer to be used to verify the integrity + */ +FILE *DB_File(char *agent, int *agent_id) +{ + int i = 0; + + /* Finding file pointer */ + while(sdb.agent_ips[i] != NULL) + { + if(strcmp(sdb.agent_ips[i], agent) == 0) + { + /* Pointing to the beginning of the file */ + fseek(sdb.agent_fps[i],0, SEEK_SET); + *agent_id = i; + return(sdb.agent_fps[i]); + } + + i++; + } + + /* If here, our agent wasn't found */ + os_strdup(agent, sdb.agent_ips[i]); + + + /* Getting agent file */ + snprintf(sdb.buf, OS_FLSIZE , "%s/%s", SYSCHECK_DIR,agent); + + + /* r+ to read and write. Do not truncate */ + sdb.agent_fps[i] = fopen(sdb.buf,"r+"); + if(!sdb.agent_fps[i]) + { + /* try opening with a w flag, file probably does not exist */ + sdb.agent_fps[i] = fopen(sdb.buf, "w"); + if(sdb.agent_fps[i]) + { + fclose(sdb.agent_fps[i]); + sdb.agent_fps[i] = fopen(sdb.buf, "r+"); + } + } + + /* Checking again */ + if(!sdb.agent_fps[i]) + { + merror("%s: Unable to open '%s'",ARGV0, sdb.buf); + + free(sdb.agent_ips[i]); + sdb.agent_ips[i] = NULL; + return(NULL); + } + + + /* Returning the opened pointer (the beginning of it) */ + fseek(sdb.agent_fps[i],0, SEEK_SET); + *agent_id = i; + + + /* Getting if the agent was completed */ + if(__iscompleted(agent)) + { + sdb.agent_cp[i][0] = '1'; + } + + return(sdb.agent_fps[i]); +} + + +/* DB_Search + * Search the DB for any entry related to the file being received + */ +int DB_Search(char *f_name, char *c_sum, Eventinfo *lf) +{ + int p = 0; + int sn_size; + int agent_id; + + char *saved_sum; + char *saved_name; + + FILE *fp; + + + /* Getting db pointer */ + fp = DB_File(lf->location, &agent_id); + if(!fp) + { + merror("%s: Error handling integrity database.",ARGV0); + sdb.db_err++; /* Increment db error */ + return(0); + } + + + /* Reads the integrity file and search for a possible + * entry + */ + if(fgetpos(fp, &sdb.init_pos) == -1) + { + merror("%s: Error handling integrity database (fgetpos).",ARGV0); + return(0); + } + + + /* Looping the file */ + while(fgets(sdb.buf, OS_MAXSTR, fp) != NULL) + { + /* Ignore blank lines and lines with a comment */ + if(sdb.buf[0] == '\n' || sdb.buf[0] == '#') + { + fgetpos(fp, &sdb.init_pos); /* getting next location */ + continue; + } + + + /* Getting name */ + saved_name = strchr(sdb.buf, ' '); + if(saved_name == NULL) + { + merror("%s: Invalid integrity message in the database.",ARGV0); + fgetpos(fp, &sdb.init_pos); /* getting next location */ + continue; + } + *saved_name = '\0'; + saved_name++; + + + /* New format - with a timestamp */ + if(*saved_name == '!') + { + saved_name = strchr(saved_name, ' '); + if(saved_name == NULL) + { + merror("%s: Invalid integrity message in the database",ARGV0); + fgetpos(fp, &sdb.init_pos); /* getting next location */ + continue; + } + saved_name++; + } + + + /* Removing new line from saved_name */ + sn_size = strlen(saved_name); + sn_size -= 1; + if(saved_name[sn_size] == '\n') + saved_name[sn_size] = '\0'; + + + /* If name is different, go to next one. */ + if(strcmp(f_name,saved_name) != 0) + { + /* Saving currently location */ + fgetpos(fp, &sdb.init_pos); + continue; + } + + + saved_sum = sdb.buf; + + + /* First three bytes are for frequency check */ + saved_sum+=3; + + + /* checksum match, we can just return and keep going */ + if(strcmp(saved_sum, c_sum) == 0) + return(0); + + + /* If we reached here, the checksum of the file has changed */ + if(saved_sum[-3] == '!') + { + p++; + if(saved_sum[-2] == '!') + { + p++; + if(saved_sum[-1] == '!') + p++; + else if(saved_sum[-1] == '?') + p+=2; + } + } + + + /* Checking the number of changes */ + if(!Config.syscheck_auto_ignore) + { + sdb.syscheck_dec->id = sdb.id1; + } + else + { + switch(p) + { + case 0: + sdb.syscheck_dec->id = sdb.id1; + break; + + case 1: + sdb.syscheck_dec->id = sdb.id2; + break; + + case 2: + sdb.syscheck_dec->id = sdb.id3; + break; + + default: + return(0); + break; + } + } + + + /* Adding new checksum to the database */ + /* Commenting the file entry and adding a new one latter */ + fsetpos(fp, &sdb.init_pos); + fputc('#',fp); + + + /* Adding the new entry at the end of the file */ + fseek(fp, 0, SEEK_END); + fprintf(fp,"%c%c%c%s !%d %s\n", + '!', + p >= 1? '!' : '+', + p == 2? '!' : (p > 2)?'?':'+', + c_sum, + lf->time, + f_name); + fflush(fp); + + + /* File deleted */ + if(c_sum[0] == '-' && c_sum[1] == '1') + { + sdb.syscheck_dec->id = sdb.idd; + snprintf(sdb.comment, OS_MAXSTR, + "File '%.756s' was deleted. Unable to retrieve " + "checksum.", f_name); + } + + /* If file was re-added, do not compare changes */ + else if(saved_sum[0] == '-' && saved_sum[1] == '1') + { + sdb.syscheck_dec->id = sdb.idn; + snprintf(sdb.comment, OS_MAXSTR, + "File '%.756s' was re-added.", f_name); + } + + else + { + int oldperm = 0, newperm = 0; + + /* Providing more info about the file change */ + char *oldsize = NULL, *newsize = NULL; + char *olduid = NULL, *newuid = NULL; + char *c_oldperm = NULL, *c_newperm = NULL; + char *oldgid = NULL, *newgid = NULL; + char *oldmd5 = NULL, *newmd5 = NULL; + char *oldsha1 = NULL, *newsha1 = NULL; + + oldsize = saved_sum; + newsize = c_sum; + + c_oldperm = strchr(saved_sum, ':'); + c_newperm = strchr(c_sum, ':'); + + /* Get old/new permissions */ + if(c_oldperm && c_newperm) + { + *c_oldperm = '\0'; + c_oldperm++; + + *c_newperm = '\0'; + c_newperm++; + + /* Get old/new uid/gid */ + olduid = strchr(c_oldperm, ':'); + newuid = strchr(c_newperm, ':'); + + if(olduid && newuid) + { + *olduid = '\0'; + *newuid = '\0'; + + olduid++; + newuid++; + + oldgid = strchr(olduid, ':'); + newgid = strchr(newuid, ':'); + + if(oldgid && newgid) + { + *oldgid = '\0'; + *newgid = '\0'; + + oldgid++; + newgid++; + + + /* Getting md5 */ + oldmd5 = strchr(oldgid, ':'); + newmd5 = strchr(newgid, ':'); + + if(oldmd5 && newmd5) + { + *oldmd5 = '\0'; + *newmd5 = '\0'; + + oldmd5++; + newmd5++; + + /* getting sha1 */ + oldsha1 = strchr(oldmd5, ':'); + newsha1 = strchr(newmd5, ':'); + + if(oldsha1 && newsha1) + { + *oldsha1 = '\0'; + *newsha1 = '\0'; + + oldsha1++; + newsha1++; + } + } + } + } + } + + /* Getting integer values */ + if(c_newperm && c_oldperm) + { + newperm = atoi(c_newperm); + oldperm = atoi(c_oldperm); + } + + /* Generating size message */ + if(!oldsize || !newsize || strcmp(oldsize, newsize) == 0) + { + sdb.size[0] = '\0'; + } + else + { + snprintf(sdb.size, OS_FLSIZE, + "Size changed from '%s' to '%s'\n", + oldsize, newsize); + } + + /* Permission message */ + if(oldperm == newperm) + { + sdb.perm[0] = '\0'; + } + else if(oldperm > 0 && newperm > 0) + { + snprintf(sdb.perm, OS_FLSIZE, "Permissions changed from " + "'%c%c%c%c%c%c%c%c%c' " + "to '%c%c%c%c%c%c%c%c%c'\n", + (oldperm & S_IRUSR)? 'r' : '-', + (oldperm & S_IWUSR)? 'w' : '-', + + (oldperm & S_ISUID)? 's' : + (oldperm & S_IXUSR)? 'x' : '-', + + (oldperm & S_IRGRP)? 'r' : '-', + (oldperm & S_IWGRP)? 'w' : '-', + + (oldperm & S_ISGID)? 's' : + (oldperm & S_IXGRP)? 'x' : '-', + + (oldperm & S_IROTH)? 'r' : '-', + (oldperm & S_IWOTH)? 'w' : '-', + + (oldperm & S_ISVTX)? 't' : + (oldperm & S_IXOTH)? 'x' : '-', + + + + (newperm & S_IRUSR)? 'r' : '-', + (newperm & S_IWUSR)? 'w' : '-', + + (newperm & S_ISUID)? 's' : + (newperm & S_IXUSR)? 'x' : '-', + + + (newperm & S_IRGRP)? 'r' : '-', + (newperm & S_IWGRP)? 'w' : '-', + + (newperm & S_ISGID)? 's' : + (newperm & S_IXGRP)? 'x' : '-', + + (newperm & S_IROTH)? 'r' : '-', + (newperm & S_IWOTH)? 'w' : '-', + + (newperm & S_ISVTX)? 't' : + (newperm & S_IXOTH)? 'x' : '-'); + } + + /* Ownership message */ + if(!newuid || !olduid || strcmp(newuid, olduid) == 0) + { + sdb.owner[0] = '\0'; + } + else + { + snprintf(sdb.owner, OS_FLSIZE, "Ownership was '%s', " + "now it is '%s'\n", + olduid, newuid); + } + + /* group ownership message */ + if(!newgid || !oldgid || strcmp(newgid, oldgid) == 0) + { + sdb.gowner[0] = '\0'; + } + else + { + snprintf(sdb.gowner, OS_FLSIZE,"Group ownership was '%s', " + "now it is '%s'\n", + oldgid, newgid); + } + + /* md5 message */ + if(!newmd5 || !oldmd5 || strcmp(newmd5, oldmd5) == 0) + { + sdb.md5[0] = '\0'; + } + else + { + snprintf(sdb.md5, OS_FLSIZE, "Old md5sum was: '%s'\n" + "New md5sum is : '%s'\n", + oldmd5, newmd5); + } + + /* sha1 */ + if(!newsha1 || !oldsha1 || strcmp(newsha1, oldsha1) == 0) + { + sdb.sha1[0] = '\0'; + } + else + { + snprintf(sdb.sha1, OS_FLSIZE, "Old sha1sum was: '%s'\n" + "New sha1sum is : '%s'\n", + oldsha1, newsha1); + } + + + /* Provide information about the file */ + snprintf(sdb.comment, 512, "Integrity checksum changed for: " + "'%.756s'\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s", + f_name, + sdb.size, + sdb.perm, + sdb.owner, + sdb.gowner, + sdb.md5, + sdb.sha1); + } + + + /* Creating a new log message */ + free(lf->full_log); + os_strdup(sdb.comment, lf->full_log); + lf->log = lf->full_log; + + + /* Setting decoder */ + lf->decoder_info = sdb.syscheck_dec; + + + return(1); + + } /* continuiing... */ + + + /* If we reach here, this file is not present on our database */ + fseek(fp, 0, SEEK_END); + + fprintf(fp,"+++%s !%d %s\n", c_sum, lf->time, f_name); + + + /* Alert if configured to notify on new files */ + if((Config.syscheck_alert_new == 1) && (DB_IsCompleted(agent_id))) + { + sdb.syscheck_dec->id = sdb.idn; + + /* New file message */ + snprintf(sdb.comment, OS_MAXSTR, + "New file '%.756s' " + "added to the file system.", f_name); + + + /* Creating a new log message */ + free(lf->full_log); + os_strdup(sdb.comment, lf->full_log); + lf->log = lf->full_log; + + + /* Setting decoder */ + lf->decoder_info = sdb.syscheck_dec; + + return(1); + } + + return(0); +} + + +/* Special decoder for syscheck + * Not using the default decoding lib for simplicity + * and to be less resource intensive + */ +int DecodeSyscheck(Eventinfo *lf) +{ + char *c_sum; + char *f_name; + + + /* Every syscheck message must be in the following format: + * checksum filename + */ + f_name = strchr(lf->log, ' '); + if(f_name == NULL) + { + /* If we don't have a valid syscheck message, it may be + * a database completed message. + */ + if(strcmp(lf->log, HC_SK_DB_COMPLETED) == 0) + { + DB_SetCompleted(lf); + return(0); + } + + merror(SK_INV_MSG, ARGV0); + return(0); + } + + + /* Zeroing to get the check sum */ + *f_name = '\0'; + f_name++; + + + /* Checking if file is supposed to be ignored */ + if(Config.syscheck_ignore) + { + char **ff_ig = Config.syscheck_ignore; + + while(*ff_ig) + { + if(strncasecmp(*ff_ig, f_name, strlen(*ff_ig)) == 0) + { + return(0); + } + + ff_ig++; + } + } + + + /* Checksum is at the beginning of the log */ + c_sum = lf->log; + + + /* Searching for file changes */ + return(DB_Search(f_name, c_sum, lf)); +} + +/* EOF */ diff --git a/src/analysisd/eventinfo.c b/src/analysisd/eventinfo.c new file mode 100755 index 0000000..e3a77b2 --- /dev/null +++ b/src/analysisd/eventinfo.c @@ -0,0 +1,596 @@ +/* @(#) $Id: eventinfo.c,v 1.41 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Part of the OSSEC. + * Available at http://www.ossec.net + */ + + + +#include "config.h" +#include "analysisd.h" +#include "eventinfo.h" +#include "os_regex/os_regex.h" + + +/* Search last times a signature fired + * Will look for only that specific signature. + */ +Eventinfo *Search_LastSids(Eventinfo *my_lf, RuleInfo *currently_rule) +{ + Eventinfo *lf; + Eventinfo *first_lf; + OSListNode *lf_node; + + + /* Setting frequency to 0 */ + currently_rule->__frequency = 0; + + + /* checking sid search is valid */ + if(!currently_rule->sid_search) + { + merror("%s: No sid search!! XXX", ARGV0); + } + + /* Getting last node */ + lf_node = OSList_GetLastNode(currently_rule->sid_search); + if(!lf_node) + { + return(NULL); + } + first_lf = (Eventinfo *)lf_node->data; + + + do + { + lf = (Eventinfo *)lf_node->data; + + /* If time is outside the timeframe, return */ + if((c_time - lf->time) > currently_rule->timeframe) + { + return(NULL); + } + + /* We avoid multiple triggers for the same rule + * or rules with a lower level. + */ + else if(lf->matched >= currently_rule->level) + { + return(NULL); + } + + + + /* Checking for same id */ + if(currently_rule->context_opts & SAME_ID) + { + if((!lf->id) || (!my_lf->id)) + continue; + + if(strcmp(lf->id,my_lf->id) != 0) + continue; + } + + /* Checking for repetitions from same src_ip */ + if(currently_rule->context_opts & SAME_SRCIP) + { + if((!lf->srcip)||(!my_lf->srcip)) + continue; + + if(strcmp(lf->srcip,my_lf->srcip) != 0) + continue; + } + + + /* Grouping of additional data */ + if(currently_rule->alert_opts & SAME_EXTRAINFO) + { + /* Checking for same source port */ + if(currently_rule->context_opts & SAME_SRCPORT) + { + if((!lf->srcport)||(!my_lf->srcport)) + continue; + + if(strcmp(lf->srcport, my_lf->srcport) != 0) + continue; + } + + /* Checking for same dst port */ + if(currently_rule->context_opts & SAME_DSTPORT) + { + if((!lf->dstport)||(!my_lf->dstport)) + continue; + + if(strcmp(lf->dstport, my_lf->dstport) != 0) + continue; + } + + /* Checking for repetitions on user error */ + if(currently_rule->context_opts & SAME_USER) + { + if((!lf->dstuser)||(!my_lf->dstuser)) + continue; + + if(strcmp(lf->dstuser,my_lf->dstuser) != 0) + continue; + } + + /* Checking for same location */ + if(currently_rule->context_opts & SAME_LOCATION) + { + if(strcmp(lf->hostname, my_lf->hostname) != 0) + continue; + } + + + /* Checking for different urls */ + if(currently_rule->context_opts & DIFFERENT_URL) + { + if((!lf->url)||(!my_lf->url)) + { + continue; + } + + if(strcmp(lf->url, my_lf->url) == 0) + { + continue; + } + } + + } + + + /* Checking if the number of matches worked */ + if(currently_rule->__frequency < currently_rule->frequency) + { + if(currently_rule->__frequency <= 10) + { + currently_rule->last_events[currently_rule->__frequency] + = lf->full_log; + currently_rule->last_events[currently_rule->__frequency+1] + = NULL; + } + + currently_rule->__frequency++; + continue; + } + + + /* If reached here, we matched */ + my_lf->matched = currently_rule->level; + lf->matched = currently_rule->level; + first_lf->matched = currently_rule->level; + + return(lf); + + + }while((lf_node = lf_node->prev) != NULL); + + return(NULL); +} + + + +/* Search last times a group fired + * Will look for only that specific group on that rule. + */ +Eventinfo *Search_LastGroups(Eventinfo *my_lf, RuleInfo *currently_rule) +{ + Eventinfo *lf; + Eventinfo *first_lf; + OSListNode *lf_node; + + + /* Setting frequency to 0 */ + currently_rule->__frequency = 0; + + + /* checking sid search is valid */ + if(!currently_rule->group_search) + { + merror("%s: No group search!! XXX", ARGV0); + } + + /* Getting last node */ + lf_node = OSList_GetLastNode(currently_rule->group_search); + if(!lf_node) + { + return(NULL); + } + first_lf = (Eventinfo *)lf_node->data; + + + do + { + lf = (Eventinfo *)lf_node->data; + + /* If time is outside the timeframe, return */ + if((c_time - lf->time) > currently_rule->timeframe) + { + return(NULL); + } + + /* We avoid multiple triggers for the same rule + * or rules with a lower level. + */ + else if(lf->matched >= currently_rule->level) + { + return(NULL); + } + + + + /* Checking for same id */ + if(currently_rule->context_opts & SAME_ID) + { + if((!lf->id) || (!my_lf->id)) + continue; + + if(strcmp(lf->id,my_lf->id) != 0) + continue; + } + + /* Checking for repetitions from same src_ip */ + if(currently_rule->context_opts & SAME_SRCIP) + { + if((!lf->srcip)||(!my_lf->srcip)) + continue; + + if(strcmp(lf->srcip,my_lf->srcip) != 0) + continue; + } + + + /* Grouping of additional data */ + if(currently_rule->alert_opts & SAME_EXTRAINFO) + { + /* Checking for same source port */ + if(currently_rule->context_opts & SAME_SRCPORT) + { + if((!lf->srcport)||(!my_lf->srcport)) + continue; + + if(strcmp(lf->srcport, my_lf->srcport) != 0) + continue; + } + + /* Checking for same dst port */ + if(currently_rule->context_opts & SAME_DSTPORT) + { + if((!lf->dstport)||(!my_lf->dstport)) + continue; + + if(strcmp(lf->dstport, my_lf->dstport) != 0) + continue; + } + + /* Checking for repetitions on user error */ + if(currently_rule->context_opts & SAME_USER) + { + if((!lf->dstuser)||(!my_lf->dstuser)) + continue; + + if(strcmp(lf->dstuser,my_lf->dstuser) != 0) + continue; + } + + /* Checking for same location */ + if(currently_rule->context_opts & SAME_LOCATION) + { + if(strcmp(lf->hostname, my_lf->hostname) != 0) + continue; + } + + + /* Checking for different urls */ + if(currently_rule->context_opts & DIFFERENT_URL) + { + if((!lf->url)||(!my_lf->url)) + { + continue; + } + + if(strcmp(lf->url, my_lf->url) == 0) + { + continue; + } + } + + } + + + /* Checking if the number of matches worked */ + if(currently_rule->__frequency < currently_rule->frequency) + { + if(currently_rule->__frequency <= 10) + { + currently_rule->last_events[currently_rule->__frequency] + = lf->full_log; + currently_rule->last_events[currently_rule->__frequency+1] + = NULL; + } + + currently_rule->__frequency++; + continue; + } + + + /* If reached here, we matched */ + my_lf->matched = currently_rule->level; + lf->matched = currently_rule->level; + first_lf->matched = currently_rule->level; + + return(lf); + + + }while((lf_node = lf_node->prev) != NULL); + + return(NULL); +} + + +/* Search LastEvents. + * Will look if any of the last events (inside the timeframe) + * match the specified rule. + */ +Eventinfo *Search_LastEvents(Eventinfo *my_lf, RuleInfo *currently_rule) +{ + EventNode *eventnode_pt; + Eventinfo *lf; + Eventinfo *first_lf; + + + merror("XXXX : remove me!"); + + + /* Last events */ + eventnode_pt = OS_GetLastEvent(); + if(!eventnode_pt) + { + /* Nothing found */ + return(NULL); + } + + /* Setting frequency to 0 */ + currently_rule->__frequency = 0; + first_lf = (Eventinfo *)eventnode_pt->event; + + + /* Searching all previous events */ + do + { + lf = eventnode_pt->event; + + /* If time is outside the timeframe, return */ + if((c_time - lf->time) > currently_rule->timeframe) + { + return(NULL); + } + + + /* We avoid multiple triggers for the same rule + * or rules with a lower level. + */ + else if(lf->matched >= currently_rule->level) + { + return(NULL); + } + + + /* The category must be the same */ + else if(lf->decoder_info->type != my_lf->decoder_info->type) + { + continue; + } + + + /* If regex does not match, go to next */ + if(currently_rule->if_matched_regex) + { + if(!OSRegex_Execute(lf->log, currently_rule->if_matched_regex)) + { + /* Didn't match */ + continue; + } + } + + /* Checking for repetitions on user error */ + if(currently_rule->context_opts & SAME_USER) + { + if((!lf->dstuser)||(!my_lf->dstuser)) + continue; + + if(strcmp(lf->dstuser,my_lf->dstuser) != 0) + continue; + } + + /* Checking for same id */ + if(currently_rule->context_opts & SAME_ID) + { + if((!lf->id) || (!my_lf->id)) + continue; + + if(strcmp(lf->id,my_lf->id) != 0) + continue; + } + + /* Checking for repetitions from same src_ip */ + if(currently_rule->context_opts & SAME_SRCIP) + { + if((!lf->srcip)||(!my_lf->srcip)) + continue; + + if(strcmp(lf->srcip,my_lf->srcip) != 0) + continue; + } + + /* Checking for different urls */ + if(currently_rule->context_opts & DIFFERENT_URL) + { + if((!lf->url)||(!my_lf->url)) + { + continue; + } + + if(strcmp(lf->url, my_lf->url) == 0) + { + continue; + } + } + + + /* Checking if the number of matches worked */ + if(currently_rule->__frequency < currently_rule->frequency) + { + if(currently_rule->__frequency <= 10) + { + currently_rule->last_events[currently_rule->__frequency] + = lf->full_log; + currently_rule->last_events[currently_rule->__frequency+1] + = NULL; + } + + currently_rule->__frequency++; + continue; + } + + + /* If reached here, we matched */ + my_lf->matched = currently_rule->level; + lf->matched = currently_rule->level; + first_lf->matched = currently_rule->level; + + return(lf); + + }while((eventnode_pt = eventnode_pt->next) != NULL); + + + return(NULL); +} + + +/* Zero the loginfo structure */ +void Zero_Eventinfo(Eventinfo *lf) +{ + lf->log = NULL; + lf->full_log = NULL; + lf->hostname = NULL; + lf->program_name = NULL; + lf->location = NULL; + + lf->srcip = NULL; + lf->dstip = NULL; + lf->srcport = NULL; + lf->dstport = NULL; + lf->protocol = NULL; + lf->action = NULL; + lf->srcuser = NULL; + lf->dstuser = NULL; + lf->id = NULL; + lf->status = NULL; + lf->command = NULL; + lf->url = NULL; + lf->data = NULL; + lf->systemname = NULL; + + lf->time = 0; + lf->matched = 0; + + lf->year = 0; + lf->mon[3] = '\0'; + lf->hour[9] = '\0'; + lf->day = 0; + + lf->generated_rule = NULL; + lf->sid_node_to_delete = NULL; + lf->decoder_info = NULL_Decoder; + + return; +} + +/* Free the loginfo structure */ +void Free_Eventinfo(Eventinfo *lf) +{ + if(!lf) + { + merror("%s: Trying to free NULL event. Inconsistent..",ARGV0); + return; + } + + if(lf->full_log) + free(lf->full_log); + if(lf->location) + free(lf->location); + + if(lf->srcip) + free(lf->srcip); + if(lf->dstip) + free(lf->dstip); + if(lf->srcport) + free(lf->srcport); + if(lf->dstport) + free(lf->dstport); + if(lf->protocol) + free(lf->protocol); + if(lf->action) + free(lf->action); + if(lf->status) + free(lf->status); + if(lf->srcuser) + free(lf->srcuser); + if(lf->dstuser) + free(lf->dstuser); + if(lf->id) + free(lf->id); + if(lf->command) + free(lf->command); + if(lf->url) + free(lf->url); + + if(lf->data) + free(lf->data); + if(lf->systemname) + free(lf->systemname); + + + /* Freeing node to delete */ + if(lf->sid_node_to_delete) + { + OSList_DeleteThisNode(lf->generated_rule->sid_prev_matched, + lf->sid_node_to_delete); + } + else if(lf->generated_rule && lf->generated_rule->group_prev_matched) + { + int i = 0; + + while(i < lf->generated_rule->group_prev_matched_sz) + { + OSList_DeleteOldestNode(lf->generated_rule->group_prev_matched[i]); + i++; + } + } + + /* We dont need to free: + * fts + * comment + */ + free(lf); + lf = NULL; + + return; +} + +/* EOF */ diff --git a/src/analysisd/eventinfo.h b/src/analysisd/eventinfo.h new file mode 100755 index 0000000..dcfeb93 --- /dev/null +++ b/src/analysisd/eventinfo.h @@ -0,0 +1,152 @@ +/* @(#) $Id: eventinfo.h,v 1.37 2009/07/24 18:34:11 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef _EVTINFO__H + +#define _EVTINFO__H + +#include "rules.h" +#include "decoders/decoder.h" + + +/* Event Information structure */ +typedef struct _Eventinfo +{ + /* Extracted from the event */ + char *log; + char *full_log; + char *location; + char *hostname; + char *program_name; + + + /* Extracted from the decoders */ + char *srcip; + char *dstip; + char *srcport; + char *dstport; + char *protocol; + char *action; + char *srcuser; + char *dstuser; + char *id; + char *status; + char *command; + char *url; + char *data; + char *systemname; + + + /* Pointer to the rule that generated it */ + RuleInfo *generated_rule; + + /* Pointer to the decoder that matched */ + OSDecoderInfo *decoder_info; + + /* Sid node to delete */ + OSListNode *sid_node_to_delete; + + /* Extract when the event fires a rule */ + int size; + int p_name_size; + + + /* Other internal variables */ + short int matched; + + int time; + int day; + int year; + char hour[9]; + char mon[4]; +}Eventinfo; + + +/* Events List structure */ +typedef struct _EventNode +{ + Eventinfo *event; + struct _EventNode *next; + struct _EventNode *prev; +}EventNode; + + + +/** Types of events (from decoders) **/ +#define UNKNOWN 0 /* Unkown */ +#define SYSLOG 1 /* syslog messages */ +#define IDS 2 /* IDS alerts */ +#define FIREWALL 3 /* Firewall events */ +#define WEBLOG 7 /* Apache logs */ +#define SQUID 8 /* Squid logs */ +#define WINDOWS 9 /* Windows logs */ +#define HOST_INFO 10 /* Host information logs (from nmap or similar) */ +#define OSSEC_RL 11 /* Ossec rules */ +#define OSSEC_ALERT 12 /* Ossec Alerts */ + + +/* FTS allowed values */ +#define FTS_NAME 001000 +#define FTS_SRCUSER 002000 +#define FTS_DSTUSER 004000 +#define FTS_SRCIP 000100 +#define FTS_DSTIP 000200 +#define FTS_LOCATION 000400 +#define FTS_ID 000010 +#define FTS_DATA 000020 +#define FTS_SYSTEMNAME 000040 +#define FTS_DONE 010000 + + +/** Functions for events **/ + +/* Search for matches in the last events */ +Eventinfo *Search_LastEvents(Eventinfo *lf, RuleInfo *currently_rule); +Eventinfo *Search_LastSids(Eventinfo *my_lf, RuleInfo *currently_rule); +Eventinfo *Search_LastGroups(Eventinfo *my_lf, RuleInfo *currently_rule); + +/* Zero the eventinfo structure */ +void Zero_Eventinfo(Eventinfo *lf); + +/* Free the eventinfo structure */ +void Free_Eventinfo(Eventinfo *lf); + +/* Add and event to the list of previous events */ +void OS_AddEvent(Eventinfo *lf); + +/* Return the last event from the Event list */ +EventNode *OS_GetLastEvent(); + +/* Create the event list. Maxsize must be specified */ +void OS_CreateEventList(int maxsize); + + +/* Pointers to the event decoders */ +void *SrcUser_FP(Eventinfo *lf, char *field); +void *DstUser_FP(Eventinfo *lf, char *field); +void *SrcIP_FP(Eventinfo *lf, char *field); +void *DstIP_FP(Eventinfo *lf, char *field); +void *SrcPort_FP(Eventinfo *lf, char *field); +void *DstPort_FP(Eventinfo *lf, char *field); +void *Protocol_FP(Eventinfo *lf, char *field); +void *Action_FP(Eventinfo *lf, char *field); +void *ID_FP(Eventinfo *lf, char *field); +void *Url_FP(Eventinfo *lf, char *field); +void *Data_FP(Eventinfo *lf, char *field); +void *Status_FP(Eventinfo *lf, char *field); +void *SystemName_FP(Eventinfo *lf, char *field); +void *None_FP(Eventinfo *lf, char *field); + + + +#endif /* _EVTINFO__H */ diff --git a/src/analysisd/eventinfo_list.c b/src/analysisd/eventinfo_list.c new file mode 100755 index 0000000..a98d455 --- /dev/null +++ b/src/analysisd/eventinfo_list.c @@ -0,0 +1,124 @@ +/* @(#) $Id: eventinfo_list.c,v 1.7 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "eventinfo.h" + + +EventNode *eventnode; +EventNode *lastnode; + +int _memoryused = 0; +int _memorymaxsize = 0; +int _max_freq = 0; + + +/* Create the Event List */ +void OS_CreateEventList(int maxsize) +{ + eventnode = NULL; + + _memorymaxsize = maxsize; + + _memoryused = 0; + + debug1("%s: OS_CreateEventList completed.", ARGV0); + return; +} + +/* Get the last event -- or first node */ +EventNode *OS_GetLastEvent() +{ + EventNode *eventnode_pt = eventnode; + + return(eventnode_pt); +} + +/* Add an event to the list -- always to the begining */ +void OS_AddEvent(Eventinfo *lf) +{ + EventNode *tmp_node = eventnode; + + if(tmp_node) + { + EventNode *new_node; + new_node = (EventNode *)calloc(1,sizeof(EventNode)); + + if(new_node == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + /* Always adding to the beginning of the list + * The new node will become the first node and + * new_node->next will be the previous first node + */ + new_node->next = tmp_node; + new_node->prev = NULL; + tmp_node->prev = new_node; + + eventnode = new_node; + + /* Adding the event to the node */ + new_node->event = lf; + + _memoryused++; + + /* Need to remove the last nodes */ + if(_memoryused > _memorymaxsize) + { + int i = 0; + EventNode *oldlast; + + /* Remove at least the last 10 events + * or the events that will not match anymore + * (higher than max frequency) + */ + while((i < 10)||((lf->time - lastnode->event->time) > _max_freq)) + { + oldlast = lastnode; + lastnode = lastnode->prev; + lastnode->next = NULL; + + /* Free event info */ + Free_Eventinfo(oldlast->event); + free(oldlast); + + _memoryused--; + i++; + } + } + } + + else + { + /* Adding first node */ + eventnode = (EventNode *)calloc(1,sizeof(EventNode)); + if(eventnode == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + eventnode->prev = NULL; + eventnode->next = NULL; + eventnode->event = lf; + + lastnode = eventnode; + } + + return; +} + +/* EOF */ diff --git a/src/analysisd/fts.c b/src/analysisd/fts.c new file mode 100755 index 0000000..34eecbd --- /dev/null +++ b/src/analysisd/fts.c @@ -0,0 +1,319 @@ +/* @(#) $Id: fts.c,v 1.34 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* First time seen functions + */ + + +#include "fts.h" +#include "eventinfo.h" + +int fts_minsize_for_str = 0; + +OSList *fts_list = NULL; +OSStore *fts_store = NULL; + +FILE *fp_list = NULL; +FILE *fp_ignore = NULL; + + +/** int FTS_Init() + * Starts the FTS module. + */ +int FTS_Init() +{ + int fts_list_size; + char _line[OS_FLSIZE + 1]; + + _line[OS_FLSIZE] = '\0'; + + + fts_list = OSList_Create(); + if(!fts_list) + { + merror(LIST_ERROR, ARGV0); + return(0); + } + + /* Creating store data */ + fts_store = OSStore_Create(); + if(!fts_store) + { + merror(LIST_ERROR, ARGV0); + return(0); + } + + /* Getting default list size */ + fts_list_size = getDefine_Int("analysisd", + "fts_list_size", + 12,512); + + /* Getting minimum string size */ + fts_minsize_for_str = getDefine_Int("analysisd", + "fts_min_size_for_str", + 6, 128); + + if(!OSList_SetMaxSize(fts_list, fts_list_size)) + { + merror(LIST_SIZE_ERROR, ARGV0); + return(0); + } + + + /* creating fts list */ + fp_list = fopen(FTS_QUEUE, "r+"); + if(!fp_list) + { + /* Create the file if we cant open it */ + fp_list = fopen(FTS_QUEUE, "w+"); + if(fp_list) + fclose(fp_list); + + fp_list = fopen(FTS_QUEUE, "r+"); + if(!fp_list) + { + merror(FOPEN_ERROR, ARGV0, FTS_QUEUE); + return(0); + } + } + + + /* Adding content from the files to memory */ + fseek(fp_list, 0, SEEK_SET); + while(fgets(_line, OS_FLSIZE , fp_list) != NULL) + { + char *tmp_s; + + /* Removing new lines */ + tmp_s = strchr(_line, '\n'); + if(tmp_s) + { + *tmp_s = '\0'; + } + + + os_strdup(_line, tmp_s); + if(!OSStore_Put(fts_store, tmp_s, NULL)) + { + merror(LIST_ADD_ERROR, ARGV0); + } + } + + + /* Creating ignore list */ + fp_ignore = fopen(IG_QUEUE, "r+"); + if(!fp_ignore) + { + /* Create the file if we cant open it */ + fp_ignore = fopen(IG_QUEUE, "w+"); + if(fp_ignore) + fclose(fp_ignore); + + fp_ignore = fopen(IG_QUEUE, "r+"); + if(!fp_ignore) + { + merror(FOPEN_ERROR, ARGV0, IG_QUEUE); + return(0); + } + } + + debug1("%s: DEBUG: FTSInit completed.", ARGV0); + + return(1); +} + +/* AddtoIGnore -- adds a pattern to be ignored. + */ +void AddtoIGnore(Eventinfo *lf) +{ + fseek(fp_ignore, 0, SEEK_END); + + #ifdef TESTRULE + return; + #endif + + /* Assigning the values to the FTS */ + fprintf(fp_ignore, "%s %s %s %s %s %s %s %s\n", + (lf->decoder_info->name && (lf->generated_rule->ignore & FTS_NAME))? + lf->decoder_info->name:"", + (lf->id && (lf->generated_rule->ignore & FTS_ID))?lf->id:"", + (lf->dstuser&&(lf->generated_rule->ignore & FTS_DSTUSER))? + lf->dstuser:"", + (lf->srcip && (lf->generated_rule->ignore & FTS_SRCIP))? + lf->srcip:"", + (lf->dstip && (lf->generated_rule->ignore & FTS_DSTIP))? + lf->dstip:"", + (lf->data && (lf->generated_rule->ignore & FTS_DATA))? + lf->data:"", + (lf->systemname && (lf->generated_rule->ignore & FTS_SYSTEMNAME))? + lf->systemname:"", + (lf->generated_rule->ignore & FTS_LOCATION)?lf->location:""); + + fflush(fp_ignore); + + return; +} + + +/* IGnore v0.1 + * Check if the event is to be ignored. + * Only after an event is matched (generated_rule must be set). + */ +int IGnore(Eventinfo *lf) +{ + char _line[OS_FLSIZE + 1]; + char _fline[OS_FLSIZE +1]; + + _line[OS_FLSIZE] = '\0'; + + + /* Assigning the values to the FTS */ + snprintf(_line,OS_FLSIZE, "%s %s %s %s %s %s %s %s\n", + (lf->decoder_info->name && (lf->generated_rule->ckignore & FTS_NAME))? + lf->decoder_info->name:"", + (lf->id && (lf->generated_rule->ckignore & FTS_ID))?lf->id:"", + (lf->dstuser && (lf->generated_rule->ckignore & FTS_DSTUSER))? + lf->dstuser:"", + (lf->srcip && (lf->generated_rule->ckignore & FTS_SRCIP))? + lf->srcip:"", + (lf->dstip && (lf->generated_rule->ckignore & FTS_DSTIP))? + lf->dstip:"", + (lf->data && (lf->generated_rule->ignore & FTS_DATA))? + lf->data:"", + (lf->systemname && (lf->generated_rule->ignore & FTS_SYSTEMNAME))? + lf->systemname:"", + (lf->generated_rule->ckignore & FTS_LOCATION)?lf->location:""); + + _fline[OS_FLSIZE] = '\0'; + + + /** Checking if the ignore is present **/ + /* Pointing to the beginning of the file */ + fseek(fp_ignore, 0, SEEK_SET); + while(fgets(_fline, OS_FLSIZE , fp_ignore) != NULL) + { + if(strcmp(_fline, _line) != 0) + continue; + + /* If we match, we can return 1 */ + return(1); + } + + return(0); +} + + +/* FTS v0.1 + * Check if the word "msg" is present on the "queue". + * If it is not, write it there. + */ +int FTS(Eventinfo *lf) +{ + int number_of_matches = 0; + + char _line[OS_FLSIZE + 1]; + + char *line_for_list = NULL; + + OSListNode *fts_node; + + _line[OS_FLSIZE] = '\0'; + + + /* Assigning the values to the FTS */ + snprintf(_line, OS_FLSIZE, "%s %s %s %s %s %s %s %s %s", + lf->decoder_info->name, + (lf->id && (lf->decoder_info->fts & FTS_ID))?lf->id:"", + (lf->dstuser && (lf->decoder_info->fts & FTS_DSTUSER))?lf->dstuser:"", + (lf->srcuser && (lf->decoder_info->fts & FTS_SRCUSER))?lf->srcuser:"", + (lf->srcip && (lf->decoder_info->fts & FTS_SRCIP))?lf->srcip:"", + (lf->dstip && (lf->decoder_info->fts & FTS_DSTIP))?lf->dstip:"", + (lf->data && (lf->decoder_info->fts & FTS_DATA))?lf->data:"", + (lf->systemname && (lf->decoder_info->fts & FTS_SYSTEMNAME))?lf->systemname:"", + (lf->decoder_info->fts & FTS_LOCATION)?lf->location:""); + + + /** Checking if FTS is already present **/ + if(lf->decoder_info->type == WINDOWS) + { + /* Windows is case insensitive */ + if(OSStore_NCaseCheck(fts_store, _line)) + { + return(0); + } + } + else if(OSStore_NCheck(fts_store, _line)) + { + return(0); + } + + + /* Checking if from the last FTS events, we had + * at least 3 "similars" before. If yes, we just + * ignore it. + */ + if(lf->decoder_info->type == IDS) + { + fts_node = OSList_GetLastNode(fts_list); + while(fts_node) + { + if(OS_StrHowClosedMatch((char *)fts_node->data, _line) > + fts_minsize_for_str) + { + number_of_matches++; + + /* We go and add this new entry to the list */ + if(number_of_matches > 2) + { + _line[fts_minsize_for_str] = '\0'; + break; + } + } + + fts_node = OSList_GetPrevNode(fts_list); + } + + os_strdup(_line, line_for_list); + OSList_AddData(fts_list, line_for_list); + } + + + /* Storing new entry */ + if(line_for_list == NULL) + { + os_strdup(_line, line_for_list); + } + + if(!OSStore_Put(fts_store, line_for_list, NULL)) + { + merror(LIST_ADD_ERROR, ARGV0); + } + + + #ifdef TESTRULE + return(1); + #endif + + + /* Saving to fts fp */ + fseek(fp_list, 0, SEEK_END); + fprintf(fp_list,"%s\n", _line); + fflush(fp_list); + + return(1); +} + + +/* EOF */ diff --git a/src/analysisd/fts.h b/src/analysisd/fts.h new file mode 100755 index 0000000..8fbb9f9 --- /dev/null +++ b/src/analysisd/fts.h @@ -0,0 +1,27 @@ +/* @(#) $Id: fts.h,v 1.8 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __FTS_H + +#define __FTS_H + + +/* FTS queues */ +#ifdef TESTRULE + #define FTS_QUEUE "queue/fts/fts-queue" + #define IG_QUEUE "queue/fts/ig-queue" +#else + #define FTS_QUEUE "/queue/fts/fts-queue" + #define IG_QUEUE "/queue/fts/ig-queue" +#endif + +#endif diff --git a/src/analysisd/picviz.c b/src/analysisd/picviz.c new file mode 100644 index 0000000..8f9a320 --- /dev/null +++ b/src/analysisd/picviz.c @@ -0,0 +1,75 @@ +/* @(#) $Id: picviz.c,v 1.2 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Sebastien Tricaud + * Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" +#include "eventinfo.h" + +static FILE *picviz_fp; + +static char *(ossec2picviz[])={"blue","blue","blue","blue", + "green","green","green","green", + "orange", "orange", "orange", "orange", + "red", "red", "red", "red", "red"}; + + +void OS_PicvizOpen(char *socket) +{ + picviz_fp = fopen(socket, "a"); + if(!picviz_fp) + { + merror("%s: Unable to open picviz socket file '%s'.", + ARGV0, socket); + } +} + +void OS_PicvizLog(Eventinfo *lf) +{ + char *color = (lf->generated_rule->level > 15) ? "red" : ossec2picviz[lf->generated_rule->level]; + + char *hostname; + char *location; + char *srcip; + char *dstip; + char *srcuser; + char *dstuser; + char *prgname; + char *comment; + + if(!picviz_fp) + return; + + + hostname = lf->hostname ? lf->hostname : ""; + location = lf->location ? lf->location : ""; + srcip = lf->srcip ? lf->srcip : ""; + dstip = lf->dstip ? lf->dstip : ""; + srcuser = lf->srcuser ? lf->srcuser : ""; + dstuser = lf->dstuser ? lf->dstuser : ""; + prgname = lf->program_name ? lf->program_name : ""; + comment = lf->generated_rule->comment ? lf->generated_rule->comment : ""; + + fprintf(picviz_fp, + "time=\"%s\", host=\"%s\", file=\"%s\", sip=\"%s\", dip=\"%s\"" + ", srcuser=\"%s\", dstuser=\"%s\", prgnme=\"%s\", alert=\"%s\" [color=\"%s\"];\n", + lf->hour, + hostname, location, srcip, dstip, srcuser, dstuser, prgname, comment, color); + + fflush(picviz_fp); + +} + +void OS_PicvizClose(void) +{ + if(picviz_fp) + fclose(picviz_fp); +} + diff --git a/src/analysisd/picviz.h b/src/analysisd/picviz.h new file mode 100644 index 0000000..89c6501 --- /dev/null +++ b/src/analysisd/picviz.h @@ -0,0 +1,24 @@ +/* @(#) $Id: picviz.h,v 1.2 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Sebastien Tricaud + * Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include +#include "eventinfo.h" + +#ifndef _PICVIZ_H_ +#define _PICVIZ_H_ + +void OS_PicvizOpen(char *socket); +void OS_PicvizLog(Eventinfo *lf); +void OS_PicvizClose(void); + +#endif /* _PICVIZ_H_ */ + diff --git a/src/analysisd/prelude.c b/src/analysisd/prelude.c new file mode 100644 index 0000000..39f8e85 --- /dev/null +++ b/src/analysisd/prelude.c @@ -0,0 +1,314 @@ +/* @(#) $Id: prelude.c,v 1.14 2009/11/09 20:18:52 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifdef PRELUDE + +#include +#include +#include + +#include "prelude.h" +#include "shared.h" +#include "eventinfo.h" + +#define DEFAULT_ANALYZER_NAME "OSSEC" +#define ANALYZER_CLASS "Host IDS, File Integrity Checker, Log Analyzer" +#define ANALYZER_MODEL "Ossec" +#define ANALYZER_MANUFACTURER __site +#define ANALYZER_VERSION __version + + +/* + * Ossec to Prelude + */ + + +/** OSSEC to prelude severity mapping. **/ +char *(ossec2prelude_sev[])={"info","info","info","info", + "low","low","low","low", + "medium", "medium", "medium", "medium", + "high", "high", "high", "high", "high"}; + + +/* Prelude client */ +static prelude_client_t *prelude_client; + + +void prelude_idmef_debug(idmef_message_t *idmef) +{ + prelude_io_t *pio; + + prelude_io_new(&pio); + prelude_io_set_file_io(pio, stderr); + idmef_message_print(idmef, pio); + prelude_io_destroy(pio); +} + + + +static int +add_idmef_object(idmef_message_t *msg, const char *object, const char *value) +{ + int ret = 0; + idmef_value_t *val; + idmef_path_t *path; + + /* Can value be null? better check in here. */ + if(value == NULL) + { + return(0); + } + + ret = idmef_path_new_fast(&path, object); + if(ret < 0) + { + return(-1); + } + + ret = idmef_value_new_from_path(&val, path, value); + if(ret < 0) + { + idmef_path_destroy(path); + return(-1); + } + + ret = idmef_path_set(path, msg, val); + if(ret < 0) + { + merror("%s: OSSEC2Prelude: IDMEF: Cannot add object '%s': %s.", + ARGV0, object, prelude_strerror(ret)); + } + + idmef_value_destroy(val); + idmef_path_destroy(path); + + return(ret); +} + + +static int +setup_analyzer(idmef_analyzer_t *analyzer) +{ + int ret; + prelude_string_t *string; + + ret = idmef_analyzer_new_model(analyzer, &string); + if ( ret < 0 ) + goto err; + prelude_string_set_constant(string, ANALYZER_MODEL); + + ret = idmef_analyzer_new_class(analyzer, &string); + if ( ret < 0 ) + goto err; + prelude_string_set_constant(string, ANALYZER_CLASS); + + ret = idmef_analyzer_new_manufacturer(analyzer, &string); + if ( ret < 0 ) + goto err; + prelude_string_set_constant(string, ANALYZER_MANUFACTURER); + + ret = idmef_analyzer_new_version(analyzer, &string); + if ( ret < 0 ) + goto err; + prelude_string_set_constant(string, ANALYZER_VERSION); + + + return 0; + + err: + merror("%s: OSSEC2Prelude: %s: IDMEF error: %s.", + ARGV0, prelude_strsource(ret), prelude_strerror(ret)); + + return -1; +} + + + +void prelude_start(char *profile, int argc, char **argv) +{ + int ret; + prelude_client = NULL; + + + ret = prelude_init(&argc, argv); + if (ret < 0) + { + merror("%s: %s: Unable to initialize the Prelude library: %s.", + ARGV0, prelude_strsource(ret), prelude_strerror(ret)); + return; + } + + ret = prelude_client_new(&prelude_client, + profile!=NULL?profile:DEFAULT_ANALYZER_NAME); + if (!prelude_client) + { + merror("%s: %s: Unable to create a prelude client object: %s.", + ARGV0, prelude_strsource(ret), prelude_strerror(ret)); + + return; + } + + + ret = setup_analyzer(prelude_client_get_analyzer(prelude_client)); + if(ret < 0) + { + merror("%s: %s: Unable to setup analyzer: %s", + ARGV0, prelude_strsource(ret), prelude_strerror(ret)); + + prelude_client_destroy(prelude_client, + PRELUDE_CLIENT_EXIT_STATUS_FAILURE); + + return; + } + + + ret = prelude_client_set_flags(prelude_client, + prelude_client_get_flags(prelude_client) + | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER); + if(ret < 0) + { + merror("%s: %s: Unable to set prelude client flags: %s.", + ARGV0, prelude_strsource(ret), prelude_strerror(ret)); + } + + + /* Setting uid and gid of ossec. */ + prelude_client_profile_set_uid(prelude_client_get_profile(prelude_client), + Privsep_GetUser(USER)); + prelude_client_profile_set_gid(prelude_client_get_profile(prelude_client), + Privsep_GetGroup(GROUPGLOBAL)); + + + ret = prelude_client_start(prelude_client); + if (ret < 0) + { + merror("%s: %s: Unable to initialize prelude client: %s.", + ARGV0, prelude_strsource(ret), prelude_strerror(ret)); + + prelude_client_destroy(prelude_client, + PRELUDE_CLIENT_EXIT_STATUS_FAILURE); + + return; + } + + + return; + +} + + + +void OS_PreludeLog(Eventinfo *lf) +{ + int ret; + idmef_message_t *idmef; + + + /* Generate prelude alert */ + ret = idmef_message_new(&idmef); + if ( ret < 0 ) + { + merror("%s: OSSEC2Prelude: Cannot create IDMEF message", ARGV0); + return; + } + + + add_idmef_object(idmef, "alert.assessment.impact.description", + lf->generated_rule->comment); + + add_idmef_object(idmef, "alert.assessment.impact.severity", + (lf->generated_rule->level > 15) ? "high": + ossec2prelude_sev[lf->generated_rule->level]); + + add_idmef_object(idmef, "alert.assessment.impact.completion", "succeeded"); + + add_idmef_object(idmef, "alert.classification.text", + lf->generated_rule->comment); + + + /* Setting source info. */ + add_idmef_object(idmef, "alert.source(0).Spoofed", "no"); + add_idmef_object(idmef, "alert.source(0).Node.Address(0).address", + lf->srcip); + add_idmef_object(idmef, "alert.source(0).Service.port", lf->srcport); + + if(lf->srcuser) + { + add_idmef_object(idmef, "alert.source(0).User.UserId(0).name", lf->srcuser); + } + + + /* Setting target */ + add_idmef_object(idmef, "alert.target(0).Service.name", lf->program_name); + add_idmef_object(idmef, "alert.target(0).Spoofed", "no"); + + if(lf->dstip) + { + add_idmef_object(idmef, "alert.target(0).Node.Address(0).address", + lf->dstip); + } + else + { + char *tmp_str; + char new_prelude_target[256]; + + new_prelude_target[255] = '\0'; + strncpy(new_prelude_target, lf->hostname, 255); + + /* The messages can have the file, so we need to remove it. + * formats can be: + * enigma->/var/log/authlog + * (esqueleto2) 192.168.2.99->/var/log/squid/access.log + */ + tmp_str = strstr(new_prelude_target, "->"); + if(tmp_str) + { + *tmp_str = '\0'; + } + add_idmef_object(idmef, "alert.target(0).Node.Address(0).address", + new_prelude_target); + } + add_idmef_object(idmef, "alert.target(0).Service.name", lf->hostname); + add_idmef_object(idmef, "alert.target(0).Service.port", lf->dstport); + + if(lf->dstuser) + { + add_idmef_object(idmef, "alert.target(0).User.category", "2"); + add_idmef_object(idmef, "alert.target(0).User.UserId(0).name", lf->dstuser); + } + + + /* Setting source file. */ + add_idmef_object(idmef, "alert.additional_data(0).type", "string"); + add_idmef_object(idmef, "alert.additional_data(0).meaning", "Source file"); + add_idmef_object(idmef, "alert.additional_data(0).data", lf->location); + + + /* Setting full log. */ + add_idmef_object(idmef, "alert.additional_data(1).type", "string"); + add_idmef_object(idmef, "alert.additional_data(1).meaning", "Full Log"); + add_idmef_object(idmef, "alert.additional_data(1).data", lf->full_log); + + idmef_alert_set_analyzer(idmef_message_get_alert(idmef), + idmef_analyzer_ref + (prelude_client_get_analyzer(prelude_client)), + IDMEF_LIST_PREPEND); + + prelude_client_send_idmef(prelude_client, idmef); + idmef_message_destroy(idmef); +} + + + +#endif /* PRELUDE */ + +/* EOF */ diff --git a/src/analysisd/prelude.h b/src/analysisd/prelude.h new file mode 100644 index 0000000..8ea6a7d --- /dev/null +++ b/src/analysisd/prelude.h @@ -0,0 +1,32 @@ +/* $Id: prelude.h,v 1.6 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * More details at the LICENSE file included with OSSEC or + * online at http://www.ossec.net/en/licensing.html . + */ + + +#ifdef PRELUDE + +#ifndef _PRELUDE_H_ +#define _PRELUDE_H_ + +#include "eventinfo.h" + +/* Starts prelude client. */ +void prelude_start(char *profile, int argc, char **argv); + +/* Logs to prelude. */ +void OS_PreludeLog(Eventinfo *lf); + +#endif /* _PRELUDE_H_ */ + + +#endif /* PRELUDE */ diff --git a/src/analysisd/rules.c b/src/analysisd/rules.c new file mode 100755 index 0000000..8c97197 --- /dev/null +++ b/src/analysisd/rules.c @@ -0,0 +1,1824 @@ +/* @(#) $Id: rules.c,v 1.79 2009/11/04 18:45:37 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#include "rules.h" +#include "config.h" +#include "eventinfo.h" +#include "compiled_rules/compiled_rules.h" + + +/* Chaging path for test rule. */ +#ifdef TESTRULE + #undef RULEPATH + #define RULEPATH "rules/" +#endif + + + +/* Internal functions */ +int getattributes(char **attributes, + char **values, + int *id, int *level, + int *maxsize, int *timeframe, + int *frequency, int *accuracy, + int *noalert, int *ignore_time, int *overwrite); + + +void Rule_AddAR(RuleInfo *config_rule); +char *loadmemory(char *at, char *str); +int getDecoderfromlist(char *name); + +extern int _max_freq; + + + +/* Rules_OP_ReadRules, v0.1, 2005/07/04 + * Will initialize the rules list + */ +void Rules_OP_CreateRules() +{ + + /* Initializing the rule list */ + OS_CreateRuleList(); + + return; +} + + + +/* Rules_OP_ReadRules, v0.3, 2005/03/21 + * Read the log rules. + * v0.3: Fixed many memory problems. + */ +int Rules_OP_ReadRules(char * rulefile) +{ + OS_XML xml; + XML_NODE node = NULL; + + /* XML variables */ + /* These are the available options for the rule configuration */ + + char *xml_group = "group"; + char *xml_rule = "rule"; + + char *xml_regex = "regex"; + char *xml_match = "match"; + char *xml_decoded = "decoded_as"; + char *xml_category = "category"; + char *xml_cve = "cve"; + char *xml_info = "info"; + char *xml_day_time = "time"; + char *xml_week_day = "weekday"; + char *xml_comment = "description"; + char *xml_ignore = "ignore"; + char *xml_check_if_ignored = "check_if_ignored"; + + char *xml_srcip = "srcip"; + char *xml_srcport = "srcport"; + char *xml_dstip = "dstip"; + char *xml_dstport = "dstport"; + char *xml_user = "user"; + char *xml_url = "url"; + char *xml_id = "id"; + char *xml_data = "extra_data"; + char *xml_hostname = "hostname"; + char *xml_program_name = "program_name"; + char *xml_status = "status"; + char *xml_action = "action"; + char *xml_compiled = "compiled_rule"; + + char *xml_if_sid = "if_sid"; + char *xml_if_group = "if_group"; + char *xml_if_level = "if_level"; + char *xml_fts = "if_fts"; + + char *xml_if_matched_regex = "if_matched_regex"; + char *xml_if_matched_group = "if_matched_group"; + char *xml_if_matched_sid = "if_matched_sid"; + + char *xml_same_source_ip = "same_source_ip"; + char *xml_same_src_port = "same_src_port"; + char *xml_same_dst_port = "same_dst_port"; + char *xml_same_user = "same_user"; + char *xml_same_location = "same_location"; + char *xml_same_id = "same_id"; + + char *xml_different_url = "different_url"; + + char *xml_notsame_source_ip = "not_same_source_ip"; + char *xml_notsame_user = "not_same_user"; + char *xml_notsame_agent = "not_same_agent"; + char *xml_notsame_id = "not_same_id"; + + char *xml_options = "options"; + + char *rulepath; + + int i; + int default_timeframe = 360; + + + /* Building the rule file name + path */ + i = strlen(RULEPATH) + strlen(rulefile) + 2; + rulepath = (char *)calloc(i,sizeof(char)); + if(!rulepath) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile); + + i = 0; + + /* Reading the XML */ + if(OS_ReadXML(rulepath,&xml) < 0) + { + merror(XML_ERROR, ARGV0, rulepath, xml.err, xml.err_line); + free(rulepath); + return(-1); + } + + + /* Debug wrapper */ + debug2("%s: DEBUG: read xml for rule.", ARGV0); + + + + /* Applying any variable found */ + if(OS_ApplyVariables(&xml) != 0) + { + merror(XML_ERROR_VAR, ARGV0, rulepath, xml.err); + return(-1); + } + + + /* Debug wrapper */ + debug2("%s: DEBUG: XML Variables applied.", ARGV0); + + + /* Getting the root elements */ + node = OS_GetElementsbyNode(&xml,NULL); + if(!node) + { + merror(CONFIG_ERROR, ARGV0, rulepath); + OS_ClearXML(&xml); + return(-1); + } + + + /* Zeroing the rule memory -- not used anymore */ + free(rulepath); + + + /* Getting default time frame */ + default_timeframe = getDefine_Int("analysisd", + "default_timeframe", + 60, 3600); + + + /* Checking if there is any invalid global option */ + while(node[i]) + { + if(node[i]->element) + { + if(strcasecmp(node[i]->element,xml_group) != 0) + { + merror("rules_op: Invalid root element \"%s\"." + "Only \"group\" is allowed",node[i]->element); + OS_ClearXML(&xml); + return(-1); + } + if((!node[i]->attributes) || (!node[i]->values)|| + (!node[i]->values[0]) || (!node[i]->attributes[0]) || + (strcasecmp(node[i]->attributes[0],"name") != 0) || + (node[i]->attributes[1])) + { + merror("rules_op: Invalid root element '%s'." + "Only the group name is allowed",node[i]->element); + OS_ClearXML(&xml); + return(-1); + } + } + else + { + merror(XML_READ_ERROR, ARGV0); + OS_ClearXML(&xml); + return(-1); + } + i++; + } + + + /* Getting the rules now */ + i=0; + while(node[i]) + { + XML_NODE rule = NULL; + + int j = 0; + + /* Getting all rules for a global group */ + rule = OS_GetElementsbyNode(&xml,node[i]); + if(rule == NULL) + { + merror("%s: Group '%s' without any rule.", + ARGV0, node[i]->element); + OS_ClearXML(&xml); + return(-1); + } + + while(rule[j]) + { + RuleInfo *config_ruleinfo = NULL; + + + /* Checking if the rule element is correct */ + if((!rule[j]->element)|| + (strcasecmp(rule[j]->element,xml_rule) != 0)) + { + merror("%s: Invalid configuration. '%s' is not " + "a valid element.", ARGV0, rule[j]->element); + OS_ClearXML(&xml); + return(-1); + } + + + /* Checking for the attributes of the rule */ + if((!rule[j]->attributes) || (!rule[j]->values)) + { + merror("%s: Invalid rule '%d'. You must specify" + " an ID and a level at least.", ARGV0, j); + OS_ClearXML(&xml); + return(-1); + } + + + /* Attribute block */ + { + int id = -1,level = -1,maxsize = 0,timeframe = 0; + int frequency = 0, accuracy = 1, noalert = 0, ignore_time = 0; + int overwrite = 0; + + /* Getting default time frame */ + timeframe = default_timeframe; + + + if(getattributes(rule[j]->attributes,rule[j]->values, + &id,&level,&maxsize,&timeframe, + &frequency,&accuracy,&noalert, + &ignore_time, &overwrite) < 0) + { + merror("%s: Invalid attribute for rule.", ARGV0); + OS_ClearXML(&xml); + return(-1); + } + + if((id == -1) || (level == -1)) + { + merror("%s: No rule id or level specified for " + "rule '%d'.",ARGV0, j); + OS_ClearXML(&xml); + return(-1); + } + + /* Allocating memory and initializing structure */ + config_ruleinfo = zerorulemember(id, level, maxsize, + frequency,timeframe, + noalert, ignore_time, overwrite); + + + /* If rule is 0, set it to level 99 to have high priority. + * set it to 0 again later + */ + if(config_ruleinfo->level == 0) + config_ruleinfo->level = 99; + + + /* Each level now is going to be multiplied by 100. + * If the accuracy is set to 0 we don't multiply, + * so it will be at the end of the list. We will + * divide by 100 later. + */ + if(accuracy) + { + config_ruleinfo->level *= 100; + } + + if(config_ruleinfo->maxsize > 0) + { + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + { + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + } + + } /* end attributes/memory allocation block */ + + + /* Here we can assign the group name to the rule. + * The level is correct so the rule is probably going to + * be fine + */ + os_strdup(node[i]->values[0], config_ruleinfo->group); + + + /* Rule elements block */ + { + int k = 0; + char *regex = NULL; + char *match = NULL; + char *url = NULL; + char *if_matched_regex = NULL; + char *if_matched_group = NULL; + char *user = NULL; + char *id = NULL; + char *srcport = NULL; + char *dstport = NULL; + char *status = NULL; + char *hostname = NULL; + char *extra_data = NULL; + char *program_name = NULL; + + XML_NODE rule_opt = NULL; + rule_opt = OS_GetElementsbyNode(&xml,rule[j]); + if(rule_opt == NULL) + { + merror("%s: Rule '%d' without any option. " + "It may lead to false positives and some " + "other problems for the system. Exiting.", + ARGV0, config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + + while(rule_opt[k]) + { + if((!rule_opt[k]->element)||(!rule_opt[k]->content)) + break; + else if(strcasecmp(rule_opt[k]->element,xml_regex)==0) + { + regex = + loadmemory(regex, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_match)==0) + { + match = + loadmemory(match, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, xml_decoded)==0) + { + config_ruleinfo->decoded_as = + getDecoderfromlist(rule_opt[k]->content); + + if(config_ruleinfo->decoded_as == 0) + { + merror("%s: Invalid decoder name: '%s'.", + ARGV0, rule_opt[k]->content); + OS_ClearXML(&xml); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element,xml_info)==0) + { + config_ruleinfo->info= + loadmemory(config_ruleinfo->info, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_day_time)==0) + { + config_ruleinfo->day_time = + OS_IsValidTime(rule_opt[k]->content); + if(!config_ruleinfo->day_time) + { + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, + rule_opt[k]->content); + return(-1); + } + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_week_day)==0) + { + config_ruleinfo->week_day = + OS_IsValidDay(rule_opt[k]->content); + + if(!config_ruleinfo->week_day) + { + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, + rule_opt[k]->content); + return(-1); + } + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_group)==0) + { + config_ruleinfo->group = + loadmemory(config_ruleinfo->group, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_cve)==0) + { + config_ruleinfo->cve= + loadmemory(config_ruleinfo->cve, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_comment)==0) + { + char *newline; + + newline = strchr(rule_opt[k]->content, '\n'); + if(newline) + { + *newline = ' '; + } + + config_ruleinfo->comment= + loadmemory(config_ruleinfo->comment, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_srcip)==0) + { + int ip_s = 0; + + /* Getting size of source ip list */ + while(config_ruleinfo->srcip && + config_ruleinfo->srcip[ip_s]) + { + ip_s++; + } + + config_ruleinfo->srcip = + realloc(config_ruleinfo->srcip, + (ip_s + 2) * sizeof(os_ip *)); + + + /* Allocating memory for the individual entries */ + os_calloc(1, sizeof(os_ip), + config_ruleinfo->srcip[ip_s]); + config_ruleinfo->srcip[ip_s +1] = NULL; + + + /* Checking if the ip is valid */ + if(!OS_IsValidIP(rule_opt[k]->content, + config_ruleinfo->srcip[ip_s])) + { + merror(INVALID_IP, ARGV0, rule_opt[k]->content); + return(-1); + } + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_dstip)==0) + { + int ip_s = 0; + + /* Getting size of source ip list */ + while(config_ruleinfo->dstip && + config_ruleinfo->dstip[ip_s]) + { + ip_s++; + } + + config_ruleinfo->dstip = + realloc(config_ruleinfo->dstip, + (ip_s + 2) * sizeof(os_ip *)); + + + /* Allocating memory for the individual entries */ + os_calloc(1, sizeof(os_ip), + config_ruleinfo->dstip[ip_s]); + config_ruleinfo->dstip[ip_s +1] = NULL; + + + /* Checking if the ip is valid */ + if(!OS_IsValidIP(rule_opt[k]->content, + config_ruleinfo->dstip[ip_s])) + { + merror(INVALID_IP, ARGV0, rule_opt[k]->content); + return(-1); + } + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_user)==0) + { + user = + loadmemory(user, + rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_id)==0) + { + id = + loadmemory(id, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_srcport)==0) + { + srcport = + loadmemory(srcport, + rule_opt[k]->content); + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_dstport)==0) + { + dstport = + loadmemory(dstport, + rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_status)==0) + { + status = + loadmemory(status, + rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_hostname)==0) + { + hostname = + loadmemory(hostname, + rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_data)==0) + { + extra_data = + loadmemory(extra_data, + rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_program_name)==0) + { + program_name = + loadmemory(program_name, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_action)==0) + { + config_ruleinfo->action = + loadmemory(config_ruleinfo->action, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_url)==0) + { + url= + loadmemory(url, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, xml_compiled)==0) + { + int it_id = 0; + + while(compiled_rules_name[it_id]) + { + if(strcmp(compiled_rules_name[it_id], + rule_opt[k]->content) == 0) + break; + it_id++; + } + + /* checking if the name is valid. */ + if(!compiled_rules_name[it_id]) + { + merror("%s: ERROR: Compiled rule not found: '%s'", + ARGV0, rule_opt[k]->content); + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, rule_opt[k]->content); + return(-1); + + } + + config_ruleinfo->compiled_rule = compiled_rules_list[it_id]; + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + + /* We allow these four categories so far */ + else if(strcasecmp(rule_opt[k]->element, xml_category)==0) + { + if(strcmp(rule_opt[k]->content, "firewall") == 0) + { + config_ruleinfo->category = FIREWALL; + } + else if(strcmp(rule_opt[k]->content, "ids") == 0) + { + config_ruleinfo->category = IDS; + } + else if(strcmp(rule_opt[k]->content, "syslog") == 0) + { + config_ruleinfo->category = SYSLOG; + } + else if(strcmp(rule_opt[k]->content, "web-log") == 0) + { + config_ruleinfo->category = WEBLOG; + } + else if(strcmp(rule_opt[k]->content, "squid") == 0) + { + config_ruleinfo->category = SQUID; + } + else if(strcmp(rule_opt[k]->content,"windows") == 0) + { + config_ruleinfo->category = WINDOWS; + } + else if(strcmp(rule_opt[k]->content,"ossec") == 0) + { + config_ruleinfo->category = OSSEC_RL; + } + else + { + merror(INVALID_CAT, ARGV0, rule_opt[k]->content); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element,xml_if_sid)==0) + { + config_ruleinfo->if_sid= + loadmemory(config_ruleinfo->if_sid, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_if_level)==0) + { + if(!OS_StrIsNum(rule_opt[k]->content)) + { + merror(INVALID_CONFIG, ARGV0, + "if_level", + rule_opt[k]->content); + return(-1); + } + + config_ruleinfo->if_level= + loadmemory(config_ruleinfo->if_level, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_if_group)==0) + { + config_ruleinfo->if_group= + loadmemory(config_ruleinfo->if_group, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, + xml_if_matched_regex) == 0) + { + config_ruleinfo->context = 1; + if_matched_regex= + loadmemory(if_matched_regex, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, + xml_if_matched_group) == 0) + { + config_ruleinfo->context = 1; + if_matched_group= + loadmemory(if_matched_group, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, + xml_if_matched_sid) == 0) + { + config_ruleinfo->context = 1; + if(!OS_StrIsNum(rule_opt[k]->content)) + { + merror(INVALID_CONFIG, ARGV0, + "if_matched_sid", + rule_opt[k]->content); + return(-1); + } + config_ruleinfo->if_matched_sid = + atoi(rule_opt[k]->content); + + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_source_ip)==0) + { + config_ruleinfo->context_opts|= SAME_SRCIP; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_src_port)==0) + { + config_ruleinfo->context_opts|= SAME_SRCPORT; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_dst_port) == 0) + { + config_ruleinfo->context_opts|= SAME_DSTPORT; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_notsame_source_ip)==0) + { + config_ruleinfo->context_opts&= NOT_SAME_SRCIP; + } + else if(strcmp(rule_opt[k]->element, xml_same_id) == 0) + { + config_ruleinfo->context_opts|= SAME_ID; + } + else if(strcmp(rule_opt[k]->element, + xml_different_url) == 0) + { + config_ruleinfo->context_opts|= DIFFERENT_URL; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcmp(rule_opt[k]->element,xml_notsame_id) == 0) + { + config_ruleinfo->context_opts&= NOT_SAME_ID; + } + else if(strcasecmp(rule_opt[k]->element, + xml_fts) == 0) + { + config_ruleinfo->alert_opts |= DO_FTS; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_user)==0) + { + config_ruleinfo->context_opts|= SAME_USER; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_notsame_user)==0) + { + config_ruleinfo->context_opts&= NOT_SAME_USER; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_location)==0) + { + config_ruleinfo->context_opts|= SAME_LOCATION; + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_notsame_agent)==0) + { + config_ruleinfo->context_opts&= NOT_SAME_AGENT; + } + else if(strcasecmp(rule_opt[k]->element, + xml_options) == 0) + { + if(strcmp("alert_by_email", + rule_opt[k]->content) == 0) + { + if(!(config_ruleinfo->alert_opts & DO_MAILALERT)) + { + config_ruleinfo->alert_opts|= DO_MAILALERT; + } + } + else if(strcmp("no_email_alert", + rule_opt[k]->content) == 0) + { + if(config_ruleinfo->alert_opts & DO_MAILALERT) + { + config_ruleinfo->alert_opts&=0xfff-DO_MAILALERT; + } + } + else if(strcmp("log_alert", + rule_opt[k]->content) == 0) + { + if(!(config_ruleinfo->alert_opts & DO_LOGALERT)) + { + config_ruleinfo->alert_opts|= DO_LOGALERT; + } + } + else if(strcmp("no_log", rule_opt[k]->content) == 0) + { + if(config_ruleinfo->alert_opts & DO_LOGALERT) + { + config_ruleinfo->alert_opts &=0xfff-DO_LOGALERT; + } + } + else + { + merror(XML_VALUEERR, ARGV0, xml_options, + rule_opt[k]->content); + + merror("%s: Invalid option '%s' for " + "rule '%d'.",ARGV0, rule_opt[k]->element, + config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element, + xml_ignore) == 0) + { + if(strstr(rule_opt[k]->content, "user") != NULL) + { + config_ruleinfo->ignore|=FTS_DSTUSER; + } + if(strstr(rule_opt[k]->content, "srcip") != NULL) + { + config_ruleinfo->ignore|=FTS_SRCIP; + } + if(strstr(rule_opt[k]->content, "dstip") != NULL) + { + config_ruleinfo->ignore|=FTS_DSTIP; + } + if(strstr(rule_opt[k]->content, "id") != NULL) + { + config_ruleinfo->ignore|=FTS_ID; + } + if(strstr(rule_opt[k]->content,"location")!= NULL) + { + config_ruleinfo->ignore|=FTS_LOCATION; + } + if(strstr(rule_opt[k]->content,"data")!= NULL) + { + config_ruleinfo->ignore|=FTS_DATA; + } + if(strstr(rule_opt[k]->content, "name") != NULL) + { + config_ruleinfo->ignore|=FTS_NAME; + + } + if(!config_ruleinfo->ignore) + { + merror("%s: Wrong ignore option: '%s'", + ARGV0, + rule_opt[k]->content); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element, + xml_check_if_ignored) == 0) + { + if(strstr(rule_opt[k]->content, "user") != NULL) + { + config_ruleinfo->ckignore|=FTS_DSTUSER; + } + if(strstr(rule_opt[k]->content, "srcip") != NULL) + { + config_ruleinfo->ckignore|=FTS_SRCIP; + } + if(strstr(rule_opt[k]->content, "dstip") != NULL) + { + config_ruleinfo->ckignore|=FTS_DSTIP; + } + if(strstr(rule_opt[k]->content, "id") != NULL) + { + config_ruleinfo->ckignore|=FTS_ID; + } + if(strstr(rule_opt[k]->content,"location")!= NULL) + { + config_ruleinfo->ckignore|=FTS_LOCATION; + } + if(strstr(rule_opt[k]->content,"data")!= NULL) + { + config_ruleinfo->ignore|=FTS_DATA; + } + if(strstr(rule_opt[k]->content, "name") != NULL) + { + config_ruleinfo->ckignore|=FTS_NAME; + + } + if(!config_ruleinfo->ckignore) + { + merror("%s: Wrong check_if_ignored option: '%s'", + ARGV0, + rule_opt[k]->content); + return(-1); + } + } + else + { + merror("%s: Invalid option '%s' for " + "rule '%d'.",ARGV0, rule_opt[k]->element, + config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + k++; + } + + + /* Checking for a valid use of frequency */ + if((config_ruleinfo->context_opts || + config_ruleinfo->frequency) && + !config_ruleinfo->context) + { + merror("%s: Invalid use of frequency/context options. " + "Missing if_matched on rule '%d'.", + ARGV0, config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + + + /* If if_matched_group we must have a if_sid or if_group */ + if(if_matched_group) + { + if(!config_ruleinfo->if_sid && !config_ruleinfo->if_group) + { + os_strdup(if_matched_group, + config_ruleinfo->if_group); + } + } + + /* If_matched_sid, we need to get the if_sid */ + if(config_ruleinfo->if_matched_sid && + !config_ruleinfo->if_sid && + !config_ruleinfo->if_group) + { + os_calloc(16, sizeof(char), config_ruleinfo->if_sid); + snprintf(config_ruleinfo->if_sid, 15, "%d", + config_ruleinfo->if_matched_sid); + } + + /* Checking the regexes */ + if(regex) + { + os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex); + if(!OSRegex_Compile(regex, config_ruleinfo->regex, 0)) + { + merror(REGEX_COMPILE, ARGV0, regex, + config_ruleinfo->regex->error); + return(-1); + } + free(regex); + regex = NULL; + } + + /* Adding in match */ + if(match) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->match); + if(!OSMatch_Compile(match, config_ruleinfo->match, 0)) + { + merror(REGEX_COMPILE, ARGV0, match, + config_ruleinfo->match->error); + return(-1); + } + free(match); + match = NULL; + } + + /* Adding in id */ + if(id) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->id); + if(!OSMatch_Compile(id, config_ruleinfo->id, 0)) + { + merror(REGEX_COMPILE, ARGV0, id, + config_ruleinfo->id->error); + return(-1); + } + free(id); + id = NULL; + } + + /* Adding srcport */ + if(srcport) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport); + if(!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0)) + { + merror(REGEX_COMPILE, ARGV0, srcport, + config_ruleinfo->id->error); + return(-1); + } + free(srcport); + srcport = NULL; + } + + /* Adding dstport */ + if(dstport) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport); + if(!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0)) + { + merror(REGEX_COMPILE, ARGV0, dstport, + config_ruleinfo->id->error); + return(-1); + } + free(dstport); + dstport = NULL; + } + + /* Adding in status */ + if(status) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->status); + if(!OSMatch_Compile(status, config_ruleinfo->status, 0)) + { + merror(REGEX_COMPILE, ARGV0, status, + config_ruleinfo->status->error); + return(-1); + } + free(status); + status = NULL; + } + + /* Adding in hostname */ + if(hostname) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname); + if(!OSMatch_Compile(hostname, config_ruleinfo->hostname,0)) + { + merror(REGEX_COMPILE, ARGV0, hostname, + config_ruleinfo->hostname->error); + return(-1); + } + free(hostname); + hostname = NULL; + } + + /* Adding extra data */ + if(extra_data) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data); + if(!OSMatch_Compile(extra_data, + config_ruleinfo->extra_data, 0)) + { + merror(REGEX_COMPILE, ARGV0, extra_data, + config_ruleinfo->extra_data->error); + return(-1); + } + free(extra_data); + extra_data = NULL; + } + + /* Adding in program name */ + if(program_name) + { + os_calloc(1,sizeof(OSMatch),config_ruleinfo->program_name); + if(!OSMatch_Compile(program_name, + config_ruleinfo->program_name,0)) + { + merror(REGEX_COMPILE, ARGV0, program_name, + config_ruleinfo->program_name->error); + return(-1); + } + free(program_name); + program_name = NULL; + } + + /* Adding in user */ + if(user) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->user); + if(!OSMatch_Compile(user, config_ruleinfo->user, 0)) + { + merror(REGEX_COMPILE, ARGV0, user, + config_ruleinfo->user->error); + return(-1); + } + free(user); + user = NULL; + } + + /* Adding in url */ + if(url) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->url); + if(!OSMatch_Compile(url, config_ruleinfo->url, 0)) + { + merror(REGEX_COMPILE, ARGV0, url, + config_ruleinfo->url->error); + return(-1); + } + free(url); + url = NULL; + } + + /* Adding matched_group */ + if(if_matched_group) + { + os_calloc(1, sizeof(OSMatch), + config_ruleinfo->if_matched_group); + + if(!OSMatch_Compile(if_matched_group, + config_ruleinfo->if_matched_group, + 0)) + { + merror(REGEX_COMPILE, ARGV0, if_matched_group, + config_ruleinfo->if_matched_group->error); + return(-1); + } + free(if_matched_group); + if_matched_group = NULL; + } + + /* Adding matched_regex */ + if(if_matched_regex) + { + os_calloc(1, sizeof(OSRegex), + config_ruleinfo->if_matched_regex); + if(!OSRegex_Compile(if_matched_regex, + config_ruleinfo->if_matched_regex, 0)) + { + merror(REGEX_COMPILE, ARGV0, if_matched_regex, + config_ruleinfo->if_matched_regex->error); + return(-1); + } + free(if_matched_regex); + if_matched_regex = NULL; + } + } /* enf of elements block */ + + + /* Assigning an active response to the rule */ + Rule_AddAR(config_ruleinfo); + + j++; /* next rule */ + + + /* Creating the last_events if necessary */ + if(config_ruleinfo->context) + { + int ii = 0; + os_calloc(MAX_LAST_EVENTS + 1, sizeof(char *), + config_ruleinfo->last_events); + + /* Zeroing each entry */ + for(;ii<=MAX_LAST_EVENTS;ii++) + { + config_ruleinfo->last_events[ii] = NULL; + } + } + + + /* Adding the rule to the rules list. + * Only the template rules are supposed + * to be at the top level. All others + * will be a "child" of someone. + */ + if(config_ruleinfo->sigid < 10) + { + OS_AddRule(config_ruleinfo); + } + else if(config_ruleinfo->alert_opts & DO_OVERWRITE) + { + if(!OS_AddRuleInfo(NULL, config_ruleinfo, + config_ruleinfo->sigid)) + { + merror("%s: Overwrite rule '%d' not found.", + ARGV0, config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + } + else + { + OS_AddChild(config_ruleinfo); + } + + /* Cleaning what we do not need */ + if(config_ruleinfo->if_group) + { + free(config_ruleinfo->if_group); + config_ruleinfo->if_group = NULL; + } + + /* Setting the event_search pointer */ + if(config_ruleinfo->if_matched_sid) + { + config_ruleinfo->event_search = + (void *)Search_LastSids; + + /* Marking rules that match this id */ + OS_MarkID(NULL, config_ruleinfo); + } + + /* Marking the rules that match if_matched_group */ + else if(config_ruleinfo->if_matched_group) + { + /* Creating list */ + config_ruleinfo->group_search = OSList_Create(); + if(!config_ruleinfo->group_search) + { + ErrorExit(MEM_ERROR, ARGV0); + } + + /* Marking rules that match this group */ + OS_MarkGroup(NULL, config_ruleinfo); + + /* Setting function pointer */ + config_ruleinfo->event_search = + (void *)Search_LastGroups; + } + else if(config_ruleinfo->context) + { + config_ruleinfo->event_search = + (void *)Search_LastEvents; + } + + } /* while(rule[j]) */ + OS_ClearNode(rule); + i++; + + } /* while (node[i]) */ + + /* Cleaning global node */ + OS_ClearNode(node); + OS_ClearXML(&xml); + + #ifdef DEBUG + { + RuleNode *dbg_node = OS_GetFirstRule(); + while(dbg_node) + { + if(dbg_node->child) + { + RuleNode *child_node = dbg_node->child; + + printf("** Child Node for %d **\n",dbg_node->ruleinfo->sigid); + while(child_node) + { + child_node = child_node->next; + } + } + dbg_node = dbg_node->next; + } + } + #endif + + /* Done over here */ + return(0); +} + + +/* loadmemory: v0.1 + * Allocate memory at "*at" and copy *str to it. + * If *at already exist, realloc the memory and cat str + * on it. + * It will return the new string + */ +char *loadmemory(char *at, char *str) +{ + if(at == NULL) + { + int strsize = 0; + if((strsize = strlen(str)) < OS_SIZE_2048) + { + at = calloc(strsize+1,sizeof(char)); + if(at == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + strncpy(at,str,strsize); + return(at); + } + else + { + merror(SIZE_ERROR,ARGV0,str); + return(NULL); + } + } + else /*at is not null. Need to reallocat its memory and copy str to it*/ + { + int strsize = strlen(str); + int atsize = strlen(at); + int finalsize = atsize+strsize+1; + + if((atsize > OS_SIZE_2048) || (strsize > OS_SIZE_2048)) + { + merror(SIZE_ERROR,ARGV0,str); + return(NULL); + } + + at = realloc(at, (finalsize)*sizeof(char)); + + if(at == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + + strncat(at,str,strsize); + + at[finalsize-1]='\0'; + + return(at); + } + return(NULL); +} + + +RuleInfo *zerorulemember(int id, int level, + int maxsize, int frequency, + int timeframe, int noalert, + int ignore_time, int overwrite) +{ + RuleInfo *ruleinfo_pt = NULL; + + /* Allocation memory for structure */ + ruleinfo_pt = (RuleInfo *)calloc(1,sizeof(RuleInfo)); + + if(ruleinfo_pt == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + /* Default values */ + ruleinfo_pt->level = level; + + /* Default category is syslog */ + ruleinfo_pt->category = SYSLOG; + + ruleinfo_pt->ar = NULL; + + ruleinfo_pt->context = 0; + + ruleinfo_pt->sigid = id; + ruleinfo_pt->firedtimes = 0; + ruleinfo_pt->maxsize = maxsize; + ruleinfo_pt->frequency = frequency; + if(ruleinfo_pt->frequency > _max_freq) + { + _max_freq = ruleinfo_pt->frequency; + } + ruleinfo_pt->ignore_time = ignore_time; + ruleinfo_pt->timeframe = timeframe; + ruleinfo_pt->time_ignored = 0; + + ruleinfo_pt->context_opts = 0; + ruleinfo_pt->alert_opts = 0; + ruleinfo_pt->ignore = 0; + ruleinfo_pt->ckignore = 0; + + if(noalert) + { + ruleinfo_pt->alert_opts |= NO_ALERT; + } + if(Config.mailbylevel <= level) + ruleinfo_pt->alert_opts |= DO_MAILALERT; + if(Config.logbylevel <= level) + ruleinfo_pt->alert_opts |= DO_LOGALERT; + + /* Overwriting a rule */ + if(overwrite) + { + ruleinfo_pt->alert_opts |= DO_OVERWRITE; + } + + ruleinfo_pt->day_time = NULL; + ruleinfo_pt->week_day = NULL; + + ruleinfo_pt->group = NULL; + ruleinfo_pt->regex = NULL; + ruleinfo_pt->match = NULL; + ruleinfo_pt->decoded_as = 0; + + ruleinfo_pt->comment = NULL; + ruleinfo_pt->info = NULL; + ruleinfo_pt->cve = NULL; + + ruleinfo_pt->if_sid = NULL; + ruleinfo_pt->if_group = NULL; + ruleinfo_pt->if_level = NULL; + + ruleinfo_pt->if_matched_regex = NULL; + ruleinfo_pt->if_matched_group = NULL; + ruleinfo_pt->if_matched_sid = 0; + + ruleinfo_pt->user = NULL; + ruleinfo_pt->srcip = NULL; + ruleinfo_pt->srcport = NULL; + ruleinfo_pt->dstip = NULL; + ruleinfo_pt->dstport = NULL; + ruleinfo_pt->url = NULL; + ruleinfo_pt->id = NULL; + ruleinfo_pt->status = NULL; + ruleinfo_pt->hostname = NULL; + ruleinfo_pt->program_name = NULL; + ruleinfo_pt->action = NULL; + + /* Zeroing last matched events */ + ruleinfo_pt->__frequency = 0; + ruleinfo_pt->last_events = NULL; + + /* zeroing the list of previous matches */ + ruleinfo_pt->sid_prev_matched = NULL; + ruleinfo_pt->group_prev_matched = NULL; + + ruleinfo_pt->sid_search = NULL; + ruleinfo_pt->group_search = NULL; + + ruleinfo_pt->event_search = NULL; + ruleinfo_pt->compiled_rule = NULL; + + return(ruleinfo_pt); +} + + +/* Get the attributes */ +int getattributes(char **attributes, char **values, + int *id, int *level, + int *maxsize, int *timeframe, + int *frequency, int *accuracy, + int *noalert, int *ignore_time, int *overwrite) +{ + int k=0; + + char *xml_id = "id"; + char *xml_level = "level"; + char *xml_maxsize = "maxsize"; + char *xml_timeframe = "timeframe"; + char *xml_frequency = "frequency"; + char *xml_accuracy = "accuracy"; + char *xml_noalert = "noalert"; + char *xml_ignore_time = "ignore"; + char *xml_overwrite = "overwrite"; + + + /* Getting attributes */ + while(attributes[k]) + { + if(!values[k]) + { + merror("rules_op: Attribute \"%s\" without value." + ,attributes[k]); + return(-1); + } + /* Getting rule Id */ + else if(strcasecmp(attributes[k],xml_id) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%6d",id); + } + else + { + merror("rules_op: Invalid rule id: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Getting level */ + else if(strcasecmp(attributes[k],xml_level) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%4d",level); + } + else + { + merror("rules_op: Invalid level: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Getting maxsize */ + else if(strcasecmp(attributes[k],xml_maxsize) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%4d",maxsize); + } + else + { + merror("rules_op: Invalid maxsize: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Getting timeframe */ + else if(strcasecmp(attributes[k],xml_timeframe) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%5d",timeframe); + } + else + { + merror("rules_op: Invalid timeframe: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Getting frequency */ + else if(strcasecmp(attributes[k],xml_frequency) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%4d",frequency); + } + else + { + merror("rules_op: Invalid frequency: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Rule accuracy */ + else if(strcasecmp(attributes[k],xml_accuracy) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%4d",accuracy); + } + else + { + merror("rules_op: Invalid accuracy: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Rule ignore_time */ + else if(strcasecmp(attributes[k],xml_ignore_time) == 0) + { + if(OS_StrIsNum(values[k])) + { + sscanf(values[k],"%6d",ignore_time); + } + else + { + merror("rules_op: Invalid ignore_time: %s. " + "Must be integer" , + values[k]); + return(-1); + } + } + /* Rule noalert */ + else if(strcasecmp(attributes[k],xml_noalert) == 0) + { + *noalert = 1; + } + else if(strcasecmp(attributes[k], xml_overwrite) == 0) + { + if(strcmp(values[k], "yes") == 0) + { + *overwrite = 1; + } + else if(strcmp(values[k], "no") == 0) + { + *overwrite = 0; + } + else + { + merror("rules_op: Invalid overwrite: %s. " + "Can only by 'yes' or 'no'.", values[k]); + return(-1); + } + } + else + { + merror("rules_op: Invalid attribute \"%s\". " + "Only id, level, maxsize, accuracy, noalert and timeframe " + "are allowed.", attributes[k]); + return(-1); + } + k++; + } + return(0); +} + + +/* Bind active responses to the rule. + * No return. + */ +void Rule_AddAR(RuleInfo *rule_config) +{ + int rule_ar_size = 0; + int mark_to_ar = 0; + int rule_real_level = 0; + + OSListNode *my_ars_node; + + + /* Setting the correctly levels + * We play internally with the rules, to set + * the priorities... Rules with 0 of accuracy, + * receive a low level and go down in the list + */ + if(rule_config->level == 9900) + rule_real_level = 0; + + else if(rule_config->level >= 100) + rule_real_level = rule_config->level/100; + + + /* No AR for ignored rules */ + if(rule_real_level == 0) + { + return; + } + + if(!active_responses) + { + return; + } + + /* Looping on all AR */ + my_ars_node = OSList_GetFirstNode(active_responses); + while(my_ars_node) + { + active_response *my_ar; + + + my_ar = (active_response *)my_ars_node->data; + mark_to_ar = 0; + + /* Checking if the level for the ar is higher */ + if(my_ar->level) + { + if(rule_real_level >= my_ar->level) + { + mark_to_ar = 1; + } + } + + /* Checking if group matches */ + if(my_ar->rules_group) + { + if(OS_Regex(my_ar->rules_group, rule_config->group)) + { + mark_to_ar = 1; + } + } + + /* Checking if rule id matches */ + if(my_ar->rules_id) + { + int r_id = 0; + char *str_pt = my_ar->rules_id; + + while(*str_pt != '\0') + { + /* We allow spaces in between */ + if(*str_pt == ' ') + { + str_pt++; + continue; + } + + /* If is digit, we get the value + * and search for the next digit + * available + */ + else if(isdigit((int)*str_pt)) + { + r_id = atoi(str_pt); + + /* mark to ar if id matches */ + if(r_id == rule_config->sigid) + { + mark_to_ar = 1; + } + + str_pt = strchr(str_pt, ','); + if(str_pt) + { + str_pt++; + } + else + { + break; + } + } + + /* Checking for duplicate commas */ + else if(*str_pt == ',') + { + str_pt++; + continue; + } + + else + { + break; + } + } + } /* eof of rules_id */ + + + /* Bind AR to the rule */ + if(mark_to_ar == 1) + { + rule_ar_size++; + + rule_config->ar = realloc(rule_config->ar, + (rule_ar_size + 1) + *sizeof(active_response *)); + + /* Always set the last node to NULL */ + rule_config->ar[rule_ar_size - 1] = my_ar; + rule_config->ar[rule_ar_size] = NULL; + } + + my_ars_node = OSList_GetNextNode(active_responses); + } + + return; +} + + +/* print rule */ +void printRuleinfo(RuleInfo *rule, int node) +{ + debug1("%d : rule:%d, level %d, timeout: %d", + node, + rule->sigid, + rule->level, + rule->ignore_time); +} + + + +/* Add Rule to hash. */ +int AddHash_Rule(RuleNode *node) +{ + while(node) + { + char _id_key[15]; + char *id_key; + + snprintf(_id_key, 14, "%d", node->ruleinfo->sigid); + os_strdup(_id_key, id_key); + + + /* Adding key to hash. */ + OSHash_Add(Config.g_rules_hash, id_key, node->ruleinfo); + if(node->child) + { + AddHash_Rule(node->child); + } + + node = node->next; + } + + return(0); +} + + + +/* _set levels */ +int _setlevels(RuleNode *node, int nnode) +{ + int l_size = 0; + while(node) + { + if(node->ruleinfo->level == 9900) + node->ruleinfo->level = 0; + + if(node->ruleinfo->level >= 100) + node->ruleinfo->level/=100; + + l_size++; + + /* Rule information */ + printRuleinfo(node->ruleinfo, nnode); + + if(node->child) + { + int chl_size = 0; + chl_size = _setlevels(node->child, nnode+1); + + l_size += chl_size; + } + + node = node->next; + } + + return(l_size); +} + + +/* EOF */ diff --git a/src/analysisd/rules.h b/src/analysisd/rules.h new file mode 100755 index 0000000..c61df28 --- /dev/null +++ b/src/analysisd/rules.h @@ -0,0 +1,204 @@ +/* @(#) $Id: rules.h,v 1.41 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _OS_RULES + +#define _OS_RULES + +#define MAX_LAST_EVENTS 11 + +#include "shared.h" +#include "active-response.h" + +/* Event context - stored on a uint8 */ +#define SAME_USER 0x001 /* 1 */ +#define SAME_SRCIP 0x002 /* 2 */ +#define SAME_ID 0x004 /* 4 */ +#define SAME_LOCATION 0x008 /* 8 */ +#define DIFFERENT_URL 0x010 /* */ +#define SAME_SRCPORT 0x020 +#define SAME_DSTPORT 0x040 +#define NOT_SAME_USER 0xffe /* 0xfff - 0x001 */ +#define NOT_SAME_SRCIP 0xffd /* 0xfff - 0x002 */ +#define NOT_SAME_ID 0xffb /* 0xfff - 0x004 */ +#define NOT_SAME_AGENT 0xff7 /* 0xfff - 0x008 */ + +/* Alert options - store on a uint8 */ +#define DO_FTS 0x001 +#define DO_MAILALERT 0x002 +#define DO_LOGALERT 0x004 +#define NO_ALERT 0x010 +#define DO_OVERWRITE 0x020 +#define DO_PACKETINFO 0x040 +#define DO_EXTRAINFO 0x100 +#define SAME_EXTRAINFO 0x200 + + +typedef struct _RuleInfo +{ + int sigid; /* id attribute -- required*/ + int level; /* level attribute --required */ + int maxsize; + int frequency; + int timeframe; + + u_int8_t context; /* Not an user option */ + + int firedtimes; /* Not an user option */ + int time_ignored; /* Not an user option */ + int ignore_time; + int ignore; + int ckignore; + int group_prev_matched_sz; + + int __frequency; + char **last_events; + + + /* Not an option in the rule */ + u_int16_t alert_opts; + + /* Context options */ + u_int16_t context_opts; + + /* category */ + u_int8_t category; + + /* Decoded as */ + u_int16_t decoded_as; + + /* List of previously matched events */ + OSList *sid_prev_matched; + + /* Pointer to a list (points to sid_prev_matched of if_matched_sid */ + OSList *sid_search; + + /* List of previously matched events in this group. + * Every rule that has if_matched_group will have this + * list. Every rule that matches this group, it going to + * have a pointer to it (group_search). + */ + OSList **group_prev_matched; + + /* Pointer to group_prev_matched */ + OSList *group_search; + + /* Function pointer to the event_search. */ + void *(*event_search)(void *lf, void *rule); + + + char *group; + OSMatch *match; + OSRegex *regex; + + /* Policy-based rules */ + char *day_time; + char *week_day; + + os_ip **srcip; + os_ip **dstip; + OSMatch *srcport; + OSMatch *dstport; + OSMatch *user; + OSMatch *url; + OSMatch *id; + OSMatch *status; + OSMatch *hostname; + OSMatch *program_name; + OSMatch *extra_data; + char *action; + + char *comment; /* description in the xml */ + char *info; + char *cve; + + char *if_sid; + char *if_level; + char *if_group; + + OSRegex *if_matched_regex; + OSMatch *if_matched_group; + int if_matched_sid; + + void *(*compiled_rule)(void *lf); + active_response **ar; + +}RuleInfo; + + +typedef struct _RuleNode +{ + RuleInfo *ruleinfo; + struct _RuleNode *next; + struct _RuleNode *child; +}RuleNode; + + +RuleInfo *currently_rule; /* */ + +/* RuleInfo functions */ +RuleInfo *zerorulemember(int id, + int level, + int maxsize, + int frequency, + int timeframe, + int noalert, + int ignore_time, + int overwrite); + + +/** Rule_list Functions **/ + +/* create the rule list */ +void OS_CreateRuleList(); + +/* Add rule information to the list */ +int OS_AddRule(RuleInfo *read_rule); + +/* Add rule information as a child */ +int OS_AddChild(RuleInfo *read_rule); + +/* Add an overwrite rule */ +int OS_AddRuleInfo(RuleNode *r_node, RuleInfo *newrule, int sid); + +/* Mark groups (if_matched_group) */ +int OS_MarkGroup(RuleNode *r_node, RuleInfo *orig_rule); + +/* Mark IDs (if_matched_sid) */ +int OS_MarkID(RuleNode *r_node, RuleInfo *orig_rule); + + +/* Get first rule */ +RuleNode *OS_GetFirstRule(); + + +/** Defition of the internal rule IDS ** + ** These SIGIDs cannot be used ** + ** **/ + +#define STATS_MODULE 11 +#define FTS_MODULE 12 +#define SYSCHECK_MODULE 13 +#define HOSTINFO_MODULE 15 + + +#define ROOTCHECK_MOD "rootcheck" +#define HOSTINFO_NEW "hostinfo_new" +#define HOSTINFO_MOD "hostinfo_modified" +#define SYSCHECK_MOD "syscheck_integrity_changed" +#define SYSCHECK_MOD2 "syscheck_integrity_changed_2nd" +#define SYSCHECK_MOD3 "syscheck_integrity_changed_3rd" +#define SYSCHECK_NEW "syscheck_new_entry" +#define SYSCHECK_DEL "syscheck_deleted" + + +#endif /* _OS_RULES */ diff --git a/src/analysisd/rules_list.c b/src/analysisd/rules_list.c new file mode 100755 index 0000000..4597b1f --- /dev/null +++ b/src/analysisd/rules_list.c @@ -0,0 +1,490 @@ +/* @(#) $Id: rules_list.c,v 1.28 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rules.h" + +/* Rulenode global */ +RuleNode *rulenode; + +/* _OS_Addrule: Internal AddRule */ +RuleNode *_OS_AddRule(RuleNode *_rulenode, RuleInfo *read_rule); + + +/* Create the RuleList */ +void OS_CreateRuleList() +{ + rulenode = NULL; + + return; +} + + +/* Get first node from rule */ +RuleNode *OS_GetFirstRule() +{ + RuleNode *rulenode_pt = rulenode; + + return(rulenode_pt); +} + + +/* Search all rules, including childs */ +int _AddtoRule(int sid, int level, int none, char *group, + RuleNode *r_node, RuleInfo *read_rule) +{ + int r_code = 0; + + /* If we don't have the first node, start from + * the beginning of the list + */ + if(!r_node) + { + r_node = OS_GetFirstRule(); + } + + while(r_node) + { + /* Checking if the sigid matches */ + if(sid) + { + if(r_node->ruleinfo->sigid == sid) + { + /* Assign the category of this rule to the child + * as they must match + */ + read_rule->category = r_node->ruleinfo->category; + + + /* If no context for rule, check if the parent has + * and use it. + */ + if(!read_rule->last_events && r_node->ruleinfo->last_events) + { + read_rule->last_events = r_node->ruleinfo->last_events; + } + + r_node->child= + _OS_AddRule(r_node->child, read_rule); + return(1); + } + } + + /* Checking if the group matches */ + else if(group) + { + if(OS_WordMatch(group, r_node->ruleinfo->group) && + (r_node->ruleinfo->sigid != read_rule->sigid)) + { + /* If no context for rule, check if the parent has + * and use it. + */ + if(!read_rule->last_events && r_node->ruleinfo->last_events) + { + read_rule->last_events = r_node->ruleinfo->last_events; + } + + /* We will loop on all rules until we find */ + r_node->child = + _OS_AddRule(r_node->child, read_rule); + r_code = 1; + } + } + + /* Checking if the level matches */ + else if(level) + { + if((r_node->ruleinfo->level >= level) && + (r_node->ruleinfo->sigid != read_rule->sigid)) + { + r_node->child= + _OS_AddRule(r_node->child, read_rule); + r_code = 1; + } + } + + + /* If we are not searching for the sid/group, the category must + * be the same. + */ + else if(read_rule->category != r_node->ruleinfo->category) + { + r_node = r_node->next; + continue; + } + + + /* If none of them is set, add for the category */ + else + { + /* Setting the parent category to it */ + read_rule->category = r_node->ruleinfo->category; + r_node->child = + _OS_AddRule(r_node->child, read_rule); + return(1); + } + + /* Checking if the child has a rule */ + if(r_node->child) + { + if(_AddtoRule(sid, level, none, group, r_node->child, read_rule)) + { + r_code = 1; + } + } + + r_node = r_node->next; + } + + return(r_code); +} + + +/* Add a child */ +int OS_AddChild(RuleInfo *read_rule) +{ + if(!read_rule) + { + merror("rules_list: Passing a NULL rule. Inconsistent state"); + return(1); + } + + /* Adding for if_sid */ + if(read_rule->if_sid) + { + int val = 0; + char *sid; + + sid = read_rule->if_sid; + + /* Loop to read all the rules (comma or space separated */ + do + { + int rule_id = 0; + if((*sid == ',')||(*sid == ' ')) + { + val = 0; + continue; + } + else if((isdigit((int)*sid)) || (*sid == '\0')) + { + if(val == 0) + { + rule_id = atoi(sid); + if(!_AddtoRule(rule_id, 0, 0, NULL, NULL, read_rule)) + { + ErrorExit("rules_list: Signature ID '%d' not " + "found. Invalid 'if_sid'.", rule_id); + } + val = 1; + } + } + else + { + ErrorExit("rules_list: Signature ID must be an integer. " + "Exiting..."); + } + }while(*sid++ != '\0'); + } + + /* Adding for if_level */ + else if(read_rule->if_level) + { + int ilevel = 0; + + ilevel = atoi(read_rule->if_level); + if(ilevel == 0) + { + merror("%s: Invalid level (atoi)",ARGV0); + return(1); + } + + ilevel*=100; + + if(!_AddtoRule(0, ilevel, 0, NULL, NULL, read_rule)) + { + ErrorExit("rules_list: Level ID '%d' not " + "found. Invalid 'if_level'.", ilevel); + } + } + + /* Adding for if_group */ + else if(read_rule->if_group) + { + if(!_AddtoRule(0, 0, 0, read_rule->if_group, NULL, read_rule)) + { + ErrorExit("rules_list: Group '%s' not " + "found. Invalid 'if_group'.", read_rule->if_group); + } + } + + /* Just add based on the category */ + else + { + if(!_AddtoRule(0, 0, 0, NULL, NULL, read_rule)) + { + ErrorExit("rules_list: Category '%d' not " + "found. Invalid 'category'.", read_rule->category); + } + } + + /* done over here */ + return(0); +} + + + +/* Add a rule in the chain */ +RuleNode *_OS_AddRule(RuleNode *_rulenode, RuleInfo *read_rule) +{ + RuleNode *tmp_rulenode = _rulenode; + + + if(tmp_rulenode != NULL) + { + int middle_insertion = 0; + RuleNode *prev_rulenode = NULL; + RuleNode *new_rulenode = NULL; + + while(tmp_rulenode != NULL) + { + if(read_rule->level > tmp_rulenode->ruleinfo->level) + { + middle_insertion = 1; + break; + } + prev_rulenode = tmp_rulenode; + tmp_rulenode = tmp_rulenode->next; + } + + new_rulenode = (RuleNode *)calloc(1,sizeof(RuleNode)); + + if(!new_rulenode) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + if(middle_insertion == 1) + { + if(prev_rulenode == NULL) + { + _rulenode = new_rulenode; + } + else + { + prev_rulenode->next = new_rulenode; + } + + new_rulenode->next = tmp_rulenode; + new_rulenode->ruleinfo = read_rule; + new_rulenode->child = NULL; + } + + else + { + prev_rulenode->next = new_rulenode; + prev_rulenode->next->ruleinfo = read_rule; + prev_rulenode->next->next = NULL; + prev_rulenode->next->child = NULL; + } + } + + else + { + _rulenode = (RuleNode *)calloc(1,sizeof(RuleNode)); + if(_rulenode == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + _rulenode->ruleinfo = read_rule; + _rulenode->next = NULL; + _rulenode->child= NULL; + } + + return(_rulenode); +} + +/* External AddRule */ +int OS_AddRule(RuleInfo *read_rule) +{ + rulenode = _OS_AddRule(rulenode,read_rule); + + return(0); +} + + +/* Update rule info for overwritten ones */ +int OS_AddRuleInfo(RuleNode *r_node, RuleInfo *newrule, int sid) +{ + /* If no r_node is given, get first node */ + if(r_node == NULL) + { + r_node = OS_GetFirstRule(); + } + + if(sid == 0) + return(0); + + while(r_node) + { + /* Checking if the sigid matches */ + if(r_node->ruleinfo->sigid == sid) + { + r_node->ruleinfo->level = newrule->level; + r_node->ruleinfo->maxsize = newrule->maxsize; + r_node->ruleinfo->frequency = newrule->frequency; + r_node->ruleinfo->timeframe = newrule->timeframe; + + r_node->ruleinfo->group = newrule->group; + r_node->ruleinfo->match = newrule->match; + r_node->ruleinfo->regex = newrule->regex; + r_node->ruleinfo->day_time = newrule->day_time; + r_node->ruleinfo->week_day = newrule->week_day; + r_node->ruleinfo->srcip = newrule->srcip; + r_node->ruleinfo->dstip = newrule->dstip; + r_node->ruleinfo->srcport = newrule->srcport; + r_node->ruleinfo->dstport = newrule->dstport; + r_node->ruleinfo->user = newrule->user; + r_node->ruleinfo->url = newrule->url; + r_node->ruleinfo->id = newrule->id; + r_node->ruleinfo->status = newrule->status; + r_node->ruleinfo->hostname = newrule->hostname; + r_node->ruleinfo->program_name = newrule->program_name; + r_node->ruleinfo->extra_data = newrule->extra_data; + r_node->ruleinfo->action = newrule->action; + r_node->ruleinfo->comment = newrule->comment; + r_node->ruleinfo->info = newrule->info; + r_node->ruleinfo->cve = newrule->cve; + r_node->ruleinfo->if_matched_regex = newrule->if_matched_regex; + r_node->ruleinfo->if_matched_group = newrule->if_matched_group; + r_node->ruleinfo->if_matched_sid = newrule->if_matched_sid; + r_node->ruleinfo->alert_opts = newrule->alert_opts; + r_node->ruleinfo->context_opts = newrule->context_opts; + r_node->ruleinfo->context = newrule->context; + r_node->ruleinfo->decoded_as = newrule->decoded_as; + r_node->ruleinfo->ar = newrule->ar; + r_node->ruleinfo->compiled_rule = newrule->compiled_rule; + + return(1); + } + + + /* Checking if the child has a rule */ + if(r_node->child) + { + if(OS_AddRuleInfo(r_node->child, newrule, sid)) + { + return(1); + } + } + + r_node = r_node->next; + } + + return(0); +} + + +/* Mark rules that match specific id (for if_matched_sid) */ +int OS_MarkID(RuleNode *r_node, RuleInfo *orig_rule) +{ + /* If no r_node is given, get first node */ + if(r_node == NULL) + { + r_node = OS_GetFirstRule(); + } + + while(r_node) + { + if(r_node->ruleinfo->sigid == orig_rule->if_matched_sid) + { + /* If child does not have a list, create one */ + if(!r_node->ruleinfo->sid_prev_matched) + { + r_node->ruleinfo->sid_prev_matched = OSList_Create(); + if(!r_node->ruleinfo->sid_prev_matched) + { + ErrorExit(MEM_ERROR, ARGV0); + } + } + + /* Assigning the parent pointer to it */ + orig_rule->sid_search = r_node->ruleinfo->sid_prev_matched; + } + + + /* Checking if the child has a rule */ + if(r_node->child) + { + OS_MarkID(r_node->child, orig_rule); + } + + r_node = r_node->next; + } + + return(0); +} + + + +/* Mark rules that match specific group (for if_matched_group) */ +int OS_MarkGroup(RuleNode *r_node, RuleInfo *orig_rule) +{ + /* If no r_node is given, get first node */ + if(r_node == NULL) + { + r_node = OS_GetFirstRule(); + } + + while(r_node) + { + if(OSMatch_Execute(r_node->ruleinfo->group, + strlen(r_node->ruleinfo->group), + orig_rule->if_matched_group)) + { + int rule_g = 0; + if(r_node->ruleinfo->group_prev_matched) + { + while(r_node->ruleinfo->group_prev_matched[rule_g]) + { + rule_g++; + } + } + + os_realloc(r_node->ruleinfo->group_prev_matched, + (rule_g + 2)*sizeof(OSList *), + r_node->ruleinfo->group_prev_matched); + + r_node->ruleinfo->group_prev_matched[rule_g] = NULL; + r_node->ruleinfo->group_prev_matched[rule_g +1] = NULL; + + /* Setting the size */ + r_node->ruleinfo->group_prev_matched_sz = rule_g +1; + + r_node->ruleinfo->group_prev_matched[rule_g] = + orig_rule->group_search; + } + + + /* Checking if the child has a rule */ + if(r_node->child) + { + OS_MarkGroup(r_node->child, orig_rule); + } + + r_node = r_node->next; + } + + return(0); +} +/* EOF */ diff --git a/src/analysisd/stats.c b/src/analysisd/stats.c new file mode 100755 index 0000000..ceb7912 --- /dev/null +++ b/src/analysisd/stats.c @@ -0,0 +1,519 @@ +/* @(#) $Id: stats.c,v 1.30 2009/06/24 17:06:22 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "analysisd.h" +#include "stats.h" +#include "rules.h" + +#include "error_messages/error_messages.h" + +#include "headers/file_op.h" +#include "alerts/alerts.h" + +#include "headers/debug_op.h" + + +char *(weekdays[])={"Sunday","Monday","Tuesday","Wednesday","Thursday", + "Friday","Saturday"}; +char *(l_month[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", + "Sep","Oct","Nov","Dec"}; + + + +/* Global vars */ + +/* Hour 25 is internally used */ +int _RWHour[7][25]; +int _CWHour[7][25]; + +int _RHour[25]; +int _CHour[25]; + +int _cignorehour = 0; +int _fired = 0; +int _daily_errors = 0; +int maxdiff = 0; +int mindiff = 0; +int percent_diff = 20; + + +char __stats_comment[192]; + +/* Last msgs, to avoid floods */ +char *_lastmsg; +char *_prevlast; +char *_pprevlast; + + +void print_totals() +{ + int i, totals = 0; + char logfile[OS_FLSIZE +1]; + FILE *flog; + + + /* Creating the path for the logs */ + snprintf(logfile, OS_FLSIZE,"%s/%d/", STATSAVED, prev_year); + if(IsDir(logfile) == -1) + if(mkdir(logfile,0770) == -1) + { + merror(MKDIR_ERROR,ARGV0,logfile); + return; + } + + snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year, prev_month); + + if(IsDir(logfile) == -1) + if(mkdir(logfile,0770) == -1) + { + merror(MKDIR_ERROR, ARGV0, logfile); + return; + } + + + /* Creating the logfile name */ + snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log", + STATSAVED, + prev_year, + prev_month, + "totals", + today); + + flog = fopen(logfile, "a"); + if(!flog) + { + merror(FOPEN_ERROR, ARGV0, logfile); + return; + } + + /* Printing the hourly stats */ + for(i=0;i<=23;i++) + { + fprintf(flog,"Hour totals - %d:%d\n", i, _CHour[i]); + totals+=_CHour[i]; + } + fprintf(flog,"Total events for day:%d\n", totals); + + fclose(flog); +} + + +/* gethour: v0.2 + * Return the parameter (event_number + 20 % of it) + * If event_number < mindiff, return mindiff + * If event_number > maxdiff, return maxdiff + */ +int gethour(int event_number) +{ + int event_diff; + + event_diff = (event_number * percent_diff)/100; + + event_diff++; + + if(event_diff < mindiff) + return(event_number + mindiff); + else if(event_diff > maxdiff) + return(event_number + maxdiff); + + return(event_number + event_diff); +} + + +/* Update_Hour: done daily */ +void Update_Hour() +{ + int i,j; + int inter; + + + /* Print total number of logs received per hour */ + print_totals(); + + + /* Hourly update */ + _RHour[24]++; + inter = _RHour[24]; + if(inter > 7) + inter = 7; + + for(i=0;i<=24;i++) + { + char _hourly[128]; /* _hourly file */ + + FILE *fp; + + if(i != 24) + { + /* If saved hourly = 0, just copy the current hourly rate */ + if(_CHour[i] == 0) + continue; + + if(_RHour[i] == 0) + _RHour[i]=_CHour[i] + 20; + + else + { + /* If we had too many errors this day */ + if(_daily_errors >= 3) + { + _RHour[i]=(((3*_CHour[i])+(inter*_RHour[i]))/(inter+3))+25; + } + + else + { + /* The average is going to be the number of interactions + + * the currently hourly rate, divided by 4 */ + _RHour[i]=((_CHour[i]+(inter*_RHour[i]))/(inter+1))+5; + } + } + } + + snprintf(_hourly,128,"%s/%d",STATQUEUE,i); + fp = fopen(_hourly, "w"); + if(fp) + { + fprintf(fp,"%d",_RHour[i]); + fclose(fp); + } + + else + { + merror(FOPEN_ERROR, "logstats", _hourly); + } + + _CHour[i] = 0; /* Zeroing the currently hour */ + } + + /* Weekly */ + for(i=0;i <= 6;i++) + { + char _weekly[128]; + FILE *fp; + + _CWHour[i][24]++; + inter = _CWHour[i][24]; + if(inter > 7) + inter = 7; + + for(j=0;j<=24;j++) + { + if(j != 24) + { + if(_CWHour[i][j] == 0) + continue; + + if(_RWHour[i][j] == 0) + _RWHour[i][j] = _CWHour[i][j] + 20; + + else + { + if(_daily_errors >= 3) + { + _RWHour[i][j]=(((3*_CWHour[i][j])+(inter*_RWHour[i][j]))/(inter+3))+25; + } + else + { + _RWHour[i][j]=((_CWHour[i][j]+(inter*_RWHour[i][j]))/(inter+1))+5; + } + } + } + + snprintf(_weekly,128,"%s/%d/%d",STATWQUEUE,i,j); + fp = fopen(_weekly, "w"); + if(fp) + { + fprintf(fp,"%d",_RWHour[i][j]); + fclose(fp); + } + else + { + merror(FOPEN_ERROR, "logstats", _weekly); + } + + _CWHour[i][j] = 0; + } + } + + _daily_errors = 0; + return; +} + + +/* Check Hourly stats */ +int Check_Hour(Eventinfo *lf) +{ + _CHour[__crt_hour]++; + _CWHour[__crt_wday][__crt_hour]++; + + if(_RHour[24] <= 2) + { + return(0); + } + + /* checking if any message was already fired for this hour */ + if((_daily_errors >= 3)||((_fired == 1)&&(_cignorehour == __crt_hour))) + return(0); + + else if(_cignorehour != __crt_hour) + { + _cignorehour=__crt_hour; + _fired = 0; + } + + + /* checking if passed the threshold */ + if(_RHour[__crt_hour] != 0) + { + if(_CHour[__crt_hour] > (_RHour[__crt_hour])) + { + if(_CHour[__crt_hour] > (gethour(_RHour[__crt_hour]))) + { + /* snprintf will null terminate */ + snprintf(__stats_comment, 191, + "The average number of logs" + " between %d:00 and %d:00 is %d. We " + "reached %d.",__crt_hour,__crt_hour+1, + _RHour[__crt_hour],_CHour[__crt_hour]); + + + _fired = 1; + _daily_errors++; + return(1); + } + } + } + + + /* We need to have at least 3 days of stats */ + if(_RWHour[__crt_wday][24] <= 2) + return(0); + + /* checking for the hour during a specific day of the week */ + if(_RWHour[__crt_wday][__crt_hour] != 0) + { + if(_CWHour[__crt_wday][__crt_hour] > _RWHour[__crt_wday][__crt_hour]) + { + if(_CWHour[__crt_wday][__crt_hour] > + gethour(_RWHour[__crt_wday][__crt_hour])) + { + snprintf(__stats_comment, 191, + "The average number of logs" + " between %d:00 and %d:00 on %s is %d. We" + " reached %d.",__crt_hour,__crt_hour+1, + weekdays[__crt_wday], + _RWHour[__crt_wday][__crt_hour], + _CWHour[__crt_wday][__crt_hour]); + + + _fired = 1; + _daily_errors++; + return(1); + } + } + } + return(0); +} + +/* Starting hourly stats and other necessary variables */ +int Start_Hour() +{ + int i=0,j=0; + struct tm *p; + + /* Current time */ + p = localtime(&c_time); + + /* Other global variables */ + _fired = 0; + _cignorehour = 0; + + today = p->tm_mday; + thishour = p->tm_hour; + prev_year = p->tm_year + 1900; + strncpy(prev_month, l_month[p->tm_mon], 3); + prev_month[3] = '\0'; + + + /* Clearing some memory */ + memset(__stats_comment, '\0', 192); + + + /* Getting maximum/minimum diffs */ + maxdiff = getDefine_Int("analysisd", + "stats_maxdiff", + 10, 99999); + + mindiff = getDefine_Int("analysisd", + "stats_mindiff", + 10, 99999); + + percent_diff = getDefine_Int("analysisd", + "stats_percent_diff", + 5, 999); + + + /* Last three messages + * They are used to keep track of the last + * messages received to avoid floods. + */ + _lastmsg = NULL; + _prevlast = NULL; + _pprevlast = NULL; + + + /* They should not be null */ + os_strdup(" ", _lastmsg); + os_strdup(" ", _prevlast); + os_strdup(" ", _pprevlast); + + + /* Creating the stat queue directories */ + if(IsDir(STATWQUEUE) == -1) + if(mkdir(STATWQUEUE,0770) == -1) + { + merror("%s: logstat: Unable to create stat queue: %s", + ARGV0, STATWQUEUE); + return(-1); + } + + if(IsDir(STATQUEUE) == -1) + if(mkdir(STATQUEUE,0770) == -1) + { + merror("%s: logstat: Unable to create stat queue: %s", + ARGV0, STATQUEUE); + return(-1); + } + + /* Creating store dir */ + if(IsDir(STATSAVED) == -1) + if(mkdir(STATSAVED,0770) == -1) + { + merror("%s: logstat: Unable to create stat directory: %s", + ARGV0, STATQUEUE); + return(-1); + } + + /* Creating hourly directory (24 hour is the stats) */ + for(i=0;i<=24;i++) + { + char _hourly[128]; + snprintf(_hourly,128,"%s/%d",STATQUEUE,i); + + _CHour[i]=0; + if(File_DateofChange(_hourly) < 0) + _RHour[i] = 0; + + else + { + FILE *fp; + fp = fopen(_hourly, "r"); + if(!fp) + _RHour[i] = 0; + else + { + if(fscanf(fp,"%d",&_RHour[i]) <= 0) + _RHour[i] = 0; + + if(_RHour[i] < 0) + _RHour[i] = 0; + fclose(fp); + } + } + } + + /* Creating weekly/hourly directories */ + for(i=0;i<=6;i++) + { + char _weekly[128]; + snprintf(_weekly,128,"%s/%d",STATWQUEUE,i); + if(IsDir(_weekly) == -1) + if(mkdir(_weekly,0770) == -1) + { + merror("%s: logstat: Unable to create stat queue: %s", + ARGV0, _weekly); + return(-1); + } + + for(j=0;j<=24;j++) + { + _CWHour[i][j]=0; + snprintf(_weekly,128,"%s/%d/%d",STATWQUEUE,i,j); + if(File_DateofChange(_weekly) < 0) + _RWHour[i][j] = 0; + else + { + FILE *fp; + fp = fopen(_weekly, "r"); + if(!fp) + _RWHour[i][j] = 0; + else + { + if(fscanf(fp,"%d",&_RWHour[i][j]) <= 0) + _RWHour[i][j] = 0; + + if(_RWHour[i][j] < 0) + _RWHour[i][j] = 0; + fclose(fp); + } + } + } + } + return(0); +} + + +/* LastMsg_Stats: v0.3: 2006/03/21 + * v0.3: Some performance fixes (2006/03/21). + * v0.2: 2005/03/17 + * check if the message received is repeated. Doing + * it to avoid floods from same message. + */ +int LastMsg_Stats(char *log) +{ + if(strcmp(log,_lastmsg) == 0) + return(1); + + else if(strcmp(log,_prevlast) == 0) + return(1); + + else if(strcmp(log,_pprevlast) == 0) + return(1); + + return(0); +} + +/* LastMsg_Change: v0.3: 2006/03/21 + * v0.3: 2006/03/21: Some performance fixes. + * v0.2: 2005/03/17 + * If the message is not repeated, rearrange the last + * received messages + */ +void LastMsg_Change(char *log) +{ + /* Removing the last one */ + free(_pprevlast); + + /* Moving the second to third and the last to second */ + _pprevlast = _prevlast; + + _prevlast = _lastmsg; + + + os_strdup(log, _lastmsg); + return; +} + + +/* EOF */ diff --git a/src/analysisd/stats.h b/src/analysisd/stats.h new file mode 100755 index 0000000..a7ac6f8 --- /dev/null +++ b/src/analysisd/stats.h @@ -0,0 +1,11 @@ +#ifndef _STAT__H + +#define _STAT__H + +/* Logstat functions */ +void LastMsg_Change(char *log); +int LastMsg_Stats(char *log); + +char __stats_comment[192]; + +#endif diff --git a/src/analysisd/testrule.c b/src/analysisd/testrule.c new file mode 100755 index 0000000..db769f7 --- /dev/null +++ b/src/analysisd/testrule.c @@ -0,0 +1,534 @@ +/* @(#) $Id: testrule.c,v 1.7 2009/08/25 11:30:57 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Part of the OSSEC + * Available at http://www.ossec.net + */ + + +/* ossec-analysisd. + * Responsible for correlation and log decoding. + */ + +#ifdef ARGV0 + #undef ARGV0 + #define ARGV0 "ossec-testrule" +#endif + +#include "shared.h" + +#include "alerts/alerts.h" +#include "alerts/getloglocation.h" +#include "os_execd/execd.h" + +#include "os_regex/os_regex.h" +#include "os_net/os_net.h" + + +/** Local headers **/ +#include "active-response.h" +#include "config.h" +#include "rules.h" +#include "stats.h" +#include "eventinfo.h" +#include "analysisd.h" + + + +/** Internal Functions **/ +void OS_ReadMSG(int m_queue); +RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node); + + +/** External functions prototypes (only called here) **/ + +/* For config */ +int GlobalConf(char * cfgfile); + + +/* For rules */ +void Rules_OP_CreateRules(); +int Rules_OP_ReadRules(char * cfgfile); +int _setlevels(RuleNode *node, int nnode); +int AddHash_Rule(RuleNode *node); + + +/* For cleanmsg */ +int OS_CleanMSG(char *msg, Eventinfo *lf); + + +/* for FTS */ +int FTS_Init(); +int FTS(Eventinfo *lf); +int AddtoIGnore(Eventinfo *lf); +int IGnore(Eventinfo *lf); + + +/* For decoders */ +void DecodeEvent(Eventinfo *lf); +int DecodeSyscheck(Eventinfo *lf); +int DecodeRootcheck(Eventinfo *lf); +int DecodeHostinfo(Eventinfo *lf); + + +/* For Decoders */ +int ReadDecodeXML(char *file); +int SetDecodeXML(); + + + + +/** int main(int argc, char **argv) + */ +int main(int argc, char **argv) +{ + int c = 0, m_queue = 0; + char *dir = DEFAULTDIR; + char *user = USER; + char *group = GROUPGLOBAL; + + char *cfg = DEFAULTCPATH; + + /* Setting the name */ + OS_SetName(ARGV0); + + thishour = 0; + today = 0; + prev_year = 0; + full_output = 0; + active_responses = NULL; + memset(prev_month, '\0', 4); + + while((c = getopt(argc, argv, "Vfdhu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user = optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group = optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir = optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 'f': + full_output = 1; + break; + default: + help(ARGV0); + break; + } + + } + + + /* Reading configuration file */ + if(GlobalConf(cfg) < 0) + { + ErrorExit(CONFIG_ERROR,ARGV0, cfg); + } + + debug1(READ_CONFIG, ARGV0); + + + + /* Getting servers hostname */ + memset(__shost, '\0', 512); + if(gethostname(__shost, 512 -1) != 0) + { + strncpy(__shost, OSSEC_SERVER, 512 -1); + } + else + { + char *_ltmp; + + /* Remove domain part if available */ + _ltmp = strchr(__shost, '.'); + if(_ltmp) + *_ltmp = '\0'; + } + + + + if(chdir(dir) != 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + + + /* Reading decoders */ + OS_CreateOSDecoderList(); + if(!ReadDecodeXML("etc/decoder.xml")) + { + ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER); + } + + c = ReadDecodeXML("etc/local_decoder.xml"); + if(!c) + { + if((c != -2)) + ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER); + } + SetDecodeXML(); + + + /* Creating the rules list */ + Rules_OP_CreateRules(); + + + /* Reading the rules */ + { + char **rulesfiles; + rulesfiles = Config.includes; + while(rulesfiles && *rulesfiles) + { + debug1("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles); + if(Rules_OP_ReadRules(*rulesfiles) < 0) + ErrorExit(RULES_ERROR, ARGV0, *rulesfiles); + + free(*rulesfiles); + rulesfiles++; + } + + free(Config.includes); + Config.includes = NULL; + } + + + /* Fixing the levels/accuracy */ + { + int total_rules; + RuleNode *tmp_node = OS_GetFirstRule(); + + total_rules = _setlevels(tmp_node, 0); + debug1("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules); + } + + + /* Creating a rules hash (for reading alerts from other servers). */ + { + RuleNode *tmp_node = OS_GetFirstRule(); + Config.g_rules_hash = OSHash_Create(); + if(!Config.g_rules_hash) + { + ErrorExit(MEM_ERROR, ARGV0); + } + AddHash_Rule(tmp_node); + } + + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, getpid()); + + + /* Going to main loop */ + OS_ReadMSG(m_queue); + + + exit(0); + +} + + + +/* OS_ReadMSG. + * Main function. Receives the messages(events) + * and analyze them all. + */ +void OS_ReadMSG(int m_queue) +{ + int i; + char msg[OS_MAXSTR +1]; + Eventinfo *lf; + + + /* Null to global currently pointers */ + currently_rule = NULL; + + + /* Creating the event list */ + OS_CreateEventList(Config.memorysize); + + + /* Initiating the FTS list */ + if(!FTS_Init()) + { + ErrorExit(FTS_LIST_ERROR, ARGV0); + } + + + + /* Getting currently time before starting */ + c_time = time(NULL); + + + /* Doing some cleanup */ + memset(msg, '\0', OS_MAXSTR +1); + + + print_out("%s: Type one log per line.\n", ARGV0); + + + /* Daemon loop */ + while(1) + { + lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); + + /* This shouldn't happen .. */ + if(lf == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + + /* Fixing the msg. */ + strncpy(msg, "1:a:", 5); + + + + /* Receive message from queue */ + if(fgets(msg +4, OS_MAXSTR, stdin)) + { + RuleNode *rulenode_pt; + + /* Getting the time we received the event */ + c_time = time(NULL); + + + /* Removing new line. */ + if(msg[strlen(msg) -1] == '\n') + msg[strlen(msg) -1] = '\0'; + + + /* Make sure we ignore blank lines. */ + if(strlen(msg) < 6) + { + continue; + } + + + print_out("\n"); + + + /* Default values for the log info */ + Zero_Eventinfo(lf); + + + /* Clean the msg appropriately */ + if(OS_CleanMSG(msg, lf) < 0) + { + merror(IMSG_ERROR,ARGV0,msg); + + Free_Eventinfo(lf); + + continue; + } + + + /* Currently rule must be null in here */ + currently_rule = NULL; + + + /*** Running decoders ***/ + + /* Getting log size */ + lf->size = strlen(lf->log); + + + /* Decoding event. */ + DecodeEvent(lf); + + + /* Looping all the rules */ + rulenode_pt = OS_GetFirstRule(); + if(!rulenode_pt) + { + ErrorExit("%s: Rules in an inconsistent state. Exiting.", + ARGV0); + } + + + #ifdef TESTRULE + if(full_output) + print_out("\n**Rule debugging:"); + #endif + + + do + { + if(lf->decoder_info->type == OSSEC_ALERT) + { + if(!lf->generated_rule) + { + break; + } + + /* We go ahead in here and process the alert. */ + currently_rule = lf->generated_rule; + } + + /* The categories must match */ + else if(rulenode_pt->ruleinfo->category != + lf->decoder_info->type) + { + continue; + } + + + /* Checking each rule. */ + else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt)) + == NULL) + { + continue; + } + + #ifdef TESTRULE + print_out("\n**Phase 3: Completed filtering (rules)."); + print_out(" Rule id: '%d'", currently_rule->sigid); + print_out(" Level: '%d'", currently_rule->level); + print_out(" Description: '%s'",currently_rule->comment); + #endif + + + + /* Ignore level 0 */ + if(currently_rule->level == 0) + { + break; + } + + + /* Checking ignore time */ + if(currently_rule->ignore_time) + { + if(currently_rule->time_ignored == 0) + { + currently_rule->time_ignored = lf->time; + } + /* If the currently time - the time the rule was ignored + * is less than the time it should be ignored, + * leave (do not alert again). + */ + else if((lf->time - currently_rule->time_ignored) + < currently_rule->ignore_time) + { + break; + } + else + { + currently_rule->time_ignored = 0; + } + } + + /* Pointer to the rule that generated it */ + lf->generated_rule = currently_rule; + + + /* Checking if we should ignore it */ + if(currently_rule->ckignore && IGnore(lf)) + { + /* Ignoring rule */ + lf->generated_rule = NULL; + break; + } + + /* Checking if we need to add to ignore list */ + if(currently_rule->ignore) + { + AddtoIGnore(lf); + } + + + /* Log the alert if configured to ... */ + if(currently_rule->alert_opts & DO_LOGALERT) + { + print_out("**Alert to be generated.\n\n"); + } + + + /* Copy the structure to the state memory of if_matched_sid */ + if(currently_rule->sid_prev_matched) + { + if(!OSList_AddData(currently_rule->sid_prev_matched, lf)) + { + merror("%s: Unable to add data to sig list.", ARGV0); + } + else + { + lf->sid_node_to_delete = + currently_rule->sid_prev_matched->last_node; + } + } + /* Group list */ + else if(currently_rule->group_prev_matched) + { + i = 0; + + while(i < currently_rule->group_prev_matched_sz) + { + if(!OSList_AddData( + currently_rule->group_prev_matched[i], + lf)) + { + merror("%s: Unable to add data to grp list.",ARGV0); + } + i++; + } + } + + OS_AddEvent(lf); + + break; + + }while((rulenode_pt = rulenode_pt->next) != NULL); + + + /* Only clear the memory if the eventinfo was not + * added to the stateful memory + * -- message is free inside clean event -- + */ + if(lf->generated_rule == NULL) + Free_Eventinfo(lf); + + } + else + { + exit(0); + } + } + return; +} + + + +/* EOF */ diff --git a/src/client-agent/COPYRIGHT b/src/client-agent/COPYRIGHT new file mode 100755 index 0000000..e857c2b --- /dev/null +++ b/src/client-agent/COPYRIGHT @@ -0,0 +1,9 @@ +Copyright (C) 2009 Trend Micro Inc. + All rights reserved. + This program is a free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License (version 3) as published by the FSF - Free Software + Foundation + +OSSEC HIDS, ossec-agent +Available at http://www.ossec.net/hids/ diff --git a/src/client-agent/Makefile b/src/client-agent/Makefile new file mode 100755 index 0000000..274a953 --- /dev/null +++ b/src/client-agent/Makefile @@ -0,0 +1,18 @@ +# Makefile for OSSEC agent +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +PT=../ +NAME=ossec-agentd + +include ../Config.Make + + +clog_OBJS = *.c ${OS_CONFIG} ${OS_ZLIB} ${OS_CRYPTO} ${OS_SHARED} ${OS_XML} ${OS_REGEX} ${OS_NET} -DCLIENT + +agent: + $(CC) $(CFLAGS) ${OS_LINK} $(clog_OBJS) -o ${NAME} +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/client-agent/VERSION b/src/client-agent/VERSION new file mode 100755 index 0000000..be58634 --- /dev/null +++ b/src/client-agent/VERSION @@ -0,0 +1 @@ +0.3 diff --git a/src/client-agent/agentd.c b/src/client-agent/agentd.c new file mode 100755 index 0000000..e21316e --- /dev/null +++ b/src/client-agent/agentd.c @@ -0,0 +1,201 @@ +/* @(#) $Id: agentd.c,v 1.44 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net/hids/ + */ + + +#include "shared.h" +#include "agentd.h" + +#include "os_net/os_net.h" + + + +/* AgentdStart v0.2, 2005/11/09 + * Starts the agent daemon. + */ +void AgentdStart(char *dir, int uid, int gid, char *user, char *group) +{ + int rc = 0; + int pid = 0; + int maxfd = 0; + + fd_set fdset; + + struct timeval fdtimeout; + + + /* Going daemon */ + pid = getpid(); + available_server = 0; + nowDaemon(); + goDaemon(); + + + /* Setting group ID */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR, ARGV0, group); + + + /* chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR, ARGV0, dir); + + + nowChroot(); + + + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR, ARGV0, user); + + + /* Create the queue. In this case we are going to create + * and read from it + * Exit if fails. + */ + if((logr->m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) + ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); + + maxfd = logr->m_queue; + logr->sock = -1; + + + + /* Creating PID file */ + if(CreatePID(ARGV0, getpid()) < 0) + merror(PID_ERROR,ARGV0); + + + /* Reading the private keys */ + verbose(ENC_READ, ARGV0); + + OS_ReadKeys(&keys); + OS_StartCounter(&keys); + os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* Initial random numbers */ + #ifdef __OpenBSD__ + srandomdev(); + #else + srandom( time(0) + getpid()+ pid + getppid()); + #endif + + random(); + + + /* Connecting UDP */ + rc = 0; + while(rc < logr->rip_id) + { + verbose("%s: INFO: Server IP Address: %s", ARGV0, logr->rip[rc]); + rc++; + } + + + /* Trying to connect to the server */ + if(!connect_server(0)) + { + ErrorExit(UNABLE_CONN, ARGV0); + } + + + /* Setting max fd for select */ + if(logr->sock > maxfd) + { + maxfd = logr->sock; + } + + + /* Connecting to the execd queue */ + if(logr->execdq == 0) + { + if((logr->execdq = StartMQ(EXECQUEUE, WRITE)) < 0) + { + merror("%s: INFO: Unable to connect to the active response " + "queue (disabled).", ARGV0); + logr->execdq = -1; + } + } + + + + /* Trying to connect to server */ + os_setwait(); + + start_agent(1); + + os_delwait(); + + + /* Sending integrity message for agent configs */ + intcheck_file(OSSECCONF, dir); + intcheck_file(OSSEC_DEFINES, dir); + + + /* Sending first notification */ + run_notify(); + + + /* Maxfd must be higher socket +1 */ + maxfd++; + + + /* monitor loop */ + while(1) + { + /* Monitoring all available sockets from here */ + FD_ZERO(&fdset); + FD_SET(logr->sock, &fdset); + FD_SET(logr->m_queue, &fdset); + + fdtimeout.tv_sec = 120; + fdtimeout.tv_usec = 0; + + + /* Wait for 120 seconds at a maximum for any descriptor */ + rc = select(maxfd, &fdset, NULL, NULL, &fdtimeout); + if(rc == -1) + { + ErrorExit(SELECT_ERROR, ARGV0); + } + + + else if(rc == 0) + { + continue; + } + + + /* For the receiver */ + if(FD_ISSET(logr->sock, &fdset)) + { + receive_msg(); + } + + + /* For the forwarder */ + if(FD_ISSET(logr->m_queue, &fdset)) + { + EventForward(); + } + } +} + + + +/* EOF */ diff --git a/src/client-agent/agentd.h b/src/client-agent/agentd.h new file mode 100755 index 0000000..c2b9dd1 --- /dev/null +++ b/src/client-agent/agentd.h @@ -0,0 +1,78 @@ +/* @(#) $Id: agentd.h,v 1.26 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net/hids/ + */ + + +#ifndef __AGENTD_H + +#define __AGENTD_H + +#include "config/config.h" +#include "config/client-config.h" + + +/*** Function Prototypes ***/ + +/* Client configuration */ +int ClientConf(char *cfgfile); + +/* Agentd init function */ +void AgentdStart(char *dir, int uid, int gid, char *user, char *group); + +/* Event Forwarder */ +void *EventForward(); + +/* Receiver messages */ +void *receive_msg(); + +/* Receiver messages for Windows */ +void *receiver_thread(void *none); + +/* intcheck_file: + * Sends integrity checking information about a file to the server. + */ +int intcheck_file(char *file_name, char *dir); + +/* Sends message to server */ +int send_msg(int agentid, char *msg); + +/* Extract the shared files */ +char *getsharedfiles(); + +/* Initializes handshake to server */ +void start_agent(int is_startup); + +/* Connects to the server. */ +int connect_server(int initial_id); + +/* notify server */ +void run_notify(); + + +/*** Global variables ***/ + +/* Global variables. Only modified + * during startup. + */ + +#include "shared.h" +#include "sec.h" + +int available_server; +keystore keys; +agent *logr; + + +#endif +/* EOF */ diff --git a/src/client-agent/config.c b/src/client-agent/config.c new file mode 100755 index 0000000..4025554 --- /dev/null +++ b/src/client-agent/config.c @@ -0,0 +1,49 @@ +/* @(#) $Id: config.c,v 1.15 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" + +#include "os_xml/os_xml.h" +#include "os_regex/os_regex.h" +#include "os_net/os_net.h" + +#include "agentd.h" + + +/* Relocated from config_op.c */ + +/* ClientConf v0.2, 2005/03/03 + * Read the config file (for the remote client) + * v0.2: New OS_XML + */ +int ClientConf(char *cfgfile) +{ + int modules = 0; + logr->port = DEFAULT_SECURE; + logr->rip = NULL; + logr->lip = NULL; + logr->rip_id = 0; + logr->execdq = 0; + + modules|= CCLIENT; + + if(ReadConfig(modules, cfgfile, logr, NULL) < 0) + { + return(OS_INVALID); + } + + return(1); +} + + +/* EOF */ diff --git a/src/client-agent/event-forward.c b/src/client-agent/event-forward.c new file mode 100755 index 0000000..8cafd1c --- /dev/null +++ b/src/client-agent/event-forward.c @@ -0,0 +1,54 @@ +/* @(#) $Id: event-forward.c,v 1.14 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net/hids/ + */ + + +#include "shared.h" +#include "agentd.h" + +#include "os_net/os_net.h" + +#include "sec.h" + + + +/* Receives a message locally on the agent and forwards to the + * manager. + */ +void *EventForward() +{ + int recv_b; + char msg[OS_MAXSTR +1]; + + + /* Initializing variables */ + msg[0] = '\0'; + msg[OS_MAXSTR] = '\0'; + + + while((recv_b = recv(logr->m_queue, msg, OS_MAXSTR, MSG_DONTWAIT)) > 0) + { + msg[recv_b] = '\0'; + + send_msg(0, msg); + + run_notify(); + } + + return(NULL); +} + + + +/* EOF */ diff --git a/src/client-agent/intcheck_op.c b/src/client-agent/intcheck_op.c new file mode 100755 index 0000000..deab8ba --- /dev/null +++ b/src/client-agent/intcheck_op.c @@ -0,0 +1,88 @@ +/* @(#) $Id: intcheck_op.c,v 1.4 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "agentd.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/sha1/sha1_op.h" + + + +/* intcheck_file + * Sends integrity checking information about a file to the + * server. + */ +int intcheck_file(char *file_name, char *dir) +{ + struct stat statbuf; + + os_md5 mf_sum; + os_sha1 sf_sum; + + char newsum[912 +1]; + + newsum[0] = '\0'; + newsum[912] = '\0'; + + + /* Stating the file */ + #ifdef WIN32 + if(stat(file_name, &statbuf) < 0) + #else + if(lstat(file_name, &statbuf) < 0) + #endif + { + snprintf(newsum, 911,"%c:%s:-1 %s%s", SYSCHECK_MQ, SYSCHECK, + dir, file_name); + send_msg(0, newsum); + + return(1); + } + + + /* Generating new checksum */ + #ifdef WIN32 + if(S_ISREG(statbuf.st_mode)) + #else + if(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) + #endif + { + /* generating md5 of the file */ + if(OS_SHA1_File(file_name, sf_sum) < 0) + { + strncpy(sf_sum, "xxx", 4); + } + + /* generating md5 of the file */ + if(OS_MD5_File(file_name, mf_sum) < 0) + { + strncpy(mf_sum, "xxx", 4); + } + } + + + snprintf(newsum,911,"%c:%s:%d:%d:%d:%d:%s:%s %s%s", + SYSCHECK_MQ, SYSCHECK, + (int)statbuf.st_size, + (int)statbuf.st_mode, + (int)statbuf.st_uid, + (int)statbuf.st_gid, + mf_sum, + sf_sum, dir, file_name); + + + send_msg(0, newsum); + return(1); +} + +/* EOF */ diff --git a/src/client-agent/main.c b/src/client-agent/main.c new file mode 100755 index 0000000..d35a1bd --- /dev/null +++ b/src/client-agent/main.c @@ -0,0 +1,138 @@ +/* @(#) $Id: main.c,v 1.16 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net + */ + + +/* agent daemon. + */ + + +#include "shared.h" +#include "agentd.h" + +#ifndef ARGV0 + #define ARGV0 "ossec-agentd" +#endif + + + + + +/* main, v0.2, 2005/11/09 + */ +int main(int argc, char **argv) +{ + int c = 0; + int test_config = 0; + + char *dir = DEFAULTDIR; + char *user = USER; + char *group = GROUPGLOBAL; + + int uid = 0; + int gid = 0; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vtdhu:g:D:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user = optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group = optarg; + break; + case 't': + test_config = 1; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir = optarg; + break; + } + } + + debug1(STARTED_MSG, ARGV0); + + logr = (agent *)calloc(1, sizeof(agent)); + if(!logr) + { + ErrorExit(MEM_ERROR, ARGV0); + } + + + /* Reading config */ + if(ClientConf(DEFAULTCPATH) < 0) + { + ErrorExit(CLIENT_ERROR,ARGV0); + } + + if(!logr->rip) + { + merror(AG_INV_IP, ARGV0); + ErrorExit(CLIENT_ERROR,ARGV0); + } + + + /* Checking auth keys */ + if(!OS_CheckKeys()) + { + ErrorExit(AG_NOKEYS_EXIT, ARGV0); + } + + + /* Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + { + ErrorExit(USER_ERROR,ARGV0,user,group); + } + + + + /* Exit if test config */ + if(test_config) + exit(0); + + + /* Starting the signal manipulation */ + StartSIG(ARGV0); + + + /* Agentd Start */ + AgentdStart(dir, uid, gid, user, group); + + + return(0); +} + +/* EOF */ diff --git a/src/client-agent/notify.c b/src/client-agent/notify.c new file mode 100755 index 0000000..373dd66 --- /dev/null +++ b/src/client-agent/notify.c @@ -0,0 +1,157 @@ +/* @(#) $Id: notify.c,v 1.23 2009/06/26 13:50:02 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + +#include "os_crypto/md5/md5_op.h" +#include "os_net/os_net.h" +#include "agentd.h" + +time_t g_saved_time = 0; + + + +/* getfiles: Return the name of the files in a directory + */ +char *getsharedfiles() +{ + int m_size = 512; + + char *ret; + + os_md5 md5sum; + + + if(OS_MD5_File(SHAREDCFG_FILE, md5sum) != 0) + { + md5sum[0] = 'x'; + md5sum[1] = 'x'; + md5sum[1] = '\0'; + } + + + /* we control these files, max size is m_size */ + ret = (char *)calloc(m_size +1, sizeof(char)); + if(!ret) + { + merror(MEM_ERROR, ARGV0); + return(NULL); + } + + + snprintf(ret, m_size, "%s merged.mg\n", md5sum); + + + return(ret); +} + +#ifndef WIN32 + +/* run_notify: Send periodically notification to server */ +void run_notify() +{ + char tmp_msg[OS_SIZE_1024 +1]; + char *uname; + char *shared_files; + + time_t curr_time; + + curr_time = time(0); + + + /* Check if the server has responded */ + if((curr_time - available_server) > (3*NOTIFY_TIME)) + { + /* If response is not available, set lock and + * wait for it. + */ + verbose(SERVER_UNAV, ARGV0); + os_setwait(); + + /* Send sync message */ + start_agent(0); + + verbose(SERVER_UP, ARGV0); + os_delwait(); + } + + + /* Check if time has elapsed */ + if((curr_time - g_saved_time) < (NOTIFY_TIME - 120)) + { + return; + } + g_saved_time = curr_time; + + debug1("%s: DEBUG: Sending agent notification.", ARGV0); + + + /* Send the message. + * Message is going to be the + * uname\n checksum file\n checksum file\n + */ + + /* Getting uname */ + uname = getuname(); + if(!uname) + { + merror(MEM_ERROR,ARGV0); + return; + } + + + /* get shared files */ + shared_files = getsharedfiles(); + if(!shared_files) + { + shared_files = strdup("\0"); + if(!shared_files) + { + free(uname); + merror(MEM_ERROR,ARGV0); + return; + } + } + + + /* creating message */ + if(File_DateofChange(AGENTCONFIGINT) > 0) + { + os_md5 md5sum; + if(OS_MD5_File(AGENTCONFIGINT, md5sum) != 0) + { + snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s",uname, shared_files); + } + else + { + snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s",uname, md5sum, shared_files); + } + } + else + { + snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s",uname, shared_files); + } + + + /* Sending status message */ + send_msg(0, tmp_msg); + + + free(uname); + free(shared_files); + + return; +} +#endif + + +/* EOF */ diff --git a/src/client-agent/receiver-win.c b/src/client-agent/receiver-win.c new file mode 100755 index 0000000..cd66a86 --- /dev/null +++ b/src/client-agent/receiver-win.c @@ -0,0 +1,285 @@ +/* @(#) $Id: receiver-win.c,v 1.8 2009/12/01 15:40:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifdef WIN32 +#include "shared.h" +#include "os_execd/execd.h" +#include "os_crypto/md5/md5_op.h" +#include "os_net/os_net.h" +#include "agentd.h" + + + +/* receiver_thread: + * Receive events from the server. + */ +void *receiver_thread(void *none) +{ + int recv_b; + + char file[OS_SIZE_1024 +1]; + char buffer[OS_MAXSTR +1]; + + char cleartext[OS_MAXSTR + 1]; + char *tmp_msg; + + char file_sum[34]; + + fd_set fdset; + struct timeval selecttime; + + FILE *fp; + + + /* Setting FP to null, before starting */ + fp = NULL; + + memset(cleartext, '\0', OS_MAXSTR +1); + memset(buffer, '\0', OS_MAXSTR +1); + memset(file, '\0', OS_SIZE_1024 +1); + memset(file_sum, '\0', 34); + + + while(1) + { + /* sock must be set. */ + if(logr->sock == -1) + { + sleep(5); + continue; + } + + FD_ZERO(&fdset); + FD_SET(logr->sock, &fdset); + + + /* Wait for 30 seconds. */ + selecttime.tv_sec = 30; + selecttime.tv_usec = 0; + + + /* Wait for 120 seconds at a maximum for any descriptor */ + recv_b = select(0, &fdset, NULL, NULL, &selecttime); + if(recv_b == -1) + { + merror(SELECT_ERROR, ARGV0); + sleep(30); + continue; + } + else if(recv_b == 0) + { + continue; + } + + /* Read until no more messages are available */ + while((recv_b = recv(logr->sock,buffer,OS_SIZE_1024, 0))>0) + { + /* Id of zero -- only one key allowed */ + tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b -1); + if(tmp_msg == NULL) + { + merror(MSG_ERROR,ARGV0,logr->rip[logr->rip_id]); + continue; + } + + + /* Check for commands */ + if(IsValidHeader(tmp_msg)) + { + /* This is the only thread that modifies it */ + available_server = (int)time(NULL); + + + /* Run timeout commands. */ + if(logr->execdq >= 0) + WinTimeoutRun(available_server); + + /* If it is an active response message */ + if(strncmp(tmp_msg, EXECD_HEADER, strlen(EXECD_HEADER)) == 0) + { + tmp_msg+=strlen(EXECD_HEADER); + + + /* Run on windows. */ + if(logr->execdq >= 0) + { + WinExecdRun(tmp_msg); + } + + + continue; + } + + + /* Restart syscheck. */ + else if(strcmp(tmp_msg, HC_SK_RESTART) == 0) + { + os_set_restart_syscheck(); + continue; + } + + + /* Ack from server */ + else if(strcmp(tmp_msg, HC_ACK) == 0) + { + continue; + } + + /* Close any open file pointer if it was being written to */ + if(fp) + { + fclose(fp); + fp = NULL; + } + + /* File update message */ + if(strncmp(tmp_msg, FILE_UPDATE_HEADER, + strlen(FILE_UPDATE_HEADER)) == 0) + { + char *validate_file; + tmp_msg+=strlen(FILE_UPDATE_HEADER); + + /* Going to after the file sum */ + validate_file = strchr(tmp_msg, ' '); + if(!validate_file) + { + continue; + } + + *validate_file = '\0'; + + /* copying the file sum */ + strncpy(file_sum, tmp_msg, 33); + + + /* Setting tmp_msg to the beginning of the file name */ + validate_file++; + tmp_msg = validate_file; + + + if((validate_file = strchr(tmp_msg, '\n')) != NULL) + { + *validate_file = '\0'; + } + + while((validate_file = strchr(tmp_msg, '/')) != NULL) + { + *validate_file = '-'; + } + + if(tmp_msg[0] == '.') + tmp_msg[0] = '-'; + + + snprintf(file, OS_SIZE_1024, "%s/%s", + SHAREDCFG_DIR, + tmp_msg); + + fp = fopen(file, "w"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, file); + } + } + + else if(strncmp(tmp_msg, FILE_CLOSE_HEADER, + strlen(FILE_CLOSE_HEADER)) == 0) + { + /* no error */ + os_md5 currently_md5; + + /* Making sure to close for the rename to work */ + if(fp) + { + fclose(fp); + fp = NULL; + } + + if(file[0] == '\0') + { + /* nada */ + } + + else if(OS_MD5_File(file, currently_md5) < 0) + { + /* Removing file */ + unlink(file); + file[0] = '\0'; + } + else + { + if(strcmp(currently_md5, file_sum) != 0) + { + debug1("%s: Failed md5 for: %s -- deleting.", + ARGV0, file); + unlink(file); + } + else + { + char *final_file; + + /* Renaming the file to its orignal name */ + final_file = strrchr(file, '/'); + if(final_file) + { + if(strcmp(final_file + 1, SHAREDCFG_FILENAME) == 0) + { + UnmergeFiles(file, SHAREDCFG_DIR); + } + } + else + { + unlink(file); + } + } + + file[0] = '\0'; + } + } + + else + { + merror("%s: WARN: Unknown message received from server.", ARGV0); + } + } + + else if(fp) + { + available_server = (int)time(NULL); + fprintf(fp, "%s", tmp_msg); + } + + else + { + merror("%s: WARN: Unknown message received. No action defined.", + ARGV0); + } + } + } + + + /* Cleaning up */ + if(fp) + { + fclose(fp); + if(file[0] != '\0') + unlink(file); + } + + return(NULL); + +} + + +#endif + +/* EOF */ diff --git a/src/client-agent/receiver.c b/src/client-agent/receiver.c new file mode 100755 index 0000000..35b7d7e --- /dev/null +++ b/src/client-agent/receiver.c @@ -0,0 +1,263 @@ +/* @(#) $Id: receiver.c,v 1.28 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + + +#ifdef WIN32 +#include "os_execd/execd.h" +#endif + + +#include "os_crypto/md5/md5_op.h" +#include "os_net/os_net.h" + + +#include "agentd.h" + +FILE *fp = NULL; +char file_sum[34] = ""; +char file[OS_SIZE_1024 +1] = ""; + + +/* receive_msg: + * Receive events from the server. + */ +void *receive_msg() +{ + int recv_b; + + char buffer[OS_MAXSTR +1]; + + char cleartext[OS_MAXSTR + 1]; + char *tmp_msg; + + + memset(cleartext, '\0', OS_MAXSTR +1); + memset(buffer, '\0', OS_MAXSTR +1); + + + + /* Read until no more messages are available */ + while((recv_b = recv(logr->sock, buffer, OS_SIZE_1024, MSG_DONTWAIT)) > 0) + { + buffer[recv_b] = '\0'; + + tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b -1); + if(tmp_msg == NULL) + { + merror(MSG_ERROR,ARGV0,logr->rip[logr->rip_id]); + continue; + } + + + /* Check for commands */ + if(IsValidHeader(tmp_msg)) + { + available_server = (int)time(NULL); + + + #ifdef WIN32 + /* Run timeout commands. */ + if(logr->execdq >= 0) + WinTimeoutRun(available_server); + #endif + + + /* If it is an active response message */ + if(strncmp(tmp_msg, EXECD_HEADER, strlen(EXECD_HEADER)) == 0) + { + tmp_msg+=strlen(EXECD_HEADER); + + #ifndef WIN32 + if(logr->execdq >= 0) + { + if(OS_SendUnix(logr->execdq, tmp_msg, 0) < 0) + { + merror("%s: Error communicating with execd", + ARGV0); + } + } + + #else + + + /* Run on windows. */ + if(logr->execdq >= 0) + { + WinExecdRun(tmp_msg); + } + + #endif + + + continue; + } + + + /* Restart syscheck. */ + else if(strcmp(tmp_msg, HC_SK_RESTART) == 0) + { + os_set_restart_syscheck(); + continue; + } + + + /* Ack from server */ + else if(strcmp(tmp_msg, HC_ACK) == 0) + { + continue; + } + + + /* Close any open file pointer if it was being written to */ + if(fp) + { + fclose(fp); + fp = NULL; + } + + + /* File update message */ + if(strncmp(tmp_msg, FILE_UPDATE_HEADER, + strlen(FILE_UPDATE_HEADER)) == 0) + { + char *validate_file; + + tmp_msg += strlen(FILE_UPDATE_HEADER); + + /* Going to after the file sum */ + validate_file = strchr(tmp_msg, ' '); + if(!validate_file) + { + continue; + } + + *validate_file = '\0'; + + /* copying the file sum */ + strncpy(file_sum, tmp_msg, 33); + + + /* Setting tmp_msg to the beginning of the file name */ + validate_file++; + tmp_msg = validate_file; + + + if((validate_file = strchr(tmp_msg, '\n')) != NULL) + { + *validate_file = '\0'; + } + + while((validate_file = strchr(tmp_msg, '/')) != NULL) + { + *validate_file = '-'; + } + + if(tmp_msg[0] == '.') + tmp_msg[0] = '-'; + + + snprintf(file, OS_SIZE_1024, "%s/%s", + SHAREDCFG_DIR, + tmp_msg); + + + fp = fopen(file, "w"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, file); + } + } + + else if(strncmp(tmp_msg, FILE_CLOSE_HEADER, + strlen(FILE_CLOSE_HEADER)) == 0) + { + /* no error */ + os_md5 currently_md5; + + /* Making sure to close for the rename to work */ + if(fp) + { + fclose(fp); + fp = NULL; + } + + if(file[0] == '\0') + { + /* nada */ + } + + else if(OS_MD5_File(file, currently_md5) < 0) + { + /* Removing file */ + unlink(file); + file[0] = '\0'; + } + else + { + if(strcmp(currently_md5, file_sum) != 0) + { + debug1("%s: ERROR: Failed md5 for: %s -- deleting.", + ARGV0, file); + unlink(file); + } + else + { + char *final_file; + + /* Renaming the file to its orignal name */ + final_file = strrchr(file, '/'); + if(final_file) + { + if(strcmp(final_file + 1, SHAREDCFG_FILENAME) == 0) + { + UnmergeFiles(file, SHAREDCFG_DIR); + } + } + else + { + /* Removing file. */ + unlink(file); + } + } + + file[0] = '\0'; + } + } + + else + { + merror("%s: WARN: Unknown message received from server.", ARGV0); + } + } + + else if(fp) + { + available_server = (int)time(NULL); + fprintf(fp, "%s", tmp_msg); + } + + else + { + merror("%s: WARN: Unknown message received. No action defined.", + ARGV0); + } + } + + + return(NULL); + +} + + +/* EOF */ diff --git a/src/client-agent/sendmsg.c b/src/client-agent/sendmsg.c new file mode 100755 index 0000000..3c36063 --- /dev/null +++ b/src/client-agent/sendmsg.c @@ -0,0 +1,42 @@ +/* @(#) $Id: sendmsg.c,v 1.7 2009/12/01 20:27:00 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "agentd.h" + +#include "os_net/os_net.h" + + +/* Sends a message to the server */ +int send_msg(int agentid, char *msg) +{ + int msg_size; + char crypt_msg[OS_MAXSTR +1]; + + msg_size = CreateSecMSG(&keys, msg, crypt_msg, agentid); + if(msg_size == 0) + { + merror(SEC_ERROR,ARGV0); + return(-1); + } + + /* Send msg_size of crypt_msg */ + if(OS_SendUDPbySize(logr->sock, msg_size, crypt_msg) < 0) + { + merror(SEND_ERROR,ARGV0, "server"); + sleep(1); + return(-1); + } + + return(0); +} + diff --git a/src/client-agent/start_agent.c b/src/client-agent/start_agent.c new file mode 100755 index 0000000..45fbf97 --- /dev/null +++ b/src/client-agent/start_agent.c @@ -0,0 +1,266 @@ +/* @(#) $Id: start_agent.c,v 1.17 2009/12/01 15:40:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "agentd.h" + +#include "os_net/os_net.h" + + +/** void connect_server() + * Attempts to connect to all configured servers. + */ +int connect_server(int initial_id) +{ + int attempts = 2; + int rc = initial_id; + + + /* Checking if the initial is zero, meaning we have to rotate to the + * beginning. + */ + if(logr->rip[initial_id] == NULL) + { + rc = 0; + initial_id = 0; + } + + + /* Closing socket if available. */ + if(logr->sock >= 0) + { + sleep(1); + close(logr->sock); + logr->sock = -1; + + if(logr->rip[1]) + { + verbose("%s: INFO: Closing connection to server (%s:%d).", + ARGV0, + logr->rip[rc], + logr->port); + } + + } + + + while(logr->rip[rc]) + { + char *tmp_str; + + /* Checking if we have a hostname. */ + tmp_str = strchr(logr->rip[rc], '/'); + if(tmp_str) + { + char *f_ip; + *tmp_str = '\0'; + + f_ip = OS_GetHost(logr->rip[rc], 5); + if(f_ip) + { + char ip_str[128]; + ip_str[127] = '\0'; + + snprintf(ip_str, 127, "%s/%s", logr->rip[rc], f_ip); + + free(f_ip); + free(logr->rip[rc]); + + os_strdup(ip_str, logr->rip[rc]); + tmp_str = strchr(logr->rip[rc], '/'); + tmp_str++; + } + else + { + merror("%s: WARN: Unable to get hostname for '%s'.", + ARGV0, logr->rip[rc]); + *tmp_str = '/'; + tmp_str++; + } + } + else + { + tmp_str = logr->rip[rc]; + } + + + verbose("%s: INFO: Trying to connect to server (%s:%d).", ARGV0, + logr->rip[rc], + logr->port); + + logr->sock = OS_ConnectUDP(logr->port, tmp_str); + if(logr->sock < 0) + { + logr->sock = -1; + merror(CONNS_ERROR, ARGV0, tmp_str); + rc++; + + if(logr->rip[rc] == NULL) + { + attempts += 10; + + /* Only log that if we have more than 1 server configured. */ + if(logr->rip[1]) + merror("%s: ERROR: Unable to connect to any server.",ARGV0); + + sleep(attempts); + rc = 0; + } + } + else + { + /* Setting socket non-blocking on HPUX */ + #ifdef HPUX + fcntl(logr->sock, O_NONBLOCK); + #endif + + #ifdef WIN32 + int bmode = 1; + + /* Setting socket to non-blocking */ + ioctlsocket(logr->sock, FIONBIO, (u_long FAR*) &bmode); + #endif + + logr->rip_id = rc; + return(1); + } + } + + return(0); +} + + + +/* start_agent: Sends the synchronization message to + * the server and waits for the ack. + */ +void start_agent(int is_startup) +{ + int recv_b = 0, attempts = 0, g_attempts = 1; + + char *tmp_msg; + char msg[OS_MAXSTR +2]; + char buffer[OS_MAXSTR +1]; + char cleartext[OS_MAXSTR +1]; + char fmsg[OS_MAXSTR +1]; + + + memset(msg, '\0', OS_MAXSTR +2); + memset(buffer, '\0', OS_MAXSTR +1); + memset(cleartext, '\0', OS_MAXSTR +1); + memset(fmsg, '\0', OS_MAXSTR +1); + snprintf(msg, OS_MAXSTR, "%s%s", CONTROL_HEADER, HC_STARTUP); + + + /* Sending start message and waiting for the ack */ + while(1) + { + /* Sending start up message */ + send_msg(0, msg); + attempts = 0; + + + /* Read until our reply comes back */ + while(((recv_b = recv(logr->sock, buffer, OS_MAXSTR, + MSG_DONTWAIT)) >= 0) || (attempts <= 5)) + { + if(recv_b <= 0) + { + /* Sleep five seconds before trying to get the reply from + * the server again. + */ + attempts++; + sleep(attempts); + + /* Sending message again (after three attempts) */ + if(attempts >= 3) + { + send_msg(0, msg); + } + + continue; + } + + /* Id of zero -- only one key allowed */ + tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b -1); + if(tmp_msg == NULL) + { + merror(MSG_ERROR, ARGV0, logr->rip[logr->rip_id]); + continue; + } + + + /* Check for commands */ + if(IsValidHeader(tmp_msg)) + { + /* If it is an ack reply */ + if(strcmp(tmp_msg, HC_ACK) == 0) + { + available_server = time(0); + + verbose(AG_CONNECTED, ARGV0, logr->rip[logr->rip_id], + logr->port); + + if(is_startup) + { + /* Send log message about start up */ + snprintf(msg, OS_MAXSTR, OS_AG_STARTED, + keys.keyentries[0]->name, + keys.keyentries[0]->ip->ip); + snprintf(fmsg, OS_MAXSTR, "%c:%s:%s", LOCALFILE_MQ, + "ossec", msg); + send_msg(0, fmsg); + } + return; + } + } + } + + /* Waiting for servers reply */ + merror(AG_WAIT_SERVER, ARGV0, logr->rip[logr->rip_id]); + + + /* If we have more than one server, try all. */ + if(logr->rip[1]) + { + int curr_rip = logr->rip_id; + merror("%s: INFO: Trying next server ip in the line: '%s'.", ARGV0, + logr->rip[logr->rip_id + 1] != NULL?logr->rip[logr->rip_id + 1]:logr->rip[0]); + connect_server(logr->rip_id +1); + + if(logr->rip_id == curr_rip) + { + sleep(g_attempts); + g_attempts+=(attempts * 3); + } + else + { + g_attempts+=5; + sleep(g_attempts); + } + } + else + { + sleep(g_attempts); + g_attempts+=(attempts * 3); + + connect_server(0); + } + } + + + return; +} + + + +/* EOF */ diff --git a/src/config/Makefile b/src/config/Makefile new file mode 100755 index 0000000..6c7bcd6 --- /dev/null +++ b/src/config/Makefile @@ -0,0 +1,21 @@ +# Makefile for the configuration check. +# Daniel B. Cid || +# http://www.ossec.net + +PT=../ +NAME=ossec-config + +include ../Config.Make + + +SOURCES = *.c + +logcollector: + ${CC} -c ${CFLAGS} ${SOURCES} + ar cru lib_config.a ${OBJECTS} + ranlib lib_config.a + +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/config/active-response.c b/src/config/active-response.c new file mode 100755 index 0000000..fad1f45 --- /dev/null +++ b/src/config/active-response.c @@ -0,0 +1,420 @@ +/* @(#) $Id: active-response.c,v 1.15 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "os_xml/os_xml.h" +#include "os_regex/os_regex.h" + +#include "active-response.h" + + +/** int ReadActiveResponses(XML_NODE node, void *d1, void *d2) + * Generates a list with all active responses. + */ +int ReadActiveResponses(XML_NODE node, void *d1, void *d2) +{ + FILE *fp; + int i = 0; + int r_ar = 0; + int l_ar = 0; + + + /* Xml options */ + char *xml_ar_command = "command"; + char *xml_ar_location = "location"; + char *xml_ar_agent_id = "agent_id"; + char *xml_ar_rules_id = "rules_id"; + char *xml_ar_rules_group = "rules_group"; + char *xml_ar_level = "level"; + char *xml_ar_timeout = "timeout"; + char *xml_ar_disabled = "disabled"; + + char *tmp_location; + + + /* Currently active response */ + active_response *tmp_ar; + + + /* Opening shared ar file */ + fp = fopen(DEFAULTARPATH, "a"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, DEFAULTARPATH); + return(-1); + } + chmod(DEFAULTARPATH, 0444); + + + /* Allocating for the active-response */ + tmp_ar = calloc(1, sizeof(active_response)); + if(!tmp_ar) + { + merror(MEM_ERROR, ARGV0); + return(-1); + } + + /* Initializing variables */ + tmp_ar->name = NULL; + tmp_ar->command = NULL; + tmp_ar->location = 0; + tmp_ar->timeout = 0; + tmp_ar->level = 0; + tmp_ar->agent_id = NULL; + tmp_ar->rules_id = NULL; + tmp_ar->rules_group = NULL; + tmp_ar->ar_cmd = NULL; + tmp_location = NULL; + + + + /* Searching for the commands */ + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + + /* Command */ + if(strcmp(node[i]->element, xml_ar_command) == 0) + { + tmp_ar->command = strdup(node[i]->content); + } + /* Target */ + else if(strcmp(node[i]->element, xml_ar_location) == 0) + { + tmp_location = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, xml_ar_agent_id) == 0) + { + tmp_ar->agent_id = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, xml_ar_rules_id) == 0) + { + tmp_ar->rules_id = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, xml_ar_rules_group) == 0) + { + tmp_ar->rules_group = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, xml_ar_level) == 0) + { + /* Level must be numeric */ + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + tmp_ar->level = atoi(node[i]->content); + + /* Making sure the level is valid */ + if((tmp_ar->level < 0) || (tmp_ar->level > 20)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_ar_timeout) == 0) + { + tmp_ar->timeout = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_ar_disabled) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { + ar_flag = -1; + } + else if(strcmp(node[i]->content, "no") == 0) + { + /* Don't do anything if disabled is set to "no" */ + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + /* Checking if ar is disabled */ + if(ar_flag == -1) + { + fclose(fp); + return(0); + } + + /* Command and location must be there */ + if(!tmp_ar->command || !tmp_location) + { + merror(AR_MISS, ARGV0); + return(-1); + } + + /* analysisd */ + if(OS_Regex("AS|analysisd|analysis-server|server", tmp_location)) + { + tmp_ar->location|= AS_ONLY; + } + + if(OS_Regex("local", tmp_location)) + { + tmp_ar->location|= REMOTE_AGENT; + } + + if(OS_Regex("defined-agent", tmp_location)) + { + if(!tmp_ar->agent_id) + { + merror(AR_DEF_AGENT, ARGV0); + return(-1); + } + + tmp_ar->location|= SPECIFIC_AGENT; + + } + if(OS_Regex("all|any", tmp_location)) + { + tmp_ar->location|=ALL_AGENTS; + } + + /* If we didn't set any value for the location */ + if(tmp_ar->location == 0) + { + merror(AR_INV_LOC, ARGV0, tmp_location); + return(-1); + } + + + /* cleaning tmp_location */ + free(tmp_location); + tmp_location = NULL; + + + /* Checking if command name is valid */ + { + OSListNode *my_commands_node; + + my_commands_node = OSList_GetFirstNode(d1); + while(my_commands_node) + { + ar_command *my_command; + my_command = (ar_command *)my_commands_node->data; + + if(strcmp(my_command->name, tmp_ar->command) == 0) + { + tmp_ar->ar_cmd = my_command; + break; + } + + my_commands_node = OSList_GetNextNode(d1); + } + + /* Didn't find a valid command */ + if(tmp_ar->ar_cmd == NULL) + { + merror(AR_INV_CMD, ARGV0, tmp_ar->command); + return(-1); + } + } + + /* Checking if timeout is allowed */ + if(tmp_ar->timeout && !tmp_ar->ar_cmd->timeout_allowed) + { + merror(AR_NO_TIMEOUT, ARGV0, tmp_ar->ar_cmd->name); + return(-1); + } + + /* d1 is the active response list */ + if(!OSList_AddData(d2, (void *)tmp_ar)) + { + merror(LIST_ADD_ERROR, ARGV0); + return(-1); + } + + + /* Setting a unique active response name */ + tmp_ar->name = calloc(OS_FLSIZE +1, sizeof(char)); + if(!tmp_ar->name) + { + ErrorExit(MEM_ERROR, ARGV0); + } + snprintf(tmp_ar->name, OS_FLSIZE, "%s%d", + tmp_ar->ar_cmd->name, + tmp_ar->timeout); + + + /* Adding to shared file */ + fprintf(fp, "%s - %s - %d\n", + tmp_ar->name, + tmp_ar->ar_cmd->executable, + tmp_ar->timeout); + + + /* Setting the configs to start the right queues */ + if(tmp_ar->location & AS_ONLY) + { + l_ar = 1; + } + if(tmp_ar->location & ALL_AGENTS) + { + r_ar = 1; + } + if(tmp_ar->location & REMOTE_AGENT) + { + r_ar = 1; + l_ar = 1; + } + if(tmp_ar->location & SPECIFIC_AGENT) + { + r_ar = 1; + } + + /* Setting the configuration for the active response */ + if(r_ar && (!(ar_flag & REMOTE_AR))) + { + ar_flag|= REMOTE_AR; + } + if(l_ar && (!(ar_flag & LOCAL_AR))) + { + ar_flag|= LOCAL_AR; + } + + /* Closing shared file for active response */ + fclose(fp); + + /* Done over here */ + return(0); +} + + + +/** int ReadActiveCommands(XML_NODE node, void *d1, void *d2) + */ +int ReadActiveCommands(XML_NODE node, void *d1, void *d2) +{ + int i = 0; + + char *tmp_str = NULL; + + /* Xml values */ + char *command_name = "name"; + char *command_expect = "expect"; + char *command_executable = "executable"; + char *timeout_allowed = "timeout_allowed"; + + ar_command *tmp_command; + + + /* Allocating the active-response command */ + tmp_command = calloc(1, sizeof(ar_command)); + if(!tmp_command) + { + merror(MEM_ERROR, ARGV0); + return(-1); + } + + tmp_command->name = NULL; + tmp_command->expect= 0; + tmp_command->executable = NULL; + tmp_command->timeout_allowed = 0; + + + /* Searching for the commands */ + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + if(strcmp(node[i]->element, command_name) == 0) + { + tmp_command->name = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, command_expect) == 0) + { + tmp_str = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, command_executable) == 0) + { + tmp_command->executable = strdup(node[i]->content); + } + else if(strcmp(node[i]->element, timeout_allowed) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + tmp_command->timeout_allowed = 1; + else if(strcmp(node[i]->content, "no") == 0) + tmp_command->timeout_allowed = 0; + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + if(!tmp_command->name || !tmp_str || !tmp_command->executable) + { + merror(AR_CMD_MISS, ARGV0); + return(-1); + } + + + /* Getting the expect */ + if(OS_Regex("user", tmp_str)) + tmp_command->expect |= USERNAME; + if(OS_Regex("srcip", tmp_str)) + tmp_command->expect |= SRCIP; + + free(tmp_str); + tmp_str = NULL; + + + /* Adding command to the list */ + if(!OSList_AddData(d1, (void *)tmp_command)) + { + merror(LIST_ADD_ERROR, ARGV0); + return(-1); + } + + + /* Done over here */ + return(0); +} + + +/* EOF */ diff --git a/src/config/active-response.h b/src/config/active-response.h new file mode 100755 index 0000000..277891a --- /dev/null +++ b/src/config/active-response.h @@ -0,0 +1,47 @@ +/* @(#) $Id: active-response.h,v 1.5 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _CAR__H +#define _CAR__H + + +/** Active response commands **/ +typedef struct _ar_command +{ + int expect; + int timeout_allowed; + + char *name; + char *executable; +}ar_command; + + +/** Active response data **/ +typedef struct _ar +{ + int timeout; + int location; + int level; + char *name; + char *command; + char *agent_id; + char *rules_id; + char *rules_group; + + ar_command *ar_cmd; +}active_response; + + +/* Active response flag */ +int ar_flag; + +#endif diff --git a/src/config/agentlessd-config.c b/src/config/agentlessd-config.c new file mode 100644 index 0000000..7157091 --- /dev/null +++ b/src/config/agentlessd-config.c @@ -0,0 +1,206 @@ +/* @(#) $Id: agentlessd-config.c,v 1.6 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the configuration files + */ + + +#include "shared.h" +#include "agentlessd-config.h" + + +int Read_CAgentless(XML_NODE node, void *config, void *config2) +{ + int i = 0,j = 0,s = 0; + + /* XML definitions */ + char *xml_lessd_server = "host"; + char *xml_lessd_port = "port"; + char *xml_lessd_type = "type"; + char *xml_lessd_frequency = "frequency"; + char *xml_lessd_state = "state"; + char *xml_lessd_command = "run_command"; + char *xml_lessd_options = "arguments"; + + + agentlessd_config *lessd_config = (agentlessd_config *)config; + + + /* Getting any configured entry. */ + if(lessd_config->entries) + { + while(lessd_config->entries[s]) + s++; + } + + + /* Allocating the memory for the config. */ + os_realloc(lessd_config->entries, (s + 2) * sizeof(agentlessd_entries *), + lessd_config->entries); + os_calloc(1, sizeof(agentlessd_entries), lessd_config->entries[s]); + lessd_config->entries[s + 1] = NULL; + + + /* Zeroing the elements. */ + lessd_config->entries[s]->server = NULL; + lessd_config->entries[s]->command = NULL; + lessd_config->entries[s]->options = ""; + lessd_config->entries[s]->type = NULL; + lessd_config->entries[s]->frequency = 86400; + lessd_config->entries[s]->state = 0; + lessd_config->entries[s]->current_state = 0; + lessd_config->entries[s]->port = 0; + lessd_config->entries[s]->error_flag = 0; + + + /* Reading the XML. */ + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + else if(strcmp(node[i]->element, xml_lessd_frequency) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + lessd_config->entries[s]->frequency = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_lessd_port) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + lessd_config->entries[s]->port = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_lessd_server) == 0) + { + char s_content[1024 +1]; + s_content[1024] = '\0'; + + /* Getting any configured entry. */ + j = 0; + if(lessd_config->entries[s]->server) + { + while(lessd_config->entries[s]->server[j]) + j++; + } + + os_realloc(lessd_config->entries[s]->server, (j + 2) * + sizeof(char *), + lessd_config->entries[s]->server); + if(strncmp(node[i]->content, "use_su ", 7) == 0) + { + snprintf(s_content, 1024, "s%s", node[i]->content +7); + } + else if(strncmp(node[i]->content, "use_sudo ", 9) == 0) + { + snprintf(s_content, 1024, "o%s", node[i]->content +9); + } + else + { + snprintf(s_content, 1024, " %s", node[i]->content); + } + + os_strdup(s_content, + lessd_config->entries[s]->server[j]); + lessd_config->entries[s]->server[j + 1] = NULL; + } + else if(strcmp(node[i]->element, xml_lessd_type) == 0) + { + char script_path[1024 +1]; + + script_path[1024] = '\0'; + snprintf(script_path, 1024, "%s/%s", AGENTLESSDIRPATH, + node[i]->content); + + if(File_DateofChange(script_path) <= 0) + { + merror("%s: ERROR: Unable to find '%s' at '%s'.", + ARGV0, node[i]->content, AGENTLESSDIRPATH); + merror(XML_VALUEERR,ARGV0, node[i]->element, node[i]->content); + return(OS_INVALID); + } + os_strdup(node[i]->content, lessd_config->entries[s]->type); + } + else if(strcmp(node[i]->element, xml_lessd_command) == 0) + { + os_strdup(node[i]->content, lessd_config->entries[s]->command); + } + else if(strcmp(node[i]->element, xml_lessd_options) == 0) + { + os_strdup(node[i]->content, lessd_config->entries[s]->options); + } + else if(strcmp(node[i]->element, xml_lessd_state) == 0) + { + if(strcmp(node[i]->content, "periodic") == 0) + { + lessd_config->entries[s]->state |= LESSD_STATE_PERIODIC; + } + else if(strcmp(node[i]->content, "stay_connected") == 0) + { + lessd_config->entries[s]->state |= LESSD_STATE_CONNECTED; + } + else if(strcmp(node[i]->content, "periodic_diff") == 0) + { + lessd_config->entries[s]->state |= LESSD_STATE_PERIODIC; + lessd_config->entries[s]->state |= LESSD_STATE_DIFF; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + + /* We must have at least one entry set */ + if(!lessd_config->entries[s]->server || + !lessd_config->entries[s]->state || + !lessd_config->entries[s]->type) + { + merror(XML_INV_MISSOPTS, ARGV0); + return(OS_INVALID); + } + + + if((lessd_config->entries[s]->state == LESSD_STATE_PERIODIC) && + !lessd_config->entries[s]->frequency) + { + merror(XML_INV_MISSFREQ, ARGV0); + return(OS_INVALID); + } + + return(0); +} + + +/* EOF */ diff --git a/src/config/agentlessd-config.h b/src/config/agentlessd-config.h new file mode 100755 index 0000000..3348d8c --- /dev/null +++ b/src/config/agentlessd-config.h @@ -0,0 +1,52 @@ +/* @(#) $Id: agentlessd-config.h,v 1.4 2009/06/24 17:06:24 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _AGENTLESSDCONFIG_H +#define _AGENTLESSDCONFIG_H + + +/* Entry states. */ +#define LESSD_STATE_CONNECTED 0x001 +#define LESSD_STATE_PERIODIC 0x002 +#define LESSD_STATE_DIFF 0x004 +#define LESSD_USE_SU 0x010 +#define LESSD_USE_SUDO 0x020 + + +/* Structure for each entry. */ +typedef struct _agentlessd_entries +{ + short int state; + + int frequency; + int current_state; + int port; + int error_flag; + + char *type; + char **server; + char *options; + char *command; + +}agentlessd_entries; + + +/* Configuration structure. */ +typedef struct _agentlessd_config +{ + int queue; + agentlessd_entries **entries; + +}agentlessd_config; + + +#endif diff --git a/src/config/alerts-config.c b/src/config/alerts-config.c new file mode 100755 index 0000000..72edcad --- /dev/null +++ b/src/config/alerts-config.c @@ -0,0 +1,77 @@ +/* $OSSEC, alerts-config.c, v0.1, 2005/04/02, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the configuration files + */ + + +#include "shared.h" +#include "global-config.h" + + +int Read_Alerts(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + + /* XML definitions */ + char *xml_email_level = "email_alert_level"; + char *xml_log_level = "log_alert_level"; + + _Config *Config; + + Config = (_Config *)configp; + + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + /* Mail notification */ + else if(strcmp(node[i]->element, xml_email_level) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + Config->mailbylevel = atoi(node[i]->content); + } + /* Log alerts */ + else if(strcmp(node[i]->element, xml_log_level) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + Config->logbylevel = atoi(node[i]->content); + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + return(0); +} + + +/* EOF */ diff --git a/src/config/client-config.c b/src/config/client-config.c new file mode 100755 index 0000000..cc776c9 --- /dev/null +++ b/src/config/client-config.c @@ -0,0 +1,167 @@ +/* $OSSEC, client-config.c, v0.1, 2005/04/01, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "client-config.h" +#include "os_net/os_net.h" + + +int Read_Client(XML_NODE node, void *d1, void *d2) +{ + int i = 0; + + /* XML definitions */ + char *xml_client_ip = "server-ip"; + char *xml_client_hostname = "server-hostname"; + char *xml_local_ip = "local_ip"; + char *xml_client_port = "port"; + char *xml_ar_disabled = "disable-active-response"; + + agent *logr; + + logr = (agent *)d1; + + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + /* Getting local ip. */ + else if(strcmp(node[i]->element, xml_local_ip) == 0) + { + os_strdup(node[i]->content, logr->lip); + if(OS_IsValidIP(logr->lip, NULL) != 1) + { + merror(INVALID_IP, ARGV0, logr->lip); + return(OS_INVALID); + } + } + /* Getting server ip */ + else if(strcmp(node[i]->element,xml_client_ip) == 0) + { + int ip_id = 0; + + /* Getting last ip */ + if(logr->rip) + { + while(logr->rip[ip_id]) + { + ip_id++; + } + } + os_realloc(logr->rip, (ip_id + 2) * sizeof(char*), logr->rip); + logr->rip[ip_id] = NULL; + logr->rip[ip_id +1] = NULL; + + os_strdup(node[i]->content, logr->rip[ip_id]); + if(OS_IsValidIP(logr->rip[ip_id], NULL) != 1) + { + merror(INVALID_IP, ARGV0, logr->rip[ip_id]); + return(OS_INVALID); + } + logr->rip_id++; + } + else if(strcmp(node[i]->element,xml_client_hostname) == 0) + { + int ip_id = 0; + char *s_ip; + char f_ip[128]; + + + /* Getting last ip. */ + if(logr->rip) + { + while(logr->rip[ip_id]) + { + ip_id++; + } + } + + os_realloc(logr->rip, (ip_id + 2) * sizeof(char*), + logr->rip); + + + s_ip = OS_GetHost(node[i]->content, 5); + if(!s_ip) + { + merror("%s: WARN: Unable to get hostname for '%s'.", + ARGV0, node[i]->content); + merror(AG_INV_HOST, ARGV0, node[i]->content); + + os_strdup("invalid_ip", s_ip); + } + + + f_ip[127] = '\0'; + snprintf(f_ip, 127, "%s/%s", node[i]->content, s_ip); + + os_strdup(f_ip, logr->rip[ip_id]); + logr->rip[ip_id +1] = NULL; + + free(s_ip); + + logr->rip_id++; + } + else if(strcmp(node[i]->element,xml_client_port) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + logr->port = atoi(node[i]->content); + + if(logr->port <= 0 || logr->port > 65535) + { + merror(PORT_ERROR, ARGV0, logr->port); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element,xml_ar_disabled) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + logr->execdq = -1; + else if(strcmp(node[i]->content, "no") == 0) + logr->execdq = 0; + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + if(!logr->rip) + { + return(OS_INVALID); + } + + return(0); +} + + +/* EOF */ diff --git a/src/config/client-config.h b/src/config/client-config.h new file mode 100755 index 0000000..fe8b906 --- /dev/null +++ b/src/config/client-config.h @@ -0,0 +1,33 @@ +/* $OSSEC, client-config.h, v0.2, 2005/11/09, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __CAGENTD_H + +#define __CAGENTD_H + +/* Configuration structure */ +typedef struct _agent +{ + int port; + int m_queue; + int sock; + int execdq; + int rip_id; + char *lip; + char **rip; /* remote (server) ip */ +}agent; + + +#endif + + +/* EOF */ diff --git a/src/config/config.c b/src/config/config.c new file mode 100755 index 0000000..c707e0f --- /dev/null +++ b/src/config/config.c @@ -0,0 +1,306 @@ +/* @(#) $Id: config.c,v 1.25 2009/08/27 18:17:41 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Unified function to read the config. + * + */ + + +#include "shared.h" +#include "os_xml/os_xml.h" +#include "config.h" + + +/* Read the main elements of the configuration. + */ +int read_main_elements(OS_XML xml, int modules, + XML_NODE node, + void *d1, + void *d2) +{ + int i = 0; + char *osglobal = "global"; + char *osrules = "rules"; + char *ossyscheck = "syscheck"; + char *osrootcheck = "rootcheck"; + char *osalerts = "alerts"; + char *osemailalerts = "email_alerts"; + char *osdbd = "database_output"; + char *oscsyslogd = "syslog_output"; + char *oscagentless = "agentless"; + char *oslocalfile = "localfile"; + char *osremote = "remote"; + char *osclient = "client"; + char *oscommand = "command"; + char *osactive_response = "active-response"; + + + while(node[i]) + { + XML_NODE chld_node = NULL; + + chld_node = OS_GetElementsbyNode(&xml,node[i]); + + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!chld_node) + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osglobal) == 0) + { + if(((modules & CGLOBAL) || (modules & CMAIL)) + && (Read_Global(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osemailalerts) == 0) + { + if((modules & CMAIL) && (Read_EmailAlerts(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osdbd) == 0) + { + if((modules & CDBD) && (Read_DB(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, oscsyslogd) == 0) + { + if((modules & CSYSLOGD) && (Read_CSyslog(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, oscagentless) == 0) + { + if((modules & CAGENTLESS) && (Read_CAgentless(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osrules) == 0) + { + if((modules & CRULES) && (Read_Rules(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, ossyscheck) == 0) + { + if((modules & CSYSCHECK) && (Read_Syscheck(chld_node, d1,d2) < 0)) + return(OS_INVALID); + if((modules & CGLOBAL) && (Read_GlobalSK(chld_node, d1, d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osrootcheck) == 0) + { + if((modules & CROOTCHECK) && (Read_Rootcheck(chld_node, d1,d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osalerts) == 0) + { + if((modules & CALERTS) && (Read_Alerts(chld_node, d1,d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, oslocalfile) == 0) + { + if((modules & CLOCALFILE) && (Read_Localfile(chld_node, d1,d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osremote) == 0) + { + if((modules & CREMOTE) && (Read_Remote(chld_node, d1,d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osclient) == 0) + { + if((modules & CCLIENT) && (Read_Client(chld_node, d1,d2) < 0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, oscommand) == 0) + { + if((modules & CAR)&&(ReadActiveCommands(chld_node, d1, d2)<0)) + return(OS_INVALID); + } + else if(strcmp(node[i]->element, osactive_response) == 0) + { + if((modules & CAR)&&(ReadActiveResponses(chld_node, d1, d2)<0)) + return(OS_INVALID); + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + + OS_ClearNode(chld_node); + i++; + } + + return(0); +} + + +/* ReadConfig(int modules, char *cfgfile) + * Read the config files + */ +int ReadConfig(int modules, char *cfgfile, void *d1, void *d2) +{ + int i; + OS_XML xml; + XML_NODE node; + + + /** XML definitions **/ + /* Global */ + char *xml_start_ossec = "ossec_config"; + char *xml_start_agent = "agent_config"; + + char *xml_agent_name = "name"; + char *xml_agent_os = "os"; + char *xml_agent_overwrite = "overwrite"; + + + if(OS_ReadXML(cfgfile,&xml) < 0) + { + if(modules & CAGENT_CONFIG) + { + } + else + { + merror(XML_ERROR, ARGV0, cfgfile, xml.err, xml.err_line); + } + return(OS_INVALID); + } + + + node = OS_GetElementsbyNode(&xml, NULL); + if(!node) + { + return(0); + } + + + /* Reading the main configuration */ + i = 0; + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!(modules & CAGENT_CONFIG) && + (strcmp(node[i]->element, xml_start_ossec) == 0)) + { + XML_NODE chld_node = NULL; + chld_node = OS_GetElementsbyNode(&xml,node[i]); + + /* Main element does not need to have any child */ + if(chld_node) + { + if(read_main_elements(xml, modules, chld_node, d1, d2) < 0) + { + merror(CONFIG_ERROR, ARGV0, cfgfile); + return(OS_INVALID); + } + + OS_ClearNode(chld_node); + } + } + else if((modules & CAGENT_CONFIG) && + (strcmp(node[i]->element, xml_start_agent) == 0)) + { + int passed_agent_test = 1; + int attrs = 0; + XML_NODE chld_node = NULL; + chld_node = OS_GetElementsbyNode(&xml,node[i]); + + + /* Checking if this is specific to any agent. */ + if(node[i]->attributes && node[i]->values) + { + while(node[i]->attributes[attrs] && node[i]->values[attrs]) + { + if(strcmp(xml_agent_name, node[i]->attributes[attrs]) == 0) + { + char *agentname = os_read_agent_name(); + + if(!agentname) + { + passed_agent_test = 0; + } + else + { + if(!OS_Match2(node[i]->values[attrs], agentname)) + { + passed_agent_test = 0; + } + free(agentname); + } + } + else if(strcmp(xml_agent_os, node[i]->attributes[attrs]) == 0) + { + char *agentos = getuname(); + + if(agentos) + { + if(!OS_Match2(node[i]->values[attrs], agentos)) + { + passed_agent_test = 0; + } + free(agentos); + } + else + { + passed_agent_test = 0; + merror("%s: ERROR: Unable to retrieve uname.", ARGV0); + } + } + else if(strcmp(xml_agent_overwrite, node[i]->attributes[attrs]) == 0) + { + } + else + { + merror(XML_INVATTR, ARGV0, node[i]->attributes[attrs], + cfgfile); + } + attrs++; + } + } + + + /* Main element does not need to have any child */ + if(chld_node) + { + if(passed_agent_test && read_main_elements(xml, modules, chld_node, d1, d2) < 0) + { + merror(CONFIG_ERROR, ARGV0, cfgfile); + return(OS_INVALID); + } + + OS_ClearNode(chld_node); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + /* Clearing node and xml */ + OS_ClearNode(node); + OS_ClearXML(&xml); + return(0); +} + + + +/* EOF */ diff --git a/src/config/config.h b/src/config/config.h new file mode 100755 index 0000000..55a2dfb --- /dev/null +++ b/src/config/config.h @@ -0,0 +1,67 @@ +/* @(#) $Id: config.h,v 1.14 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#ifndef _HCONFIG__H +#define _HCONFIG__H + +#define CGLOBAL 0000001 +#define CRULES 0000002 +#define CSYSCHECK 0000004 +#define CROOTCHECK 0000010 +#define CALERTS 0000020 +#define CLOCALFILE 0000040 +#define CREMOTE 0000100 +#define CCLIENT 0000200 +#define CMAIL 0000400 +#define CAR 0001000 +#define CDBD 0002000 +#define CSYSLOGD 0004000 +#define CAGENTLESS 0020000 + +#define CAGENT_CONFIG 0010000 + +#include "os_xml/os_xml.h" + + +/* Main function to read the config */ +int ReadConfig(int modules, char *cfgfile, void *d1, void *d2); + +int Read_Global(XML_NODE node, void *d1, void *d2); +int Read_GlobalSK(XML_NODE node, void *configp, void *mailp); +int Read_Rules(XML_NODE node, void *d1, void *d2); +int Read_Syscheck(XML_NODE node, void *d1, void *d2); +int Read_Rootcheck(XML_NODE node, void *d1, void *d2); +int Read_Alerts(XML_NODE node, void *d1, void *d2); +int Read_EmailAlerts(XML_NODE node, void *d1, void *d2); +int Read_DB(XML_NODE node, void *config1, void *config2); +int Read_CSyslog(XML_NODE node, void *config1, void *config2); +int Read_CAgentless(XML_NODE node, void *config1, void *config2); +int Read_Localfile(XML_NODE node, void *d1, void *d2); +int Read_Remote(XML_NODE node, void *d1, void *d2); +int Read_Client(XML_NODE node, void *d1, void *d2); +int ReadActiveResponses(XML_NODE node, void *d1, void *d2); +int ReadActiveCommands(XML_NODE node, void *d1, void *d2); +void AssignIgnore_Global(char **ignores, void *configp); + + +/* General config, for passing blobs of data. */ +typedef struct _GeneralConfig +{ + void *data; +}GeneralConfig; + + +#endif diff --git a/src/config/csyslogd-config.c b/src/config/csyslogd-config.c new file mode 100644 index 0000000..15dd486 --- /dev/null +++ b/src/config/csyslogd-config.c @@ -0,0 +1,218 @@ +/* @(#) $Id: csyslogd-config.c,v 1.3 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the configuration files + */ + + +#include "csyslogd-config.h" +#include "config.h" + + +int Read_CSyslog(XML_NODE node, void *config, void *config2) +{ + int i = 0,s = 0; + + /* XML definitions */ + char *xml_syslog_server = "server"; + char *xml_syslog_port = "port"; + char *xml_syslog_format = "format"; + char *xml_syslog_level = "level"; + char *xml_syslog_id = "rule_id"; + char *xml_syslog_group = "group"; + char *xml_syslog_location = "event_location"; + + + GeneralConfig *gen_config = (GeneralConfig *)config; + SyslogConfig **syslog_config = (SyslogConfig **)gen_config->data; + + + /* Getting Granular mail_to size */ + if(syslog_config) + { + while(syslog_config[s]) + s++; + } + + + /* Allocating the memory for the config. */ + os_realloc(syslog_config, (s + 2) * sizeof(SyslogConfig *), syslog_config); + os_calloc(1, sizeof(SyslogConfig), syslog_config[s]); + syslog_config[s + 1] = NULL; + + + /* Zeroing the elements. */ + syslog_config[s]->server = NULL; + syslog_config[s]->rule_id = NULL; + syslog_config[s]->group = NULL; + syslog_config[s]->location = NULL; + syslog_config[s]->level = 0; + syslog_config[s]->port = 514; + /* local 0 facility (16) + severity 4 - warning. --default */ + syslog_config[s]->priority = (16 * 8) + 4; + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + else if(strcmp(node[i]->element, xml_syslog_level) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + syslog_config[s]->level = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_syslog_port) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + syslog_config[s]->port = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_syslog_server) == 0) + { + os_strdup(node[i]->content, syslog_config[s]->server); + } + else if(strcmp(node[i]->element, xml_syslog_id) == 0) + { + int r_id = 0; + char *str_pt = node[i]->content; + + while(*str_pt != '\0') + { + /* We allow spaces in between */ + if(*str_pt == ' ') + { + str_pt++; + continue; + } + + /* If is digit, we get the value + * and search for the next digit + * available + */ + else if(isdigit((int)*str_pt)) + { + int id_i = 0; + + r_id = atoi(str_pt); + debug1("%s: DEBUG: Adding '%d' to syslog alerting", + ARGV0, r_id); + + if(syslog_config[s]->rule_id) + { + while(syslog_config[s]->rule_id[id_i]) + id_i++; + } + + os_realloc(syslog_config[s]->rule_id, + (id_i +2) * sizeof(int), + syslog_config[s]->rule_id); + + syslog_config[s]->rule_id[id_i + i] = 0; + syslog_config[s]->rule_id[id_i] = r_id; + + str_pt = strchr(str_pt, ','); + if(str_pt) + { + str_pt++; + } + else + { + break; + } + } + + /* Checking for duplicate commas */ + else if(*str_pt == ',') + { + str_pt++; + continue; + } + + else + { + break; + } + } + + } + else if(strcmp(node[i]->element, xml_syslog_format) == 0) + { + if(strcmp(node[i]->content, "default") == 0) + { + /* Default is full format */ + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_syslog_location) == 0) + { + os_calloc(1, sizeof(OSMatch),syslog_config[s]->location); + if(!OSMatch_Compile(node[i]->content, + syslog_config[s]->location, 0)) + { + merror(REGEX_COMPILE, ARGV0, node[i]->content, + syslog_config[s]->location->error); + return(-1); + } + } + else if(strcmp(node[i]->element, xml_syslog_group) == 0) + { + os_calloc(1, sizeof(OSMatch),syslog_config[s]->group); + if(!OSMatch_Compile(node[i]->content, + syslog_config[s]->group, 0)) + { + merror(REGEX_COMPILE, ARGV0, node[i]->content, + syslog_config[s]->group->error); + return(-1); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + + /* We must have at least one entry set */ + if(!syslog_config[s]->server) + { + merror(XML_INV_CSYSLOG, ARGV0); + return(OS_INVALID); + } + + + gen_config->data = syslog_config; + return(0); +} + + +/* EOF */ diff --git a/src/config/csyslogd-config.h b/src/config/csyslogd-config.h new file mode 100755 index 0000000..182d975 --- /dev/null +++ b/src/config/csyslogd-config.h @@ -0,0 +1,50 @@ +/* @(#) $Id: csyslogd-config.h,v 1.3 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + + +#ifndef _CSYSLOGCONFIG__H +#define _CSYSLOGCONFIG__H + + +/* Database config structure */ +typedef struct _SyslogConfig +{ + unsigned int port; + unsigned int format; + unsigned int level; + unsigned int *rule_id; + unsigned int priority; + int socket; + + char *server; + OSMatch *group; + OSMatch *location; +}SyslogConfig; + + +/* Syslog formats. */ +#define DEFAULT_CSYSLOG 0 + + +/* Syslog severities */ +#define SLOG_EMERG 0 /* system is unusable */ +#define SLOG_ALERT 1 /* action must be taken immediately */ +#define SLOG_CRIT 2 /* critical conditions */ +#define SLOG_ERR 3 /* error conditions */ +#define SLOG_WARNING 4 /* warning conditions */ +#define SLOG_NOTICE 5 /* normal but significant condition */ +#define SLOG_INFO 6 /* informational */ +#define SLOG_DEBUG 7 /* debug-level messages */ + +#endif diff --git a/src/config/dbd-config.c b/src/config/dbd-config.c new file mode 100644 index 0000000..17a8249 --- /dev/null +++ b/src/config/dbd-config.c @@ -0,0 +1,110 @@ +/* @(#) $Id: dbd-config.c,v 1.7 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the dbd configuration files + */ + + +#include "shared.h" +#include "dbd-config.h" + + +int Read_DB(XML_NODE node, void *config1, void *config2) +{ + int i = 0; + DBConfig *db_config; + + + /* XML definitions */ + char *xml_dbhost = "hostname"; + char *xml_dbuser = "username"; + char *xml_dbpass = "password"; + char *xml_dbdb = "database"; + char *xml_dbport = "port"; + char *xml_dbsock = "socket"; + char *xml_dbtype = "type"; + + + db_config = (DBConfig *)config2; + if(!db_config) + { + return(0); + } + + + /* Reading the xml */ + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + /* Mail notification */ + else if(strcmp(node[i]->element, xml_dbhost) == 0) + { + os_strdup(node[i]->content, db_config->host); + } + else if(strcmp(node[i]->element, xml_dbuser) == 0) + { + os_strdup(node[i]->content, db_config->user); + } + else if(strcmp(node[i]->element, xml_dbpass) == 0) + { + os_strdup(node[i]->content, db_config->pass); + } + else if(strcmp(node[i]->element, xml_dbdb) == 0) + { + os_strdup(node[i]->content, db_config->db); + } + else if(strcmp(node[i]->element, xml_dbport) == 0) + { + db_config->port = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_dbsock) == 0) + { + os_strdup(node[i]->content, db_config->sock); + } + else if(strcmp(node[i]->element, xml_dbtype) == 0) + { + if(strcmp(node[i]->content, "mysql") == 0) + { + db_config->db_type = MYSQLDB; + } + else if(strcmp(node[i]->content, "postgresql") == 0) + { + db_config->db_type = POSTGDB; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + + return(0); +} + + +/* EOF */ diff --git a/src/config/dbd-config.h b/src/config/dbd-config.h new file mode 100755 index 0000000..786561f --- /dev/null +++ b/src/config/dbd-config.h @@ -0,0 +1,44 @@ +/* @(#) $Id: dbd-config.h,v 1.9 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef _DBDCONFIG__H +#define _DBDONFIG__H + + +/* Database config structure */ +typedef struct _DBConfig +{ + unsigned int db_type; + unsigned int alert_id; + unsigned int server_id; + unsigned int error_count; + unsigned int maxreconnect; + unsigned int port; + + char *host; + char *user; + char *pass; + char *db; + char *sock; + + void *conn; + void *location_hash; + + char **includes; +}DBConfig; + + +#define MYSQLDB 0x002 +#define POSTGDB 0x004 + +#endif diff --git a/src/config/email-alerts-config.c b/src/config/email-alerts-config.c new file mode 100644 index 0000000..ee5d7f3 --- /dev/null +++ b/src/config/email-alerts-config.c @@ -0,0 +1,273 @@ +/* @(#) $Id: email-alerts-config.c,v 1.10 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the configuration files + */ + + +#include "shared.h" +#include "mail-config.h" + + +int Read_EmailAlerts(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + int granto_size = 1; + + /* XML definitions */ + char *xml_email_to = "email_to"; + char *xml_email_format = "format"; + char *xml_email_level = "level"; + char *xml_email_id = "rule_id"; + char *xml_email_group = "group"; + char *xml_email_location = "event_location"; + char *xml_email_donotdelay = "do_not_delay"; + char *xml_email_donotgroup = "do_not_group"; + + MailConfig *Mail; + + Mail = (MailConfig *)mailp; + if(!Mail) + { + return(0); + } + + + /* Getting Granular mail_to size */ + if(Mail && Mail->gran_to) + { + char **ww; + ww = Mail->gran_to; + while(*ww != NULL) + { + ww++; + granto_size++; + } + } + + + if(Mail) + { + os_realloc(Mail->gran_to, + sizeof(char *)*(granto_size +1), Mail->gran_to); + os_realloc(Mail->gran_id, + sizeof(int *)*(granto_size +1), Mail->gran_id); + os_realloc(Mail->gran_level, + sizeof(int)*(granto_size +1), Mail->gran_level); + os_realloc(Mail->gran_set, + sizeof(int)*(granto_size +1), Mail->gran_set); + os_realloc(Mail->gran_format, + sizeof(int)*(granto_size +1), Mail->gran_format); + os_realloc(Mail->gran_location, + sizeof(OSMatch)*(granto_size +1), Mail->gran_location); + os_realloc(Mail->gran_group, + sizeof(OSMatch)*(granto_size +1), Mail->gran_group); + + Mail->gran_to[granto_size -1] = NULL; + Mail->gran_to[granto_size] = NULL; + + Mail->gran_id[granto_size -1] = NULL; + Mail->gran_id[granto_size] = NULL; + + Mail->gran_location[granto_size -1] = NULL; + Mail->gran_location[granto_size] = NULL; + + Mail->gran_group[granto_size -1] = NULL; + Mail->gran_group[granto_size] = NULL; + + Mail->gran_level[granto_size -1] = 0; + Mail->gran_level[granto_size] = 0; + + Mail->gran_format[granto_size -1] = FULL_FORMAT; + Mail->gran_format[granto_size] = FULL_FORMAT; + + Mail->gran_set[granto_size -1] = 0; + Mail->gran_set[granto_size] = 0; + } + + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + /* Mail notification */ + else if(strcmp(node[i]->element, xml_email_level) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + Mail->gran_level[granto_size -1] = atoi(node[i]->content); + } + else if(strcmp(node[i]->element, xml_email_to) == 0) + { + os_strdup(node[i]->content, Mail->gran_to[granto_size -1]); + } + else if(strcmp(node[i]->element, xml_email_id) == 0) + { + int r_id = 0; + char *str_pt = node[i]->content; + + while(*str_pt != '\0') + { + /* We allow spaces in between */ + if(*str_pt == ' ') + { + str_pt++; + continue; + } + + /* If is digit, we get the value + * and search for the next digit + * available + */ + else if(isdigit((int)*str_pt)) + { + int id_i = 0; + + r_id = atoi(str_pt); + debug1("%s: DEBUG: Adding '%d' to granular e-mail", + ARGV0, r_id); + + if(!Mail->gran_id[granto_size -1]) + { + os_calloc(2,sizeof(int),Mail->gran_id[granto_size -1]); + Mail->gran_id[granto_size -1][0] = 0; + Mail->gran_id[granto_size -1][1] = 0; + } + else + { + while(Mail->gran_id[granto_size -1][id_i] != 0) + { + id_i++; + } + + os_realloc(Mail->gran_id[granto_size -1], + (id_i +2) * sizeof(int), + Mail->gran_id[granto_size -1]); + Mail->gran_id[granto_size -1][id_i +1] = 0; + } + Mail->gran_id[granto_size -1][id_i] = r_id; + + + str_pt = strchr(str_pt, ','); + if(str_pt) + { + str_pt++; + } + else + { + break; + } + } + + /* Checking for duplicate commas */ + else if(*str_pt == ',') + { + str_pt++; + continue; + } + + else + { + break; + } + } + + } + else if(strcmp(node[i]->element, xml_email_format) == 0) + { + if(strcmp(node[i]->content, "sms") == 0) + { + Mail->gran_format[granto_size -1] = SMS_FORMAT; + } + else if(strcmp(node[i]->content, "default") == 0) + { + /* Default is full format */ + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_email_donotdelay) == 0) + { + if((Mail->gran_format[granto_size -1] != SMS_FORMAT) && + (Mail->gran_format[granto_size -1] != DONOTGROUP)) + { + Mail->gran_format[granto_size -1] = FORWARD_NOW; + } + } + else if(strcmp(node[i]->element, xml_email_donotgroup) == 0) + { + if(Mail->gran_format[granto_size -1] != SMS_FORMAT) + { + Mail->gran_format[granto_size -1] = DONOTGROUP; + } + } + else if(strcmp(node[i]->element, xml_email_location) == 0) + { + os_calloc(1, sizeof(OSMatch),Mail->gran_location[granto_size -1]); + if(!OSMatch_Compile(node[i]->content, + Mail->gran_location[granto_size -1], 0)) + { + merror(REGEX_COMPILE, ARGV0, node[i]->content, + Mail->gran_location[granto_size -1]->error); + return(-1); + } + } + else if(strcmp(node[i]->element, xml_email_group) == 0) + { + os_calloc(1, sizeof(OSMatch),Mail->gran_group[granto_size -1]); + if(!OSMatch_Compile(node[i]->content, + Mail->gran_group[granto_size -1], 0)) + { + merror(REGEX_COMPILE, ARGV0, node[i]->content, + Mail->gran_group[granto_size -1]->error); + return(-1); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + /* We must have at least one entry set */ + if((Mail->gran_location[granto_size -1] == NULL && + Mail->gran_level[granto_size -1] == 0 && + Mail->gran_group[granto_size -1] == NULL && + Mail->gran_id[granto_size -1] == NULL && + Mail->gran_format[granto_size -1] == FULL_FORMAT) || + Mail->gran_to[granto_size -1] == NULL) + { + merror(XML_INV_GRAN_MAIL, ARGV0); + return(OS_INVALID); + } + + return(0); +} + + +/* EOF */ diff --git a/src/config/global-config.c b/src/config/global-config.c new file mode 100755 index 0000000..a3ded2e --- /dev/null +++ b/src/config/global-config.c @@ -0,0 +1,534 @@ +/* @(#) $Id: global-config.c,v 1.24 2009/07/23 19:31:35 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the configuration files + */ + + +#include "shared.h" +#include "os_net/os_net.h" +#include "global-config.h" +#include "mail-config.h" + + +void AssignIgnore_Global(char **ignores, void *configp) +{ + _Config *Config; + + Config = (_Config *)configp; + if(Config) + { + Config->syscheck_ignore = ignores; + } +} + + +/* GlobalConfSK v0.1: 2006/04/26 + * v0.1 Getting the ignore fields. + */ +int Read_GlobalSK(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + int ign_size = 1; + char *xml_ignore = "ignore"; + char *xml_auto_ignore = "auto_ignore"; + char *xml_alert_new_files = "alert_new_files"; + + _Config *Config; + + Config = (_Config *)configp; + + + /* Shouldn't be here if !Config */ + if(!Config) + return(0); + + + /* Getting right white_size */ + if(Config && Config->syscheck_ignore) + { + char **ww; + ww = Config->syscheck_ignore; + + while(*ww != NULL) + { + ign_size++; + ww++; + } + } + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + else if(strcmp(node[i]->element,xml_auto_ignore) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { + Config->syscheck_auto_ignore = 1; + } + else if(strcmp(node[i]->content, "no") == 0) + { + Config->syscheck_auto_ignore = 0; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element,xml_alert_new_files) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { + Config->syscheck_alert_new = 1; + } + else if(strcmp(node[i]->content, "no") == 0) + { + Config->syscheck_alert_new = 0; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element,xml_ignore) == 0) + { + ign_size++; + Config->syscheck_ignore = + realloc(Config->syscheck_ignore, sizeof(char *)*ign_size); + if(!Config->syscheck_ignore) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + + os_strdup(node[i]->content,Config->syscheck_ignore[ign_size -2]); + Config->syscheck_ignore[ign_size -1] = NULL; + } + i++; + } + + return(0); +} + + +/* GlobalConf v0.2: 2005/03/03 + * v0.2: Changing to support the new OS_XML + */ +int Read_Global(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + + /* White list size */ + int white_size = 1; + int hostname_white_size = 1; + int mailto_size = 1; + + + /* XML definitions */ + char *xml_mailnotify = "email_notification"; + char *xml_logall = "logall"; + char *xml_integrity = "integrity_checking"; + char *xml_rootcheckd = "rootkit_detection"; + char *xml_hostinfo = "host_information"; + char *xml_picviz = "picviz_output"; + char *xml_picviz_socket = "picviz_socket"; + char *xml_prelude = "prelude_output"; + char *xml_prelude_profile = "prelude_profile"; + char *xml_prelude_log_level = "prelude_log_level"; + char *xml_stats = "stats"; + char *xml_memorysize = "memory_size"; + char *xml_white_list = "white_list"; + char *xml_compress_alerts = "compress_alerts"; + + char *xml_emailto = "email_to"; + char *xml_emailfrom = "email_from"; + char *xml_smtpserver = "smtp_server"; + char *xml_mailmaxperhour = "email_maxperhour"; + + _Config *Config; + MailConfig *Mail; + + Config = (_Config *)configp; + Mail = (MailConfig *)mailp; + + /* Getting right white_size */ + if(Config && Config->white_list) + { + os_ip **ww; + ww = Config->white_list; + + while(*ww != NULL) + { + white_size++; + ww++; + } + } + + /* Getting right white_size */ + if(Config && Config->hostname_white_list) + { + OSMatch **ww; + ww = Config->hostname_white_list; + + while(*ww != NULL) + { + hostname_white_size++; + ww++; + } + } + + /* Getting mail_to size */ + if(Mail && Mail->to) + { + char **ww; + ww = Mail->to; + while(*ww != NULL) + { + mailto_size++; + ww++; + } + } + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + /* Mail notification */ + else if(strcmp(node[i]->element, xml_mailnotify) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { + if(Config) Config->mailnotify = 1; + if(Mail) Mail->mn = 1; + } + else if(strcmp(node[i]->content, "no") == 0) + { + if(Config) Config->mailnotify = 0; + if(Mail) Mail->mn = 0; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + /* Picviz support */ + else if(strcmp(node[i]->element, xml_picviz) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { + if(Config) Config->picviz = 1; + } + else if(strcmp(node[i]->content, "no") == 0) + { + if(Config) Config->picviz = 0; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element, node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_picviz_socket) == 0) + { + if(Config) + { + os_strdup(node[i]->content, Config->picviz_socket); + } + } + /* Prelude support */ + else if(strcmp(node[i]->element, xml_prelude) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { + if(Config) Config->prelude = 1; + } + else if(strcmp(node[i]->content, "no") == 0) + { + if(Config) Config->prelude = 0; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element, node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_prelude_profile) == 0) + { + if(Config) + { + Config->prelude_profile = strdup(node[i]->content); + } + } + else if(strcmp(node[i]->element, xml_prelude_log_level) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + if(Config) + { + Config->prelude_log_level = atoi(node[i]->content); + } + } + /* Log all */ + else if(strcmp(node[i]->element, xml_logall) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + { if(Config) Config->logall = 1;} + else if(strcmp(node[i]->content, "no") == 0) + {if(Config) Config->logall = 0;} + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + /* compress alerts */ + else if(strcmp(node[i]->element, xml_compress_alerts) == 0) + { + /* removed from here -- compatility issues only */ + } + /* Integrity */ + else if(strcmp(node[i]->element, xml_integrity) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + if(Config) + { + Config->integrity = atoi(node[i]->content); + } + } + /* rootcheck */ + else if(strcmp(node[i]->element, xml_rootcheckd) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + if(Config) + { + Config->rootcheck = atoi(node[i]->content); + } + } + /* hostinfo */ + else if(strcmp(node[i]->element, xml_hostinfo) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + if(Config) + { + Config->hostinfo = atoi(node[i]->content); + } + } + /* stats */ + else if(strcmp(node[i]->element, xml_stats) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + if(Config) + { + Config->stats = atoi(node[i]->content); + } + } + else if(strcmp(node[i]->element, xml_memorysize) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + if(Config) + { + Config->memorysize = atoi(node[i]->content); + } + } + /* whitelist */ + else if(strcmp(node[i]->element, xml_white_list) == 0) + { + /* Windows do not need it */ + #ifndef WIN32 + + char *ip_address_regex = + "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/?" + "([0-9]{0,2}|[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})$"; + + if(Config && OS_PRegex(node[i]->content, ip_address_regex)) + { + white_size++; + Config->white_list = + realloc(Config->white_list, sizeof(os_ip *)*white_size); + if(!Config->white_list) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + + os_calloc(1, sizeof(os_ip), Config->white_list[white_size -2]); + Config->white_list[white_size -1] = NULL; + + if(!OS_IsValidIP(node[i]->content, + Config->white_list[white_size -2])) + { + merror(INVALID_IP, ARGV0, + node[i]->content); + return(OS_INVALID); + } + } + /* Adding hostname */ + else if(Config) + { + hostname_white_size++; + Config->hostname_white_list = + realloc(Config->hostname_white_list, + sizeof(OSMatch *)*hostname_white_size); + + if(!Config->hostname_white_list) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + os_calloc(1, + sizeof(OSMatch), + Config->hostname_white_list[hostname_white_size -2]); + Config->hostname_white_list[hostname_white_size -1] = NULL; + + if(!OSMatch_Compile( + node[i]->content, + Config->hostname_white_list[hostname_white_size -2], + 0)) + { + merror(REGEX_COMPILE, ARGV0, node[i]->content, + Config->hostname_white_list + [hostname_white_size -2]->error); + return(-1); + } + } + + #endif + + } + + /* For the email now + * email_to, email_from, smtp_Server and maxperhour. + * We will use a separate structure for that. + */ + else if(strcmp(node[i]->element, xml_emailto) == 0) + { + #ifndef WIN32 + if(!OS_PRegex(node[i]->content, "[a-zA-Z0-9\\._-]+@[a-zA-Z0-9\\._-]")) + { + merror("%s: ERROR: Invalid Email address: %s.", ARGV0, node[i]->content); + return(OS_INVALID); + } + #endif + + if(Mail) + { + mailto_size++; + Mail->to = realloc(Mail->to, sizeof(char *)*mailto_size); + if(!Mail->to) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + + os_strdup(node[i]->content, Mail->to[mailto_size - 2]); + Mail->to[mailto_size - 1] = NULL; + } + } + else if(strcmp(node[i]->element, xml_emailfrom) == 0) + { + if(Mail) + { + if(Mail->from) + { + free(Mail->from); + } + os_strdup(node[i]->content, Mail->from); + } + } + else if(strcmp(node[i]->element, xml_smtpserver) == 0) + { + #ifndef WIN32 + if(Mail && (Mail->mn)) + { + Mail->smtpserver = OS_GetHost(node[i]->content, 5); + if(!Mail->smtpserver) + { + merror(INVALID_SMTP, ARGV0, node[i]->content); + return(OS_INVALID); + } + } + #endif + } + else if(strcmp(node[i]->element, xml_mailmaxperhour) == 0) + { + if(Mail) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + Mail->maxperhour = atoi(node[i]->content); + + if((Mail->maxperhour <= 0) || (Mail->maxperhour > 9999)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + return(0); +} + + +/* EOF */ diff --git a/src/config/global-config.h b/src/config/global-config.h new file mode 100755 index 0000000..b8fcbbc --- /dev/null +++ b/src/config/global-config.h @@ -0,0 +1,74 @@ +/* @(#) $Id: global-config.h,v 1.16 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef _CCONFIG__H +#define _CCONFIG__H +#include "shared.h" + + +/* Configuration structure */ +typedef struct __Config +{ + u_int8_t logall; + u_int8_t stats; + u_int8_t integrity; + u_int8_t syscheck_auto_ignore; + u_int8_t syscheck_alert_new; + u_int8_t rootcheck; + u_int8_t hostinfo; + u_int8_t mailbylevel; + u_int8_t logbylevel; + u_int8_t logfw; + + /* Prelude support */ + u_int8_t prelude; + /* which min. level the alert must be sent to prelude */ + u_int8_t prelude_log_level; + /* prelude profile name */ + char *prelude_profile; + + /* Picviz support */ + u_int8_t picviz; + char *picviz_socket; + + /* Not currently used */ + u_int8_t keeplogdate; + + /* Mail alerting */ + short int mailnotify; + + /* For the active response */ + int ar; + + /* For the correlation */ + int memorysize; + + /* List of files to ignore (syscheck) */ + char **syscheck_ignore; + + /* List of ips to never block */ + os_ip **white_list; + + /* List of hostnames to never block */ + OSMatch **hostname_white_list; + + /* List of rules */ + char **includes; + + /* Global rule hash. */ + void *g_rules_hash; + +}_Config; + + +#endif diff --git a/src/config/localfile-config.c b/src/config/localfile-config.c new file mode 100755 index 0000000..dd523e8 --- /dev/null +++ b/src/config/localfile-config.c @@ -0,0 +1,381 @@ +/* @(#) $Id: localfile-config.c,v 1.25 2009/11/03 21:07:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "localfile-config.h" + + +int Read_Localfile(XML_NODE node, void *d1, void *d2) +{ + int pl = 0; + int i = 0; + + int glob_set = 0; + + #ifndef WIN32 + int glob_offset = 0; + #endif + + + /* XML Definitions */ + char *xml_localfile_location = "location"; + char *xml_localfile_command = "command"; + char *xml_localfile_logformat = "log_format"; + + + logreader *logf; + logreader_config *log_config; + + log_config = (logreader_config *)d1; + + + /* If config is not set, we need to create it */ + if(!log_config->config) + { + os_calloc(2, sizeof(logreader), log_config->config); + logf = log_config->config; + logf[0].file = NULL; + logf[0].command = NULL; + logf[0].logformat = NULL; + logf[1].file = NULL; + logf[1].command = NULL; + logf[1].logformat = NULL; + } + else + { + logf = log_config->config; + while(logf[pl].file != NULL) + { + pl++; + } + + /* Allocating more memory */ + os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config); + logf = log_config->config; + logf[pl +1].file = NULL; + logf[pl +1].command = NULL; + logf[pl +1].logformat = NULL; + } + + logf[pl].file = NULL; + logf[pl].command = NULL; + logf[pl].logformat = NULL; + logf[pl].fp = NULL; + logf[pl].ffile = NULL; + logf[pl].djb_program_name = NULL; + + + /* Searching for entries related to files */ + i = 0; + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + else if(strcmp(node[i]->element,xml_localfile_command) == 0) + { + os_strdup(node[i]->content, logf[pl].file); + logf[pl].command = logf[pl].file; + } + else if(strcmp(node[i]->element,xml_localfile_location) == 0) + { + #ifdef WIN32 + /* Expand variables on Windows. */ + if(strchr(node[i]->content, '%')) + { + int expandreturn = 0; + char newfile[OS_MAXSTR +1]; + + newfile[OS_MAXSTR] = '\0'; + expandreturn = ExpandEnvironmentStrings(node[i]->content, + newfile, OS_MAXSTR); + + if((expandreturn > 0) && (expandreturn < OS_MAXSTR)) + { + free(node[i]->content); + + os_strdup(newfile, node[i]->content); + } + } + #endif + + + /* This is a glob*. + * We will call this file multiple times until + * there is no one else available. + */ + #ifndef WIN32 /* No windows support for glob */ + if(strchr(node[i]->content, '*') || + strchr(node[i]->content, '?') || + strchr(node[i]->content, '[')) + { + glob_t g; + + /* Setting ot the first entry of the glob */ + if(glob_set == 0) + glob_set = pl +1; + + if(glob(node[i]->content, 0, NULL, &g) != 0) + { + merror(GLOB_ERROR, ARGV0, node[i]->content); + os_strdup(node[i]->content, logf[pl].file); + i++; + continue; + } + + /* Checking for the last entry */ + if((g.gl_pathv[glob_offset]) == NULL) + { + /* Checking when nothing is found. */ + if(glob_offset == 0) + { + merror(GLOB_NFOUND, ARGV0, node[i]->content); + return(OS_INVALID); + } + i++; + continue; + } + + + /* Checking for strftime on globs too. */ + if(strchr(g.gl_pathv[glob_offset], '%')) + { + struct tm *p; + time_t l_time = time(0); + char lfile[OS_FLSIZE + 1]; + size_t ret; + + p = localtime(&l_time); + + lfile[OS_FLSIZE] = '\0'; + ret = strftime(lfile, OS_FLSIZE, g.gl_pathv[glob_offset], p); + if(ret == 0) + { + merror(PARSE_ERROR, ARGV0, g.gl_pathv[glob_offset]); + return(OS_INVALID); + } + + os_strdup(g.gl_pathv[glob_offset], logf[pl].ffile); + os_strdup(g.gl_pathv[glob_offset], logf[pl].file); + } + else + { + os_strdup(g.gl_pathv[glob_offset], logf[pl].file); + } + + + glob_offset++; + globfree(&g); + + /* Now we need to create another file entry */ + pl++; + os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config); + logf = log_config->config; + + logf[pl].file = NULL; + logf[pl].logformat = NULL; + logf[pl].fp = NULL; + logf[pl].ffile = NULL; + + logf[pl +1].file = NULL; + logf[pl +1].logformat = NULL; + + /* We can not increment the file count in here */ + continue; + } + else if(strchr(node[i]->content, '%')) + #else + if(strchr(node[i]->content, '%')) + #endif /* WIN32 */ + + /* We need the format file (based on date) */ + { + struct tm *p; + time_t l_time = time(0); + char lfile[OS_FLSIZE + 1]; + size_t ret; + + p = localtime(&l_time); + + lfile[OS_FLSIZE] = '\0'; + ret = strftime(lfile, OS_FLSIZE, node[i]->content, p); + if(ret == 0) + { + merror(PARSE_ERROR, ARGV0, node[i]->content); + return(OS_INVALID); + } + + os_strdup(node[i]->content, logf[pl].ffile); + os_strdup(node[i]->content, logf[pl].file); + } + + + /* Normal file */ + else + { + os_strdup(node[i]->content, logf[pl].file); + } + } + + /* Getting log format */ + else if(strcasecmp(node[i]->element,xml_localfile_logformat) == 0) + { + os_strdup(node[i]->content, logf[pl].logformat); + + if(strcmp(logf[pl].logformat, "syslog") == 0) + { + } + else if(strcmp(logf[pl].logformat, "snort-full") == 0) + { + } + else if(strcmp(logf[pl].logformat, "snort-fast") == 0) + { + } + else if(strcmp(logf[pl].logformat, "apache") == 0) + { + } + else if(strcmp(logf[pl].logformat, "iis") == 0) + { + } + else if(strcmp(logf[pl].logformat, "squid") == 0) + { + } + else if(strcmp(logf[pl].logformat, "nmapg") == 0) + { + } + else if(strcmp(logf[pl].logformat, "mysql_log") == 0) + { + } + else if(strcmp(logf[pl].logformat, "mssql_log") == 0) + { + } + else if(strcmp(logf[pl].logformat, "postgresql_log") == 0) + { + } + else if(strcmp(logf[pl].logformat, "djb-multilog") == 0) + { + } + else if(strcmp(logf[pl].logformat, "syslog-pipe") == 0) + { + } + else if(strcmp(logf[pl].logformat, "command") == 0) + { + } + else if(strcmp(logf[pl].logformat, EVENTLOG) == 0) + { + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + + i++; + } + + + /* Validating glob entries */ + if(glob_set) + { + char *format; + + /* Getting log format */ + if(logf[pl].logformat) + { + format = logf[pl].logformat; + } + else if(logf[glob_set -1].logformat) + { + format = logf[glob_set -1].logformat; + } + else + { + merror(MISS_LOG_FORMAT, ARGV0); + return(OS_INVALID); + } + + /* The last entry is always null on glob */ + pl--; + + + /* Setting format for all entries */ + for(i = (glob_set -1); i<= pl; i++) + { + /* Every entry must be valid */ + if(!logf[i].file) + { + merror(MISS_FILE, ARGV0); + return(OS_INVALID); + } + + if(logf[i].logformat == NULL) + { + logf[i].logformat = format; + } + + } + } + + /* Missing log format */ + if(!logf[pl].logformat) + { + merror(MISS_LOG_FORMAT, ARGV0); + return(OS_INVALID); + } + + /* Missing file */ + if(!logf[pl].file) + { + merror(MISS_FILE, ARGV0); + return(OS_INVALID); + } + + /* Verifying a valid event log config */ + if(strcmp(logf[pl].logformat, EVENTLOG) == 0) + { + if((strcmp(logf[pl].file, "Application") != 0)&& + (strcmp(logf[pl].file, "System") != 0)&& + (strcmp(logf[pl].file, "Security") != 0)) + { + /* Invalid event log */ + merror(NSTD_EVTLOG, ARGV0, logf[pl].file); + return(0); + } + } + + if(strcmp(logf[pl].logformat, "command") == 0) + { + if(!logf[pl].command) + { + merror("%s: ERROR: Missing 'command' argument. " + "This option will be ignored.", ARGV0); + } + } + + return(0); +} + +/* EOF */ diff --git a/src/config/localfile-config.h b/src/config/localfile-config.h new file mode 100755 index 0000000..2714799 --- /dev/null +++ b/src/config/localfile-config.h @@ -0,0 +1,61 @@ +/* $OSSEC, localfile-config.h, v0.3, 2005/11/11, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef __CLOGREADER_H + +#define __CLOGREADER_H + +#define EVENTLOG "eventlog" +#define VCHECK_FILES 64 +#define DATE_MODIFIED 1 + + +/* For ino_t */ +#include + + +/* Logreader config */ +typedef struct _logreader +{ + unsigned int size; + int ign; + + #ifdef WIN32 + HANDLE h; + int fd; + #else + ino_t fd; + #endif + + + /* ffile - format file is only used when + * the file has format string to retrieve + * the date, + */ + char *ffile; + char *file; + char *logformat; + char *djb_program_name; + char *command; + + void (*read)(int i, int *rc, int drop_it); + + FILE *fp; +}logreader; + +typedef struct _logreader_config +{ + logreader *config; +}logreader_config; + +#endif diff --git a/src/config/mail-config.h b/src/config/mail-config.h new file mode 100755 index 0000000..92cc81f --- /dev/null +++ b/src/config/mail-config.h @@ -0,0 +1,49 @@ +/* $OSSEC, mail-config.h, v0.1, 2006/04/06, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef _MCCONFIG__H +#define _MCCONFIG__H +#include "shared.h" + + +/* Mail config structure */ +typedef struct _MailConfig +{ + int mn; + int maxperhour; + int strict_checking; + int groupping; + int subject_full; + int priority; + char **to; + char *from; + char *smtpserver; + + /* Granular e-mail options */ + int *gran_level; + int **gran_id; + int *gran_set; + int *gran_format; + char **gran_to; + OSMatch **gran_location; + OSMatch **gran_group; +}MailConfig; + + +/** Email message formats **/ +#define FULL_FORMAT 2 +#define SMS_FORMAT 3 +#define FORWARD_NOW 4 +#define DONOTGROUP 5 + +#endif diff --git a/src/config/remote-config.c b/src/config/remote-config.c new file mode 100755 index 0000000..9a41089 --- /dev/null +++ b/src/config/remote-config.c @@ -0,0 +1,251 @@ +/* $OSSEC, remote-config.c, v0.3, 2005/11/09, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "remote-config.h" + + +/* Read_Remote: Reads remote config + */ +int Read_Remote(XML_NODE node, void *d1, void *d2) +{ + int i = 0; + int pl = 0; + + int allow_size = 1; + int deny_size = 1; + remoted *logr; + + /*** XML Definitions ***/ + + /* Allowed and denied IPS */ + char *xml_allowips = "allowed-ips"; + char *xml_denyips = "denied-ips"; + + /* Remote options */ + char *xml_remote_port = "port"; + char *xml_remote_proto = "protocol"; + char *xml_remote_connection = "connection"; + char *xml_remote_lip = "local_ip"; + + logr = (remoted *)d1; + + /* Getting allowed-ips */ + if(logr->allowips) + { + while(logr->allowips[allow_size -1]) + allow_size++; + } + + /* Getting denied-ips */ + if(logr->denyips) + { + while(logr->denyips[deny_size -1]) + deny_size++; + } + + + /* conn and port must not be null */ + if(!logr->conn) + { + os_calloc(1, sizeof(int), logr->conn); + logr->conn[0] = 0; + } + if(!logr->port) + { + os_calloc(1, sizeof(int), logr->port); + logr->port[0] = 0; + } + if(!logr->proto) + { + os_calloc(1, sizeof(int), logr->proto); + logr->proto[0] = 0; + } + if(!logr->lip) + { + os_calloc(1, sizeof(char *), logr->lip); + logr->lip[0] = NULL; + } + + + /* Cleaning */ + while(logr->conn[pl] != 0) + pl++; + + + /* Adding space for the last null connection/port */ + logr->port = realloc(logr->port, sizeof(int)*(pl +2)); + logr->conn = realloc(logr->conn, sizeof(int)*(pl +2)); + logr->proto = realloc(logr->proto, sizeof(int)*(pl +2)); + logr->lip = realloc(logr->lip, sizeof(char *)*(pl +2)); + if(!logr->port || !logr->conn || !logr->proto || !logr->lip) + { + merror(MEM_ERROR, ARGV0); + } + + logr->port[pl] = 0; + logr->conn[pl] = 0; + logr->proto[pl] = 0; + logr->lip[pl] = NULL; + + logr->port[pl +1] = 0; + logr->conn[pl +1] = 0; + logr->proto[pl +1] = 0; + logr->lip[pl +1] = NULL; + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + else if(strcasecmp(node[i]->element,xml_remote_connection) == 0) + { + if(strcmp(node[i]->content, "syslog") == 0) + { + logr->conn[pl] = SYSLOG_CONN; + } + else if(strcmp(node[i]->content, "secure") == 0) + { + logr->conn[pl] = SECURE_CONN; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcasecmp(node[i]->element,xml_remote_port) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + logr->port[pl] = atoi(node[i]->content); + + if(logr->port[pl] <= 0 || logr->port[pl] > 65535) + { + merror(PORT_ERROR, ARGV0, logr->port[pl]); + return(OS_INVALID); + } + } + else if(strcasecmp(node[i]->element,xml_remote_proto) == 0) + { + if(strcasecmp(node[i]->content, "tcp") == 0) + { + logr->proto[pl] = TCP_PROTO; + } + else if(strcasecmp(node[i]->content, "udp") == 0) + { + logr->proto[pl] = UDP_PROTO; + } + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element, + node[i]->content); + return(OS_INVALID); + } + } + else if(strcasecmp(node[i]->element,xml_remote_lip) == 0) + { + os_strdup(node[i]->content,logr->lip[pl]); + if(OS_IsValidIP(logr->lip[pl], NULL) != 1) + { + merror(INVALID_IP, ARGV0, node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_allowips) == 0) + { + allow_size++; + logr->allowips =realloc(logr->allowips,sizeof(os_ip *)*allow_size); + if(!logr->allowips) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + + os_calloc(1, sizeof(os_ip), logr->allowips[allow_size -2]); + logr->allowips[allow_size -1] = NULL; + + if(!OS_IsValidIP(node[i]->content,logr->allowips[allow_size -2])) + { + merror(INVALID_IP, ARGV0, node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_denyips) == 0) + { + deny_size++; + logr->denyips = realloc(logr->denyips,sizeof(os_ip *)*deny_size); + if(!logr->denyips) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + + os_calloc(1, sizeof(os_ip), logr->denyips[deny_size -2]); + logr->denyips[deny_size -1] = NULL; + if(!OS_IsValidIP(node[i]->content, logr->denyips[deny_size -2])) + { + merror(INVALID_IP, ARGV0, node[i]->content); + return(OS_INVALID); + } + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + /* conn must be set */ + if(logr->conn[pl] == 0) + { + merror(CONN_ERROR, ARGV0); + return(OS_INVALID); + } + + /* Set port in here */ + if(logr->port[pl] == 0) + { + if(logr->conn[pl] == SECURE_CONN) + logr->port[pl] = DEFAULT_SECURE; + else + logr->port[pl] = DEFAULT_SYSLOG; + } + + /* set default protocol */ + if(logr->proto[pl] == 0) + { + logr->proto[pl] = UDP_PROTO; + } + + /* Secure connections only run on UDP */ + if((logr->conn[pl] == SECURE_CONN) && (logr->proto[pl] == TCP_PROTO)) + { + logr->proto[pl] = UDP_PROTO; + } + + return(0); +} + + +/* EOF */ diff --git a/src/config/remote-config.h b/src/config/remote-config.h new file mode 100755 index 0000000..65bf8d7 --- /dev/null +++ b/src/config/remote-config.h @@ -0,0 +1,40 @@ +/* $OSSEC, remote-config.h, v0.3, 2005/02/09, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __CLOGREMOTE_H + +#define __CLOGREMOTE_H + +#define SYSLOG_CONN 1 +#define SECURE_CONN 2 +#define UDP_PROTO 6 +#define TCP_PROTO 17 + +#include "shared.h" + +/* socklen_t header */ +typedef struct _remoted +{ + int *proto; + int *port; + int *conn; + + char **lip; + os_ip **allowips; + os_ip **denyips; + + int m_queue; + int sock; + socklen_t peer_size; +}remoted; + +#endif diff --git a/src/config/rootcheck-config.c b/src/config/rootcheck-config.c new file mode 100755 index 0000000..dceb6a8 --- /dev/null +++ b/src/config/rootcheck-config.c @@ -0,0 +1,163 @@ +/* $OSSEC, rootcheck-config.c, v0.1, 2005/09/30, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck-config.h" + + +/* Read_Rootcheck: Reads the rootcheck config + */ +int Read_Rootcheck(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + + rkconfig *rootcheck; + + /* XML Definitions */ + char *xml_rootkit_files = "rootkit_files"; + char *xml_rootkit_trojans = "rootkit_trojans"; + char *xml_winaudit = "windows_audit"; + char *xml_unixaudit = "system_audit"; + char *xml_winapps = "windows_apps"; + char *xml_winmalware = "windows_malware"; + char *xml_scanall = "scanall"; + char *xml_readall = "readall"; + char *xml_time = "frequency"; + char *xml_disabled = "disabled"; + char *xml_base_dir = "base_directory"; + char *xml_ignore = "ignore"; + + + rootcheck = (rkconfig *)configp; + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + + /* Getting frequency */ + else if(strcmp(node[i]->element,xml_time) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + rootcheck->time = atoi(node[i]->content); + } + /* getting scan all */ + else if(strcmp(node[i]->element,xml_scanall) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + rootcheck->scanall = 1; + else if(strcmp(node[i]->content, "no") == 0) + rootcheck->scanall = 0; + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element, xml_disabled) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + rootcheck->disabled = 1; + else if(strcmp(node[i]->content, "no") == 0) + rootcheck->disabled = 0; + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element,xml_readall) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + rootcheck->readall = 1; + else if(strcmp(node[i]->content, "no") == 0) + rootcheck->readall = 0; + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + else if(strcmp(node[i]->element,xml_rootkit_files) == 0) + { + os_strdup(node[i]->content, rootcheck->rootkit_files); + } + else if(strcmp(node[i]->element,xml_rootkit_trojans) == 0) + { + os_strdup(node[i]->content, rootcheck->rootkit_trojans); + } + else if(strcmp(node[i]->element, xml_winaudit) == 0) + { + os_strdup(node[i]->content, rootcheck->winaudit); + } + else if(strcmp(node[i]->element, xml_unixaudit) == 0) + { + int j = 0; + while(rootcheck->unixaudit && rootcheck->unixaudit[j]) + j++; + + os_realloc(rootcheck->unixaudit, sizeof(char *)*(j+2), + rootcheck->unixaudit); + rootcheck->unixaudit[j] = NULL; + rootcheck->unixaudit[j + 1] = NULL; + + os_strdup(node[i]->content, rootcheck->unixaudit[j]); + } + else if(strcmp(node[i]->element, xml_ignore) == 0) + { + int j = 0; + while(rootcheck->ignore && rootcheck->ignore[j]) + j++; + + os_realloc(rootcheck->ignore, sizeof(char *)*(j+2), + rootcheck->ignore); + rootcheck->ignore[j] = NULL; + rootcheck->ignore[j + 1] = NULL; + + os_strdup(node[i]->content, rootcheck->ignore[j]); + } + else if(strcmp(node[i]->element, xml_winmalware) == 0) + { + os_strdup(node[i]->content, rootcheck->winmalware); + } + else if(strcmp(node[i]->element, xml_winapps) == 0) + { + os_strdup(node[i]->content, rootcheck->winapps); + } + else if(strcmp(node[i]->element, xml_base_dir) == 0) + { + os_strdup(node[i]->content, rootcheck->basedir); + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + return(0); +} + +/* EOF */ diff --git a/src/config/rootcheck-config.h b/src/config/rootcheck-config.h new file mode 100755 index 0000000..988be6c --- /dev/null +++ b/src/config/rootcheck-config.h @@ -0,0 +1,45 @@ +/* $OSSEC, rootcheck.h, v0.1, 2005/10/03, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __CROOTCHECK_H + +#define __CROOTCHECK_H + +#include + +typedef struct _rkconfig +{ + char *workdir; + char *basedir; + char *rootkit_files; + char *rootkit_trojans; + char **unixaudit; + char **ignore; + char *winaudit; + char *winmalware; + char *winapps; + char **alert_msg; + + FILE *fp; + int daemon; + int notify; /* QUEUE or SYSLOG */ + int scanall; + int readall; + int disabled; + + int time; + int queue; +}rkconfig; + +#endif + +/* EOF */ diff --git a/src/config/rules-config.c b/src/config/rules-config.c new file mode 100755 index 0000000..f9da8f3 --- /dev/null +++ b/src/config/rules-config.c @@ -0,0 +1,73 @@ +/* @(#) $Id: rules-config.c,v 1.5 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions to handle the configuration files + */ + + +#include "shared.h" +#include "global-config.h" + + +int Read_Rules(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + + /* White list size */ + int rules_size = 1; + + + /* XML definitions */ + char *xml_rules_include = "include"; + + _Config *Config; + + Config = (_Config *)configp; + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + /* Mail notification */ + else if(strcmp(node[i]->element, xml_rules_include) == 0) + { + rules_size++; + Config->includes = realloc(Config->includes, + sizeof(char *)*rules_size); + if(!Config->includes) + { + merror(MEM_ERROR, ARGV0); + return(OS_INVALID); + } + + os_strdup(node[i]->content,Config->includes[rules_size -2]); + Config->includes[rules_size -1] = NULL; + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + return(0); +} + + +/* EOF */ diff --git a/src/config/syscheck-config.c b/src/config/syscheck-config.c new file mode 100755 index 0000000..92e538d --- /dev/null +++ b/src/config/syscheck-config.c @@ -0,0 +1,786 @@ +/* @(#) $Id: syscheck-config.c,v 1.25 2009/11/04 15:18:59 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + +#include "syscheck-config.h" + + + +int dump_syscheck_entry(config *syscheck, char *entry, int vals, int reg) +{ + int pl = 0; + + if(reg == 1) + { + #ifdef WIN32 + if(syscheck->registry == NULL) + { + os_calloc(2, sizeof(char *), syscheck->registry); + syscheck->registry[pl + 1] = NULL; + os_strdup(entry, syscheck->registry[pl]); + } + else + { + while(syscheck->registry[pl] != NULL) + { + pl++; + } + os_realloc(syscheck->registry, (pl +2) * sizeof(char *), + syscheck->registry); + syscheck->registry[pl + 1] = NULL; + os_strdup(entry, syscheck->registry[pl]); + } + #endif + + } + + + else + { + if(syscheck->dir == NULL) + { + os_calloc(2, sizeof(char *), syscheck->dir); + syscheck->dir[pl + 1] = NULL; + os_strdup(entry, syscheck->dir[pl]); + + os_calloc(2, sizeof(int), syscheck->opts); + syscheck->opts[pl + 1] = 0; + syscheck->opts[pl] = vals; + } + else + { + while(syscheck->dir[pl] != NULL) + { + pl++; + } + os_realloc(syscheck->dir, (pl +2) * sizeof(char *), + syscheck->dir); + syscheck->dir[pl + 1] = NULL; + os_strdup(entry, syscheck->dir[pl]); + + os_realloc(syscheck->opts, (pl +2) * sizeof(int), + syscheck->opts); + syscheck->opts[pl + 1] = 0; + syscheck->opts[pl] = vals; + } + } + + return(1); +} + + + +/* Read Windows registry configuration */ +#ifdef WIN32 +int read_reg(config *syscheck, char *entries) +{ + int i; + char **entry; + char *tmp_str; + + + /* Getting each entry separately */ + entry = OS_StrBreak(',', entries, MAX_DIR_SIZE); /* Max number */ + + + /* entry can not be null */ + if(entry == NULL) + { + return(0); + } + + + /* Doing it for each Entry */ + while(*entry) + { + char *tmp_entry; + + tmp_entry = *entry; + + /* Removing spaces at the beginning */ + while(*tmp_entry == ' ') + { + tmp_entry++; + } + + /* Removing spaces at the end */ + tmp_str = strchr(tmp_entry, ' '); + if(tmp_str) + { + tmp_str++; + + /* Checking if it is really at the end */ + if((*tmp_str == '\0') || (*tmp_str == ' ')) + { + tmp_str--; + *tmp_str = '\0'; + } + } + + + /* Adding entries - looking for the last available */ + i = 0; + while(syscheck->registry && syscheck->registry[i]) + { + int str_len_i; + int str_len_dir; + + str_len_dir = strlen(tmp_entry); + str_len_i = strlen(syscheck->registry[i]); + + if(str_len_dir > str_len_i) + { + str_len_dir = str_len_i; + } + + /* Duplicated entry */ + if(strcmp(syscheck->registry[i], tmp_entry) == 0) + { + merror(SK_DUP, ARGV0, tmp_entry); + return(1); + } + i++; + } + + /* Adding new entry */ + dump_syscheck_entry(syscheck, tmp_entry, 0, 1); + + + /* Next entry */ + entry++; + } + + return(1); +} +#endif /* For read_reg */ + + + + +/* Read directories attributes */ +int read_attr(config *syscheck, char *dirs, char **g_attrs, char **g_values) +{ + char *xml_check_all = "check_all"; + char *xml_check_sum = "check_sum"; + char *xml_check_sha1sum = "check_sha1sum"; + char *xml_check_md5sum = "check_md5sum"; + char *xml_check_size = "check_size"; + char *xml_check_owner = "check_owner"; + char *xml_check_group = "check_group"; + char *xml_check_perm = "check_perm"; + char *xml_real_time = "realtime"; + + char **dir; + char *tmp_str; + dir = OS_StrBreak(',', dirs, MAX_DIR_SIZE); /* Max number */ + + /* Dir can not be null */ + if(dir == NULL) + { + return(0); + } + + + /* Doing it for each directory */ + while(*dir) + { + int i = 0; + int opts = 0; + char *tmp_dir; + + char **attrs = NULL; + char **values = NULL; + + tmp_dir = *dir; + + /* Removing spaces at the beginning */ + while(*tmp_dir == ' ') + { + tmp_dir++; + } + + /* Removing spaces at the end */ + tmp_str = strchr(tmp_dir, ' '); + if(tmp_str) + { + tmp_str++; + + /* Checking if it is really at the end */ + if((*tmp_str == '\0') || (*tmp_str == ' ')) + { + tmp_str--; + *tmp_str = '\0'; + } + } + + + /* Getting the options */ + if(!g_attrs || !g_values) + { + merror(SYSCHECK_NO_OPT, ARGV0, dirs); + return(0); + } + + attrs = g_attrs; + values = g_values; + + while(*attrs && *values) + { + /* Checking all */ + if(strcmp(*attrs, xml_check_all) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_MD5SUM; + opts|=CHECK_SHA1SUM; + opts|=CHECK_PERM; + opts|=CHECK_SIZE; + opts|=CHECK_OWNER; + opts|=CHECK_GROUP; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking sum */ + else if(strcmp(*attrs, xml_check_sum) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_MD5SUM; + opts|=CHECK_SHA1SUM; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking md5sum */ + else if(strcmp(*attrs, xml_check_md5sum) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_MD5SUM; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking sha1sum */ + else if(strcmp(*attrs, xml_check_sha1sum) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_SHA1SUM; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking permission */ + else if(strcmp(*attrs, xml_check_perm) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_PERM; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking size */ + else if(strcmp(*attrs, xml_check_size) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_SIZE; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking owner */ + else if(strcmp(*attrs, xml_check_owner) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_OWNER; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + /* Checking group */ + else if(strcmp(*attrs, xml_check_group) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_GROUP; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + else if(strcmp(*attrs, xml_real_time) == 0) + { + if(strcmp(*values, "yes") == 0) + { + opts|=CHECK_REALTIME; + } + else if(strcmp(*values, "no") == 0) + { + } + else + { + merror(SK_INV_OPT, ARGV0, *values, *attrs); + return(0); + } + } + else + { + merror(SK_INV_ATTR, ARGV0, *attrs); + return(0); + } + attrs++; values++; + } + + + /* You must have something set */ + if(opts == 0) + { + merror(SYSCHECK_NO_OPT, ARGV0, dirs); + return(0); + } + + + /* Adding directory - looking for the last available */ + i = 0; + while(syscheck->dir && syscheck->dir[i]) + { + int str_len_i; + int str_len_dir; + + str_len_dir = strlen(tmp_dir); + str_len_i = strlen(syscheck->dir[i]); + + if(str_len_dir > str_len_i) + { + str_len_dir = str_len_i; + } + + /* Duplicate entry */ + if(strcmp(syscheck->dir[i], tmp_dir) == 0) + { + merror(SK_DUP, ARGV0, tmp_dir); + return(1); + } + + i++; + } + + + /* Checking for glob. */ + #ifndef WIN32 + if(strchr(tmp_dir, '*') || + strchr(tmp_dir, '?') || + strchr(tmp_dir, '[')) + { + int gindex = 0; + glob_t g; + + if(glob(tmp_dir, 0, NULL, &g) != 0) + { + merror(GLOB_ERROR, ARGV0, tmp_dir); + return(1); + } + + if(g.gl_pathv[0] == NULL) + { + merror(GLOB_NFOUND, ARGV0, tmp_dir); + return(1); + } + + while(g.gl_pathv[gindex]) + { + dump_syscheck_entry(syscheck, g.gl_pathv[gindex], opts, 0); + gindex++; + } + + globfree(&g); + } + + else + { + dump_syscheck_entry(syscheck, tmp_dir, opts, 0); + } + #else + dump_syscheck_entry(syscheck, tmp_dir, opts, 0); + #endif + + + /* Next entry */ + dir++; + } + + return(1); +} + + + +int Read_Syscheck(XML_NODE node, void *configp, void *mailp) +{ + int i = 0; + + /* XML Definitions */ + char *xml_directories = "directories"; + char *xml_registry = "windows_registry"; + char *xml_time = "frequency"; + char *xml_scanday = "scan_day"; + char *xml_scantime = "scan_time"; + char *xml_ignore = "ignore"; + char *xml_registry_ignore = "registry_ignore"; + char *xml_auto_ignore = "auto_ignore"; + char *xml_alert_new_files = "alert_new_files"; + char *xml_disabled = "disabled"; + char *xml_scan_on_start = "scan_on_start"; + + /* Configuration example + /etc,/usr/bin + /var/log + */ + + config *syscheck; + + syscheck = (config *)configp; + + + while(node[i]) + { + if(!node[i]->element) + { + merror(XML_ELEMNULL, ARGV0); + return(OS_INVALID); + } + else if(!node[i]->content) + { + merror(XML_VALUENULL, ARGV0, node[i]->element); + return(OS_INVALID); + } + + /* Getting directories */ + else if(strcmp(node[i]->element,xml_directories) == 0) + { + char dirs[OS_MAXSTR]; + + #ifdef WIN32 + ExpandEnvironmentStrings(node[i]->content, dirs, sizeof(dirs) -1); + #else + strncpy(dirs, node[i]->content, sizeof(dirs) -1); + #endif + + if(!read_attr(syscheck, + dirs, + node[i]->attributes, + node[i]->values)) + { + return(OS_INVALID); + } + } + /* Getting windows registry */ + else if(strcmp(node[i]->element,xml_registry) == 0) + { + #ifdef WIN32 + if(!read_reg(syscheck, node[i]->content)) + { + return(OS_INVALID); + } + #endif + } + /* Getting frequency */ + else if(strcmp(node[i]->element,xml_time) == 0) + { + if(!OS_StrIsNum(node[i]->content)) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + + syscheck->time = atoi(node[i]->content); + } + /* Getting scan time */ + else if(strcmp(node[i]->element,xml_scantime) == 0) + { + syscheck->scan_time = OS_IsValidUniqueTime(node[i]->content); + if(!syscheck->scan_time) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + + /* Getting scan day */ + else if(strcmp(node[i]->element,xml_scanday) == 0) + { + syscheck->scan_day = OS_IsValidDay(node[i]->content); + if(!syscheck->scan_day) + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + + /* Getting if xml_scan_on_start. */ + else if(strcmp(node[i]->element, xml_scan_on_start) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + syscheck->scan_on_start = 1; + else if(strcmp(node[i]->content, "no") == 0) + syscheck->scan_on_start = 0; + else + { + merror(XML_VALUEERR,ARGV0, node[i]->element, node[i]->content); + return(OS_INVALID); + } + } + + /* Getting if disabled. */ + else if(strcmp(node[i]->element,xml_disabled) == 0) + { + if(strcmp(node[i]->content, "yes") == 0) + syscheck->disabled = 1; + else if(strcmp(node[i]->content, "no") == 0) + syscheck->disabled = 0; + else + { + merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); + return(OS_INVALID); + } + } + + /* Getting file/dir ignore */ + else if(strcmp(node[i]->element,xml_ignore) == 0) + { + int ign_size = 0; + + /* For Windows, we attempt to expand environment variables. */ + #ifdef WIN32 + char *new_ig = NULL; + os_calloc(2048, sizeof(char), new_ig); + + ExpandEnvironmentStrings(node[i]->content, new_ig, 2047); + + free(node[i]->content); + node[i]->content = new_ig; + #endif + + /* Adding if regex */ + if(node[i]->attributes && node[i]->values) + { + if(node[i]->attributes[0] && node[i]->values[0] && + (strcmp(node[i]->attributes[0], "type") == 0) && + (strcmp(node[i]->values[0], "sregex") == 0)) + { + OSMatch *mt_pt; + + if(!syscheck->ignore_regex) + { + os_calloc(2, sizeof(OSMatch *),syscheck->ignore_regex); + syscheck->ignore_regex[0] = NULL; + syscheck->ignore_regex[1] = NULL; + } + else + { + while(syscheck->ignore_regex[ign_size] != NULL) + ign_size++; + + os_realloc(syscheck->ignore_regex, + sizeof(OSMatch *)*(ign_size +2), + syscheck->ignore_regex); + syscheck->ignore_regex[ign_size +1] = NULL; + } + os_calloc(1, sizeof(OSMatch), + syscheck->ignore_regex[ign_size]); + + if(!OSMatch_Compile(node[i]->content, + syscheck->ignore_regex[ign_size], 0)) + { + mt_pt = (OSMatch *)syscheck->ignore_regex[ign_size]; + merror(REGEX_COMPILE, ARGV0, node[i]->content, + mt_pt->error); + return(0); + } + } + else + { + merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]); + return(OS_INVALID); + } + } + + /* Adding if simple entry -- checking for duplicates */ + else if(!os_IsStrOnArray(node[i]->content, syscheck->ignore)) + { + if(!syscheck->ignore) + { + os_calloc(2, sizeof(char *), syscheck->ignore); + syscheck->ignore[0] = NULL; + syscheck->ignore[1] = NULL; + } + else + { + while(syscheck->ignore[ign_size] != NULL) + ign_size++; + + os_realloc(syscheck->ignore, + sizeof(char *)*(ign_size +2), + syscheck->ignore); + syscheck->ignore[ign_size +1] = NULL; + } + os_strdup(node[i]->content,syscheck->ignore[ign_size]); + } + } + + /* Getting registry ignore list */ + else if(strcmp(node[i]->element,xml_registry_ignore) == 0) + { + #ifdef WIN32 + int ign_size = 0; + + /* Adding if regex */ + if(node[i]->attributes && node[i]->values) + { + if(node[i]->attributes[0] && node[i]->values[0] && + (strcmp(node[i]->attributes[0], "type") == 0) && + (strcmp(node[i]->values[0], "sregex") == 0)) + { + OSMatch *mt_pt; + + if(!syscheck->registry_ignore_regex) + { + os_calloc(2, sizeof(OSMatch *), + syscheck->registry_ignore_regex); + syscheck->registry_ignore_regex[0] = NULL; + syscheck->registry_ignore_regex[1] = NULL; + } + else + { + while(syscheck->registry_ignore_regex[ign_size] !=NULL) + ign_size++; + + os_realloc(syscheck->registry_ignore_regex, + sizeof(OSMatch *)*(ign_size +2), + syscheck->registry_ignore_regex); + syscheck->registry_ignore_regex[ign_size +1] = NULL; + } + + os_calloc(1, sizeof(OSMatch), + syscheck->registry_ignore_regex[ign_size]); + + if(!OSMatch_Compile(node[i]->content, + syscheck->registry_ignore_regex[ign_size], 0)) + { + mt_pt = (OSMatch *) + syscheck->registry_ignore_regex[ign_size]; + merror(REGEX_COMPILE, ARGV0, node[i]->content, + mt_pt->error); + return(0); + } + } + else + { + merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]); + return(OS_INVALID); + } + } + /* We do not add duplicated entries */ + else if(!os_IsStrOnArray(node[i]->content, + syscheck->registry_ignore)) + { + if(!syscheck->registry_ignore) + { + os_calloc(2, sizeof(char *), syscheck->registry_ignore); + syscheck->registry_ignore[0] = NULL; + syscheck->registry_ignore[1] = NULL; + } + else + { + while(syscheck->registry_ignore[ign_size] != NULL) + ign_size++; + + os_realloc(syscheck->registry_ignore, + sizeof(char *)*(ign_size +2), + syscheck->registry_ignore); + syscheck->registry_ignore[ign_size +1] = NULL; + } + os_strdup(node[i]->content,syscheck->registry_ignore[ign_size]); + } + #endif + } + else if(strcmp(node[i]->element,xml_auto_ignore) == 0) + { + /* auto_ignore is not read here. */ + } + else if(strcmp(node[i]->element,xml_alert_new_files) == 0) + { + /* alert_new_files option is not read here. */ + } + else + { + merror(XML_INVELEM, ARGV0, node[i]->element); + return(OS_INVALID); + } + i++; + } + + return(0); +} diff --git a/src/config/syscheck-config.h b/src/config/syscheck-config.h new file mode 100755 index 0000000..816ed11 --- /dev/null +++ b/src/config/syscheck-config.h @@ -0,0 +1,84 @@ +/* @(#) $Id: syscheck-config.h,v 1.20 2009/10/02 19:28:34 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __SYSCHECKC_H +#define __SYSCHECKC_H + + +#define MAX_DIR_SIZE 64 +#define MAX_DIR_ENTRY 128 +#define SYSCHECK_WAIT 300 + + +/* Checking options */ +#define CHECK_MD5SUM 0000001 +#define CHECK_PERM 0000002 +#define CHECK_SIZE 0000004 +#define CHECK_OWNER 0000010 +#define CHECK_GROUP 0000020 +#define CHECK_SHA1SUM 0000040 +#define CHECK_REALTIME 0000100 + + +#include +typedef struct _rtfim +{ + int fd; + void *dirtb; + #ifdef WIN32 + HANDLE evt; + #endif +}rtfim; + +typedef struct _config +{ + int tsleep; + int sleep_after; + int rootcheck; + int disabled; + int scan_on_start; + int realtime_count; + + int time; + int queue; + + int *opts; + + char *workdir; + char *remote_db; + char *db; + + char *scan_day; + char *scan_time; + + char **ignore; + void **ignore_regex; + + char **dir; + + /* Windows only registry checking */ + #ifdef WIN32 + char **registry_ignore; + void **registry_ignore_regex; + char **registry; + FILE *reg_fp; + #endif + + FILE *fp; + + rtfim *realtime; + +}config; + +#endif + +/* EOF */ diff --git a/src/error_messages/error_messages.h b/src/error_messages/error_messages.h new file mode 100755 index 0000000..d1e0ab7 --- /dev/null +++ b/src/error_messages/error_messages.h @@ -0,0 +1,313 @@ +/* @(#) $Id: error_messages.h,v 1.88 2009/06/24 17:06:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of OSSEC HIDS ( http://www.ossec.net ) + * Error/debug messages + */ + + +#ifndef _ERROR_MESSAGES__H + +#define _ERROR_MESSAGES__H + + + /*** Error messages - English ***/ + + +/* SYSTEM ERRORS */ +#define FORK_ERROR "%s(1101): ERROR: Unable to fork. Exiting." +#define MEM_ERROR "%s(1102): ERROR: Not enough Memory. Exiting." +#define FOPEN_ERROR "%s(1103): ERROR: Unable to open file '%s'." +#define SIZE_ERROR "%s(1104): ERROR: Maximum string size reached for: %s." +#define NULL_ERROR "%s(1105): ERROR: Attempted to use null string. " +#define FORMAT_ERROR "%s(1106): ERROR: String not correctly formated." +#define MKDIR_ERROR "%s(1107): ERROR: Unable to create directory: '%s'" +#define PERM_ERROR "%s(1108): ERROR: Permission error. Operation not completed." +#define THREAD_ERROR "%s(1109): ERROR: Unable to create new pthread." +#define READ_ERROR "%s(1110): ERROR: Unable to read from socket." +#define WAITPID_ERROR "%s(1111): ERROR: Unable to Waitpid()." +#define SETSID_ERROR "%s(1112): ERROR: Unable to Setsid()." +#define MUTEX_ERROR "%s(1113): ERROR: Unable to set pthread mutex." +#define SELECT_ERROR "%s(1114): ERROR: Unable to select()." +#define FREAD_ERROR "%s(1115): ERROR: Error reading file '%s'." +#define FSEEK_ERROR "%s(1116): ERROR: Error handling file '%s' (fseek)." +#define FILE_ERROR "%s(1117): ERROR: Error handling file '%s' (date)." +#define SYSTEM_ERROR "%s(1118): ERROR: Internal error. Exiting.." +#define FGETS_ERROR "%s(1119): ERROR: Invalid line on file '%s': %s." +#define PIPE_ERROR "%s(1120): ERROR: Pipe error." +#define GLOB_ERROR "%s(1121): ERROR: Glob error. Invalid pattern: '%s'." +#define GLOB_NFOUND "%s(1122): ERROR: No file found by pattern: '%s'." +#define UNLINK_ERROR "%s(1123): ERROR: Unable to delete file: '%s'." +#define RENAME_ERROR "%s(1124): ERROR: Unable to rename file: '%s'." +#define INT_ERROR "%s(1125): ERROR: Internal error (undefined)." + + +/* COMMON ERRORS */ +#define CONN_ERROR "%s(1201): ERROR: No remote connection configured." +#define CONFIG_ERROR "%s(1202): ERROR: Configuration error at '%s'. Exiting." +#define USER_ERROR "%s(1203): ERROR: Invalid user '%s' or group '%s' given." +#define CONNTYPE_ERROR "%s(1204): ERROR: Invalid connection type: '%s'." +#define PORT_ERROR "%s(1205): INFO: No port specified. Using default: '%d'." +#define BIND_ERROR "%s(1206): ERROR: Unable to Bind port '%d'" +#define SETGID_ERROR "%s(1207): ERROR: Unable to switch to group: '%s'." +#define SETUID_ERROR "%s(1208): ERROR: Unable to switch to user: '%s'." +#define CHROOT_ERROR "%s(1209): ERROR: Unable to chroot to directory: '%s'." +#define QUEUE_ERROR "%s(1210): ERROR: Queue '%s' not accessible: '%s'." +#define QUEUE_FATAL "%s(1211): ERROR: Unable to access queue: '%s'. Giving up.." +#define PID_ERROR "%s(1212): ERROR: Unable to create PID file." +#define DENYIP_WARN "%s(1213): WARN: Message from %s not allowed." +#define MSG_ERROR "%s(1214): WARN: Problem receiving message from %s." +#define CLIENT_ERROR "%s(1215): ERROR: No client configured. Exiting." +#define CONNS_ERROR "%s(1216): ERROR: Unable to connect to '%s'." +#define UNABLE_CONN "%s(1242): ERROR: Unable to connect to server. Exausted all options." +#define SEC_ERROR "%s(1217): ERROR: Error creating encrypted message." +#define SEND_ERROR "%s(1218): ERROR: Unable to send message to %s." +#define RULESLOAD_ERROR "%s(1219): ERROR: Unable to access the rules directory." +#define RULES_ERROR "%s(1220): ERROR: Error loading the rules: '%s'." +#define QUEUE_SEND "%s(1224): ERROR: Error sending message to queue." +#define SIGNAL_RECV "%s(1225): INFO: SIGNAL Received. Exit Cleaning..." +#define XML_ERROR "%s(1226): ERROR: Error reading XML file '%s': %s (line %d)." +#define XML_ERROR_VAR "%s(1227): ERROR: Error applying XML variables '%s': %s." +#define XML_NO_ELEM "%s(1228): ERROR: Element '%s' without any option." +#define XML_INVALID "%s(1229): ERROR: Invalid element '%s' on the '%s' config." +#define XML_INVELEM "%s(1230): ERROR: Invalid element in the configuration: '%s'." +#define XML_INVATTR "%s(1243): ERROR: Invalid attribute '%s' in the configuration: '%s'." +#define XML_ELEMNULL "%s(1231): ERROR: Invalid NULL element in the configuration." +#define XML_READ_ERROR "%s(1232): ERROR: Error reading XML. Unknown cause." +#define XML_VALUENULL "%s(1234): ERROR: Invalid NULL content for element: %s." +#define XML_VALUEERR "%s(1235): ERROR: Invalid value for element '%s': %s." +#define XML_MAXREACHED "%s(1236): ERROR: Maximum number of elements reached for: %s." +#define INVALID_IP "%s(1237): ERROR: Invalid ip address: '%s'." +#define INVALID_ELEMENT "%s(1238): ERROR: Invalid value for element '%s': %s" +#define NO_CONFIG "%s(1239): ERROR: Configuration file not found: '%s'." +#define INVALID_TIME "%s(1240): ERROR: Invalid time format: '%s'." +#define INVALID_DAY "%s(1241): ERROR: Invalid day format: '%s'." + +#define MAILQ_ERROR "%s(1221): ERROR: No Mail queue at %s" +#define IMSG_ERROR "%s(1222): ERROR: Invalid msg: %s" +#define SNDMAIL_ERROR "%s(1223): ERROR: Error Sending email to %s (smtp server)" +#define XML_INV_GRAN_MAIL "%s(1224): ERROR: Invalid 'email_alerts' config (missing parameters)." + + +/* rootcheck */ +#define MAX_RK_MSG "%s(1250): ERROR: Maximum number of global files reached: %d" +#define INVALID_RKCL_NAME "%s(1251): ERROR: Invalid rk configuration name: '%s'." +#define INVALID_RKCL_VALUE "%s(1252): ERROR: Invalid rk configuration value: '%s'." +#define INVALID_ROOTDIR "%s(1253): ERROR: Invalid rootdir (unable to retrieve)." +#define INVALID_RKCL_VAR "%s(1254): ERROR: Invalid rk variable: '%s'." + + +/* syscheck */ +#define SYSCHECK_NO_OPT "%s(1701): WARN: No option provided for directories: '%s', ignoring it." +#define SK_NO_DIR "%s(1702): INFO: No directory provided for syscheck to monitor." +#define SK_INV_ATTR "%s(1703): ERROR: Invalid attribute '%s' for directory option." +#define SK_INV_OPT "%s(1704): ERROR: Invalid option '%s' for attribute '%s'" +#define SK_NO_DB "%s(1705): ERROR: No integrity database found at '%s'." +#define SK_INV_MSG "%s(1755): ERROR: Invalid syscheck message received." +#define SK_DUP "%s(1756): ERROR: Duplicated directory given: '%s'." +#define SK_INV_REG "%s(1757): ERROR: Invalid syscheck registry entry: '%s'." +#define SK_REG_OPEN "%s(1758): ERROR: Unable to open registry key: '%s'." + + +/* Analysisd */ +#define FTS_LIST_ERROR "%s(1260): ERROR: Error initiating FTS list" +#define CRAFTED_IP "%s(1271): WARN: Invalid IP Address '%s'. Possible logging attack." +#define CRAFTED_USER "%s(1272): WARN: Invalid username '%s'. Possible logging attack." +#define INVALID_CAT "%s(1273): ERROR: Invalid category '%s' chosen." +#define INVALID_CONFIG "%s(1274): ERROR: Invalid configuration. Element '%s': %s." +#define INVALID_HOSTNAME "%s(1275): ERROR: Invalid hostname in syslog message: '%s'." + + +/* Log collector */ + + +/* Remoted */ +#define NO_REM_CONN "%s(1750): ERROR: No remote connection configured. Exiting." + + +/* 1760 - 1769 -- reserver for maild */ + + +/* Active response */ +#define AR_CMD_MISS "%s(1280): ERROR: Missing command options. " \ + "You must specify a 'name', 'executable' and 'expect'." +#define AR_MISS "%s(1281): ERROR: Missing options in the active response " \ + "configuration. " +#define ARQ_ERROR "%s(1301): ERROR: Unable to connect to active response queue." +#define AR_INV_LOC "%s(1302): ERROR: Invalid active response location: '%s'." +#define AR_INV_CMD "%s(1303): ERROR: Invalid command '%s' in the active response." +#define AR_DEF_AGENT "%s(1304): ERROR: No agent defined for response." +#define AR_NO_TIMEOUT "%s(1305): ERROR: Timeout not allowed for command: '%s'." + + +#define EXECD_INV_MSG "%s(1310): WARN: Invalid active response (execd) message '%s'." +#define EXEC_INV_NAME "%s(1311): ERROR: Invalid command name '%s' provided." +#define EXEC_CMDERROR "%s(1312): ERROR: Error executing '%s': %s" +#define EXEC_INV_CONF "%s(1313): ERROR: Invalid active response config: '%s'." +#define EXEC_DISABLED "%s(1350): INFO: Active response disabled. Exiting." +#define EXEC_SHUTDOWN "%s(1314): INFO: Shutdown received. Deleting responses." + +#define AR_NOAGENT_ERROR "%s(1320): ERROR: Agent '%s' not found." + + +/* List operations */ +#define LIST_ERROR "%s(1290): ERROR: Unable to create a new list (calloc)." +#define LIST_ADD_ERROR "%s(1291): ERROR: Error adding nodes to list." +#define LIST_SIZE_ERROR "%s(1292): ERROR: Error setting error size." +#define LIST_FREE_ERROR "%s(1293): ERROR: Error setting data free pointer." + + +/* Log collector messages */ +#define MISS_LOG_FORMAT "%s(1901): ERROR: Missing 'log_format' element." +#define MISS_FILE "%s(1902): ERROR: Missing 'location' element." +#define INV_EVTLOG "%s(1903): ERROR: Invalid event log: '%s'." +#define NSTD_EVTLOG "%s(1907): INFO: Non-standard event log set: '%s'." +#define LOGC_FILE_ERROR "%s(1904): INFO: File not available, ignoring it: '%s'." +#define NO_FILE "%s(1905): INFO: No file configured to monitor." +#define PARSE_ERROR "%s(1906): ERROR: Error parsing file: '%s'." +#define READING_FILE "%s(1950): INFO: Analyzing file: '%s'." +#define READING_EVTLOG "%s(1951): INFO: Analyzing event log: '%s'." +#define VAR_LOG_MON "%s(1952): INFO: Monitoring variable log file: '%s'." +#define INV_MULTILOG "%s(1953): ERROR: Invalid DJB multilog file: '%s'." + + +/* Encryption/ auth errors */ +#define INVALID_KEY "%s(1401): ERROR: Error reading authentication key: '%s'." +#define NO_AUTHFILE "%s(1402): ERROR: Authentication key file '%s' not found." +#define ENCFORMAT_ERROR "%s(1403): ERROR: Incorrectly formated message from '%s'." +#define ENCKEY_ERROR "%s(1404): ERROR: Authentication error. Wrong key from '%s'." +#define ENCSIZE_ERROR "%s(1405): ERROR: Message size not valid: '%s'." +#define ENCSUM_ERROR "%s(1406): ERROR: Checksum mismatch on message from '%s'." +#define ENCTIME_ERROR "%s(1407): ERROR: Duplicated counter for '%s'." +#define ENC_IP_ERROR "%s(1408): ERROR: Invalid ID for the source ip: '%s'." +#define ENCFILE_CHANGED "%s(1409): INFO: Authentication file changed. Updating." +#define ENC_READ "%s(1410): INFO: Reading authentication keys file." + + +/* Regex errors */ +#define REGEX_COMPILE "%s(1450): ERROR: Syntax error on regex: '%s': %d." +#define REGEX_SUBS "%s(1451): ERROR: Missing sub_strings on regex: '%s'." + + +/* Mail errors */ +#define INVALID_SMTP "%s(1501): ERROR: Invalid SMTP Server: %s" +#define INVALID_MAIL "%s(1502): ERROR: Invalid Email Address: %s" + + +/* Decoders */ +#define PPLUGIN_INV "%s(2101): ERROR: Parent decoder name invalid: '%s'." +#define PDUP_INV "%s(2102): ERROR: Duplicated decoder with prematch: '%s'." +#define PDUPFTS_INV "%s(2103): ERROR: Duplicated decoder with fts set: '%s'." +#define DUP_INV "%s(2104): ERROR: Invalid duplicated decoder: '%s'." +#define DEC_PLUGIN_ERR "%s(2105): ERROR: Error loading decoder options." +#define DECODER_ERROR "%s(2106): ERROR: Error adding decoder plugin." +#define DEC_REGEX_ERROR "%s(2107): ERROR: Decoder configuration error: '%s'." +#define DECODE_NOPRE "%s(2108): ERROR: No 'prematch' found in decoder: '%s'." +#define DUP_REGEX "%s(2109): ERROR: Duplicated offsets for same regex: '%s'." +#define INV_DECOPTION "%s(2110): ERROR: Invalid decoder argument for %s: '%s'." +#define DECODE_ADD "%s(2111): ERROR: Additional data to plugin decoder: '%s'." + +#define INV_OFFSET "%s(2120): ERROR: Invalid offset value: '%s'" +#define INV_ATTR "%s(2121): ERROR: Invalid decoder attribute: '%s'" + + +/* os_zlib */ +#define COMPRESS_ERR "%s(2201): ERROR: Error compressing string: '%s'." +#define UNCOMPRESS_ERR "%s(2202): ERROR: Error uncompressing string." + + +/* read defines */ +#define DEF_NOT_FOUND "%s(2301): ERROR: Definition not found for: '%s.%s'." +#define INV_DEF "%s(2302): ERROR: Invalid definition for %s.%s: '%s'." + + +/* Agent errors */ +#define AG_WAIT_SERVER "%s(4101): WARN: Waiting for server reply (not started). Tried: '%s'." +#define AG_CONNECTED "%s(4102): INFO: Connected to the server (%s:%d)." +#define AG_USINGIP "%s(4103): INFO: Server IP address already set. Trying that before the hostname." +#define AG_INV_HOST "%s(4104): ERROR: Invalid hostname: '%s'." +#define AG_INV_IP "%s(4105): ERROR: No valid server IP found." +#define EVTLOG_OPEN "%s(4106): ERROR: Unable to open event log: '%s'." +#define EVTLOG_GETLAST "%s(4107): ERROR: Unable to query last event log from: '%s'." +#define EVTLOG_DUP "%s(4108): ERROR: Duplicated event log entry: '%s'." +#define AG_NOKEYS_EXIT "%s(4109): ERROR: Unable to start without auth keys. Exiting." +#define AG_MAX_ERROR "%s(4110): ERROR: Maximum number of agents '%d' reached." +#define AG_AX_AGENTS "%s(4111): INFO: Maximum number of agents allowed: '%d'." + + +/* Rules reading errors */ +#define RL_INV_ROOT "%s(5101): ERROR: Invalid root element: '%s'." +#define RL_INV_RULE "%s(5102): ERROR: Invalid rule element: '%s'." +#define RL_INV_ENTRY "%s(5103): ERROR: Invalid rule on '%s'. Missing id/level." +#define RL_EMPTY_ATTR "%s(5104): ERROR: Rule attribute '%s' empty." +#define RL_INV_ATTR "%s(5105): ERROR: Invalid rule attributes inside file: '%s'." +#define RL_NO_OPT "%s(5106): ERROR: Rule '%d' without any options. "\ + "It may lead to false positives. Exiting. " + + +/* Syslog output */ +#define XML_INV_CSYSLOG "%s(5301): ERROR: Invalid client-syslog configuration." + + +/* Agentless */ +#define XML_INV_AGENTLESS "%s(7101): ERROR: Invalid agentless configuration." +#define XML_INV_MISSFREQ "%s(7102): ERROR: Frequency not set for the periodic option." +#define XML_INV_MISSOPTS "%s(7103): ERROR: Missing agentless options." + + +/* Database messages */ +#define DBINIT_ERROR "%s(5201): ERROR: Error initializing database handler." +#define DBCONN_ERROR "%s(5202): ERROR: Error connecting to database '%s'(%s): ERROR: %s." +#define DBQUERY_ERROR "%s(5203): ERROR: Error executing query '%s'. Error: '%s'." +#define DB_GENERROR "%s(5204): ERROR: Database error. Unable to run query." +#define DB_MISS_CONFIG "%s(5205): ERROR: Missing database configuration. "\ + "It requires host, user, pass and database." +#define DB_CONFIGERR "%s(5206): ERROR: Database configuration error." +#define DB_COMPILED "%s(5207): ERROR: OSSEC not compiled with support for '%s'." +#define DB_MAINERROR "%s(5208): ERROR: Multiple database errors. Exiting." +#define DB_CLOSING "%s(5209): INFO: Closing connection to database." +#define DB_ATTEMPT "%s(5210): INFO: Attempting to reconnect to database." + + + +/* Verbose messages */ +#define STARTUP_MSG "%s: INFO: Started (pid: %d)." +#define PRIVSEP_MSG "%s: INFO: Chrooted to directory: %s, using user: %s" +#define MSG_SOCKET_SIZE "%s: INFO: (unix_domain) Maximum send buffer set to: '%d'." + +#define NO_SYSLOG "%s(1501): ERROR: No IP or network allowed in the access list" \ + " for syslog. No reason for running it. Exiting." +#define CONN_TO "%s: INFO: Connected to '%s' (%s queue)" +#define MAIL_DIS "%s: INFO: E-Mail notification disabled. Clean Exit." + + +/* Debug Messages */ +#define STARTED_MSG "%s: DEBUG: Starting ..." +#define FOUND_USER "%s: DEBUG: Found user/group ..." +#define ASINIT "%s: DEBUG: Active response initialized ..." +#define READ_CONFIG "%s: DEBUG: Read configuration ..." + + +/* Wait operations */ +#define WAITING_MSG "%s: WARN: Process locked. Waiting for permission..." +#define WAITING_FREE "%s: INFO: Lock free. Continuing..." +#define SERVER_UNAV "%s: WARN: Server unavailable. Setting lock." +#define SERVER_UP "%s: INFO: Server responded. Releasing lock." + + +/* Ossec alert messages */ +#define OS_AD_STARTED "ossec: Ossec started." +#define OS_AG_STARTED "ossec: Agent started: '%s->%s'." +#define OS_AG_DISCON "ossec: Agent disconnected: '%s'." + + +#endif /* _ERROR_MESSAGES__H */ + diff --git a/src/external/zlib-1.2.3/COPYRIGHT b/src/external/zlib-1.2.3/COPYRIGHT new file mode 100755 index 0000000..e3841e4 --- /dev/null +++ b/src/external/zlib-1.2.3/COPYRIGHT @@ -0,0 +1,49 @@ +ZLIB DATA COMPRESSION LIBRARY + +*OSSEC note: + +-- Included on OSSEC to avoid problems with some old systems. +-- Not developed or changed in any way by OSSEC developers. +-- Copyright bellow. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + 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. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/src/external/zlib-1.2.3/Makefile b/src/external/zlib-1.2.3/Makefile new file mode 100755 index 0000000..9a860f2 --- /dev/null +++ b/src/external/zlib-1.2.3/Makefile @@ -0,0 +1,19 @@ +# Makefile for zlib. +# Daniel B. Cid +# http://www.ossec.net + +NAME=zlib +PT=../../ + +include ${PT}Config.Make + +shared: + ${CC} -c ${CFLAGS} ${SOURCES} + ar cru libz.a ${OBJECTS} + ranlib libz.a +clean: + ${CLEAN} ../../headers/zlib.h ../../headers/zconf.h ../libz.a + +ossec: + cp -pr zlib.h zconf.h ../../headers/ + cp -pr libz.a ../ diff --git a/src/external/zlib-1.2.3/README b/src/external/zlib-1.2.3/README new file mode 100755 index 0000000..758cc50 --- /dev/null +++ b/src/external/zlib-1.2.3/README @@ -0,0 +1,125 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.3 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install". For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.3 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + 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. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/src/external/zlib-1.2.3/adler32.c b/src/external/zlib-1.2.3/adler32.c new file mode 100755 index 0000000..66a70a8 --- /dev/null +++ b/src/external/zlib-1.2.3/adler32.c @@ -0,0 +1,149 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/06/13 16:50:58 dcid Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/src/external/zlib-1.2.3/algorithm.txt b/src/external/zlib-1.2.3/algorithm.txt new file mode 100755 index 0000000..b022dde --- /dev/null +++ b/src/external/zlib-1.2.3/algorithm.txt @@ -0,0 +1,209 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The key question is how to represent a Huffman code (or any prefix code) so +that you can decode fast. The most important characteristic is that shorter +codes are much more common than longer codes, so pay attention to decoding the +short codes fast, and let the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and then +to set that variable for the maximum speed. + +For inflate, which has 286 possible codes for the literal/length tree, the size +of the first table is nine bits. Also the distance trees have 30 possible +values, and the size of the first table is six bits. Note that for each of +those cases, the table ended up one bit longer than the ``average'' code +length, i.e. the code length of an approximately flat code which would be a +little more than eight bits for 286 symbols and a little less than five bits +for 30 symbols. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend two much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode as and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +http://www.ietf.org/rfc/rfc1951.txt diff --git a/src/external/zlib-1.2.3/compress.c b/src/external/zlib-1.2.3/compress.c new file mode 100755 index 0000000..c71d987 --- /dev/null +++ b/src/external/zlib-1.2.3/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.2 2006/08/11 14:49:04 dcid Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uInt)stream.avail_out != (uInt)*destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/src/external/zlib-1.2.3/crc32.c b/src/external/zlib-1.2.3/crc32.c new file mode 100755 index 0000000..d02c797 --- /dev/null +++ b/src/external/zlib-1.2.3/crc32.c @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/06/13 16:50:58 dcid Exp $ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/src/external/zlib-1.2.3/crc32.h b/src/external/zlib-1.2.3/crc32.h new file mode 100755 index 0000000..8053b61 --- /dev/null +++ b/src/external/zlib-1.2.3/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/src/external/zlib-1.2.3/deflate.c b/src/external/zlib-1.2.3/deflate.c new file mode 100755 index 0000000..bc23f1d --- /dev/null +++ b/src/external/zlib-1.2.3/deflate.c @@ -0,0 +1,1736 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/06/13 16:50:58 dcid Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/src/external/zlib-1.2.3/deflate.h b/src/external/zlib-1.2.3/deflate.h new file mode 100755 index 0000000..0cc7e6b --- /dev/null +++ b/src/external/zlib-1.2.3/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/06/13 16:50:58 dcid Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/src/external/zlib-1.2.3/gzio.c b/src/external/zlib-1.2.3/gzio.c new file mode 100755 index 0000000..025bc54 --- /dev/null +++ b/src/external/zlib-1.2.3/gzio.c @@ -0,0 +1,1034 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.2 2006/08/09 00:42:42 dcid Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int path_size; + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + path_size = strlen(path) +1; + + s->path = (char*)ALLOC(path_size +1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + s->path[path_size] = '\0'; + strncpy(s->path, path, path_size); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[46]; /* allow for up to 128-bit integers */ + + if (fd < 0) return (gzFile)Z_NULL; + name[45] = '\0'; + snprintf(name, 45, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + start++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + if (len == s->stream.avail_out && + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) + return -1; + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Returns 1 if reading and doing so transparently, otherwise zero. +*/ +int ZEXPORT gzdirect (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return 0; + return s->transparent; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + if (do_flush (file, Z_FINISH) != Z_OK) + return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +#ifdef STDC +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +/* =========================================================================== + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + int msg_size; + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + msg_size = strlen(s->path) + strlen(m) + 4; + + s->msg = (char*)ALLOC(msg_size +1); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + + s->msg[msg_size] = '\0'; + snprintf(s->msg, msg_size, "%s: %s", s->path, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/src/external/zlib-1.2.3/infback.c b/src/external/zlib-1.2.3/infback.c new file mode 100755 index 0000000..455dbc9 --- /dev/null +++ b/src/external/zlib-1.2.3/infback.c @@ -0,0 +1,623 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/src/external/zlib-1.2.3/inffast.c b/src/external/zlib-1.2.3/inffast.c new file mode 100755 index 0000000..bbee92e --- /dev/null +++ b/src/external/zlib-1.2.3/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/src/external/zlib-1.2.3/inffast.h b/src/external/zlib-1.2.3/inffast.h new file mode 100755 index 0000000..1e88d2d --- /dev/null +++ b/src/external/zlib-1.2.3/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/src/external/zlib-1.2.3/inffixed.h b/src/external/zlib-1.2.3/inffixed.h new file mode 100755 index 0000000..75ed4b5 --- /dev/null +++ b/src/external/zlib-1.2.3/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/src/external/zlib-1.2.3/inflate.c b/src/external/zlib-1.2.3/inflate.c new file mode 100755 index 0000000..792fdee --- /dev/null +++ b/src/external/zlib-1.2.3/inflate.c @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/src/external/zlib-1.2.3/inflate.h b/src/external/zlib-1.2.3/inflate.h new file mode 100755 index 0000000..07bd3e7 --- /dev/null +++ b/src/external/zlib-1.2.3/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/src/external/zlib-1.2.3/inftrees.c b/src/external/zlib-1.2.3/inftrees.c new file mode 100755 index 0000000..8a9c13f --- /dev/null +++ b/src/external/zlib-1.2.3/inftrees.c @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/src/external/zlib-1.2.3/inftrees.h b/src/external/zlib-1.2.3/inftrees.h new file mode 100755 index 0000000..b1104c8 --- /dev/null +++ b/src/external/zlib-1.2.3/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/src/external/zlib-1.2.3/trees.c b/src/external/zlib-1.2.3/trees.c new file mode 100755 index 0000000..1028562 --- /dev/null +++ b/src/external/zlib-1.2.3/trees.c @@ -0,0 +1,1219 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/06/13 16:50:59 dcid Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(s) + deflate_state *s; +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/src/external/zlib-1.2.3/trees.h b/src/external/zlib-1.2.3/trees.h new file mode 100755 index 0000000..72facf9 --- /dev/null +++ b/src/external/zlib-1.2.3/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/src/external/zlib-1.2.3/uncompr.c b/src/external/zlib-1.2.3/uncompr.c new file mode 100755 index 0000000..c6a290e --- /dev/null +++ b/src/external/zlib-1.2.3/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.2 2006/08/17 00:41:20 dcid Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uInt)stream.avail_in != (uInt)sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uInt)stream.avail_out != (uInt)*destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/src/external/zlib-1.2.3/zconf.h b/src/external/zlib-1.2.3/zconf.h new file mode 100755 index 0000000..2b25598 --- /dev/null +++ b/src/external/zlib-1.2.3/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/06/13 16:50:59 dcid Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/src/external/zlib-1.2.3/zconf.in.h b/src/external/zlib-1.2.3/zconf.in.h new file mode 100755 index 0000000..476550a --- /dev/null +++ b/src/external/zlib-1.2.3/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.in.h,v 1.1 2006/06/13 16:50:59 dcid Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/src/external/zlib-1.2.3/zlib.h b/src/external/zlib-1.2.3/zlib.h new file mode 100755 index 0000000..34a2d89 --- /dev/null +++ b/src/external/zlib-1.2.3/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + 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. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3-ossec" +#define ZLIB_VERNUM 0x1230f + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/src/external/zlib-1.2.3/zutil.c b/src/external/zlib-1.2.3/zutil.c new file mode 100755 index 0000000..2c43306 --- /dev/null +++ b/src/external/zlib-1.2.3/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/06/13 16:51:00 dcid Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/src/external/zlib-1.2.3/zutil.h b/src/external/zlib-1.2.3/zutil.h new file mode 100755 index 0000000..00ea89b --- /dev/null +++ b/src/external/zlib-1.2.3/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/06/13 16:51:00 dcid Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/src/headers/agent_op.h b/src/headers/agent_op.h new file mode 100755 index 0000000..9da70c2 --- /dev/null +++ b/src/headers/agent_op.h @@ -0,0 +1,62 @@ +/* @(#) $Id: agent_op.h,v 1.3 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __AGENT_OP_H +#define __AGENT_OP_H + + + +/** Checks if syscheck is to be executed/restarted. + * Returns 1 on success or 0 on failure (shouldn't be executed now). + */ +int os_check_restart_syscheck() ; + + +/** Sets syscheck to be restarted. + * Returns 1 on success or 0 on failure. + */ +int os_set_restart_syscheck(); + + +/** char *os_read_agent_name() + * Reads the agent name for the current agent. + * Returns NULL on error. + */ +char *os_read_agent_name(); + + +/** char *os_read_agent_ip() + * Reads the agent ip for the current agent. + * Returns NULL on error. + */ +char *os_read_agent_ip(); + + +/** char *os_read_agent_id() + * Reads the agent id for the current agent. + * Returns NULL on error. + */ +char *os_read_agent_id(); + + +/** int os_write_agent_info(char *agent_name, char *agent_ip, char *agent_id) + * Writes the agent info inside the queue, for the other processes to read. + * Returns 1 on success or <= 0 on failure. + */ +int os_write_agent_info(char *agent_name, char *agent_ip, char *agent_id); + + +int os_agent_config_changed(); + + +#endif +/* EOF */ diff --git a/src/headers/ar.h b/src/headers/ar.h new file mode 100755 index 0000000..6f950c3 --- /dev/null +++ b/src/headers/ar.h @@ -0,0 +1,48 @@ +/* @(#) $Id: ar.h,v 1.7 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Active response shared headers */ + +#ifndef __AR_H + +#define __AR_H + + +/* Recepient agents */ +#define ALL_AGENTS 0000001 +#define REMOTE_AGENT 0000002 +#define SPECIFIC_AGENT 0000004 +#define AS_ONLY 0000010 + +/* We now also support non active response messages in here. */ +#define NO_AR_MSG 0000020 + +#define ALL_AGENTS_C 'A' +#define REMOTE_AGENT_C 'R' +#define SPECIFIC_AGENT_C 'S' +#define NONE_C 'N' +#define NO_AR_C '!' + + +/* AR Queues to use */ +#define REMOTE_AR 00001 +#define LOCAL_AR 00002 + + +/* Expected values */ +#define SRCIP 0000004 +#define DSTIP 0000002 +#define USERNAME 0000001 + + +#endif + +/* EOF */ diff --git a/src/headers/debug_op.h b/src/headers/debug_op.h new file mode 100755 index 0000000..71e4920 --- /dev/null +++ b/src/headers/debug_op.h @@ -0,0 +1,66 @@ +/* @(#) $Id: debug_op.h,v 1.10 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net + */ + +/* Functions to generate debug/verbose/err reports. + * Right now, we have two debug levels: 1,2, + * a verbose mode and a error (merror) function. + * To see these messages, use the "-d","-v" options + * (or "-d" twice to see debug2). The merror is printed + * by default when an important error occur. + * */ + +#ifndef __DEBUG_H + +#define __DEBUG_H + +#ifndef __GNUC__ +#define __attribute__(x) +#endif + +void debug1(const char *msg,...) __attribute__((format(printf, 1, 2))); + +void debug2(const char *msg,...) __attribute__((format(printf, 1, 2))); + +void merror(const char *msg,...) __attribute__((format(printf, 1, 2))); + +void verbose(const char *msg,...) __attribute__((format(printf, 1, 2))); + +void print_out(const char *msg,...) __attribute__((format(printf, 1, 2))); + +void log2file(const char * msg,... ) __attribute__((format(printf, 1, 2))); + +void ErrorExit(const char *msg,...) __attribute__((format(printf, 1, 2))); + + +/* Use these three functions to set when you + * enter in debug, chroot or daemon mode + */ +void nowDebug(); + +void nowChroot(); + +void nowDaemon(); + +int isChroot(); + +/* Debug analysisd */ +#ifdef DEBUGAD + #define DEBUG_MSG(x,y,z) verbose(x,y,z) +#else + #define DEBUG_MSG(x,y,z) +#endif /* end debug analysisd */ + +#endif diff --git a/src/headers/defs.h b/src/headers/defs.h new file mode 100755 index 0000000..47a8d72 --- /dev/null +++ b/src/headers/defs.h @@ -0,0 +1,332 @@ +/* @(#) $Id: defs.h,v 1.77 2009/11/23 18:52:44 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +/* Global definitions + */ + +#ifndef __OS_HEADERS +#define __OS_HEADERS + + +/* Read / Write definitions + */ +#define READ 1 +#define WRITE 2 + + +/* Size limit control */ +#define OS_SIZE_8192 8192 +#define OS_SIZE_6144 6144 +#define OS_SIZE_4096 4096 +#define OS_SIZE_2048 2048 +#define OS_SIZE_1024 1024 +#define OS_SIZE_256 256 +#define OS_SIZE_128 128 + +#define OS_MAXSTR OS_SIZE_6144 /* Size for logs, sockets, etc */ +#define OS_BUFFER_SIZE OS_SIZE_2048 /* Size of general buffers */ +#define OS_FLSIZE OS_SIZE_256 /* Maximum file size */ +#define OS_HEADER_SIZE OS_SIZE_128 /* Maximum header size */ +#define OS_LOG_HEADER OS_SIZE_256 /* Maximum log header size */ +#define IPSIZE 16 /* IP Address size */ + + +/* Some Global names */ +#define __name "OSSEC HIDS" +#define __version "v2.3" +#define __author "Trend Micro Inc." +#define __contact "contact@ossec.net" +#define __site "http://www.ossec.net" +#define __license "\ +This program is free software; you can redistribute it and/or modify\n\ +it under the terms of the GNU General Public License (version 3) as \n\ +published by the Free Software Foundation. For more details, go to \n\ +http://www.ossec.net/main/license/\n" + +/* Maximum allowed PID */ +#ifdef SOLARIS + #define MAX_PID 29999 +#else + #define MAX_PID 32768 +#endif + + +/* Max limit of 256 agents */ +#ifndef MAX_AGENTS + #define MAX_AGENTS 256 +#endif + + +/* manager notification */ +#define NOTIFY_TIME 600 /* every 10 minutes */ + + +/* User Configuration */ +#ifndef MAILUSER + #define MAILUSER "ossecm" +#endif + +#ifndef USER + #define USER "ossec" +#endif + +#ifndef REMUSER + #define REMUSER "ossecr" +#endif + +#ifndef GROUPGLOBAL + #define GROUPGLOBAL "ossec" +#endif + +#ifndef DEFAULTDIR + #define DEFAULTDIR "/var/ossec" +#endif + + +/* Default queue */ +#define DEFAULTQUEUE "/queue/ossec/queue" + + +/* Active response files */ +#ifndef WIN32 + #define DEFAULTAR "/etc/shared/ar.conf" + #define AR_BINDIR "/active-response/bin" + #define AGENTCONFIGINT "/etc/shared/agent.conf" + #define AGENTCONFIG DEFAULTDIR "/etc/shared/agent.conf" +#else + #define DEFAULTAR "shared/ar.conf" + #define AR_BINDIR "active-response/bin" + #define AGENTCONFIG "shared/agent.conf" + #define AGENTCONFIGINT "shared/agent.conf" +#endif + + +/* Exec queue */ +#define EXECQUEUE "/queue/alerts/execq" + + +/* Active response queue */ +#define ARQUEUE "/queue/alerts/ar" + + +/* Decoder file */ +#define XML_DECODER "/etc/decoder.xml" +#define XML_LDECODER "/etc/local_decoder.xml" + + +/* Agent information location */ +#define AGENTINFO_DIR "/queue/agent-info" + + +/* Syscheck directory */ +#define SYSCHECK_DIR "/queue/syscheck" + +/* Rootcheck directory */ +#define ROOTCHECK_DIR "/queue/rootcheck" + +/* Diff queue */ +#define DIFF_DIR "/queue/diff" +#define DIFF_DIR_PATH DEFAULTDIR DIFF_DIR +#define DIFF_NEW_FILE "new-entry" +#define DIFF_LAST_FILE "last-entry" + + +/* Syscheck data */ +#define SYSCHECK "syscheck" +#define SYSCHECK_REG "syscheck-registry" + + +/* Rule path */ +#define RULEPATH "/rules" + + +/* Wait file */ +#ifndef WIN32 + #define WAIT_FILE "/queue/ossec/.wait" +#else + #define WAIT_FILE ".wait" +#endif + + +/* Agent information file */ +#ifndef WIN32 + #define AGENT_INFO_FILE "/queue/ossec/.agent_info" + #define AGENT_INFO_FILEP DEFAULTDIR AGENT_INFO_FILE +#else + #define AGENT_INFO_FILE ".agent_info" + #define AGENT_INFO_FILEP AGENT_INFO_FILE +#endif + + +/* Syscheck restart */ +#ifndef WIN32 + #define SYSCHECK_RESTART "/var/run/.syscheck_run" + #define SYSCHECK_RESTART_PATH DEFAULTDIR SYSCHECK_RESTART +#else + #define SYSCHECK_RESTART "syscheck/.syscheck_run" + #define SYSCHECK_RESTART_PATH "syscheck/.syscheck_run" +#endif + + +/* Agentless directories. */ +#define AGENTLESSDIR "/agentless" +#define AGENTLESSPASS "/agentless/.passlist" +#define AGENTLESS_ENTRYDIR "/queue/agentless" + + +/* Internal definitions files */ +#ifndef WIN32 + #define OSSEC_DEFINES "/etc/internal_options.conf" + #define OSSEC_LDEFINES "/etc/local_internal_options.conf" +#else + #define OSSEC_DEFINES "internal_options.conf" + #define OSSEC_LDEFINES "local_internal_options.conf" +#endif + + +/* Log directories */ +#define EVENTS "/logs/archives" +#define EVENTS_DAILY "/logs/archives/archives.log" +#define ALERTS "/logs/alerts" +#define ALERTS_DAILY "/logs/alerts/alerts.log" +#define FWLOGS "/logs/firewall" +#define FWLOGS_DAILY "/logs/firewall/firewall.log" + + +/* Stats directories */ +#define STATWQUEUE "/stats/weekly-average" +#define STATQUEUE "/stats/hourly-average" +#define STATSAVED "/stats/totals" + + +/* Authentication keys file */ +#ifndef WIN32 +#define KEYS_FILE "/etc/client.keys" +#define KEYSFILE_PATH DEFAULTDIR KEYS_FILE +#else +#define KEYS_FILE "client.keys" +#define KEYSFILE_PATH KEYS_FILE +#endif + +#ifndef AUTH_FILE +#define AUTH_FILE KEYS_FILE +#endif + + +/* Shared config directory */ +#ifndef WIN32 + #define SHAREDCFG_DIR "/etc/shared" +#else + #define SHAREDCFG_DIR "shared" +#endif + +/* Built in defines */ +#define DEFAULTQPATH DEFAULTDIR DEFAULTQUEUE + +#ifndef WIN32 +#define OSSECCONF "/etc/ossec.conf" +#define DEFAULTCPATH DEFAULTDIR OSSECCONF +#else +#define OSSECCONF "ossec.conf" +#define DEFAULTCPATH "ossec.conf" +#endif + +#ifndef WIN32 + #define DEFAULTARPATH DEFAULTDIR DEFAULTAR + #define AR_BINDIRPATH DEFAULTDIR AR_BINDIR + #define AGENTLESSDIRPATH DEFAULTDIR AGENTLESSDIR + #define AGENTLESSPASSPATH DEFAULTDIR AGENTLESSPASS + #define AGENTLESS_ENTRYDIRPATH DEFAULTDIR AGENTLESS_ENTRYDIR +#else + #define DEFAULTARPATH "shared/ar.conf" + #define AR_BINDIRPATH "active-response/bin" + #define AGENTLESSDIRPATH AGENTLESSDIR + #define AGENTLESSPASSPATH AGENTLESSPASS + #define AGENTLESS_ENTRYDIRPATH AGENTLESS_ENTRYDIR +#endif +#define EXECQUEUEPATH DEFAULTDIR EXECQUEUE + +#ifdef WIN32 + #define SHAREDCFG_DIRPATH SHAREDCFG_DIR +#else + #define SHAREDCFG_DIRPATH DEFAULTDIR SHAREDCFG_DIR +#endif + +#define SHAREDCFG_FILE SHAREDCFG_DIR "/merged.mg" +#define SHAREDCFG_FILEPATH SHAREDCFG_DIRPATH "/merged.mg" +#define SHAREDCFG_FILENAME "merged.mg" + + +#define WAIT_FILE_PATH DEFAULTDIR WAIT_FILE + + +/* Default ports */ +#ifndef DEFAULT_SECURE + #define DEFAULT_SECURE 1514 /* Default encrypted */ +#endif + +#ifndef DEFAULT_SYSLOG + #define DEFAULT_SYSLOG 514 /* Default syslog port - udp */ +#endif + + + +/* Xml global elements */ +#ifndef xml_global +#define xml_global "global" +#endif + +#ifndef xml_alerts +#define xml_alerts "alerts" +#endif + +#ifndef xml_rules +#define xml_rules "rules" +#endif + +#ifndef xml_localfile +#define xml_localfile "localfile" +#endif + +#ifndef xml_remote +#define xml_remote "remote" +#endif + +#ifndef xml_client +#define xml_client "client" +#endif + +#ifndef xml_execd +#define xml_execd "execd" +#endif + +#ifndef xml_syscheck +#define xml_syscheck "syscheck" +#endif + +#ifndef xml_rootcheck +#define xml_rootcheck "rootcheck" +#endif + +#ifndef xml_command +#define xml_command "command" +#endif + +#ifndef xml_ar +#define xml_ar "active-response" +#endif + +#endif /* __OS_HEADERS */ diff --git a/src/headers/dirtree_op.h b/src/headers/dirtree_op.h new file mode 100755 index 0000000..50e9aed --- /dev/null +++ b/src/headers/dirtree_op.h @@ -0,0 +1,46 @@ +/* @(#) $Id: dirtree_op.h,v 1.3 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Common API for dealing with directory trees */ + + +#ifndef _OS_DIRTREE +#define _OS_DIRTREE + +typedef struct _OSTreeNode +{ + struct _OSTreeNode *next; + void *child; + + char *value; + void *data; +}OSTreeNode; + + +typedef struct _OSDirTree +{ + OSTreeNode *first_node; + OSTreeNode *last_node; +}OSDirTree; + + +OSDirTree *OSDirTree_Create(); +void OSDirTree_AddToTree(OSDirTree *tree, char *str, void *data, char sep); +void *OSDirTree_SearchTree(OSDirTree *tree, char *str, char sep); + + + +#endif + +/* EOF */ diff --git a/src/headers/file-queue.h b/src/headers/file-queue.h new file mode 100755 index 0000000..eabea60 --- /dev/null +++ b/src/headers/file-queue.h @@ -0,0 +1,42 @@ +/* @(#) $Id: file-queue.h,v 1.6 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef __CFQUEUE_H +#define __CFQUEUE_H + +#define MAX_FQUEUE 256 +#define FQ_TIMEOUT 5 + +/* File queue */ +typedef struct _file_queue +{ + int last_change; + int year; + int day; + int flags; + + char mon[4]; + char file_name[MAX_FQUEUE +1]; + + FILE *fp; + struct stat f_status; +}file_queue; + + +/*** Prototypes */ +#include "read-alert.h" +int Init_FileQueue(file_queue *fileq, struct tm *p, int flags); + +alert_data *Read_FileMon(file_queue *fileq, struct tm *p, int timeout); + +#endif diff --git a/src/headers/file_op.h b/src/headers/file_op.h new file mode 100755 index 0000000..921b46d --- /dev/null +++ b/src/headers/file_op.h @@ -0,0 +1,57 @@ +/* @(#) $Id: file_op.h,v 1.14 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net/hids/ + */ + +/* Functions to handle operation with files + */ + +#ifndef __FILE_H + +#define __FILE_H + +#define OS_PIDFILE "/var/run" + +/* Set the program name. Must be done before **anything** else */ +void OS_SetName(char *name); + +int File_DateofChange(char *file); + +int IsDir(char *file); + +int CreatePID(char *name, int pid); + +int DeletePID(char *name); + +int MergeFiles(char *finalpath, char **files); + +int MergeAppendFile(char *finalpath, char *files); + +int UnmergeFiles(char *finalpath, char *optdir); + +/* daemonize a process */ +void goDaemon(); + +/* daemonize a process without closing stdin/stdou/stderr */ +void goDaemonLight(); + +/* not really a file operation, but returns the uname */ +char *getuname(); + +/* Checks for vista. */ +#ifdef WIN32 +int checkVista(); +int isVista; +#endif + +#endif diff --git a/src/headers/hash_op.h b/src/headers/hash_op.h new file mode 100755 index 0000000..fd3d842 --- /dev/null +++ b/src/headers/hash_op.h @@ -0,0 +1,79 @@ +/* @(#) $Id: hash_op.h,v 1.4 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Common API for dealing with directory trees */ + + +#ifndef _OS_HASHOP +#define _OS_HASHOP + + +/* Node structure */ +typedef struct _OSHashNode +{ + struct _OSHashNode *next; + + void *key; + void *data; +}OSHashNode; + + +typedef struct _OSHash +{ + unsigned int rows; + unsigned int initial_seed; + unsigned int constant; + + OSHashNode **table; +}OSHash; + + + +/** Prototypes **/ + + +/** OSHash *OSHash_Create(); + * Creates and initializes hash. + */ +OSHash *OSHash_Create(); + + + +/** void *OSHash_Free(OSHash *self) + * Frees the memory used by the hash. + */ +void *OSHash_Free(OSHash *self); + + + +/** void OSHash_Add(OSHash *hash, char *key, void *data) + * Returns 0 on error. + * Returns 1 on duplicated key (not added) + * Returns 2 on success + * Key must not be NULL. + */ +int OSHash_Add(OSHash *hash, char *key, void *data); + + +/** void *OSHash_Get(OSHash *self, char *key) + * Returns NULL on error (key not found). + * Returns the key otherwise. + * Key must not be NULL. + */ +void *OSHash_Get(OSHash *self, char *key); + + +#endif + +/* EOF */ diff --git a/src/headers/help.h b/src/headers/help.h new file mode 100755 index 0000000..1312387 --- /dev/null +++ b/src/headers/help.h @@ -0,0 +1,21 @@ +/* @(#) $Id: help.h,v 1.7 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Help Function + */ + +#ifndef __HELP_H + +#define __HELP_H +void help(const char *); +void print_version(); + +#endif diff --git a/src/headers/list_op.h b/src/headers/list_op.h new file mode 100755 index 0000000..536e06c --- /dev/null +++ b/src/headers/list_op.h @@ -0,0 +1,58 @@ +/* @(#) $Id: list_op.h,v 1.12 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Common list API */ + + +#ifndef _OS_LIST +#define _OS_LIST + +typedef struct _OSListNode +{ + struct _OSListNode *next; + struct _OSListNode *prev; + void *data; +}OSListNode; + + +typedef struct _OSList +{ + OSListNode *first_node; + OSListNode *last_node; + OSListNode *cur_node; + + int currently_size; + int max_size; + + void (*free_data_function)(void *data); +}OSList; + + +OSList *OSList_Create(); + +int OSList_SetMaxSize(OSList *list, int max_size); +int OSList_SetFreeDataPointer(OSList *list, void *free_data_function); + +OSListNode *OSList_GetFirstNode(OSList *); +OSListNode *OSList_GetLastNode(OSList *); +OSListNode *OSList_GetPrevNode(OSList *); +OSListNode *OSList_GetNextNode(OSList *); +OSListNode *OSList_GetCurrentlyNode(OSList *list); + +void OSList_DeleteCurrentlyNode(OSList *list); +void OSList_DeleteThisNode(OSList *list, OSListNode *thisnode); +void OSList_DeleteOldestNode(OSList *list); + +int OSList_AddData(OSList *list, void *data); + +#endif + +/* EOF */ diff --git a/src/headers/math_op.h b/src/headers/math_op.h new file mode 100755 index 0000000..bfc460f --- /dev/null +++ b/src/headers/math_op.h @@ -0,0 +1,29 @@ +/* @(#) $Id: math_op.h,v 1.3 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef H_MATHOP_OS +#define H_MATHOP_OS + + +/** int os_getprime + * Get the first available prime after the provided value. + * Returns 0 on error. + */ +int os_getprime(int val); + + +#endif + +/* EOF */ diff --git a/src/headers/mem_op.h b/src/headers/mem_op.h new file mode 100755 index 0000000..7e2db48 --- /dev/null +++ b/src/headers/mem_op.h @@ -0,0 +1,23 @@ +/* @(#) $Id: mem_op.h,v 1.6 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __MEM_H + +#define __MEM_H + +#include "shared.h" + +void os_FreeArray(char *ch1, char **ch2); +int os_IsStrOnArray(char *str, char **array); +char *os_LoadString(char *at, char *str); + +#endif diff --git a/src/headers/mq_op.h b/src/headers/mq_op.h new file mode 100755 index 0000000..e4407c9 --- /dev/null +++ b/src/headers/mq_op.h @@ -0,0 +1,33 @@ +/* @(#) $Id: mq_op.h,v 1.10 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _MQ__H +#define _MQ__H + +/* Default queues */ +#define LOCALFILE_MQ '1' +#define SYSLOG_MQ '2' +#define HOSTINFO_MQ '3' +#define SECURE_MQ '4' +#define SYSCHECK_MQ '8' +#define ROOTCHECK_MQ '9' + +/* Queues for additional log types */ +#define MYSQL_MQ 'a' +#define POSTGRESQL_MQ 'b' + + +int StartMQ(char * key, short int type); + +int SendMSG(int queue, char * message, char *locmsg, char loc); + +#endif diff --git a/src/headers/os_err.h b/src/headers/os_err.h new file mode 100755 index 0000000..4f0e47d --- /dev/null +++ b/src/headers/os_err.h @@ -0,0 +1,35 @@ +/* @(#) $Id: os_err.h,v 1.7 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Basic err codes + * + */ + +#ifndef __OS_ERR /* Definition of the __OS_ERR */ +#define __OS_ERR + +#define OS_SUCCESS 0 /* Success */ +#define OS_INVALID -1 /* Invalid entry */ +#define OS_NOTFOUND -2 /* Entry not found */ +#define OS_FILERR -3 /* Error in the file */ +#define OS_SIZELIM -4 /* Size limit problem */ +#define OS_CFGERR -5 /* Configuration error */ +#define OS_SOCKTERR -6 /* Socket error */ +#define OS_MISVALUE -7 /* There are values missing */ +#define OS_CONNERR -8 /* Connection failed */ +#define OS_UNDEF -9 /* Uknown error */ +#define OS_MEMERR -10 /* Memory Error */ +#define OS_SOCKBUSY -11 /* Socket busy -- try again */ + +#define OS_ENDFILE -20 /* End of file */ +#define OS_FINISH -21 /* Finished this task */ + +#endif /* __OS_ERR */ diff --git a/src/headers/privsep_op.h b/src/headers/privsep_op.h new file mode 100755 index 0000000..b3e8683 --- /dev/null +++ b/src/headers/privsep_op.h @@ -0,0 +1,30 @@ +/* @(#) $Id: privsep_op.h,v 1.6 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Functions for privilege separation. + */ + +#ifndef __PRIV_H + +#define __PRIV_H +#include "shared.h" + +int Privsep_GetUser(char * name); + +int Privsep_GetGroup(char * name); + +int Privsep_SetUser(uid_t uid); + +int Privsep_SetGroup(gid_t gid); + +int Privsep_Chroot(char * path); + +#endif diff --git a/src/headers/pthreads_op.h b/src/headers/pthreads_op.h new file mode 100755 index 0000000..53cf4c4 --- /dev/null +++ b/src/headers/pthreads_op.h @@ -0,0 +1,20 @@ +/* @(#) $Id: pthreads_op.h,v 1.6 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef PTHREADS_OP_H +#define PTHREADS_OP_H + +#ifndef WIN32 +int CreateThread(void *function_pointer(void *data), void *data); +#endif + +#endif diff --git a/src/headers/rc.h b/src/headers/rc.h new file mode 100755 index 0000000..409aa1b --- /dev/null +++ b/src/headers/rc.h @@ -0,0 +1,52 @@ +/* @(#) $Id: rc.h,v 1.10 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Remote Control shared headers */ + +#ifndef __RC_H + +#define __RC_H + + +/* Global headers */ +#define CONTROL_HEADER "#!-" + +#define IsValidHeader(str) ((str[0] == '#') && \ + (str[1] == '!') && \ + (str[2] == '-') && \ + (str+=3) ) + + +/* Exec message */ +#define EXECD_HEADER "execd " + +/* File update message */ +#define FILE_UPDATE_HEADER "up file " + +/* File closing message */ +#define FILE_CLOSE_HEADER "close file " + +/* Agent startup */ +#define HC_STARTUP "agent startup " + +/* Agent startup ack */ +#define HC_ACK "agent ack " + +/* Syscheck database completed */ +#define HC_SK_DB_COMPLETED "syscheck-db-completed" + +/* Syscheck restart msg. */ +#define HC_SK_RESTART "syscheck restart" + + +#endif + +/* EOF */ diff --git a/src/headers/read-agents.h b/src/headers/read-agents.h new file mode 100755 index 0000000..d6e9547 --- /dev/null +++ b/src/headers/read-agents.h @@ -0,0 +1,97 @@ +/* @(#) $Id: read-agents.h,v 1.12 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef __CRAGENT_H +#define __CRAGENT_H + + +/* Unique key for each agent. */ +typedef struct _agent_info +{ + char *last_keepalive; + char *syscheck_time; + char *syscheck_endtime; + char *rootcheck_time; + char *rootcheck_endtime; + char *os; + char *version; +}agent_info; + + +/* Print syscheck db (of modified files). */ +int print_syscheck(char *sk_name, char *sk_ip, char *fname, int print_registry, + int all_files, int csv_output, int update_counter); + +/* Print rootcheck db. */ +int print_rootcheck(char *sk_name, char *sk_ip, char *fname, int resolved, + int csv_output, int show_last); + +/* Delete syscheck db */ +int delete_syscheck(char *sk_name, char *sk_ip, int full_delete); + +/* Delete rootcheck db. */ +int delete_rootcheck(char *sk_name, char *sk_ip, int full_delete); + +/* Delete agent information */ +int delete_agentinfo(char *name); + +/* Get all available agents */ +char **get_agents(int flag); + +/* Free the agent list */ +void free_agents(char **agent_list); + +/** char *print_agent_status(int status) + * Prints the text representation of the agent status. + */ +char *print_agent_status(int status); + +/** int get_agent_status(char *agent_name, char *agent_ip) + * Gets the status of an agent, based on the name/ip. + */ +int get_agent_status(char *agent_name, char *agent_ip); + +/** agent_info *get_agent_info(char *agent_name, char *agent_ip) + * Get information from an agent. + */ +agent_info *get_agent_info(char *agent_name, char *agent_ip); + + +/** int connect_to_remoted() + * Connects to remoted to be able to send messages to the agents. + * Returns the socket on success or -1 on failure. + */ +int connect_to_remoted(); + +/** int send_msg_to_agent(int socket, char *msg) + * Sends a message to an agent. + * returns -1 on error. + */ +int send_msg_to_agent(int msocket, char *msg, char *agt_id, char *exec); + + + + +#define GA_NOTACTIVE 2 +#define GA_ACTIVE 3 +#define GA_ALL 5 +#define GA_ALL_WSTATUS 7 + +/* Status */ +#define GA_STATUS_ACTIVE 12 +#define GA_STATUS_NACTIVE 13 +#define GA_STATUS_INV 14 + + + +#endif diff --git a/src/headers/read-alert.h b/src/headers/read-alert.h new file mode 100755 index 0000000..1455e08 --- /dev/null +++ b/src/headers/read-alert.h @@ -0,0 +1,42 @@ +/* @(#) $Id: read-alert.h,v 1.7 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef __CRALERT_H +#define __CRALERT_H + +#define CRALERT_MAIL_SET 0x001 +#define CRALERT_EXEC_SET 0x002 +#define CRALERT_READ_ALL 0x004 +#define CRALERT_FP_SET 0x010 + + +/* File queue */ +typedef struct _alert_data +{ + int rule; + int level; + char *date; + char *location; + char *comment; + char *group; + char *srcip; + char *user; + char **log; +}alert_data; + + +alert_data *GetAlertData(int flag, FILE *fp); +void FreeAlertData(alert_data *al_data); + + +#endif diff --git a/src/headers/regex_op.h b/src/headers/regex_op.h new file mode 100755 index 0000000..1c2cbf2 --- /dev/null +++ b/src/headers/regex_op.h @@ -0,0 +1,20 @@ +/* @(#) $Id: regex_op.h,v 1.6 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef OS_REGEX_OP_H +#define OS_REGEX_OP_H + +/* Posix regex pattern matching */ +int OS_PRegex(char *str, char *regex); + + +#endif diff --git a/src/headers/report_op.h b/src/headers/report_op.h new file mode 100755 index 0000000..41711cc --- /dev/null +++ b/src/headers/report_op.h @@ -0,0 +1,64 @@ +/* @(#) $Id: report_op.h,v 1.2 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __REPORT_OP_H +#define __REPORT_OP_H + + +#define REPORT_RELATED 1 +#define REPORT_FILTER 2 + + +#define REPORT_REL_USER 0x001 +#define REPORT_REL_SRCIP 0x002 +#define REPORT_REL_LEVEL 0x004 +#define REPORT_REL_RULE 0x010 +#define REPORT_REL_GROUP 0x020 +#define REPORT_REL_LOCATION 0x040 + + + +typedef struct _report_filter +{ + char *report_name; + + char *group; + char *rule; + char *level; + char *location; + + void *top_user; + void *top_srcip; + void *top_level; + void *top_rule; + void *top_group; + void *top_location; + + int related_user; + int related_srcip; + int related_level; + int related_rule; + int related_group; + int related_location; + +}report_filter; + + + + +int os_report_configfilter(char *filter_by, char *filter_value, + report_filter *r_filter, int arg_type); +void os_report_printtop(void *topstore, char *hname, int print_related); +void os_ReportdStart(report_filter *r_filter); + + +#endif diff --git a/src/headers/rules_op.h b/src/headers/rules_op.h new file mode 100755 index 0000000..3adc5c3 --- /dev/null +++ b/src/headers/rules_op.h @@ -0,0 +1,175 @@ +/* @(#) $Id: rules_op.h,v 1.3 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Common API for dealing with directory trees */ + + +#ifndef _OS_RULESOP_H +#define _OS_RULESOP_H + +#include "shared.h" + + +/* Event context - stored on a uint8 */ +#define SAME_USER 0x001 /* 1 */ +#define SAME_SRCIP 0x002 /* 2 */ +#define SAME_ID 0x004 /* 4 */ +#define SAME_LOCATION 0x008 /* 8 */ +#define DIFFERENT_URL 0x010 /* */ +#define SAME_SRCPORT 0x020 +#define SAME_DSTPORT 0x040 +#define NOT_SAME_USER 0xffe /* 0xfff - 0x001 */ +#define NOT_SAME_SRCIP 0xffd /* 0xfff - 0x002 */ +#define NOT_SAME_ID 0xffb /* 0xfff - 0x004 */ +#define NOT_SAME_AGENT 0xff7 /* 0xfff - 0x008 */ + + +/* Alert options - store on a uint8 */ +#define DO_FTS 0x001 +#define DO_MAILALERT 0x002 +#define DO_LOGALERT 0x004 +#define NO_ALERT 0x010 +#define DO_OVERWRITE 0x020 +#define DO_PACKETINFO 0x040 +#define DO_EXTRAINFO 0x100 +#define SAME_EXTRAINFO 0x200 + + +/** Types of events (from decoders) **/ +#define UNKNOWN 0 /* Unkown */ +#define SYSLOG 1 /* syslog messages */ +#define IDS 2 /* IDS alerts */ +#define FIREWALL 3 /* Firewall events */ +#define WEBLOG 7 /* Apache logs */ +#define SQUID 8 /* Squid logs */ +#define WINDOWS 9 /* Windows logs */ +#define HOST_INFO 10 /* Host information logs (from nmap or similar) */ +#define OSSEC_RL 11 /* Ossec rules */ + + +/* FTS allowed values */ +#define FTS_NAME 001000 +#define FTS_USER 002000 +#define FTS_DSTUSER 004000 +#define FTS_SRCIP 000100 +#define FTS_DSTIP 000200 +#define FTS_LOCATION 000400 +#define FTS_ID 000010 +#define FTS_DATA 000020 +#define FTS_SYSTEMNAME 000040 + + + + +typedef struct _RuleInfo +{ + int sigid; /* id attribute -- required*/ + int level; /* level attribute --required */ + int maxsize; + int frequency; + int timeframe; + + u_int8_t context; /* Not an user option */ + + int firedtimes; /* Not an user option */ + int time_ignored; /* Not an user option */ + int ignore_time; + int ignore; + int ckignore; + int group_prev_matched_sz; + + int __frequency; + char **last_events; + + + /* Not an option in the rule */ + u_int16_t alert_opts; + + /* Context options */ + u_int16_t context_opts; + + /* category */ + u_int8_t category; + + /* Decoded as */ + u_int16_t decoded_as; + + /* List of previously matched events */ + OSList *sid_prev_matched; + + /* Pointer to a list (points to sid_prev_matched of if_matched_sid */ + OSList *sid_search; + + /* List of previously matched events in this group. + * Every rule that has if_matched_group will have this + * list. Every rule that matches this group, it going to + * have a pointer to it (group_search). + */ + OSList **group_prev_matched; + + /* Pointer to group_prev_matched */ + OSList *group_search; + + /* Function pointer to the event_search. */ + void *(*event_search)(void *lf, void *rule); + + + char *group; + OSMatch *match; + OSRegex *regex; + + /* Policy-based rules */ + char *day_time; + char *week_day; + + os_ip **srcip; + os_ip **dstip; + OSMatch *srcport; + OSMatch *dstport; + OSMatch *user; + OSMatch *url; + OSMatch *id; + OSMatch *status; + OSMatch *hostname; + OSMatch *program_name; + OSMatch *extra_data; + char *action; + + char *comment; /* description in the xml */ + char *info; + char *cve; + + char *if_sid; + char *if_level; + char *if_group; + + OSRegex *if_matched_regex; + OSMatch *if_matched_group; + int if_matched_sid; + + void **ar; + +}RuleInfo; + + +/** Prototypes **/ +int OS_ReadXMLRules(char *rulefile, + void *(*ruleact_function)(RuleInfo *rule, void *data), + void *data); + + +#endif + + +/* EOF */ diff --git a/src/headers/sec.h b/src/headers/sec.h new file mode 100755 index 0000000..290cc3e --- /dev/null +++ b/src/headers/sec.h @@ -0,0 +1,122 @@ +/* @(#) $Id: sec.h,v 1.20 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __SEC_H +#define __SEC_H + + +/* Unique key for each agent. */ +typedef struct _keyentry +{ + unsigned int rcvd; + unsigned int local; + unsigned int keyid; + unsigned int global; + + char *id; + char *key; + char *name; + + os_ip *ip; + struct sockaddr_in peer_info; + FILE *fp; +}keyentry; + + +/* Key storage. */ +typedef struct _keystore +{ + /* Array with all the keys */ + keyentry **keyentries; + + + /* Hashes, based on the id/ip to lookup the keys. */ + void *keyhash_id; + void *keyhash_ip; + + + /* Total key size */ + int keysize; + + /* Key file stat */ + int file_change; +}keystore; + + + +/** Function prototypes -- key management **/ + +/* Checks if the authentication keys are present */ +int OS_CheckKeys(); + +/* Read the keys */ +void OS_ReadKeys(keystore *keys); + +/* Frees the auth keys. */ +void OS_FreeKeys(keystore *keys); + +/* Checks if key changed. */ +int OS_CheckUpdateKeys(keystore *keys); + +/* Update the keys if they changed on the system. */ +int OS_UpdateKeys(keystore *keys); + + +/* Starts counter for all agents */ +void OS_StartCounter(keystore *keys); + +/* Remove counter for id. */ +void OS_RemoveCounter(char *id); + + +/** Function prototypes -- agent authorization **/ + +/* Checks if the ip is allowed */ +int OS_IsAllowedIP(keystore *keys, char *srcip); + +/* Checks if the id is allowed */ +int OS_IsAllowedID(keystore *keys, char *id); + +/* Checks if name is valid */ +int OS_IsAllowedName(keystore *keys, char *name); + +/* Check if the id is valid and dynamic */ +int OS_IsAllowedDynamicID(keystore *keys, char *id, char *srcip); + + + +/** Function prototypes -- send/recv messages **/ + +/* Decrypt and decompress a remote message. */ +char *ReadSecMSG(keystore *keys, char *buffer, char *cleartext, + int id, int buffer_size); + +/* Creates an ossec message (encrypts and compress) */ +int CreateSecMSG(keystore *keys, char *msg, char *msg_encrypted, int id); + + + + +/** Remote IDs directories and internal definitions */ +#ifndef WIN32 + #define RIDS_DIR "/queue/rids" +#else + #define RIDS_DIR "rids" +#endif + +#define SENDER_COUNTER "sender_counter" +#define KEYSIZE 128 + + +#endif + +/* EOF */ diff --git a/src/headers/shared.h b/src/headers/shared.h new file mode 100755 index 0000000..d3e019b --- /dev/null +++ b/src/headers/shared.h @@ -0,0 +1,221 @@ +/* @(#) $Id: shared.h,v 1.47 2009/09/17 18:47:23 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* v0.3 (2007/12/23): Adding SSP & FORTIFY_SOURCE + * v0.2 (2005/12/23): Adding 'u_int16_t' for Solaris. + * v0.1 (2005/10/27): first version. + */ + +/* + * The stack smashing protector defeats some BoF via: gcc -fstack-protector + * Reference: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/cpp.pdf + */ + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1) && (__GNUC_PATCHLEVEL__ >= 2)) || \ + ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || \ + (__GNUC__ >= 5)) + +/* Heuristicly enable the stack protector on sensitive functions */ +#define __SSP__ 1 + +/* FORTIFY_SOURCE is Redhat / Fedora specific */ +#define FORTIFY_SOURCE +#endif + +#ifndef __SHARED_H + +#define __SHARED_H +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + + +/* Global headers */ +#include +#include +#include +#include + + +/* Making windows happy */ +#ifndef WIN32 +#include + +/* HPUX does not have select.h */ +#ifndef HPUX +#include +#endif + +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Making Windows happy */ +#ifndef WIN32 +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#endif + +#include +#include + +#include "defs.h" +#include "help.h" + +#include "os_err.h" + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + + +/* Global portability code */ + +#ifdef SOLARIS +#include +typedef uint32_t u_int32_t; +typedef uint16_t u_int16_t; +typedef uint8_t u_int8_t; + +#ifndef va_copy +#define va_copy __va_copy +#endif + +#endif /* SOLARIS */ + + +/* For HP-UX */ +#if defined HPUX +#include +typedef uint32_t u_int32_t; +typedef uint16_t u_int16_t; +typedef uint8_t u_int8_t; + +#define MSG_DONTWAIT 0 +#endif + + +/* For Darwin */ +#ifdef Darwin +typedef int sock2len_t; +#endif + +/* For Windows (so high maintenance :)) */ +#ifdef WIN32 +typedef int uid_t; +typedef int gid_t; +typedef int socklen_t; +#define sleep(x) Sleep(x * 1000) +#define srandom(x) srand(x) +#define random(x) rand(x) +#define lstat(x,y) stat(x,y) +void WinSetError(); +typedef unsigned short int u_int16_t; +typedef unsigned char u_int8_t; +/* typedef closesocket close; */ + +#define MSG_DONTWAIT 0 + +#ifndef PROCESSOR_ARCHITECTURE_AMD64 + #define PROCESSOR_ARCHITECTURE_AMD64 9 +#endif +#endif + +/* For AIX */ +#ifdef AIX +#define MSG_DONTWAIT MSG_NONBLOCK +#endif + + + +/* Local name */ +char *__local_name; + + +/*** Global prototypes ***/ +/*** These functions will exit on error. No need to check return code ***/ + +/* for calloc: x = calloc(4,sizeof(char)) -> os_calloc(4,sizeof(char),x) */ +#define os_calloc(x,y,z) (z = calloc(x,y))?(void)1:ErrorExit(MEM_ERROR, ARGV0) + +#define os_strdup(x,y) (y = strdup(x))?(void)1:ErrorExit(MEM_ERROR, ARGV0) + +#define os_malloc(x,y) (y = malloc(x))?(void)1:ErrorExit(MEM_ERROR, ARGV0) + +#define os_free(x) (x)?free(x):merror("free a null") + +#define os_realloc(x,y,z) (z = realloc(x,y))?(void)1:ErrorExit(MEM_ERROR, ARGV0) + +#define os_clearnl(x,p) if((p = strrchr(x, '\n')))*p = '\0'; + +#ifdef CLIENT + #define isAgent 1 +#else + #define isAgent 0 +#endif + + + +#include "debug_op.h" +#include "wait_op.h" +#include "agent_op.h" +#include "file_op.h" +#include "mem_op.h" +#include "math_op.h" +#include "mq_op.h" +#include "privsep_op.h" +#include "pthreads_op.h" +#include "regex_op.h" +#include "sig_op.h" +#include "list_op.h" +#include "dirtree_op.h" +#include "hash_op.h" +#include "store_op.h" +#include "rc.h" +#include "ar.h" +#include "validate_op.h" +#include "file-queue.h" +#include "read-agents.h" +#include "report_op.h" + +#include "os_xml/os_xml.h" +#include "os_regex/os_regex.h" + +#include "error_messages/error_messages.h" + + +#endif /* __SHARED_H */ + +/* EOF */ diff --git a/src/headers/sig_op.h b/src/headers/sig_op.h new file mode 100755 index 0000000..508fbb6 --- /dev/null +++ b/src/headers/sig_op.h @@ -0,0 +1,29 @@ +/* @(#) $Id: sig_op.h,v 1.6 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Functions to handle signal manipulation + */ + +#ifndef __SIG_H + +#define __SIG_H + +void HandleSIG(); +void HandleSIGPIPE(); + +/* Start signal manipulation */ +void StartSIG(char *process_name); + +/* Start signal manipulation -- function as an argument */ +void StartSIG2(char *process_name, void (*func)(int)); + +#endif diff --git a/src/headers/store_op.h b/src/headers/store_op.h new file mode 100755 index 0000000..73b6b17 --- /dev/null +++ b/src/headers/store_op.h @@ -0,0 +1,58 @@ +/* @(#) $Id: store_op.h,v 1.8 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Common list API */ + + +#ifndef _OS_STORE +#define _OS_STORE + +/* Store node */ +typedef struct _OSStoreNode +{ + struct _OSStoreNode *next; + struct _OSStoreNode *prev; + void *data; + char *key; + int key_size; +}OSStoreNode; + +/* Store list */ +typedef struct _OSStore +{ + OSStoreNode *first_node; + OSStoreNode *last_node; + OSStoreNode *cur_node; + + int currently_size; + int max_size; + + void (*free_data_function)(void *data); +}OSStore; + + +OSStore *OSStore_Create(); +OSStore *OSStore_Free(OSStore *list); + +int OSStore_Put(OSStore *list, char *key, void *data); +int OSStore_Check(OSStore *list, char *key); +int OSStore_NCheck(OSStore *list, char *key); +int OSStore_NCaseCheck(OSStore *list, char *key); +int OSStore_GetPosition(OSStore *list, char *key); +void *OSStore_Get(OSStore *list, char *key); +OSStoreNode *OSStore_GetFirstNode(OSStore *list); +int OSStore_Sort(OSStore *list, void*(sort_data_function)(void *d1, void *d2)); + + + +#endif + +/* EOF */ diff --git a/src/headers/validate_op.h b/src/headers/validate_op.h new file mode 100755 index 0000000..6aafdfe --- /dev/null +++ b/src/headers/validate_op.h @@ -0,0 +1,129 @@ +/* @(#) $Id: validate_op.h,v 1.13 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net + */ + + +#ifndef __VALIDATE_H + +#define __VALIDATE_H + +/* IP structure */ +typedef struct _os_ip +{ + char *ip; + unsigned int ip_address; + unsigned int netmask; +}os_ip; + + +/* Getting the netmask based on the integer value. */ +int getNetmask(int mask, char *strmask, int size); + + +/* Run time definitions. */ +int getDefine_Int(char *high_name, char *low_name, int min, int max); + + + +/** int OS_IPFound(char *ip_address, os_ip *that_ip) + * Checks if ip_address is present at that_ip. + * Returns 1 on success or 0 on failure. + */ +int OS_IPFound(char *ip_address, os_ip *that_ip); + + + +/** int OS_IPFoundList(char *ip_address, char **list_of_ips) + * Checks if ip_address is present on the "list_of_ips". + * Returns 1 on success or 0 on failure. + * The list MUST be NULL terminated + */ +int OS_IPFoundList(char *ip_address, os_ip **list_of_ips); + + + +/** int OS_IsValidIP(char *ip) + * Validates if an ip address is in the right + * format. + * Returns 0 if doesn't match or 1 if it does (or 2 if it has a cidr). + * ** On success this function may modify the value of ip_address + */ +int OS_IsValidIP(char *ip_address, os_ip *final_ip); + + +/** Time range validations **/ + +/** char *OS_IsValidTime(char *time_str) + * Validates if a time is in an acceptable format + * for ossec. + * Returns 0 if doesn't match or a valid string for + * ossec usage in success. + * ** On success this function may modify the value of date + * Acceptable formats: + * hh:mm - hh:mm (24 hour format) + * !hh:mm -hh:mm (24 hour format) + * hh - hh (24 hour format) + * hh:mm am - hh:mm pm (12 hour format) + * hh am - hh pm (12 hour format) + */ +char *OS_IsValidTime(char *time_str); + +/* Same as above, but only accepts a unique time, not a range. */ +char *OS_IsValidUniqueTime(char *time_str); + + + +/** int OS_IsonTime(char *time_str, char *ossec_time) + * Must be a valid string, called after OS_IsValidTime. + * Returns 1 on success or 0 on failure. + */ +int OS_IsonTime(char *time_str, char *ossec_time); + +/* Same as above, but checks if time is the same or has passed a specified one. */ +int OS_IsAfterTime(char *time_str, char *ossec_time); + + + +/** Day validations **/ + + +/** int OS_IsonDay(int week_day, char *ossec_day) + * Checks if the specified week day is in the + * range. + */ +int OS_IsonDay(int week_day, char *ossec_day); + + +/** char *OS_IsValidDay(char *day_str) + * Validates if an day is in an acceptable format + * for ossec. + * Returns 0 if doesn't match or a valid string for + * ossec usage in success. + * ** On success this function may modify the value of date + * Acceptable formats: + * weekdays, weekends, monday, tuesday, thursday,.. + * monday,tuesday + * mon,tue wed + */ +char *OS_IsValidDay(char *day_str); + + +/* Macros */ + +/* Checks if the ip is a single host, not a network with a netmask */ +#define isSingleHost(x) (x->netmask == 0xFFFFFFFF) + +#endif + +/* EOF */ diff --git a/src/headers/wait_op.h b/src/headers/wait_op.h new file mode 100755 index 0000000..315909f --- /dev/null +++ b/src/headers/wait_op.h @@ -0,0 +1,22 @@ +/* @(#) $Id: wait_op.h,v 1.4 2009/06/24 17:06:26 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#ifndef __WAIT_OP_H +#define __WAIT_OP_H + + +void os_setwait(); + +void os_delwait(); + +void os_wait(); + +#endif diff --git a/src/init/darwin-addusers.pl b/src/init/darwin-addusers.pl new file mode 100755 index 0000000..70bf744 --- /dev/null +++ b/src/init/darwin-addusers.pl @@ -0,0 +1,96 @@ +#!/usr/bin/env perl +####################################### +# Name: ossec-add-ung.pl +# Desc: Add ossec users and groups on OSX using the NetInfo cmds. +# Author: Chuck L. +# License: GPL +### +# for vi: set tabstop=4 +### +# Rev history: +# v0.1 - Initial coding. +# v0.2 - Modified script to use subroutines. It gets the job done, +# but more work required to add further functionality. -CL +# v0.2.1 - Modified the user add lines to have the users disabled +# from the start ('*' was missing in passwd field). -CL +####################################### + +# Variables and whatnot +my ($debug, $oUid, $oGid, @inUseUids, @inUseGids, $rev, $revDate); +$rev = '0.2-1'; +$revDate = '30-Aug-2006'; +$debug = '0'; +$fName = "/tmp/niusers.tmp"; + +# Commands +$NILOAD = "/usr/bin/niload"; +$NIRPT = "/usr/bin/nireport"; +$NIUTIL = "/usr/bin/niutil"; +$SORT = "/usr/bin/sort"; +$GREP = "/usr/bin/grep"; +$SUDO = "/usr/bin/sudo"; + +# Subroutine calls +findUsersGroups(); +createUsersGroups(); + +####################################### +####################################### +# Subroutines +####################################### +sub findUsersGroups { + @inUseUids = `$NIRPT . /users uid | $GREP "^5[0-9][0-9]" | $SORT -ru`; + @inUseGids = `$NIRPT . /groups gid | $GREP "^5[0-9][0-9]" | $SORT -ru`; + + foreach (@inUseUids) { + chomp(); + print "In use UID: $_\n" if $debug; + if ($oUid < $_) { + $oUid = $_; + } + } + $oUid++; + print "Next available UID: $oUid\n" if $debug; + + foreach (@inUseGids) { + chomp(); + print "In use GID: $_\n" if $debug; + if ($oGid < $_) { + $oGid = $_; + } + } + $oGid++; + print "Next available GID: $oGid\n" if $debug; +} # end sub + +sub createUsersGroups { + print "Sub - UID is: $oUid\n" if $debug; + print "Sub - GID is: $oGid\n" if $debug; + + my $oUidM = $oUid + 1; + my $oUidE = $oUid + 2; + my $oUidR = $oUid + 3; + + $niPid = open (NIFH, "| $SUDO $NILOAD -v group /"); + print "Adding ossec group\n" if $debug; + print NIFH "ossec:*:" . $oGid . ":ossec,ossecm,ossecr\n"; + close (NIFH); + + $fh = open (NITMP, ">$fName") or die "Unable to create temp file: $!\n"; + + print "Adding ossec users\n" if $debug; + print NITMP "ossec:*:" . $oUid . ":" . $oGid . "::0:0:ossec acct:/var/ossec:/sbin/nologin\n"; + print NITMP "ossecm:*:" . $oUidM . ":" . $oGid . "::0:0:ossecm acct:/var/ossec:/sbin/nologin\n"; + print NITMP "ossecr:*:" . $oUidR . ":" . $oGid . "::0:0:ossecr acct:/var/ossec:/sbin/nologin\n"; + + close ($fh); + $rtnVal = system("$SUDO $NILOAD -v passwd / < $fName"); + print "Return value from syscmd: $rtnVal\n" if $debug; + unlink ($fName); + +} # end sub + +################# +# End program +################# + diff --git a/src/init/darwin-init.sh b/src/init/darwin-init.sh new file mode 100755 index 0000000..2641786 --- /dev/null +++ b/src/init/darwin-init.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# Darwin init script. +# by Lorenzo Costanzia di Costigliole + +mkdir -p /Library/StartupItems/OSSEC +cat </Library/StartupItems/OSSEC/StartupParameters.plist + + + + + Description + OSSEC Host-based Intrusion Detection System + Messages + + start + Starting OSSEC + stop + Stopping OSSEC + + Provides + + OSSEC + + Requires + + IPFilter + + + +EOF + +cat </Library/StartupItems/OSSEC/OSSEC +#!/bin/sh + +. /etc/rc.common +. /etc/ossec-init.conf +if [ "X\${DIRECTORY}" = "X" ]; then + DIRECTORY="/var/ossec" +fi + + +StartService () +{ + \${DIRECTORY}/bin/ossec-control start +} + +StopService () +{ + \${DIRECTORY}/bin/ossec-control stop +} + +RestartService () +{ + \${DIRECTORY}/bin/ossec-control restart +} + +RunService "\$1" +EOF +chmod 755 /Library/StartupItems/OSSEC +chmod 644 /Library/StartupItems/OSSEC/StartupParameters.plist +chmod 755 /Library/StartupItems/OSSEC/OSSEC diff --git a/src/init/functions.sh b/src/init/functions.sh new file mode 100755 index 0000000..d531dc2 --- /dev/null +++ b/src/init/functions.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Shell script functions for the OSSEC HIDS +# Author: Daniel B. Cid +# Last modification: Mar 02, 2006 + + +TRUE="true"; +FALSE="false"; + + +########## +# isFile +########## +isFile() +{ + FILE=$1 + ls ${FILE} >/dev/null 2>&1 + if [ $? = 0 ]; then + echo "${TRUE}" + return 0; + fi + echo "${FALSE}" + return 1; +} + + diff --git a/src/init/fw-check.sh b/src/init/fw-check.sh new file mode 100755 index 0000000..c8fde4c --- /dev/null +++ b/src/init/fw-check.sh @@ -0,0 +1,48 @@ +#!/bin/sh + + +# Checking which firewall to use. +UNAME=`uname` +FILE=""; +EXECUTE="$1"; + +if [ "X${UNAME}" = "XFreeBSD" ]; then + # Is ipfw enabled? + grep 'firewall_enable="YES"' /etc/rc.conf >/dev/null 2>&1 + if [ $? = 0 ]; then + # Firewall is IPFW + FILE="ipfw.sh"; + echo "IPFW"; + fi + + # if pf enabled? + grep 'pf_enable="YES"' /etc/rc.conf >/dev/null 2>&1 + if [ $? = 0 ]; then + # Firewall is PF + FILE="pf.sh"; + echo "PF"; + fi + +# Darwin +elif [ "X${UNAME}" = "Darwin" ]; then + echo "IPFW"; + FILE="ipfw_mac.sh"; + +elif [ "X${UNAME}" = "XOpenBSD" ]; then + if [ $? = 0 ]; then + # Firewall is PF + FILE="pf.sh"; + echo "PF"; + fi +fi + + +# If file is set and execute flag is set +if [ ! "X$FILE" = "X" ]; then + if [ "X$EXECUTE" = "Xexecute" ]; then + cp -pr ../active-response/firewall-drop.sh ../active-response/firewalls/default-firewall-drop.sh + cp -pr ../active-response/firewalls/$FILE ../active-response/firewall-drop.sh + fi +fi + +exit 0; diff --git a/src/init/init.sh b/src/init/init.sh new file mode 100755 index 0000000..7be15f2 --- /dev/null +++ b/src/init/init.sh @@ -0,0 +1,148 @@ +#!/bin/sh +# Init functions for the OSSEC HIDS +# v0.3 +# Author: Daniel B. Cid +# Last modification: May 04, 2006 (by Kayvan A. Sylvan ) +# v0,2: Mar 03, 2006 +# v0.1: Jan 01, 2005 + +UN=${NUNAME}; + +runInit() +{ + echo "" + echo "" + # Checking if it is a Redhat system. + if [ -r "/etc/redhat-release" ]; then + if [ -d /etc/rc.d/init.d ]; then + echo " - ${systemis} Redhat Linux." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids-rh.init /etc/rc.d/init.d/ossec + chmod 555 /etc/rc.d/init.d/ossec + chown root:ossec /etc/rc.d/init.d/ossec + /sbin/chkconfig --add ossec > /dev/null 2>&1 + return 0; + fi + fi + # Checking for Gentoo + if [ -r "/etc/gentoo-release" ]; then + echo " - ${systemis} Gentoo Linux." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids-gentoo.init /etc/init.d/ossec + chmod 555 /etc/init.d/ossec + chown root:ossec /etc/init.d/ossec + rc-update add ossec default + return 0; + fi + + # Suse + if [ -r "/etc/SuSE-release" ]; then + echo " - ${systemis} Suse Linux." + echo " - ${modifiedinit}" + + cp -pr ./src/init/ossec-hids-suse.init /etc/init.d/ossec + chmod 555 /etc/init.d/ossec + chown root:ossec /etc/init.d/ossec + + /sbin/chkconfig --add ossec > /dev/null 2>&1 + return 0; + fi + + # Checking for slackware (by Jack S. Lai) + if [ -r "/etc/slackware-version" ]; then + echo " - ${systemis} Slackware Linux." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids.init /etc/rc.d/rc.ossec + chmod 555 /etc/rc.d/rc.ossec + chown root:ossec /etc/rc.d/rc.ossec + + grep ossec /etc/rc.d/rc.local > /dev/null 2>&1 + if [ $? != 0 ]; then + echo "if [ -x /etc/rc.d/rc.ossec ]; then" >> /etc/rc.d/rc.local + echo " /etc/rc.d/rc.ossec start" >>/etc/rc.d/rc.local + echo "fi" >>/etc/rc.d/rc.local + fi + + return 0; + fi + + # Darwin init script (by Lorenzo Costanzia di Costigliole ) + if [ "X${NUNAME}" = "XDarwin" ]; then + # Generating darwin init script. + + echo " - ${systemis} Darwin." + echo " - ${modifiedinit}" + sh ./src/init/darwin-init.sh + return 0; + fi + + if [ "X${UN}" = "XSunOS" ]; then + echo " - ${systemis} Solaris (SunOS)." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids-solaris.init /etc/init.d/ossec + chmod 755 /etc/init.d/ossec + ln -s /etc/init.d/ossec /etc/rc2.d/S97ossec + ln -s /etc/init.d/ossec /etc/rc3.d/S97ossec + return 0; + fi + + if [ "X${UN}" = "XAIX" ]; then + echo " - ${systemis} AIX." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids-aix.init /etc/init.d/ossec + chmod 755 /etc/init.d/ossec + ln -s /etc/init.d/ossec /etc/rc2.d/S97ossec + ln -s /etc/init.d/ossec /etc/rc3.d/S97ossec + return 0; + fi + + if [ "X${UN}" = "XOpenBSD" -o "X${UN}" = "XNetBSD" -o "X${UN}" = "XFreeBSD" -o "X${UN}" = "XDragonFly" ]; then + # Checking for the presence of ossec-control on rc.local + grep ossec-control /etc/rc.local > /dev/null 2>&1 + if [ $? != 0 ]; then + echo "echo \"${starting}\"" >> /etc/rc.local + echo "${INSTALLDIR}/bin/ossec-control start" >> /etc/rc.local + fi + echo " - ${systemis} ${NUNAME}." + echo " - ${modifiedinit}" + return 0; + elif [ "X${NUNAME}" = "XLinux" ]; then + if [ -e "/etc/rc.d/rc.local" ]; then + echo " - ${systemis} Linux." + echo " - ${modifiedinit}" + + grep ossec-control /etc/rc.d/rc.local > /dev/null 2>&1 + if [ $? != 0 ]; then + echo "echo \"${starting}\"" >> /etc/rc.d/rc.local + echo "${INSTALLDIR}/bin/ossec-control start" >> /etc/rc.d/rc.local + fi + return 0; + elif [ -d "/etc/rc.d/init.d" ]; then + echo " - ${systemis} Linux (SysV)." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids.init /etc/rc.d/init.d/ossec + chmod 555 /etc/rc.d/init.d/ossec + chown root:ossec /etc/rc.d/init.d/ossec + return 0; + # Taken from Stephen Bunn ossec howto. + elif [ -d "/etc/init.d" -a -f "/usr/sbin/update-rc.d" ]; then + echo " - ${systemis} Debian (Ubuntu or derivative)." + echo " - ${modifiedinit}" + cp -pr ./src/init/ossec-hids.init /etc/init.d/ossec + chmod +x /etc/init.d/ossec + chmod go-w /etc/init.d/ossec + chown root:ossec /etc/init.d/ossec + update-rc.d ossec defaults > /dev/null 2>&1 + return 0; + else + echo " - ${noboot}" + fi + else + echo " - ${noboot}" + fi + + return 1; +} + + +# EOF diff --git a/src/init/language.sh b/src/init/language.sh new file mode 100755 index 0000000..128200b --- /dev/null +++ b/src/init/language.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# language.sh +# Author: Daniel B. Cid +# Last modification: Mar 03, 2006 + + +########## +# catError() +########## +catError() +{ + FILE=$1; + + FILE_PATH="${TEMPLATE}/${LANGUAGE}/${ERROR}/${FILE}.txt" + if [ `isFile ${FILE_PATH}` = "${FALSE}" ]; then + # If we can't file in that specific language, try + # the english one. + FILE_PATH="${TEMPLATE}/en/${ERROR}/${FILE}.txt" + if [ `isFile ${FILE_PATH}` = "${FALSE}" ]; then + echo "0x0000 - Internal error for ${FILE}" + exit 1; + fi + fi + cat ${FILE_PATH} + exit 1; +} + + +########## +# catMsg() +########## +catMsg() +{ + FILE=$1; + + FILE_PATH="${TEMPLATE}/${LANGUAGE}/${MSG}/${FILE}.txt" + if [ `isFile ${FILE_PATH}` = "${FALSE}" ]; then + # If we can't file in that specific language, try + # the english one. + FILE_PATH="${TEMPLATE}/en/${MSG}/${FILE}.txt" + FILE_PATH="${MSG_TEMPLATE}/en/${FILE}.txt" + if [ `isFile ${FILE_PATH}` = "${FALSE}" ]; then + echo "0x0001 - Internal error for ${FILE}" + exit 1; + fi + fi + + cat ${FILE_PATH} +} + + + +## EOF ## diff --git a/src/init/ossec-client.sh b/src/init/ossec-client.sh new file mode 100755 index 0000000..e05d615 --- /dev/null +++ b/src/init/ossec-client.sh @@ -0,0 +1,234 @@ +#!/bin/sh +# ossec-control This shell script takes care of starting +# or stopping ossec-hids +# Author: Daniel B. Cid + + +LOCAL=`dirname $0`; +cd ${LOCAL} +PWD=`pwd` +DIR=`dirname $PWD`; + +### Do not modify bellow here ### +NAME="OSSEC HIDS" +VERSION="v2.3" +AUTHOR="Trend Micro Inc." +DAEMONS="ossec-logcollector ossec-syscheckd ossec-agentd ossec-execd" + + +## Locking for the start/stop +LOCK="${DIR}/var/start-script-lock" +LOCK_PID="${LOCK}/pid" + + +# This number should be more than enough (even if it is +# started multiple times together). It will try for up +# to 10 attempts (or 10 seconds) to execute. +MAX_ITERATION="10" + + + +# Check pid +checkpid() +{ + for i in ${DAEMONS}; do + for j in `cat ${DIR}/var/run/${i}*.pid 2>/dev/null`; do + ps -p $j |grep ossec >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "Deleting PID file '${DIR}/var/run/${i}-${j}.pid' not used..." + rm ${DIR}/var/run/${i}-${j}.pid + fi + done + done +} + + + +# Lock function +lock() +{ + i=0; + + # Providing a lock. + while [ 1 ]; do + mkdir ${LOCK} > /dev/null 2>&1 + MSL=$? + if [ "${MSL}" = "0" ]; then + # Lock aquired (setting the pid) + echo "$$" > ${LOCK_PID} + return; + fi + + # Waiting 1 second before trying again + sleep 1; + i=`expr $i + 1`; + + # If PID is not present, speed things a bit. + kill -0 `cat ${LOCK_PID}` >/dev/null 2>&1 + if [ ! $? = 0 ]; then + # Pid is not present. + i=`expr $i + 1`; + fi + + # We tried 10 times to acquire the lock. + if [ "$i" = "${MAX_ITERATION}" ]; then + # Unlocking and executing + unlock; + mkdir ${LOCK} > /dev/null 2>&1 + echo "$$" > ${LOCK_PID} + return; + fi + done +} + + +# Unlock function +unlock() +{ + rm -rf ${LOCK} +} + + +# Help message +help() +{ + # Help message + echo "Usage: $0 {start|stop|restart|status}"; + exit 1; +} + + +# Status function +status() +{ + for i in ${DAEMONS}; do + pstatus ${i}; + if [ $? = 0 ]; then + echo "${i} not running..." + else + echo "${i} is running..." + fi + done +} + + +# Start function +start() +{ + SDAEMONS="ossec-execd ossec-agentd ossec-logcollector ossec-syscheckd" + + echo "Starting $NAME $VERSION (by $AUTHOR)..." + lock; + checkpid; + + # We first loop to check the config. + for i in ${SDAEMONS}; do + ${DIR}/bin/${i} -t; + if [ $? != 0 ]; then + echo "${i}: Configuration error. Exiting" + unlock; + exit 1; + fi + done + + # We actually start them now. + for i in ${SDAEMONS}; do + pstatus ${i}; + if [ $? = 0 ]; then + ${DIR}/bin/${i}; + if [ $? != 0 ]; then + unlock; + exit 1; + fi + + echo "Started ${i}..." + else + echo "${i} already running..." + fi + + done + + # After we start we give 2 seconds for the daemons + # to internally create their PID files. + sleep 2; + unlock; + echo "Completed." +} + +# Process status +pstatus() +{ + pfile=$1; + + # pfile must be set + if [ "X${pfile}" = "X" ]; then + return 0; + fi + + ls ${DIR}/var/run/${pfile}*.pid > /dev/null 2>&1 + if [ $? = 0 ]; then + for j in `cat ${DIR}/var/run/${pfile}*.pid 2>/dev/null`; do + ps -p $j |grep ossec >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "${pfile}: Process $j not used by ossec, removing .." + rm -f ${DIR}/var/run/${pfile}-$j.pid + continue; + fi + + kill -0 $j > /dev/null 2>&1 + if [ $? = 0 ]; then + return 1; + fi + done + fi + + return 0; +} + + +# Stop all +stopa() +{ + lock; + checkpid; + for i in ${DAEMONS}; do + pstatus ${i}; + if [ $? = 1 ]; then + echo "Killing ${i} .. "; + + kill `cat ${DIR}/var/run/${i}*.pid`; + else + echo "${i} not running .."; + fi + + rm -f ${DIR}/var/run/${i}*.pid + + done + + unlock; + echo "$NAME $VERSION Stopped" +} + + +### MAIN HERE ### + +case "$1" in + start) + start + ;; + stop) + stopa + ;; + restart) + stopa + start + ;; + status) + status + ;; + help) + help + ;; + *) + help +esac diff --git a/src/init/ossec-hids-aix.init b/src/init/ossec-hids-aix.init new file mode 100644 index 0000000..f23c860 --- /dev/null +++ b/src/init/ossec-hids-aix.init @@ -0,0 +1,29 @@ +#!/bin/ksh +# +# name: ossec +# purpose: Init script for ossec-hids +# Aug. 07 2008 Chris Cuevas +# + +case "$1" in +start ) + if [ -f /var/ossec/bin/ossec-control ]; then + echo "Starting OSSEC" + /var/ossec/bin/ossec-control start + fi + ;; +stop ) + if [ -f /var/ossec/bin/ossec-control ]; then + echo "Stopping OSSEC" + /var/ossec/bin/ossec-control stop + fi + ;; +status ) + if [ -f /var/ossec/bin/ossec-control ]; then + /var/ossec/bin/ossec-control status + fi + ;; +* ) + echo "Usage: $0 (start | stop | status)" + exit 1 +esac diff --git a/src/init/ossec-hids-gentoo.init b/src/init/ossec-hids-gentoo.init new file mode 100755 index 0000000..c2d06f6 --- /dev/null +++ b/src/init/ossec-hids-gentoo.init @@ -0,0 +1,69 @@ +#!/sbin/runscript +# Gentoo init script +# by gentuxx + + +opts="${opts} status configtest" + +# Finding where ossec is installed +. /etc/ossec-init.conf +if [ "X${DIRECTORY}" = "X" ]; then + DIRECTORY="/var/ossec" +fi + +OSSEC_CONTROL="${DIRECTORY}/bin/ossec-control" + +depend() { + need net + use logger +} + +configtest() { + ebegin "Checking OSSEC Configuration" + checkconfig + eend $? +} + +checkconfig() { + + CONFIGFILE="${CONFIGFILE:-/var/ossec/etc/ossec.conf}" + if [ ! -r "${CONFIGFILE}" ]; then + eerror "Unable to read configuration file: ${CONFIGFILE}" + return 1 + fi + + # Maybe put some kind of config file syntax checking in here? XML is a little different + # so maybe not. + return $ret +} + +start() { + checkconfig || return 1 + ebegin "Starting ossec-hids" + ${OSSEC_CONTROL} start > /dev/null 2>&1 + eend $? +} + +stop() { + checkconfig || return 1 + ebegin "Stopping ossec-hids" + ${OSSEC_CONTROL} stop > /dev/null 2>&1 + eend $? +} + +restart() { + if ! service_started "${myservice}" ; then + eerror "OSSEC is not running! Please start it before trying to reload it." + else + checkconfig || return 1 + ebegin "Reloading ossec" + svc_stop ${OSSEC_CONTROL} + svc_start ${OSSEC_CONTROL} + eend $? + fi +} + +status() { + checkconfig || return 1 + ${OSSEC_CONTROL} status +} diff --git a/src/init/ossec-hids-rh.init b/src/init/ossec-hids-rh.init new file mode 100755 index 0000000..2ce397b --- /dev/null +++ b/src/init/ossec-hids-rh.init @@ -0,0 +1,71 @@ +#!/bin/sh +# OSSEC Controls OSSEC HIDS on Redhat-based systems +# Author: Kayvan A. Sylvan +# Author: Daniel B. Cid +# +# chkconfig: 2345 99 15 +# description: Starts and stops OSSEC HIDS (Host Intrusion Detection System) +# +# This will work on Redhat systems (maybe others too) + +# Source function library. +export LANG=C + +. /etc/init.d/functions +. /etc/ossec-init.conf + +if [ "X${DIRECTORY}" = "X" ]; then + DIRECTORY="/var/ossec" +fi + +start() { + echo -n "Starting OSSEC: " + ${DIRECTORY}/bin/ossec-control start > /dev/null + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + success + else + failure + fi + echo + return $RETVAL +} + +stop() { + echo -n "Stopping OSSEC: " + ${DIRECTORY}/bin/ossec-control stop > /dev/null + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + success + else + failure + fi + echo + return $RETVAL +} + +status() { + ${DIRECTORY}/bin/ossec-control status +} + + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + status + ;; + *) + echo "*** Usage: ossec {start|stop|restart|status}" + exit 1 +esac + +exit $? diff --git a/src/init/ossec-hids-solaris.init b/src/init/ossec-hids-solaris.init new file mode 100644 index 0000000..5d1fcd6 --- /dev/null +++ b/src/init/ossec-hids-solaris.init @@ -0,0 +1,73 @@ +#!/bin/sh +# OSSEC Controls OSSEC HIDS on Solaris systems +# Author: Kayvan A. Sylvan +# Author: Daniel B. Cid +# +# chkconfig: 2345 99 15 +# description: Starts and stops OSSEC HIDS (Host Intrusion Detection System) +# +# This will work on Solaris systems (maybe others too) +# +# Modified by Chris Cuevas and Darryl Marsee to work on Solaris +# +# Source function library. +LANG=C +export $LANG + +. /etc/ossec-init.conf + +if [ "X${DIRECTORY}" = "X" ]; then + DIRECTORY="/var/ossec" +fi + +start() { + echo -n "Starting OSSEC: " + ${DIRECTORY}/bin/ossec-control start > /dev/null + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + echo success + else + echo failure + fi + echo + return $RETVAL +} + +stop() { + echo -n "Stopping OSSEC: " + ${DIRECTORY}/bin/ossec-control stop > /dev/null + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + echo success + else + echo failure + fi + echo + return $RETVAL +} + +status() { + ${DIRECTORY}/bin/ossec-control status +} + + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + status + ;; + *) + echo "*** Usage: ossec {start|stop|restart|status}" + exit 1 +esac + +exit $? diff --git a/src/init/ossec-hids-suse.init b/src/init/ossec-hids-suse.init new file mode 100755 index 0000000..ce51d1c --- /dev/null +++ b/src/init/ossec-hids-suse.init @@ -0,0 +1,96 @@ +#!/bin/sh +# Author: Scott Knauss scott@knauss.com +# +# /etc/init.d/ossec +# +# +### BEGIN INIT INFO +# Provides: ossec +# Required-Start: $syslog +# Required-Stop: +# Default-Start: 2 3 5 +# Default-Stop: +# Description: Start the ossec HIDS daemon +### END INIT INFO + +# Shell functions sourced from /etc/rc.status: +# rc_check check and set local and overall rc status +# rc_status check and set local and overall rc status +# rc_status -v ditto but be verbose in local rc status +# rc_status -v -r ditto and clear the local rc status +# rc_failed set local and overall rc status to failed +# rc_failed set local and overall rc status to +# rc_reset clear local rc status (overall remains) +# rc_exit exit appropriate to overall rc status +. /etc/rc.status + +# First reset status of this service +rc_reset + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - insufficient privilege +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signalling is not supported) are +# considered a success. + + +# Reading ossec init conf. +if [ -f /etc/ossec-init.conf ]; then + . /etc/ossec-init.conf +fi + +if [ "X${DIRECTORY}" = "X" ]; then + DIRECTORY="/var/ossec" +fi + + +#Just to make sure ossec is installed ... +CONTROL="$DIRECTORY/bin/ossec-control" + +test -x $CONTROL || { echo "$CONTROL not installed"; + if [ "$1" = "stop" ]; then exit 0; + else exit 5; fi; } + + +start() { + ${DIRECTORY}/bin/ossec-control start +} + +stop() { + ${DIRECTORY}/bin/ossec-control stop +} + +status() { + ${DIRECTORY}/bin/ossec-control status +} + + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + status + ;; + *) + echo "*** Usage: $0 {start|stop|restart|status}" + exit 1 +esac + +exit 0 diff --git a/src/init/ossec-hids.init b/src/init/ossec-hids.init new file mode 100755 index 0000000..f1543d4 --- /dev/null +++ b/src/init/ossec-hids.init @@ -0,0 +1,45 @@ +#!/bin/sh +# OSSEC Controls OSSEC HIDS +# Author: Daniel B. Cid +# Modified for slackware by Jack S. Lai + + +. /etc/ossec-init.conf +if [ "X${DIRECTORY}" = "X" ]; then + DIRECTORY="/var/ossec" +fi + + +start() { + ${DIRECTORY}/bin/ossec-control start +} + +stop() { + ${DIRECTORY}/bin/ossec-control stop +} + +status() { + ${DIRECTORY}/bin/ossec-control status +} + + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + status + ;; + *) + echo "*** Usage: $0 {start|stop|restart|status}" + exit 1 +esac + +exit 0 diff --git a/src/init/ossec-local.sh b/src/init/ossec-local.sh new file mode 100755 index 0000000..259bd5d --- /dev/null +++ b/src/init/ossec-local.sh @@ -0,0 +1,312 @@ +#!/bin/sh +# ossec-control This shell script takes care of starting +# or stopping ossec-hids +# Author: Daniel B. Cid + + +# Getting where we are installed +LOCAL=`dirname $0`; +cd ${LOCAL} +PWD=`pwd` +DIR=`dirname $PWD`; +PLIST=${DIR}/bin/.process_list; + + +### Do not modify bellow here ### + +# Getting additional processes +ls -la ${PLIST} > /dev/null 2>&1 +if [ $? = 0 ]; then +. ${PLIST}; +fi + + +NAME="OSSEC HIDS" +VERSION="v2.3" +AUTHOR="Trend Micro Inc." +DAEMONS="ossec-monitord ossec-logcollector ossec-syscheckd ossec-analysisd ossec-maild ossec-execd ${DB_DAEMON} ${CSYSLOG_DAEMON} ${AGENTLESS_DAEMON}" + + +## Locking for the start/stop +LOCK="${DIR}/var/start-script-lock" +LOCK_PID="${LOCK}/pid" + + +# This number should be more than enough (even if it is +# started multiple times together). It will try for up +# to 10 attempts (or 10 seconds) to execute. +MAX_ITERATION="10" + + + +# Check pid +checkpid() +{ + for i in ${DAEMONS}; do + for j in `cat ${DIR}/var/run/${i}*.pid 2>/dev/null`; do + ps -p $j |grep ossec >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "Deleting PID file '${DIR}/var/run/${i}-${j}.pid' not used..." + rm ${DIR}/var/run/${i}-${j}.pid + fi + done + done +} + + + +# Lock function +lock() +{ + i=0; + + # Providing a lock. + while [ 1 ]; do + mkdir ${LOCK} > /dev/null 2>&1 + MSL=$? + if [ "${MSL}" = "0" ]; then + # Lock aquired (setting the pid) + echo "$$" > ${LOCK_PID} + return; + fi + + # Waiting 1 second before trying again + sleep 1; + i=`expr $i + 1`; + + # If PID is not present, speed things a bit. + kill -0 `cat ${LOCK_PID}` >/dev/null 2>&1 + if [ ! $? = 0 ]; then + # Pid is not present. + i=`expr $i + 1`; + fi + + # We tried 10 times to acquire the lock. + if [ "$i" = "${MAX_ITERATION}" ]; then + # Unlocking and executing + unlock; + mkdir ${LOCK} > /dev/null 2>&1 + echo "$$" > ${LOCK_PID} + return; + fi + done +} + + +# Unlock function +unlock() +{ + rm -rf ${LOCK} +} + + +# Help message +help() +{ + # Help message + echo "" + echo "Usage: $0 {start|stop|restart|status|enable|disable}"; + exit 1; +} + + +# Enables/disables additional daemons +enable() +{ + if [ "X$2" = "X" ]; then + echo "" + echo "Enable options: database, client-syslog, agentless" + echo "Usage: $0 enable [database|client-syslog|agentless]" + exit 1; + fi + + if [ "X$2" = "Xdatabase" ]; then + echo "DB_DAEMON=ossec-dbd" >> ${PLIST}; + elif [ "X$2" = "Xclient-syslog" ]; then + echo "CSYSLOG_DAEMON=ossec-csyslogd" >> ${PLIST}; + elif [ "X$2" = "Xagentless" ]; then + echo "AGENTLESS_DAEMON=ossec-agentlessd" >> ${PLIST}; + else + echo "" + echo "Invalid enable option." + echo "" + echo "Enable options: database, client-syslog, agentless" + echo "Usage: $0 enable [database|client-syslog|agentless]" + exit 1; + fi + + +} + + + +# Enables/disables additional daemons +disable() +{ + if [ "X$2" = "X" ]; then + echo "" + echo "Disable options: database, client-syslog, agentless" + echo "Usage: $0 disable [database|client-syslog|agentless]" + exit 1; + fi + + if [ "X$2" = "Xdatabase" ]; then + echo "DB_DAEMON=\"\"" >> ${PLIST}; + elif [ "X$2" = "Xclient-syslog" ]; then + echo "CSYSLOG_DAEMON=\"\"" >> ${PLIST}; + elif [ "X$2" = "Xagentless" ]; then + echo "AGENTLESS_DAEMON=\"\"" >> ${PLIST}; + else + echo "" + echo "Invalid disable option." + echo "" + echo "Disable options: database, client-syslog, agentless" + echo "Usage: $0 disable [database|client-syslog|agentless]" + exit 1; + fi + + +} + + + +# Status function +status() +{ + for i in ${DAEMONS}; do + pstatus ${i}; + if [ $? = 0 ]; then + echo "${i} not running..." + else + echo "${i} is running..." + fi + done +} + + +# Start function +start() +{ + SDAEMONS="${DB_DAEMON} ${CSYSLOG_DAEMON} ${AGENTLESS_DAEMON} ossec-maild ossec-execd ossec-analysisd ossec-logcollector ossec-syscheckd ossec-monitord" + + echo "Starting $NAME $VERSION (by $AUTHOR)..." + lock; + checkpid; + + # We first loop to check the config. + for i in ${SDAEMONS}; do + ${DIR}/bin/${i} -t; + if [ $? != 0 ]; then + echo "${i}: Configuration error. Exiting" + unlock; + exit 1; + fi + done + + # We actually start them now. + for i in ${SDAEMONS}; do + pstatus ${i}; + if [ $? = 0 ]; then + ${DIR}/bin/${i}; + if [ $? != 0 ]; then + unlock; + exit 1; + fi + + echo "Started ${i}..." + else + echo "${i} already running..." + fi + + done + + # After we start we give 2 seconds for the daemons + # to internally create their PID files. + sleep 2; + unlock; + echo "Completed." +} + +# Process status +pstatus() +{ + pfile=$1; + + # pfile must be set + if [ "X${pfile}" = "X" ]; then + return 0; + fi + + ls ${DIR}/var/run/${pfile}*.pid > /dev/null 2>&1 + if [ $? = 0 ]; then + for j in `cat ${DIR}/var/run/${pfile}*.pid 2>/dev/null`; do + ps -p $j |grep ossec >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "${pfile}: Process $j not used by ossec, removing .." + rm -f ${DIR}/var/run/${pfile}-$j.pid + continue; + fi + + kill -0 $j > /dev/null 2>&1 + if [ $? = 0 ]; then + return 1; + fi + done + fi + + return 0; +} + + +# Stop all +stopa() +{ + lock; + checkpid; + for i in ${DAEMONS}; do + pstatus ${i}; + if [ $? = 1 ]; then + echo "Killing ${i} .. "; + + kill `cat ${DIR}/var/run/${i}*.pid`; + else + echo "${i} not running .."; + fi + + rm -f ${DIR}/var/run/${i}*.pid + + done + + unlock; + echo "$NAME $VERSION Stopped" +} + + +### MAIN HERE ### + +case "$1" in + start) + start + ;; + stop) + stopa + ;; + restart) + stopa + start + ;; + status) + status + ;; + help) + help + ;; + enable) + enable $1 $2; + ;; + disable) + disable $1 $2; + ;; + *) + help +esac diff --git a/src/init/ossec-server.sh b/src/init/ossec-server.sh new file mode 100755 index 0000000..307502d --- /dev/null +++ b/src/init/ossec-server.sh @@ -0,0 +1,312 @@ +#!/bin/sh +# ossec-control This shell script takes care of starting +# or stopping ossec-hids +# Author: Daniel B. Cid + + +# Getting where we are installed +LOCAL=`dirname $0`; +cd ${LOCAL} +PWD=`pwd` +DIR=`dirname $PWD`; +PLIST=${DIR}/bin/.process_list; + + +### Do not modify bellow here ### + +# Getting additional processes +ls -la ${PLIST} > /dev/null 2>&1 +if [ $? = 0 ]; then +. ${PLIST}; +fi + + +NAME="OSSEC HIDS" +VERSION="v2.3" +AUTHOR="Trend Micro Inc." +DAEMONS="ossec-monitord ossec-logcollector ossec-remoted ossec-syscheckd ossec-analysisd ossec-maild ossec-execd ${DB_DAEMON} ${CSYSLOG_DAEMON} ${AGENTLESS_DAEMON}" + + +## Locking for the start/stop +LOCK="${DIR}/var/start-script-lock" +LOCK_PID="${LOCK}/pid" + + +# This number should be more than enough (even if it is +# started multiple times together). It will try for up +# to 10 attempts (or 10 seconds) to execute. +MAX_ITERATION="10" + + + +# Check pid +checkpid() +{ + for i in ${DAEMONS}; do + for j in `cat ${DIR}/var/run/${i}*.pid 2>/dev/null`; do + ps -p $j |grep ossec >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "Deleting PID file '${DIR}/var/run/${i}-${j}.pid' not used..." + rm ${DIR}/var/run/${i}-${j}.pid + fi + done + done +} + + + +# Lock function +lock() +{ + i=0; + + # Providing a lock. + while [ 1 ]; do + mkdir ${LOCK} > /dev/null 2>&1 + MSL=$? + if [ "${MSL}" = "0" ]; then + # Lock aquired (setting the pid) + echo "$$" > ${LOCK_PID} + return; + fi + + # Waiting 1 second before trying again + sleep 1; + i=`expr $i + 1`; + + # If PID is not present, speed things a bit. + kill -0 `cat ${LOCK_PID}` >/dev/null 2>&1 + if [ ! $? = 0 ]; then + # Pid is not present. + i=`expr $i + 1`; + fi + + # We tried 10 times to acquire the lock. + if [ "$i" = "${MAX_ITERATION}" ]; then + # Unlocking and executing + unlock; + mkdir ${LOCK} > /dev/null 2>&1 + echo "$$" > ${LOCK_PID} + return; + fi + done +} + + +# Unlock function +unlock() +{ + rm -rf ${LOCK} +} + + +# Help message +help() +{ + # Help message + echo "" + echo "Usage: $0 {start|stop|restart|status|enable|disable}"; + exit 1; +} + + +# Enables/disables additional daemons +enable() +{ + if [ "X$2" = "X" ]; then + echo "" + echo "Enable options: database, client-syslog, agentless" + echo "Usage: $0 enable [database|client-syslog|agentless]" + exit 1; + fi + + if [ "X$2" = "Xdatabase" ]; then + echo "DB_DAEMON=ossec-dbd" >> ${PLIST}; + elif [ "X$2" = "Xclient-syslog" ]; then + echo "CSYSLOG_DAEMON=ossec-csyslogd" >> ${PLIST}; + elif [ "X$2" = "Xagentless" ]; then + echo "AGENTLESS_DAEMON=ossec-agentlessd" >> ${PLIST}; + else + echo "" + echo "Invalid enable option." + echo "" + echo "Enable options: database, client-syslog, agentless" + echo "Usage: $0 enable [database|client-syslog|agentless]" + exit 1; + fi + + +} + + + +# Enables/disables additional daemons +disable() +{ + if [ "X$2" = "X" ]; then + echo "" + echo "Disable options: database, client-syslog, agentless" + echo "Usage: $0 disable [database|client-syslog|agentless]" + exit 1; + fi + + if [ "X$2" = "Xdatabase" ]; then + echo "DB_DAEMON=\"\"" >> ${PLIST}; + elif [ "X$2" = "Xclient-syslog" ]; then + echo "CSYSLOG_DAEMON=\"\"" >> ${PLIST}; + elif [ "X$2" = "Xagentless" ]; then + echo "AGENTLESS_DAEMON=\"\"" >> ${PLIST}; + else + echo "" + echo "Invalid disable option." + echo "" + echo "Disable options: database, client-syslog, agentless" + echo "Usage: $0 disable [database|client-syslog|agentless]" + exit 1; + fi + + +} + + + +# Status function +status() +{ + for i in ${DAEMONS}; do + pstatus ${i}; + if [ $? = 0 ]; then + echo "${i} not running..." + else + echo "${i} is running..." + fi + done +} + + +# Start function +start() +{ + SDAEMONS="${DB_DAEMON} ${CSYSLOG_DAEMON} ${AGENTLESS_DAEMON} ossec-maild ossec-execd ossec-analysisd ossec-logcollector ossec-remoted ossec-syscheckd ossec-monitord" + + echo "Starting $NAME $VERSION (by $AUTHOR)..." + lock; + checkpid; + + # We first loop to check the config. + for i in ${SDAEMONS}; do + ${DIR}/bin/${i} -t; + if [ $? != 0 ]; then + echo "${i}: Configuration error. Exiting" + unlock; + exit 1; + fi + done + + # We actually start them now. + for i in ${SDAEMONS}; do + pstatus ${i}; + if [ $? = 0 ]; then + ${DIR}/bin/${i}; + if [ $? != 0 ]; then + unlock; + exit 1; + fi + + echo "Started ${i}..." + else + echo "${i} already running..." + fi + + done + + # After we start we give 2 seconds for the daemons + # to internally create their PID files. + sleep 2; + unlock; + echo "Completed." +} + +# Process status +pstatus() +{ + pfile=$1; + + # pfile must be set + if [ "X${pfile}" = "X" ]; then + return 0; + fi + + ls ${DIR}/var/run/${pfile}*.pid > /dev/null 2>&1 + if [ $? = 0 ]; then + for j in `cat ${DIR}/var/run/${pfile}*.pid 2>/dev/null`; do + ps -p $j |grep ossec >/dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "${pfile}: Process $j not used by ossec, removing .." + rm -f ${DIR}/var/run/${pfile}-$j.pid + continue; + fi + + kill -0 $j > /dev/null 2>&1 + if [ $? = 0 ]; then + return 1; + fi + done + fi + + return 0; +} + + +# Stop all +stopa() +{ + lock; + checkpid; + for i in ${DAEMONS}; do + pstatus ${i}; + if [ $? = 1 ]; then + echo "Killing ${i} .. "; + + kill `cat ${DIR}/var/run/${i}*.pid`; + else + echo "${i} not running .."; + fi + + rm -f ${DIR}/var/run/${i}*.pid + + done + + unlock; + echo "$NAME $VERSION Stopped" +} + + +### MAIN HERE ### + +case "$1" in + start) + start + ;; + stop) + stopa + ;; + restart) + stopa + start + ;; + status) + status + ;; + help) + help + ;; + enable) + enable $1 $2; + ;; + disable) + disable $1 $2; + ;; + *) + help +esac diff --git a/src/init/osx105-addusers.sh b/src/init/osx105-addusers.sh new file mode 100644 index 0000000..b3bf14d --- /dev/null +++ b/src/init/osx105-addusers.sh @@ -0,0 +1,39 @@ +#! /bin/sh +# By Spransy, Derek" and Charlie Scott + + + +# Creating the groups. +sudo dscl localhost -create /Local/Default/Groups/ossec +sudo dscl localhost -createprop /Local/Default/Groups/ossec PrimaryGroupID 600 +sudo dscl localhost -createprop /Local/Default/Groups/ossec RealName ossec +sudo dscl localhost -createprop /Local/Default/Groups/ossec RecordName ossec +sudo dscl localhost -createprop /Local/Default/Groups/ossec RecordType: dsRecTypeStandard:Groups +sudo dscl localhost -createprop /Local/Default/Groups/ossec Password "*" + + +# Creating the users. +sudo dscl localhost -create /Local/Default/Users/ossec +sudo dscl localhost -createprop /Local/Default/Users/ossec RecordName ossec +sudo dscl localhost -createprop /Local/Default/Users/ossec RealName "ossecacct" +sudo dscl localhost -createprop /Local/Default/Users/ossec NFSHomeDirectory /var/ossec +sudo dscl localhost -createprop /Local/Default/Users/ossec UniqueID 600 +sudo dscl localhost -createprop /Local/Default/Users/ossec PrimaryGroupID 600 +sudo dscl localhost -createprop /Local/Default/Users/ossec Password "*" + +sudo dscl localhost -create /Local/Default/Users/ossecm +sudo dscl localhost -createprop /Local/Default/Users/ossecm RecordName ossecm +sudo dscl localhost -createprop /Local/Default/Users/ossecm RealName "ossecmacct" +sudo dscl localhost -createprop /Local/Default/Users/ossecm NFSHomeDirectory /var/ossec +sudo dscl localhost -createprop /Local/Default/Users/ossecm UniqueID 601 +sudo dscl localhost -createprop /Local/Default/Users/ossecm PrimaryGroupID 600 +sudo dscl localhost -createprop /Local/Default/Users/ossecm Password "*" + +sudo dscl localhost -create /Local/Default/Users/ossecr +sudo dscl localhost -createprop /Local/Default/Users/ossecr RecordName ossecr +sudo dscl localhost -createprop /Local/Default/Users/ossecr RealName "ossecracct" +sudo dscl localhost -createprop /Local/Default/Users/ossecr NFSHomeDirectory /var/ossec +sudo dscl localhost -createprop /Local/Default/Users/ossecr UniqueID 602 +sudo dscl localhost -createprop /Local/Default/Users/ossecr PrimaryGroupID 600 +sudo dscl localhost -createprop /Local/Default/Users/ossecr Password "*" + diff --git a/src/init/shared.sh b/src/init/shared.sh new file mode 100755 index 0000000..6d7f8ab --- /dev/null +++ b/src/init/shared.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# Shared variables and functions +# Author: Daniel B. Cid +# Last modification: Mar 03, 2006 + + + +### Setting up variables +VERSION_FILE="./src/VERSION" +VERSION=`cat ${VERSION_FILE}` +LOCATION="./src/LOCATION" +UNAME=`uname -snr` +NUNAME=`uname` + +# If whoami does not exist, try id +ls "`which whoami`" > /dev/null 2>&1 +if [ ! $? = 0 ]; then + ME=`id | cut -d " " -f 1` + if [ "X${ME}" = "Xuid=0(root)" ]; then + ME="root" + fi +else + ME=`whoami 2>/dev/null` +fi + +OSSEC_INIT="/etc/ossec-init.conf" +HOST=`hostname` +NAMESERVERS=`cat /etc/resolv.conf | grep "^nameserver" | cut -d " " -sf 2` +NAMESERVERS2=`cat /etc/resolv.conf | grep "^nameserver" | cut -sf 2` +HOST_CMD=`which host` +CC="" +NAME="OSSEC HIDS" +INSTYPE="server" +DEFAULT_DIR=`grep DIR ${LOCATION} | cut -f2 -d\"` +INSTALLDIR="$DEFAULT_DIR"; +WORKDIR="$INSTALLDIR" +CEXTRA="" + +# Internal definitions +NEWCONFIG="./etc/ossec.mc" +PRECONFIG="./etc/PRECONFIG" + +## Templates +TEMPLATE="./etc/templates" +ERROR="errors" +MSG="messages" + +## Config templates +SYSCHECK_TEMPLATE="./etc/templates/config/syscheck.template" +SYSLOG_TEMPLATE="./etc/templates/config/syslog-logs.template" +APACHE_TEMPLATE="./etc/templates/config/apache-logs.template" +SNORT_TEMPLATE="./etc/templates/config/snort-logs.template" +PGSQL_TEMPLATE="./etc/templates/config/pgsql-logs.template" +HOST_DENY_TEMPLATE="./etc/templates/config/ar-host-deny.template" +FIREWALL_DROP_TEMPLATE="./etc/templates/config/ar-firewall-drop.template" +DISABLE_ACCOUNT_TEMPLATE="./etc/templates/config/ar-disable-account.template" +ACTIVE_RESPONSE_TEMPLATE="./etc/templates/config/active-response.template" +ROUTENULL_TEMPLATE="./etc/templates/config/ar-routenull.template" +RULES_TEMPLATE="./etc/templates/config/rules.template" + + +## Host output +OSSECMX="devmail.ossec.net mail is handled by 10 ossec.mooo.com." +OSSECMX2="devmail.ossec.net mail is handled (pri=10) by ossec.mooo.com" +OSSECMX3="devmail.ossec.net mail is handled by 10 ossec.mooo.COM." + +## Predefined file +PREDEF_FILE="./etc/preloaded-vars.conf" + + + +## EOF ## diff --git a/src/init/update.sh b/src/init/update.sh new file mode 100755 index 0000000..a822f3a --- /dev/null +++ b/src/init/update.sh @@ -0,0 +1,142 @@ +#!/bin/sh +# Shell script update functions for the OSSEC HIDS +# Author: Daniel B. Cid +# Last modification: May 24, 2006 + + +FALSE="false" +TRUE="true" + + +########## +# isUpdate +########## +isUpdate() +{ + ls -la ${OSSEC_INIT} > /dev/null 2>&1 + if [ $? = 0 ]; then + . ${OSSEC_INIT} + if [ "X$DIRECTORY" = "X" ]; then + echo "${FALSE}" + return 1; + fi + ls -la $DIRECTORY > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "${TRUE}" + return 0; + fi + fi + + echo "${FALSE}" + return 1; +} + + +########## +# doUpdatecleanup +########## +doUpdatecleanup() +{ + . ${OSSEC_INIT} + + if [ "X$DIRECTORY" = "X" ]; then + # Invalid ossec init file. Unable to update + echo "${FALSE}" + return 1; + fi + + # Checking if the directory is valid. + echo $DIRECTORY | grep -E "^/[a-zA-Z0-9/-]{3,128}$" > /dev/null 2>&1 + if [ ! $? = 0 ]; then + echo "${FALSE}" + return 1; + fi +} + + +########## +# getPreinstalled +########## +getPreinstalled() +{ + . ${OSSEC_INIT} + + # agent + cat $DIRECTORY/etc/ossec.conf | grep "" > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "agent" + return 0; + fi + + cat $DIRECTORY/etc/ossec.conf | grep "" > /dev/null 2>&1 + if [ $? = 0 ]; then + echo "server" + return 0; + fi + + echo "local" + return 0; +} + + +########## +# getPreinstalledDir +########## +getPreinstalledDir() +{ + . ${OSSEC_INIT} + echo "$DIRECTORY" + return 0; +} + + +########## +# UpdateStartOSSEC +########## +UpdateStartOSSEC() +{ + . ${OSSEC_INIT} + + $DIRECTORY/bin/ossec-control start +} + + +########## +# UpdateStopOSSEC +########## +UpdateStopOSSEC() +{ + . ${OSSEC_INIT} + + $DIRECTORY/bin/ossec-control stop + + # We also need to remove all syscheck queue file (format changed) + if [ "X$VERSION" = "X0.9-3" ]; then + rm -f $DIRECTORY/queue/syscheck/* > /dev/null 2>&1 + rm -f $DIRECTORY/queue/agent-info/* > /dev/null 2>&1 + fi + rm -f $DIRECTORY/queue/syscheck/.* > /dev/null 2>&1 +} + + +########## +# UpdateOSSECRules +########## +UpdateOSSECRules() +{ + . ${OSSEC_INIT} + + OSSEC_CONF_FILE="$DIRECTORY/etc/ossec.conf" + + # Backing up the old config + cp -pr ${OSSEC_CONF_FILE} "${OSSEC_CONF_FILE}.$$.bak" + + cat ${OSSEC_CONF_FILE}|grep -v "" |grep -v "" |grep -v "" > "${OSSEC_CONF_FILE}.$$.tmp" + + cat "${OSSEC_CONF_FILE}.$$.tmp" > ${OSSEC_CONF_FILE} + rm "${OSSEC_CONF_FILE}.$$.tmp" + echo "" >> ${OSSEC_CONF_FILE} + echo " " >> ${OSSEC_CONF_FILE} + cat ${RULES_TEMPLATE} >> ${OSSEC_CONF_FILE} + echo " " >> ${OSSEC_CONF_FILE} +} diff --git a/src/logcollector/COPYRIGHT b/src/logcollector/COPYRIGHT new file mode 100755 index 0000000..cd65eb1 --- /dev/null +++ b/src/logcollector/COPYRIGHT @@ -0,0 +1,9 @@ +Copyright (C) 2009 Trend Micro Inc. + All right reserved. + This program is a free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License (version 3) as published by the FSF - Free Software + Foundation + +OSSEC, logcollector. +Available at http://www.ossec.net/hids/ diff --git a/src/logcollector/Makefile b/src/logcollector/Makefile new file mode 100755 index 0000000..298c065 --- /dev/null +++ b/src/logcollector/Makefile @@ -0,0 +1,19 @@ +# Makefile for logcollector +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +PT=../ +NAME=ossec-logcollector + +include ../Config.Make + + +logr_OBJS = *.c ${OS_CONFIG} ${OS_SHARED} ${OS_XML} ${OS_REGEX} ${OS_NET} ${OS_CRYPTO} + +logcollector: + ${CC} ${CFLAGS} ${OS_LINK} -DARGV0=\"${NAME}\" ${logr_OBJS} -o ${NAME} + +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/logcollector/VERSION b/src/logcollector/VERSION new file mode 100755 index 0000000..be58634 --- /dev/null +++ b/src/logcollector/VERSION @@ -0,0 +1 @@ +0.3 diff --git a/src/logcollector/config.c b/src/logcollector/config.c new file mode 100755 index 0000000..67ed253 --- /dev/null +++ b/src/logcollector/config.c @@ -0,0 +1,51 @@ +/* @(#) $Id: config.c,v 1.20 2009/06/24 18:52:13 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* v0.3 (2005/08/23): Using the new OS_XML syntax and changing some usage + * v0.2 (2005/01/17) + */ + + +#include "shared.h" + +#include "logcollector.h" + + +/* LogCollectorConfig v0.3, 2005/03/03 + * Read the config file (the localfiles) + * v0.3: Changed for the new OS_XML + */ +int LogCollectorConfig(char * cfgfile) +{ + int modules = 0; + + logreader_config log_config; + + modules|= CLOCALFILE; + + log_config.config = NULL; + + if(ReadConfig(modules, cfgfile, &log_config, NULL) < 0) + return(OS_INVALID); + + #ifdef CLIENT + modules|= CAGENT_CONFIG; + ReadConfig(modules, AGENTCONFIG, &log_config, NULL); + #endif + + logff = log_config.config; + + return(1); + + +} + +/* EOF */ diff --git a/src/logcollector/logcollector.c b/src/logcollector/logcollector.c new file mode 100755 index 0000000..f14f007 --- /dev/null +++ b/src/logcollector/logcollector.c @@ -0,0 +1,703 @@ +/* @(#) $Id: logcollector.c,v 1.59 2009/11/03 21:07:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + + +#include "shared.h" + +#include "logcollector.h" + +int _cday = 0; +int update_fname(int i); + + +/** void LogCollectorStart() v0.4 + * Handle file management. + */ +void LogCollectorStart() +{ + int i = 0, r = 0; + int max_file = 0; + int f_check = 0; + + /* To check for inode changes */ + struct stat tmp_stat; + + + #ifndef WIN32 + + int int_error = 0; + struct timeval fp_timeout; + + #else + + /* Checking if we are on vista. */ + checkVista(); + + + /* Reading vista descriptions. */ + if(isVista) + { + win_read_vista_sec(); + } + + #endif + + debug1("%s: DEBUG: Entering LogCollectorStart().", ARGV0); + + + /* Initializing each file and structure */ + for(i = 0;;i++) + { + if(logff[i].file == NULL) + break; + + + /* Removing duplicate entries. */ + for(r = 0; r < i; r++) + { + if(logff[r].file && strcmp(logff[i].file, logff[r].file) == 0) + { + merror("%s: WARN: Duplicated log file given: '%s'.", + ARGV0, logff[i].file); + logff[i].file = NULL; + logff[i].command = NULL; + logff[i].fp = NULL; + + break; + } + } + + if(logff[i].file == NULL) + { + /* do nothing, duplicated entry. */ + } + + else if(strcmp(logff[i].logformat,"eventlog") == 0) + { + #ifdef WIN32 + + verbose(READING_EVTLOG, ARGV0, logff[i].file); + win_startel(logff[i].file); + + #endif + logff[i].file = NULL; + logff[i].command = NULL; + logff[i].fp = NULL; + } + + else if(strcmp(logff[i].logformat, "command") == 0) + { + logff[i].file = NULL; + logff[i].fp = NULL; + + if(logff[i].command) + { + logff[i].read = (void *)read_command; + } + else + { + merror("%s: ERROR: Missing command argument. Ignoring it.", + ARGV0); + } + } + + else + { + logff[i].command = NULL; + + + /* Initializing the files */ + if(logff[i].ffile) + { + /* Day must be zero for all files to be initialized */ + _cday = 0; + if(update_fname(i)) + { + handle_file(i, 1, 1); + } + else + { + ErrorExit(PARSE_ERROR, ARGV0, logff[i].ffile); + } + + } + else + { + handle_file(i, 1, 1); + } + + verbose(READING_FILE, ARGV0, logff[i].file); + + /* Getting the log type */ + if(strcmp("snort-full", logff[i].logformat) == 0) + { + logff[i].read = (void *)read_snortfull; + } + else if(strcmp("nmapg", logff[i].logformat) == 0) + { + logff[i].read = (void *)read_nmapg; + } + else if(strcmp("mysql_log", logff[i].logformat) == 0) + { + logff[i].read = (void *)read_mysql_log; + } + else if(strcmp("mssql_log", logff[i].logformat) == 0) + { + logff[i].read = (void *)read_mssql_log; + } + else if(strcmp("postgresql_log", logff[i].logformat) == 0) + { + logff[i].read = (void *)read_postgresql_log; + } + else if(strcmp("djb-multilog", logff[i].logformat) == 0) + { + if(!init_djbmultilog(i)) + { + merror(INV_MULTILOG, ARGV0, logff[i].file); + if(logff[i].fp) + { + fclose(logff[i].fp); + logff[i].fp = NULL; + } + logff[i].file = NULL; + } + logff[i].read = (void *)read_djbmultilog; + } + else + { + logff[i].read = (void *)read_syslog; + } + + /* More tweaks for Windows. For some reason IIS places + * some wierd characters at the end of the files and getc + * always returns 0 (even after clearerr). + */ + #ifdef WIN32 + if(logff[i].fp) + { + logff[i].read(i, &r, 1); + } + #endif + } + } + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + max_file = i -1; + + + /* Cannot be zero */ + if(max_file < 0) + { + max_file = 0; + } + + + /* Daemon loop */ + while(1) + { + #ifndef WIN32 + fp_timeout.tv_sec = loop_timeout; + fp_timeout.tv_usec = 0; + + /* Waiting for the select timeout */ + if ((r = select(0, NULL, NULL, NULL, &fp_timeout)) < 0) + { + merror(SELECT_ERROR, ARGV0); + int_error++; + + if(int_error >= 5) + { + ErrorExit(SYSTEM_ERROR, ARGV0); + } + continue; + } + #else + + /* Windows don't like select that way */ + sleep(loop_timeout + 2); + + + /* Check for messages in the event viewer */ + win_readel(); + #endif + + f_check++; + + + /* Checking which file is available */ + for(i = 0; i <= max_file; i++) + { + if(!logff[i].fp) + { + /* Run the command. */ + if((f_check == VCHECK_FILES) && logff[i].command) + { + logff[i].read(i, &r, 0); + } + continue; + } + + /* Windows with IIS logs is very strange. + * For some reason it always returns 0 (not EOF) + * the fgetc. To solve this problem, we always + * pass it to the function pointer directly. + */ + #ifndef WIN32 + /* We check for the end of file. If is returns EOF, + * we don't attempt to read it. + */ + if((r = fgetc(logff[i].fp)) == EOF) + { + clearerr(logff[i].fp); + continue; + } + + + /* If it is not EOF, we need to return the read character */ + ungetc(r, logff[i].fp); + #endif + + + /* Finally, send to the function pointer to read it */ + logff[i].read(i, &r, 0); + + + /* Checking for error */ + if(!ferror(logff[i].fp)) + { + /* Clearing EOF */ + clearerr(logff[i].fp); + + /* Parsing error */ + if(r != 0) + { + logff[i].ign++; + } + } + /* If ferror is set */ + else + { + merror(FREAD_ERROR, ARGV0, logff[i].file); + #ifndef WIN32 + if(fseek(logff[i].fp, 0, SEEK_END) < 0) + #else + if(1) + #endif + { + + #ifndef WIN32 + merror(FSEEK_ERROR, ARGV0, logff[i].file); + #endif + + /* Closing the file */ + if(logff[i].fp) + { + fclose(logff[i].fp); + #ifdef WIN32 + CloseHandle(logff[i].h); + #endif + } + logff[i].fp = NULL; + + + /* Trying to open it again */ + if(handle_file(i, 1, 1) != 0) + { + logff[i].ign++; + continue; + } + + #ifdef WIN32 + logff[i].read(i, &r, 1); + #endif + } + + /* Increase the error count */ + logff[i].ign++; + clearerr(logff[i].fp); + } + } + + + /* Only check bellow if check > VCHECK_FILES */ + if(f_check <= VCHECK_FILES) + continue; + + + /* Send keep alive message */ + SendMSG(logr_queue, "--MARK--", "ossec-keepalive", LOCALFILE_MQ); + + + /* Zeroing f_check */ + f_check = 0; + + + /* Checking if any file has been renamed/removed */ + for(i = 0; i <= max_file; i++) + { + /* These are the windows logs or ignored files */ + if(!logff[i].file) + continue; + + + /* Files with date -- check for day change */ + if(logff[i].ffile) + { + if(update_fname(i)) + { + if(logff[i].fp) + { + fclose(logff[i].fp); + #ifdef WIN32 + CloseHandle(logff[i].h); + #endif + } + logff[i].fp = NULL; + handle_file(i, 0, 1); + continue; + } + + /* Variable file name */ + else if(!logff[i].fp) + { + handle_file(i, 0, 0); + continue; + } + } + + + /* Check for file change -- if the file is open already */ + if(logff[i].fp) + { + #ifndef WIN32 + if(stat(logff[i].file, &tmp_stat) == -1) + { + fclose(logff[i].fp); + logff[i].fp = NULL; + + merror(FILE_ERROR, ARGV0, logff[i].file); + } + + #else + BY_HANDLE_FILE_INFORMATION lpFileInformation; + HANDLE h1; + + h1 = CreateFile(logff[i].file, GENERIC_READ, + FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(h1 == INVALID_HANDLE_VALUE) + { + fclose(logff[i].fp); + CloseHandle(logff[i].h); + logff[i].fp = NULL; + merror(FILE_ERROR, ARGV0, logff[i].file); + } + else if(GetFileInformationByHandle(h1, &lpFileInformation) == 0) + { + fclose(logff[i].fp); + CloseHandle(logff[i].h); + CloseHandle(h1); + logff[i].fp = NULL; + merror(FILE_ERROR, ARGV0, logff[i].file);; + } + #endif + + + #ifdef WIN32 + else if(logff[i].fd != (lpFileInformation.nFileIndexLow + lpFileInformation.nFileIndexHigh)) + #else + else if(logff[i].fd != tmp_stat.st_ino) + #endif + { + char msg_alert[512 +1]; + + snprintf(msg_alert, 512, "ossec: File rotated (inode " + "changed): '%s'.", + logff[i].file); + + /* Send message about log rotated */ + SendMSG(logr_queue, msg_alert, + "ossec-logcollector", LOCALFILE_MQ); + + debug1("%s: DEBUG: File inode changed. %s", + ARGV0, logff[i].file); + + fclose(logff[i].fp); + + #ifdef WIN32 + CloseHandle(logff[i].h); + CloseHandle(h1); + #endif + + logff[i].fp = NULL; + handle_file(i, 0, 1); + continue; + } + #ifdef WIN32 + else if(logff[i].size > (lpFileInformation.nFileSizeHigh + lpFileInformation.nFileSizeLow)) + #else + else if(logff[i].size > tmp_stat.st_size) + #endif + { + char msg_alert[512 +1]; + + snprintf(msg_alert, 512, "ossec: File size reduced " + "(inode remained): '%s'.", + logff[i].file); + + /* Send message about log rotated */ + SendMSG(logr_queue, msg_alert, + "ossec-logcollector", LOCALFILE_MQ); + + debug1("%s: DEBUG: File size reduced. %s", + ARGV0, logff[i].file); + + + /* Fixing size so we don't alert more than once */ + logff[i].size = tmp_stat.st_size; + + + /* Getting new file. */ + fclose(logff[i].fp); + + #ifdef WIN32 + CloseHandle(logff[i].h); + CloseHandle(h1); + #endif + + logff[i].fp = NULL; + handle_file(i, 1, 1); + } + #ifdef WIN32 + else + { + CloseHandle(h1); + } + #endif + } + + + /* Too many errors for the file */ + if(logff[i].ign > open_file_attempts) + { + /* 999 Maximum ignore */ + if(logff[i].ign == 999) + { + continue; + } + + merror(LOGC_FILE_ERROR, ARGV0, logff[i].file); + if(logff[i].fp) + { + fclose(logff[i].fp); + #ifdef WIN32 + CloseHandle(logff[i].h); + #endif + } + + logff[i].fp = NULL; + + + /* If the file has a variable date, ignore it for + * today only. + */ + if(!logff[i].ffile) + { + /* Variable log files should always be attempted + * to be open... + */ + //logff[i].file = NULL; + } + logff[i].ign = 999; + continue; + } + + + /* File not opened */ + if(!logff[i].fp) + { + if(logff[i].ign >= 999) + continue; + else + { + /* Try for a few times to open the file */ + if(handle_file(i, 1, 1) < 0) + { + logff[i].ign++; + } + continue; + } + } + } + } +} + + + +/**int update_fname(int i): updates file name */ +int update_fname(int i) +{ + struct tm *p; + time_t __ctime = time(0); + + char lfile[OS_FLSIZE + 1]; + size_t ret; + + + p = localtime(&__ctime); + + + /* Handle file */ + if(p->tm_mday == _cday) + { + return(0); + } + + + lfile[OS_FLSIZE] = '\0'; + ret = strftime(lfile, OS_FLSIZE, logff[i].ffile, p); + if(ret == 0) + { + ErrorExit(PARSE_ERROR, ARGV0, logff[i].ffile); + } + + + /* Update the file name */ + if(strcmp(lfile, logff[i].file) != 0) + { + os_free(logff[i].file); + + os_strdup(lfile, logff[i].file); + + verbose(VAR_LOG_MON, ARGV0, logff[i].file); + + /* Setting cday to zero because other files may need + * to be changed. + */ + _cday = 0; + return(1); + } + + _cday = p->tm_mday; + return(0); +} + + +/* handle_file: Open, get the fileno, seek to the end and update mtime */ +int handle_file(int i, int do_fseek, int do_log) +{ + int fd; + struct stat stat_fd; + + /* We must be able to open the file, fseek and get the + * time of change from it. + */ + #ifndef WIN32 + logff[i].fp = fopen(logff[i].file, "r"); + if(!logff[i].fp) + { + if(do_log == 1) + { + merror(FOPEN_ERROR, ARGV0, logff[i].file); + } + return(-1); + } + /* Getting inode number for fp */ + fd = fileno(logff[i].fp); + if(fstat(fd, &stat_fd) == -1) + { + merror(FILE_ERROR,ARGV0,logff[i].file); + fclose(logff[i].fp); + logff[i].fp = NULL; + return(-1); + } + + logff[i].fd = stat_fd.st_ino; + logff[i].size = stat_fd.st_size; + + + #else + BY_HANDLE_FILE_INFORMATION lpFileInformation; + + logff[i].fp = NULL; + logff[i].h = CreateFile(logff[i].file, GENERIC_READ, + FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(logff[i].h == INVALID_HANDLE_VALUE) + { + if(do_log == 1) + { + merror(FOPEN_ERROR, ARGV0, logff[i].file); + } + return(-1); + } + fd = _open_osfhandle((long)logff[i].h, 0); + if(fd == -1) + { + merror(FOPEN_ERROR, ARGV0, logff[i].file); + CloseHandle(logff[i].h); + return(-1); + } + logff[i].fp = _fdopen(fd, "r"); + if(logff[i].fp == NULL) + { + merror(FOPEN_ERROR, ARGV0, logff[i].file); + CloseHandle(logff[i].h); + return(-1); + } + + + /* On windows, we also need the real inode, which is the combination + * of the index low + index high numbers. + */ + if(GetFileInformationByHandle(logff[i].h, &lpFileInformation) == 0) + { + merror("%s: Unable to get file information by handle.", ARGV0); + fclose(logff[i].fp); + CloseHandle(logff[i].h); + logff[i].fp = NULL; + return(-1); + } + + logff[i].fd = (lpFileInformation.nFileIndexLow + lpFileInformation.nFileIndexHigh); + logff[i].size = (lpFileInformation.nFileSizeHigh + lpFileInformation.nFileSizeLow); + + #endif + + + /* Only seek the end of the file if set to. */ + if(do_fseek == 1 && S_ISREG(stat_fd.st_mode)) + { + /* Windows and fseek causes some weird issues.. */ + #ifndef WIN32 + if(fseek(logff[i].fp, 0, SEEK_END) < 0) + { + merror(FSEEK_ERROR, ARGV0,logff[i].file); + fclose(logff[i].fp); + logff[i].fp = NULL; + return(-1); + } + #endif + } + + + /* Setting ignore to zero */ + logff[i].ign = 0; + return(0); +} + + +/* EOF */ diff --git a/src/logcollector/logcollector.h b/src/logcollector/logcollector.h new file mode 100755 index 0000000..143bcac --- /dev/null +++ b/src/logcollector/logcollector.h @@ -0,0 +1,87 @@ +/* @(#) $Id: logcollector.h,v 1.28 2009/11/03 21:07:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#ifndef __LOGREADER_H + +#define __LOGREADER_H + +#ifndef ARGV0 +#define ARGV0 "ossec-logcollector" +#endif + + +#include "shared.h" +#include "config/localfile-config.h" +#include "config/config.h" + + + + +/*** Function prototypes ***/ + + +/* Read logcollector config */ +int LogCollectorConfig(char * cfgfile); + +/* Stary log collector daemon */ +void LogCollectorStart(); + +/* Handle files */ +int handle_file(int i, int do_fseek, int do_log); + +/* Read syslog file */ +void *read_syslog(int pos, int *rc, int drop_it); + +/* Read snort full file */ +void *read_snortfull(int pos, int *rc, int drop_it); + +/* Read nmap grepable format */ +void *read_nmapg(int pos, int *rc, int drop_it); + +/* Read mysql log format */ +void *read_mysql_log(int pos, int *rc, int drop_it); + +/* Read mysql log format */ +void *read_mssql_log(int pos, int *rc, int drop_it); + +/* Read postgresql log format */ +void *read_postgresql_log(int pos, int *rc, int drop_it); + +/* Read DJB multilog format */ +/* Initializes multilog. */ +int init_djbmultilog(int pos); +void *read_djbmultilog(int pos, int *rc, int drop_it); + + +/* Read events from output of command */ +void *read_command(int pos, int *rc, int drop_it); + + +#ifdef WIN32 +/* Windows only */ +void win_startel(); +void win_readel(); +void win_read_vista_sec(); +#endif + + +/*** Global variables ***/ + + +int loop_timeout; +int logr_queue; +int open_file_attempts; +logreader *logff; + + +#endif diff --git a/src/logcollector/main.c b/src/logcollector/main.c new file mode 100755 index 0000000..5340c85 --- /dev/null +++ b/src/logcollector/main.c @@ -0,0 +1,173 @@ +/* @(#) $Id: main.c,v 1.27 2009/11/18 19:07:40 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* v0.4 (2005/11/11): Some cleanup and bug fixes + * v0.3 (2005/08/26): Reading all files in just one process + * v0.2 (2005/04/04): + */ + + +/* Logcollector daemon. + * Monitor some files and forward the output to our analysis system. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "os_regex/os_regex.h" + +#include "logcollector.h" + + + +/* main: v0.3: 2005/04/04 */ +int main(int argc, char **argv) +{ + int c; + int debug_flag = 0; + int test_config = 0,run_foreground = 0; + char *cfg = DEFAULTCPATH; + char *dir = DEFAULTDIR; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "VtdhfD:c:")) != -1) + { + switch(c) + { + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir = optarg; + break; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + debug1(STARTED_MSG,ARGV0); + + + /* Reading config file */ + if(LogCollectorConfig(cfg) < 0) + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + + + /* Getting loop timeout */ + loop_timeout = getDefine_Int("logcollector", + "loop_timeout", + 1, 120); + + open_file_attempts = getDefine_Int("logcollector", "open_attempts", + 2, 998); + + debug_flag = getDefine_Int("logcollector", + "debug", + 0,2); + + /* Getting debug values */ + while(debug_flag != 0) + { + nowDebug(); + debug_flag--; + } + + + /* Exit if test config */ + if(test_config) + exit(0); + + + /* No file available to monitor -- continue */ + if(logff == NULL) + { + os_calloc(2, sizeof(logreader), logff); + logff[0].file = NULL; + logff[0].ffile = NULL; + logff[0].logformat = NULL; + logff[0].fp = NULL; + logff[1].file = NULL; + logff[1].logformat = NULL; + + merror(NO_FILE, ARGV0); + } + + + /* Starting signal handler */ + StartSIG(ARGV0); + + + if (!run_foreground) + { + /* Going on daemon mode */ + nowDaemon(); + goDaemon(); + } + + + /* Creating PID file */ + if(CreatePID(ARGV0, getpid()) < 0) + merror(PID_ERROR, ARGV0); + + + + /* Waiting 6 seconds for the analysisd/agentd to settle */ + debug1("%s: DEBUG: Waiting main daemons to settle.", ARGV0); + sleep(6); + + + /* Starting the queue. */ + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + + + /* Main loop */ + LogCollectorStart(); + + + return(0); +} + + + +/* EOF */ diff --git a/src/logcollector/read_command.c b/src/logcollector/read_command.c new file mode 100755 index 0000000..9c1f7ca --- /dev/null +++ b/src/logcollector/read_command.c @@ -0,0 +1,83 @@ +/* @(#) $Id: read_command.c,v 1.3 2009/11/05 19:55:34 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Read the syslog */ + + +#include "shared.h" +#include "logcollector.h" + + + +/* Read Output of commands */ +void *read_command(int pos, int *rc, int drop_it) +{ + int cmd_size = 0; + char *p; + char str[OS_MAXSTR+1]; + + FILE *cmd_output; + + str[OS_MAXSTR]= '\0'; + *rc = 0; + + + debug2("%s: DEBUG: Running command '%s'", ARGV0, logff[pos].command); + + + cmd_output = popen(logff[pos].command, "r"); + if(!cmd_output) + { + merror("%s: ERROR: Unable to execute command: '%s'.", + ARGV0, logff[pos].command); + + logff[pos].command = NULL; + } + + + snprintf(str, 256, "ossec: output: '%s': ", logff[pos].command); + cmd_size = strlen(str); + + + while(fgets(str + cmd_size, OS_MAXSTR - OS_LOG_HEADER - 256, cmd_output) != NULL) + { + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + *p = '\0'; + } + + debug2("%s: DEBUG: Reading command message: '%s'", ARGV0, str); + + + /* Sending message to queue */ + if(drop_it == 0) + { + if(SendMSG(logr_queue,str,logff[pos].command, + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + continue; + } + + pclose(cmd_output); + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_djb_multilog.c b/src/logcollector/read_djb_multilog.c new file mode 100755 index 0000000..8a6ceec --- /dev/null +++ b/src/logcollector/read_djb_multilog.c @@ -0,0 +1,232 @@ +/* @(#) $Id: read_djb_multilog.c,v 1.4 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Read DJB multilog */ + + +#include "shared.h" +#include "logcollector.h" + + +/* To translante between month (int) to month (char) */ +char *(djb_month[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", + "Sep","Oct","Nov","Dec"}; + +char djb_host[512 +1]; + + + +/* Initializes multilog. */ +int init_djbmultilog(int pos) +{ + char *djbp_name = NULL; + char *tmp_str = NULL; + + + logff[pos].djb_program_name = NULL; + + + /* Initializing hostname. */ + memset(djb_host, '\0', 512 +1); + + #ifndef WIN32 + if(gethostname(djb_host, 512 -1) != 0) + { + strncpy(djb_host, "unknown", 512 -1); + } + else + { + char *_ltmp; + + /* Remove domain part if available */ + _ltmp = strchr(djb_host, '.'); + if(_ltmp) + *_ltmp = '\0'; + } + #else + strncpy(djb_host, "win32", 512 -1); + #endif + + + + /* Multilog must be in the following format: /path/program_name/current */ + tmp_str = strrchr(logff[pos].file, '/'); + if(!tmp_str) + return(0); + + + /* Must end with /current and must not be in the beginning of the string. */ + if((strcmp(tmp_str, "/current") != 0) || (tmp_str == logff[pos].file)) + { + return(0); + } + + + tmp_str[0] = '\0'; + + + /* Getting final name. */ + djbp_name = strrchr(logff[pos].file, '/'); + if(djbp_name == logff[pos].file) + { + tmp_str[0] = '/'; + return(0); + } + + + os_strdup(djbp_name+1, logff[pos].djb_program_name); + tmp_str[0] = '/'; + + + verbose("%s: INFO: Using program name '%s' for DJB multilog file: '%s'.", + ARGV0, logff[pos].djb_program_name, logff[pos].file); + + + return(1); +} + + + +/* Read DJB multilog. */ +void *read_djbmultilog(int pos, int *rc, int drop_it) +{ + int str_len = 0; + int need_clear = 0; + char *p; + char str[OS_MAXSTR + 1]; + char buffer[OS_MAXSTR + 1]; + + str[OS_MAXSTR]= '\0'; + *rc = 0; + + + /* Must have a valid program name. */ + if(!logff[pos].djb_program_name) + { + return(NULL); + } + + + + /* Getting new entry */ + while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) + { + + /* Getting buffer size */ + str_len = strlen(str); + + + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + *p = '\0'; + + /* If need clear is set, we just get the line and ignore it. */ + if(need_clear) + { + need_clear = 0; + continue; + } + } + else + { + need_clear = 1; + } + + + /* Multilog messages have the following format: + * @40000000463246020c2ca16c xx... + */ + if((str_len > 26) && + (str[0] == '@') && + isalnum((int)str[1]) && + isalnum((int)str[2]) && + isalnum((int)str[3]) && + isalnum((int)str[24]) && + (str[25] == ' ')) + { + /* Removing spaces and tabs */ + p = str + 26; + while(*p == ' ' || *p == '\t') + { + p++; + } + + + /* If message has a valid syslog header, send as is. */ + if((str_len > 44) && + (p[3] == ' ') && + (p[6] == ' ') && + (p[9] == ':') && + (p[12] == ':') && + (p[15] == ' ')) + { + p+=16; + strncpy(buffer, p, OS_MAXSTR); + } + else + { + /* We will add a proper syslog header. */ + time_t djbtime; + struct tm *pt; + + + djbtime = time(NULL); + pt = localtime(&djbtime); + + + /* Syslog time: Apr 27 14:50:32 */ + snprintf(buffer, OS_MAXSTR, "%s %02d %02d:%02d:%02d %s %s: %s", + djb_month[pt->tm_mon], + pt->tm_mday, + pt->tm_hour, + pt->tm_min, + pt->tm_sec, + djb_host, + logff[pos].djb_program_name, + p); + } + } + + + else + { + debug2("%s: DEBUG: Invalid DJB log: '%s'", ARGV0, str); + continue; + } + + + debug2("%s: DEBUG: Reading DJB multilog message: '%s'", ARGV0, buffer); + + + /* Sending message to queue */ + if(drop_it == 0) + { + if(SendMSG(logr_queue, buffer, logff[pos].file, MYSQL_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + continue; + } + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_mssql_log.c b/src/logcollector/read_mssql_log.c new file mode 100755 index 0000000..025a7cd --- /dev/null +++ b/src/logcollector/read_mssql_log.c @@ -0,0 +1,195 @@ +/* @(#) $Id: read_mssql_log.c,v 1.2 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Read MSSQL logs */ + + +#include "shared.h" +#include "logcollector.h" + + + +/* Send mssql message and check the return code. + */ +void __send_mssql_msg(int pos, int drop_it, char *buffer) +{ + debug2("%s: DEBUG: Reading MSSQL message: '%s'", ARGV0, buffer); + if(drop_it == 0) + { + if(SendMSG(logr_queue, buffer, logff[pos].file, LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } +} + + + +/* Read PostgreSQL log files */ +void *read_mssql_log(int pos, int *rc, int drop_it) +{ + int str_len = 0; + int need_clear = 0; + char *p; + char str[OS_MAXSTR + 1]; + char buffer[OS_MAXSTR + 1]; + + + /* Zeroing buffer and str */ + buffer[0] = '\0'; + buffer[OS_MAXSTR] = '\0'; + str[OS_MAXSTR]= '\0'; + *rc = 0; + + + /* Getting new entry */ + while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) + { + + /* Getting buffer size */ + str_len = strlen(str); + + + /* Checking str_len size. Very useless, but just to make sure.. */ + if(str_len >= sizeof(buffer) -2) + { + str_len = sizeof(buffer) -10; + } + + + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + *p = '\0'; + + /* If need clear is set, we just get the line and ignore it. */ + if(need_clear) + { + need_clear = 0; + continue; + } + } + else + { + need_clear = 1; + } + + + #ifdef WIN32 + if ((p = strrchr(str, '\r')) != NULL) + { + *p = '\0'; + } + + + /* Looking for empty string (only on windows) */ + if(str_len <= 1) + { + continue; + } + + + /* Windows can have comment on their logs */ + if(str[0] == '#') + { + continue; + } + #endif + + + + /* MSSQL messages have the following formats: + * 2009-03-25 04:47:30.01 Server + * 2003-10-09 00:00:06.68 sys1 + * 2009-02-06 11:48:59 Server + */ + if((str_len > 19) && + (str[4] == '-') && + (str[7] == '-') && + (str[10] == ' ') && + (str[13] == ':') && + (str[16] == ':') && + isdigit((int)str[0]) && + isdigit((int)str[1]) && + isdigit((int)str[2]) && + isdigit((int)str[3])) + { + + /* If the saved message is empty, set it and continue. */ + if(buffer[0] == '\0') + { + strncpy(buffer, str, str_len + 2); + continue; + } + + /* If not, send the saved one and store the new one for later */ + else + { + __send_mssql_msg(pos, drop_it, buffer); + + + /* Storing current one at the buffer */ + strncpy(buffer, str, str_len + 2); + } + } + + + /* Query logs can be in multiple lines. + * They always start with a tab in the additional ones. + */ + else if((str_len > 2) && (buffer[0] != '\0')) + { + /* Size of the buffer */ + int buffer_len = strlen(buffer); + + p = str; + + /* Removing extra spaces and tabs */ + while(*p == ' ' || *p == '\t') + { + p++; + } + + + /* Adding additional message to the saved buffer. */ + if(sizeof(buffer) - buffer_len > str_len +256) + { + /* Here we make sure that the size of the buffer + * minus what was used (strlen) is greater than + * the length of the received message. + */ + buffer[buffer_len] = ' '; + buffer[buffer_len +1] = '\0'; + strncat(buffer, str, str_len +3); + } + } + + continue; + } + + + /* Send whatever is stored. */ + if(buffer[0] != '\0') + { + __send_mssql_msg(pos, drop_it, buffer); + } + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_mysql_log.c b/src/logcollector/read_mysql_log.c new file mode 100755 index 0000000..926a760 --- /dev/null +++ b/src/logcollector/read_mysql_log.c @@ -0,0 +1,178 @@ +/* @(#) $Id: read_mysql_log.c,v 1.5 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Read MySQL logs */ + + +#include "shared.h" +#include "logcollector.h" + + +/* Starting last time */ +char __mysql_last_time[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + + +/* Read syslog files/snort fast/apache files */ +void *read_mysql_log(int pos, int *rc, int drop_it) +{ + int str_len = 0; + int need_clear = 0; + char *p; + char str[OS_MAXSTR + 1]; + char buffer[OS_MAXSTR + 1]; + + str[OS_MAXSTR]= '\0'; + *rc = 0; + + + /* Getting new entry */ + while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) + { + + /* Getting buffer size */ + str_len = strlen(str); + + + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + *p = '\0'; + + /* If need clear is set, we just get the line and ignore it. */ + if(need_clear) + { + need_clear = 0; + continue; + } + } + else + { + need_clear = 1; + } + + + #ifdef WIN32 + if ((p = strrchr(str, '\r')) != NULL) + { + *p = '\0'; + } + + + /* Looking for empty string (only on windows) */ + if(str_len <= 2) + { + continue; + } + + + /* Windows can have comment on their logs */ + if(str[0] == '#') + { + continue; + } + #endif + + + /* Mysql messages have the following format: + * 070823 21:01:30 xx + */ + if((str_len > 18) && + (str[6] == ' ') && + (str[9] == ':') && + (str[12] == ':') && + isdigit((int)str[0]) && + isdigit((int)str[1]) && + isdigit((int)str[2]) && + isdigit((int)str[3]) && + isdigit((int)str[4]) && + isdigit((int)str[5]) && + isdigit((int)str[7]) && + isdigit((int)str[8])) + { + /* Saving last time */ + strncpy(__mysql_last_time, str, 16); + __mysql_last_time[15] = '\0'; + + + /* Removing spaces and tabs */ + p = str + 15; + while(*p == ' ' || *p == '\t') + { + p++; + } + + + /* Valid MySQL message */ + snprintf(buffer, OS_MAXSTR, "MySQL log: %s %s", + __mysql_last_time, p); + } + + + /* Multiple events at the same second share the same + * time stamp. + * 0909 2020 2020 2020 20 + */ + else if((str_len > 10) && (__mysql_last_time[0] != '\0') && + (str[0] == 0x09) && + (str[1] == 0x09) && + (str[2] == 0x20) && + (str[3] == 0x20) && + (str[4] == 0x20) && + (str[5] == 0x20) && + (str[6] == 0x20) && + (str[7] == 0x20)) + { + p = str +2; + + + /* Removing extra spaces and tabs */ + while(*p == ' ' || *p == '\t') + { + p++; + } + + /* Valid MySQL message */ + snprintf(buffer, OS_MAXSTR, "MySQL log: %s %s", + __mysql_last_time, p); + } + else + { + continue; + } + + + debug2("%s: DEBUG: Reading mysql messages: '%s'", ARGV0, buffer); + + + /* Sending message to queue */ + if(drop_it == 0) + { + if(SendMSG(logr_queue, buffer, logff[pos].file, MYSQL_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + continue; + } + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_nmapg.c b/src/logcollector/read_nmapg.c new file mode 100755 index 0000000..d06648a --- /dev/null +++ b/src/logcollector/read_nmapg.c @@ -0,0 +1,325 @@ +/* @(#) $Id: read_nmapg.c,v 1.11 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "logcollector.h" + + +#define NMAPG_HOST "Host: " +#define NMAPG_PORT "Ports:" +#define NMAPG_OPEN "open/" +#define NMAPG_STAT "Status:" + + + +/** Function Prototypes **/ +static char *__go_after(char *x, char *y); +static char *__get_port(char *str, char *proto, char *port, int msize); + + + +/* Get port and protocol. + */ +static char *__get_port(char *str, char *proto, char *port, int msize) +{ + int filtered = 0; + char *p, *q; + + + /* Removing white spaces */ + while(*str == ' ') + { + str++; + } + + + /* Getting port */ + p = strchr(str, '/'); + if(!p) + return(NULL); + *p = '\0'; + p++; + + + /* Getting port */ + strncpy(port, str, msize); + port[msize -1] = '\0'; + + + + /* Checking if the port is open */ + q = __go_after(p, NMAPG_OPEN); + if(!q) + { + /* Port is not open */ + filtered = 1; + q = p; + + + /* Going to the start of protocol field */ + p = strchr(q, '/'); + if(!p) + return(NULL); + p++; + } + else + { + p = q; + } + + + + /* Getting protocol */ + str = p; + p = strchr(str, '/'); + if(!p) + { + return(NULL); + } + *p = '\0'; + p++; + + + strncpy(proto, str, msize); + proto[msize -1] = '\0'; + + + /* Setting proto to null if port is not open */ + if(filtered) + proto[0] = '\0'; + + + /* Removing slashes */ + if(*p == '/') + { + p++; + q = p; + p = strchr(p, ','); + if(p) + { + return(p); + } + + return(q); + } + + + return(NULL); +} + + +/* Check if the string matches. + */ +static char *__go_after(char *x, char *y) +{ + int x_s; + int y_s; + + /* X and Y must be not null */ + if(!x || !y) + return(NULL); + + x_s = strlen(x); + y_s = strlen(y); + + if(x_s <= y_s) + { + return(NULL); + } + + /* String does not match */ + if(strncmp(x,y,y_s) != 0) + { + return(NULL); + } + + x+=y_s; + + return(x); +} + + +/* Read Nmap grepable files */ +void *read_nmapg(int pos, int *rc, int drop_it) +{ + int final_msg_s; + int need_clear = 0; + + char str[OS_MAXSTR + 1]; + char final_msg[OS_MAXSTR + 1]; + char buffer[OS_MAXSTR + 1]; + char port[17]; + char proto[17]; + + char *ip = NULL; + char *p; + char *q; + + *rc = 0; + str[OS_MAXSTR] = '\0'; + final_msg[OS_MAXSTR] = '\0'; + buffer[OS_MAXSTR] = '\0'; + + port[16] = '\0'; + proto[16] = '\0'; + + while(fgets(str, OS_MAXSTR -OS_LOG_HEADER, logff[pos].fp) != NULL) + { + /* If need clear is set, we need to clear the line */ + if(need_clear) + { + if((q = strchr(str, '\n')) != NULL) + { + need_clear = 0; + } + continue; + } + + /* Removing \n at the end of the string */ + if ((q = strchr(str, '\n')) != NULL) + { + *q = '\0'; + } + else + { + need_clear = 1; + } + + + /* Do not get commented lines */ + if((str[0] == '#') || (str[0] == '\0')) + { + continue; + } + + + /* Getting host */ + q = __go_after(str, NMAPG_HOST); + if(!q) + { + goto file_error; + } + + + /* Getting ip/hostname */ + p = strchr(q, ')'); + if(!p) + { + goto file_error; + } + + + /* Setting the valid ip */ + ip = q; + + + + /* Getting the ports */ + q = strchr(p, '\t'); + if(!q) + { + goto file_error; + } + q++; + + + /* Now fixing p, to have the closing parenthesis */ + p++; + *p = '\0'; + + + /* q now should point to the ports */ + p = __go_after(q, NMAPG_PORT); + if(!p) + { + /* Checking if no port is available */ + p = __go_after(q, NMAPG_STAT); + if(p) + { + continue; + } + + goto file_error; + } + + + /* Generating final msg */ + snprintf(final_msg, OS_MAXSTR, "Host: %s, open ports:", + ip); + final_msg_s = OS_MAXSTR - ((strlen(final_msg) +3)); + + + /* Getting port and protocol */ + do + { + /* Avoid filling the buffer (3*port size). */ + if(final_msg_s < 27) + { + break; + } + + p = __get_port(p, proto, port, 9); + if(!p) + { + debug1("%s: Bad formated nmap grepable file (port).", ARGV0); + break; + } + + + /* Port not open */ + if(proto[0] == '\0') + { + continue; + } + + + /* Adding ports */ + snprintf(buffer, OS_MAXSTR, " %s(%s)", port, proto); + strncat(final_msg, buffer, final_msg_s); + final_msg_s-=(strlen(buffer) +2); + + }while(*p == ',' && (p++)); + + + if(drop_it == 0) + { + /* Sending message to queue */ + if(SendMSG(logr_queue, final_msg, logff[pos].file, + HOSTINFO_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + + /* Getting next */ + continue; + + + /* Handling errors */ + file_error: + + merror("%s: Bad formated nmap grepable file.", ARGV0); + *rc = -1; + return(NULL); + + } + + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_postgresql_log.c b/src/logcollector/read_postgresql_log.c new file mode 100755 index 0000000..d2262d5 --- /dev/null +++ b/src/logcollector/read_postgresql_log.c @@ -0,0 +1,193 @@ +/* @(#) $Id: read_postgresql_log.c,v 1.5 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Read PostgreSQL logs */ + + +#include "shared.h" +#include "logcollector.h" + + + +/* Send pgsql message and check the return code. + */ +void __send_pgsql_msg(int pos, int drop_it, char *buffer) +{ + debug2("%s: DEBUG: Reading PostgreSQL message: '%s'", ARGV0, buffer); + if(drop_it == 0) + { + if(SendMSG(logr_queue, buffer, logff[pos].file, POSTGRESQL_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } +} + + + +/* Read PostgreSQL log files */ +void *read_postgresql_log(int pos, int *rc, int drop_it) +{ + int str_len = 0; + int need_clear = 0; + char *p; + char str[OS_MAXSTR + 1]; + char buffer[OS_MAXSTR + 1]; + + + /* Zeroing buffer and str */ + buffer[0] = '\0'; + buffer[OS_MAXSTR] = '\0'; + str[OS_MAXSTR]= '\0'; + *rc = 0; + + + /* Getting new entry */ + while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) + { + + /* Getting buffer size */ + str_len = strlen(str); + + + /* Checking str_len size. Very useless, but just to make sure.. */ + if(str_len >= sizeof(buffer) -2) + { + str_len = sizeof(buffer) -10; + } + + + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + *p = '\0'; + + /* If need clear is set, we just get the line and ignore it. */ + if(need_clear) + { + need_clear = 0; + continue; + } + } + else + { + need_clear = 1; + } + + + #ifdef WIN32 + if ((p = strrchr(str, '\r')) != NULL) + { + *p = '\0'; + } + + + /* Looking for empty string (only on windows) */ + if(str_len <= 1) + { + continue; + } + + + /* Windows can have comment on their logs */ + if(str[0] == '#') + { + continue; + } + #endif + + + + /* PostgreSQL messages have the following format: + * [2007-08-31 19:17:32.186 ADT] 192.168.2.99:db_name + */ + if((str_len > 32) && + (str[0] == '[') && + (str[5] == '-') && + (str[8] == '-') && + (str[11] == ' ') && + (str[14] == ':') && + (str[17] == ':') && + isdigit((int)str[1]) && + isdigit((int)str[12])) + { + + /* If the saved message is empty, set it and continue. */ + if(buffer[0] == '\0') + { + strncpy(buffer, str, str_len + 2); + continue; + } + + /* If not, send the saved one and store the new one for later */ + else + { + __send_pgsql_msg(pos, drop_it, buffer); + + + /* Storing current one at the buffer */ + strncpy(buffer, str, str_len + 2); + } + } + + + /* Query logs can be in multiple lines. + * They always start with a tab in the additional ones. + */ + else if((str_len > 2) && (buffer[0] != '\0') && + (str[0] == '\t')) + { + /* Size of the buffer */ + int buffer_len = strlen(buffer); + + p = str +1; + + /* Removing extra spaces and tabs */ + while(*p == ' ' || *p == '\t') + { + p++; + } + + + /* Adding additional message to the saved buffer. */ + if(sizeof(buffer) - buffer_len > str_len +256) + { + /* Here we make sure that the size of the buffer + * minus what was used (strlen) is greater than + * the length of the received message. + */ + buffer[buffer_len] = ' '; + buffer[buffer_len +1] = '\0'; + strncat(buffer, str, str_len +3); + } + } + + continue; + } + + + /* Send whatever is stored. */ + if(buffer[0] != '\0') + { + __send_pgsql_msg(pos, drop_it, buffer); + } + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_snortfull.c b/src/logcollector/read_snortfull.c new file mode 100755 index 0000000..56d09c5 --- /dev/null +++ b/src/logcollector/read_snortfull.c @@ -0,0 +1,163 @@ +/* @(#) $Id: read_snortfull.c,v 1.19 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* v0.4 (2006/01/13): Fixing to read snort-full logs correctly. + * + */ + + +#include "shared.h" +#include "logcollector.h" + + +/* Read snort_full files */ +void *read_snortfull(int pos, int *rc, int drop_it) +{ + int f_msg_size = OS_MAXSTR; + + char *one = "one"; + char *two = "two"; + + char *p = NULL; + char *q; + char str[OS_MAXSTR + 1]; + char f_msg[OS_MAXSTR +1]; + + *rc = 0; + str[OS_MAXSTR]='\0'; + f_msg[OS_MAXSTR] = '\0'; + + while(fgets(str, OS_MAXSTR, logff[pos].fp) != NULL) + { + /* Removing \n at the end of the string */ + if ((q = strrchr(str, '\n')) != NULL) + { + *q = '\0'; + } + else + { + goto file_error; + } + + /* First part of the message */ + if(p == NULL) + { + if(strncmp(str, "[**] [", 6) == 0) + { + strncpy(f_msg, str, OS_MAXSTR); + f_msg_size -= strlen(str)+1; + p = one; + } + } + else + { + if(p == one) + { + /* Second line has the [Classification: */ + if(strncmp(str, "[Classification: ", 16) == 0) + { + strncat(f_msg, str, f_msg_size); + f_msg_size -= strlen(str)+1; + p = two; + } + else if(strncmp(str, "[Priority: ", 10) == 0) + { + strncat(f_msg, "[Classification: Preprocessor] " + "[Priority: 3] ", f_msg_size); + f_msg_size -= strlen(str)+1; + p = two; + } + + /* If it is a preprocessor message, it will not have + * the classification. + */ + else if((str[2] == '/')&&(str[5] == '-')&&(q = strchr(str,' '))) + { + strncat(f_msg, "[Classification: Preprocessor] " + "[Priority: 3] ", f_msg_size); + strncat(f_msg, ++q, f_msg_size -40); + + /* Cleaning for next event */ + p = NULL; + + /* Sending the message */ + if(drop_it == 0) + { + if(SendMSG(logr_queue,f_msg, logff[pos].file, + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + f_msg[0] = '\0'; + f_msg_size = OS_MAXSTR; + str[0] = '\0'; + } + else + { + goto file_error; + } + } + else if(p == two) + { + /* Third line has the 01/13-15 (date) */ + if((str[2] == '/')&&(str[5] == '-')&&(q = strchr(str,' '))) + { + strncat(f_msg, ++q, f_msg_size); + f_msg_size -= strlen(q)+1; + p = NULL; + + /* Sending the message */ + if(drop_it == 0) + { + if(SendMSG(logr_queue,f_msg, logff[pos].file, + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + f_msg[0] = '\0'; + f_msg_size = OS_MAXSTR; + str[0] = '\0'; + } + else + { + goto file_error; + } + + } + } + + continue; + + file_error: + + merror("%s: Bad formated snort full file.", ARGV0); + *rc = -1; + return(NULL); + + } + + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_syslog.c b/src/logcollector/read_syslog.c new file mode 100755 index 0000000..5f0bd69 --- /dev/null +++ b/src/logcollector/read_syslog.c @@ -0,0 +1,123 @@ +/* @(#) $Id: read_syslog.c,v 1.24 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Read the syslog */ + + +#include "shared.h" +#include "logcollector.h" + + + +/* v0.3 (2005/08/24): Using fgets instead of fgetc + * v0.2 (2005/04/04) + */ + +/* Read syslog files/snort fast/apache files */ +void *read_syslog(int pos, int *rc, int drop_it) +{ + int __ms = 0; + char *p; + char str[OS_MAXSTR+1]; + + fpos_t fp_pos; + + str[OS_MAXSTR]= '\0'; + *rc = 0; + + /* Getting initial file location */ + fgetpos(logff[pos].fp, &fp_pos); + + while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) + { + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + *p = '\0'; + } + + /* If we didn't get the new line, because the + * size is large, send what we got so far. + */ + else if(strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2)) + { + /* Message size > maximum allowed */ + __ms = 1; + } + else + { + /* Message not complete. Return. */ + debug1("%s: Message not complete. Trying again: '%s'", ARGV0,str); + fsetpos(logff[pos].fp, &fp_pos); + break; + } + + #ifdef WIN32 + if ((p = strrchr(str, '\r')) != NULL) + { + *p = '\0'; + } + + /* Looking for empty string (only on windows) */ + if(strlen(str) <= 2) + { + fgetpos(logff[pos].fp, &fp_pos); + continue; + } + + /* Windows can have comment on their logs */ + if(str[0] == '#') + { + fgetpos(logff[pos].fp, &fp_pos); + continue; + } + #endif + + debug2("%s: DEBUG: Reading syslog message: '%s'", ARGV0, str); + + + /* Sending message to queue */ + if(drop_it == 0) + { + if(SendMSG(logr_queue,str,logff[pos].file, + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + } + + /* Incorrectly message size */ + if(__ms) + { + merror("%s: Large message size: '%s'", ARGV0, str); + while(fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL) + { + /* Getting the last occurence of \n */ + if ((p = strrchr(str, '\n')) != NULL) + { + break; + } + } + __ms = 0; + } + + fgetpos(logff[pos].fp, &fp_pos); + continue; + } + + return(NULL); +} + +/* EOF */ diff --git a/src/logcollector/read_win_el.c b/src/logcollector/read_win_el.c new file mode 100755 index 0000000..a0d077f --- /dev/null +++ b/src/logcollector/read_win_el.c @@ -0,0 +1,769 @@ +/* @(#) $Id: read_win_el.c,v 1.21 2009/09/04 19:23:11 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "logcollector.h" + + +/* This is only for windows */ +#ifdef WIN32 + +#define BUFFER_SIZE 2048*256 + + + +/* Event logging local structure */ +typedef struct _os_el +{ + int time_of_last; + char *name; + + EVENTLOGRECORD *er; + HANDLE h; + + DWORD record; + +}os_el; + + +/** Global variables **/ + +/* Maximum of 9 event log sources. */ +os_el el[9]; +int el_last = 0; +void *vista_sec_id_hash = NULL; +void *dll_hash = NULL; + + + +/** int startEL(char *app, os_el *el) + * Starts the event logging for each el + */ +int startEL(char *app, os_el *el) +{ + DWORD NumberOfRecords = 0; + + /* Opening the event log */ + el->h = OpenEventLog(NULL, app); + if(!el->h) + { + merror(EVTLOG_OPEN, ARGV0, app); + return(-1); + } + + el->name = app; + if(GetOldestEventLogRecord(el->h, &el->record) == 0) + { + /* Unable to read oldest event log record */ + merror(EVTLOG_GETLAST, ARGV0, app); + CloseEventLog(el->h); + el->h = NULL; + return(-1); + } + + if(GetNumberOfEventLogRecords(el->h, &NumberOfRecords) == 0) + { + merror(EVTLOG_GETLAST, ARGV0, app); + CloseEventLog(el->h); + el->h = NULL; + return(-1); + } + + if(NumberOfRecords <= 0) + { + return(0); + } + + return((int)NumberOfRecords); +} + + + +/** char *el_getCategory(int category_id) + * Returns a string related to the category id of the log. + */ +char *el_getCategory(int category_id) +{ + char *cat; + switch(category_id) + { + case EVENTLOG_ERROR_TYPE: + cat = "ERROR"; + break; + case EVENTLOG_WARNING_TYPE: + cat = "WARNING"; + break; + case EVENTLOG_INFORMATION_TYPE: + cat = "INFORMATION"; + break; + case EVENTLOG_AUDIT_SUCCESS: + cat = "AUDIT_SUCCESS"; + break; + case EVENTLOG_AUDIT_FAILURE: + cat = "AUDIT_FAILURE"; + break; + default: + cat = "Unknown"; + break; + } + return(cat); +} + + + +/** char *el_getEventDLL(char *evt_name, char *source, char *event) + * Returns the event. + */ +char *el_getEventDLL(char *evt_name, char *source, char *event) +{ + char *ret_str; + HKEY key; + DWORD ret; + char keyname[512]; + + + keyname[511] = '\0'; + + snprintf(keyname, 510, + "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s", + evt_name, + source); + + + /* Checking if we have it in memory. */ + ret_str = OSHash_Get(dll_hash, keyname + 42); + if(ret_str) + { + return(ret_str); + } + + + /* Opening registry */ + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, + KEY_ALL_ACCESS, &key) != ERROR_SUCCESS) + { + return(NULL); + } + + + ret = MAX_PATH -1; + if (RegQueryValueEx(key, "EventMessageFile", NULL, + NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS) + { + event[0] = '\0'; + RegCloseKey(key); + return(NULL); + } + else + { + /* Adding to memory. */ + char *skey; + char *sval; + + skey = strdup(keyname + 42); + sval = strdup(event); + + if(skey && sval) + { + OSHash_Add(dll_hash, skey, sval); + } + else + { + merror(MEM_ERROR, ARGV0); + } + } + + RegCloseKey(key); + return(event); +} + + + +/** char *el_vista_getmessage() + * Returns a descriptive message of the event - Vista only. + */ +char *el_vista_getMessage(int evt_id_int, LPTSTR *el_sstring) +{ + DWORD fm_flags = 0; + LPSTR message = NULL; + char *desc_string; + char evt_id[16]; + + + /* Flags for format event */ + fm_flags |= FORMAT_MESSAGE_FROM_STRING; + fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; + fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY; + + + /* Getting descriptive message. */ + evt_id[15] = '\0'; + snprintf(evt_id, 15, "%d", evt_id_int); + + desc_string = OSHash_Get(vista_sec_id_hash, evt_id); + if(!desc_string) + { + return(NULL); + } + + + if(!FormatMessage(fm_flags, desc_string, 0, 0, + (LPTSTR) &message, 0, el_sstring)) + { + return(NULL); + } + + return(message); +} + + + +/** char *el_getmessage() + * Returns a descriptive message of the event. + */ +char *el_getMessage(EVENTLOGRECORD *er, char *name, + char * source, LPTSTR *el_sstring) +{ + DWORD fm_flags = 0; + char tmp_str[257]; + char event[MAX_PATH +1]; + char *curr_str; + char *next_str; + LPSTR message = NULL; + + HMODULE hevt; + + /* Initializing variables */ + event[MAX_PATH] = '\0'; + tmp_str[256] = '\0'; + + + /* Flags for format event */ + fm_flags |= FORMAT_MESSAGE_FROM_HMODULE; + fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; + fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY; + + + + /* Get the file name from the registry (stored on event) */ + if(!(curr_str = el_getEventDLL(name, source, event))) + { + return(NULL); + } + + + + /* If our event has multiple libraries, try each one of them */ + while((next_str = strchr(curr_str, ';'))) + { + *next_str = '\0'; + + ExpandEnvironmentStrings(curr_str, tmp_str, 255); + + /* Reverting back old value. */ + *next_str = ';'; + + + /* Loading library. */ + hevt = LoadLibraryEx(tmp_str, NULL, + DONT_RESOLVE_DLL_REFERENCES | + LOAD_LIBRARY_AS_DATAFILE); + if(hevt) + { + if(!FormatMessage(fm_flags, hevt, er->EventID, 0, + (LPTSTR) &message, 0, el_sstring)) + { + message = NULL; + } + FreeLibrary(hevt); + + /* If we have a message, we can return it */ + if(message) + return(message); + } + + + curr_str = next_str +1; + } + + + /* Getting last value. */ + ExpandEnvironmentStrings(curr_str, tmp_str, 255); + hevt = LoadLibraryEx(tmp_str, NULL, + DONT_RESOLVE_DLL_REFERENCES | + LOAD_LIBRARY_AS_DATAFILE); + if(hevt) + { + int hr; + if(!(hr = FormatMessage(fm_flags, hevt, er->EventID, + 0, + (LPTSTR) &message, 0, el_sstring))) + { + message = NULL; + } + FreeLibrary(hevt); + + /* If we have a message, we can return it */ + if(message) + return(message); + } + + return(NULL); +} + + + +/** void readel(os_el *el) + * Reads the event log. + */ +void readel(os_el *el, int printit) +{ + DWORD _evtid = 65535; + DWORD nstr; + DWORD user_size; + DWORD domain_size; + DWORD read, needed; + int size_left; + int str_size; + int id; + + char mbuffer[BUFFER_SIZE +1]; + LPSTR sstr = NULL; + + char *tmp_str = NULL; + char *category; + char *source; + char *computer_name; + char *descriptive_msg; + + char el_user[OS_FLSIZE +1]; + char el_domain[OS_FLSIZE +1]; + char el_string[OS_MAXSTR +1]; + char final_msg[OS_MAXSTR +1]; + LPSTR el_sstring[OS_FLSIZE +1]; + + /* Er must point to the mbuffer */ + el->er = (EVENTLOGRECORD *) &mbuffer; + + /* Zeroing the values */ + el_string[OS_MAXSTR] = '\0'; + el_user[OS_FLSIZE] = '\0'; + el_domain[OS_FLSIZE] = '\0'; + final_msg[OS_MAXSTR] = '\0'; + el_sstring[0] = NULL; + el_sstring[OS_FLSIZE] = NULL; + + + /* Event log is not open */ + if(!el->h) + { + return; + } + + /* Reading the event log */ + while(ReadEventLog(el->h, + EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ, + 0, + el->er, BUFFER_SIZE -1, &read, &needed)) + { + if(!printit) + { + /* Setting er to the beginning of the buffer */ + el->er = (EVENTLOGRECORD *)&mbuffer; + continue; + } + + + while(read > 0) + { + + /* We need to initialize every variable before the loop */ + category = el_getCategory(el->er->EventType); + source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD)); + computer_name = source + strlen(source) + 1; + descriptive_msg = NULL; + + + /* Getting event id. */ + id = (int)el->er->EventID & _evtid; + + + + /* Initialing domain/user size */ + user_size = 255; domain_size = 255; + el_domain[0] = '\0'; + el_user[0] = '\0'; + + + + /* We must have some description */ + if(el->er->NumStrings) + { + size_left = OS_MAXSTR - OS_SIZE_1024; + + sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset); + el_string[0] = '\0'; + + for (nstr = 0;nstr < el->er->NumStrings;nstr++) + { + str_size = strlen(sstr); + if(size_left > 1) + { + strncat(el_string, sstr, size_left); + } + + tmp_str = strchr(el_string, '\0'); + if(tmp_str) + { + *tmp_str = ' '; + tmp_str++; *tmp_str = '\0'; + } + else + { + merror("%s: Invalid application string (size+)", + ARGV0); + } + size_left-=str_size + 2; + + if(nstr <= 92) + { + el_sstring[nstr] = (LPSTR)sstr; + el_sstring[nstr +1] = NULL; + } + + sstr = strchr( (LPSTR)sstr, '\0'); + if(sstr) + sstr++; + else + break; + } + + /* Get a more descriptive message (if available) */ + if(isVista && strcmp(el->name, "Security") == 0) + { + descriptive_msg = el_vista_getMessage(id, el_sstring); + } + + else + { + descriptive_msg = el_getMessage(el->er, + el->name, + source, + el_sstring); + } + + if(descriptive_msg != NULL) + { + /* Remove any \n or \r */ + /* Replace tabs from the argument field to spaces. + * So whenever we have option:\tvalue\t, it will + * become option: value\t + */ + tmp_str = descriptive_msg; + while(*tmp_str != '\0') + { + if(*tmp_str == '\n') + *tmp_str = ' '; + else if(*tmp_str == '\r') + *tmp_str = ' '; + else if((*tmp_str == ':') && (tmp_str[1] == '\t')) + { + tmp_str[1] = ' '; + tmp_str++; + } + + tmp_str++; + } + } + } + else + { + strncpy(el_string, "(no message)", 128); + } + + + /* Getting username */ + if(el->er->UserSidLength) + { + SID_NAME_USE account_type; + if(!LookupAccountSid(NULL, + (SID *)((LPSTR)el->er + + el->er->UserSidOffset), + el_user, + &user_size, + el_domain, + &domain_size, + &account_type)) + { + strncpy(el_user, "(no user)", 255); + strncpy(el_domain, "no domain", 255); + } + + } + + else if(isVista && strcmp(el->name, "Security") == 0) + { + int uid_array_id = -1; + + switch(id) + { + case 4624: + uid_array_id = 5; + break; + case 4634: + uid_array_id = 1; + break; + case 4647: + uid_array_id = 1; + break; + case 4769: + uid_array_id = 0; + break; + } + + if((uid_array_id >= 0) && + el_sstring[uid_array_id] && + el_sstring[uid_array_id +1]) + { + strncpy(el_user, el_sstring[uid_array_id], OS_FLSIZE); + strncpy(el_domain, el_sstring[uid_array_id +1], OS_FLSIZE); + } + else + { + strncpy(el_user, "(no user)", 255); + strncpy(el_domain, "no domain", 255); + } + } + + else + { + strncpy(el_user, "(no user)", 255); + strncpy(el_domain, "no domain", 255); + } + + + if(printit) + { + DWORD _evtid = 65535; + int id = (int)el->er->EventID & _evtid; + + final_msg[OS_MAXSTR - OS_LOG_HEADER] = '\0'; + final_msg[OS_MAXSTR - OS_LOG_HEADER -1] = '\0'; + + snprintf(final_msg, OS_MAXSTR - OS_LOG_HEADER -1, + "WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s", + el->name, + category, + id, + source, + el_user, + el_domain, + computer_name, + descriptive_msg != NULL?descriptive_msg:el_string); + + if(SendMSG(logr_queue, final_msg, "WinEvtLog", + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + } + } + + if(descriptive_msg != NULL) + { + LocalFree(descriptive_msg); + } + + /* Changing the point to the er */ + read -= el->er->Length; + el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length); + } + + /* Setting er to the beginning of the buffer */ + el->er = (EVENTLOGRECORD *)&mbuffer; + } + + + id = GetLastError(); + if(id == ERROR_HANDLE_EOF) + { + return; + } + + + /* Event log was cleared. */ + else if(id == ERROR_EVENTLOG_FILE_CHANGED) + { + char msg_alert[512 +1]; + msg_alert[512] = '\0'; + merror("%s: WARN: Event log cleared: '%s'", ARGV0, el->name); + + + /* Send message about cleared */ + snprintf(msg_alert, 512, "ossec: Event log cleared: '%s'", el->name); + SendMSG(logr_queue, msg_alert, "WinEvtLog", LOCALFILE_MQ); + + + /* Closing the event log and reopenning. */ + CloseEventLog(el->h); + el->h = NULL; + + /* Reopening. */ + if(startEL(el->name, el) < 0) + { + merror("%s: ERROR: Unable to reopen event log '%s'", + ARGV0, el->name); + } + } + + else + { + debug1("%s: WARN: Error reading event log: %d", ARGV0, id); + } +} + + +/** void win_read_vista_sec() + * Reads vista security description. + */ +void win_read_vista_sec() +{ + char *p; + char buf[OS_MAXSTR +1]; + FILE *fp; + + + /* Vista security csv. */ + fp = fopen("vista_sec.csv", "r"); + if(!fp) + { + merror("%s: ERROR: Unable to read vista security descriptions.", + ARGV0); + exit(1); + } + + + /* Creating the hash. */ + vista_sec_id_hash = OSHash_Create(); + if(!vista_sec_id_hash) + { + merror("%s: ERROR: Unable to read vista security descriptions.", + ARGV0); + exit(1); + } + + + /* Reading the whole file and adding to memory. */ + while(fgets(buf, OS_MAXSTR, fp) != NULL) + { + char *key; + char *desc; + + /* Getting the last occurence of \n */ + if ((p = strrchr(buf, '\n')) != NULL) + { + *p = '\0'; + } + + p = strchr(buf, ','); + if(!p) + { + merror("%s: ERROR: Invalid entry on the Vista security " + "description.", ARGV0); + continue; + } + + *p = '\0'; + p++; + + /* Removing white spaces. */ + while(*p == ' ') + p++; + + + /* Allocating memory. */ + desc = strdup(p); + key = strdup(buf); + if(!key || !desc) + { + merror("%s: ERROR: Invalid entry on the Vista security " + "description.", ARGV0); + continue; + } + + + /* Inserting on hash. */ + OSHash_Add(vista_sec_id_hash, key, desc); + } + + fclose(fp); +} + + +/** void win_startel() + * Starts the event logging for windows + */ +void win_startel(char *evt_log) +{ + int entries_count = 0; + + /* Maximum size */ + if(el_last == 9) + { + merror(EVTLOG_DUP, ARGV0, evt_log); + return; + } + + + /* Creating the dll hash. */ + if(!dll_hash) + { + dll_hash = OSHash_Create(); + if(!dll_hash) + { + merror("%s: ERROR: Unable to create DLL hash.", + ARGV0); + } + } + + + /* Starting event log -- going to last available record */ + if((entries_count = startEL(evt_log, &el[el_last])) < 0) + { + merror(INV_EVTLOG, ARGV0, evt_log); + return; + } + else + { + readel(&el[el_last], 0); + } + el_last++; +} + + +/** void win_readel() + * Reads the event logging for windows + */ +void win_readel() +{ + int i = 0; + + /* Sleep plus 2 seconds before reading again */ + Sleep(2000); + + for(;i + +PT=../ +NAME=ossec-monitord + +include ../Config.Make + +LOCAL = compress_log.c main.c manage_files.c monitor_agents.c monitord.c sign_log.c + +OBJS = ${OS_SHARED} ${OS_NET} ${OS_REGEX} ${OS_CRYPTO} ${OS_ZLIB} + +mmonitor: + ${CC} ${CFLAGS} ${OS_LINK} ${LOCAL} ${OBJS} -o ${NAME} + ${CC} ${CFLAGS} ${OS_LINK} -UARGV0 -DARGV0=\"ossec-reportd\" report.c ${OBJS} -o ossec-reportd +clean: + ${CLEAN} + rm -f ossec-reportd +build: + ${BUILD} + cp -pr ossec-reportd ${PT}../bin diff --git a/src/monitord/compress_log.c b/src/monitord/compress_log.c new file mode 100755 index 0000000..7cf11bd --- /dev/null +++ b/src/monitord/compress_log.c @@ -0,0 +1,84 @@ +/* @(#) $Id: compress_log.c,v 1.4 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" +#include "monitord.h" +#include "os_zlib/os_zlib.h" + + +/* gzips a log file */ +void OS_CompressLog(char *logfile) +{ + FILE *log; + gzFile *zlog; + + char logfileGZ[OS_FLSIZE + 1]; + int len, err; + + char buf[OS_MAXSTR + 1]; + + + /* Do not compress */ + if(mond.compress == 0) + return; + + + /* Clearing the memory */ + memset(logfileGZ,'\0',OS_FLSIZE +1); + memset(buf, '\0', OS_MAXSTR + 1); + + + /* Setting the umask */ + umask(0027); + + + /* Creating the gzip file name */ + snprintf(logfileGZ, OS_FLSIZE, "%s.gz", logfile); + + + /* Reading log file */ + log = fopen(logfile, "r"); + if(!log) + { + /* Do not warn in here, since the alert file may not exist. */ + return; + } + + /* Opening compressed file */ + zlog = gzopen(logfileGZ, "w"); + if(!zlog) + { + fclose(log); + merror(FOPEN_ERROR, ARGV0, logfileGZ); + return; + } + + for(;;) + { + len = fread(buf, 1, OS_MAXSTR, log); + if(len <= 0) + break; + if(gzwrite(zlog, buf, (unsigned)len) != len) + merror("%s: Compression error: %s", ARGV0, gzerror(zlog, &err)); + } + + /* Closing */ + fclose(log); + gzclose(zlog); + + /* Removing uncompressed file */ + unlink(logfile); + + return; +} + + +/* EOF */ diff --git a/src/monitord/main.c b/src/monitord/main.c new file mode 100755 index 0000000..0eee48b --- /dev/null +++ b/src/monitord/main.c @@ -0,0 +1,155 @@ +/* @(#) $Id: main.c,v 1.9 2009/11/18 19:07:40 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "monitord.h" + + +int main(int argc, char **argv) +{ + int c, test_config = 0, run_foreground = 0; + int uid=0,gid=0; + char *dir = DEFAULTDIR; + char *user = USER; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTCPATH; + + /* Initializing global variables */ + mond.a_queue = 0; + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user=optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group=optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir=optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + /* Starting daemon */ + debug1(STARTED_MSG,ARGV0); + + /*Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + ErrorExit(USER_ERROR,ARGV0,user,group); + + + /* Getting config options */ + mond.day_wait = getDefine_Int("monitord", + "day_wait", + 5,240); + mond.compress = getDefine_Int("monitord", + "compress", + 0,1); + mond.sign = getDefine_Int("monitord","sign",0,1); + + mond.monitor_agents = getDefine_Int("monitord","monitor_agents",0,1); + + mond.agents = NULL; + + + /* Exit here if test config is set */ + if(test_config) + exit(0); + + + if (!run_foreground) + { + /* Going on daemon mode */ + nowDaemon(); + goDaemon(); + } + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + nowChroot(); + + + + /* Changing user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + debug1(PRIVSEP_MSG,ARGV0,dir,user); + + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + + /* Creating PID files */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR,ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* the real daemon now */ + Monitord(); + exit(0); +} + + +/* EOF */ diff --git a/src/monitord/manage_files.c b/src/monitord/manage_files.c new file mode 100755 index 0000000..2c1d492 --- /dev/null +++ b/src/monitord/manage_files.c @@ -0,0 +1,122 @@ +/* @(#) $Id: manage_files.c,v 1.10 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "monitord.h" + +char *(months[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", + "Sep","Oct","Nov","Dec"}; + + +/* OS_GetLogLocation: v0.1, 2005/04/25 */ +void manage_files(int cday, int cmon, int cyear) +{ + time_t tm_old; + + struct tm *pp_old; + + #ifndef SOLARIS + struct tm p_old; + #endif + + char elogfile[OS_FLSIZE +1]; + char elogfile_old[OS_FLSIZE +1]; + + char alogfile[OS_FLSIZE +1]; + char alogfile_old[OS_FLSIZE +1]; + + char flogfile[OS_FLSIZE +1]; + char flogfile_old[OS_FLSIZE +1]; + + + /* Getting time from the day before (for log signing) */ + tm_old = time(NULL); + tm_old -= 93500; + #ifndef SOLARIS + pp_old = localtime_r(&tm_old, &p_old); + #else + pp_old = localtime(&tm_old); + #endif + + + memset(elogfile, '\0', OS_FLSIZE +1); + memset(elogfile_old, '\0', OS_FLSIZE +1); + memset(alogfile, '\0', OS_FLSIZE +1); + memset(alogfile_old, '\0', OS_FLSIZE +1); + memset(flogfile, '\0', OS_FLSIZE +1); + memset(flogfile_old, '\0', OS_FLSIZE +1); + + + /* When the day changes, we wait up to day_wait + * before compressing the file. + */ + sleep(mond.day_wait); + + + /* Event logfile */ + snprintf(elogfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log", + EVENTS, + cyear, + months[cmon], + "archive", + cday); + /* Event log file old */ + snprintf(elogfile_old, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log", + EVENTS, + pp_old->tm_year+1900, + months[pp_old->tm_mon], + "archive", + pp_old->tm_mday); + + OS_SignLog(elogfile, elogfile_old, 0); + OS_CompressLog(elogfile); + + + /* alert logfile */ + snprintf(alogfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log", + ALERTS, + cyear, + months[cmon], + "alerts", + cday); + /* alert logfile old */ + snprintf(alogfile_old, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log", + ALERTS, + pp_old->tm_year+1900, + months[pp_old->tm_mon], + "alerts", + pp_old->tm_mday); + OS_SignLog(alogfile, alogfile_old, 1); + OS_CompressLog(alogfile); + + + /* firewall events */ + snprintf(flogfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log", + FWLOGS, + cyear, + months[cmon], + "firewall", + cday); + /* firewall events old */ + snprintf(flogfile_old, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log", + FWLOGS, + pp_old->tm_year+1900, + months[pp_old->tm_mon], + "firewall", + pp_old->tm_mday); + OS_SignLog(flogfile, flogfile_old, 0); + OS_CompressLog(flogfile); + + return; +} + +/* EOF */ diff --git a/src/monitord/monitor_agents.c b/src/monitord/monitor_agents.c new file mode 100755 index 0000000..66c1587 --- /dev/null +++ b/src/monitord/monitor_agents.c @@ -0,0 +1,78 @@ +/* @(#) $Id: monitor_agents.c,v 1.5 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "monitord.h" +#include "read-agents.h" + + + +void monitor_agents() +{ + char **cr_agents; + char **av_agents; + + av_agents = get_agents(GA_ACTIVE); + + + /* No agent saved */ + if(!mond.agents) + { + mond.agents = av_agents; + return; + } + + /* Checking if any of the previous available agents + * are disconnected. + */ + cr_agents = mond.agents; + while(*cr_agents) + { + int available = 0; + char **tmp_av; + + tmp_av = av_agents; + while(tmp_av && *tmp_av) + { + if(strcmp(*cr_agents, *tmp_av) == 0) + { + available = 1; + break; + } + tmp_av++; + } + + /* Agent disconnected */ + if(available == 0) + { + char str[OS_SIZE_1024 +1]; + + /* Sending disconnected message */ + snprintf(str, OS_SIZE_1024 -1, OS_AG_DISCON, *cr_agents); + if(SendMSG(mond.a_queue, str, ARGV0, + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + } + } + + cr_agents++; + } + + + /* Removing old agent list and adding currently one */ + free_agents(mond.agents); + mond.agents = av_agents; + return; +} + +/* EOF */ diff --git a/src/monitord/monitord.c b/src/monitord/monitord.c new file mode 100755 index 0000000..b68d984 --- /dev/null +++ b/src/monitord/monitord.c @@ -0,0 +1,92 @@ +/* @(#) $Id: monitord.c,v 1.9 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "monitord.h" + + +/* Real monitord global */ +void Monitord() +{ + time_t tm; + struct tm *p; + + int today = 0; + int thismonth = 0; + int thisyear = 0; + + char str[OS_SIZE_1024 +1]; + + /* Waiting a few seconds to settle */ + sleep(10); + + memset(str, '\0', OS_SIZE_1024 +1); + + + /* Getting currently time before starting */ + tm = time(NULL); + p = localtime(&tm); + + today = p->tm_mday; + thismonth = p->tm_mon; + thisyear = p->tm_year+1900; + + + + /* Connecting to the message queue + * Exit if it fails. + */ + if((mond.a_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); + } + + + /* Sending startup message */ + snprintf(str, OS_SIZE_1024 -1, OS_AD_STARTED); + if(SendMSG(mond.a_queue, str, ARGV0, + LOCALFILE_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + } + + + /* Main monitor loop */ + while(1) + { + tm = time(NULL); + p = localtime(&tm); + + + /* Checking unavailable agents */ + if(mond.monitor_agents) + { + monitor_agents(); + } + + /* Day changed, deal with log files */ + if(today != p->tm_mday) + { + manage_files(today, thismonth, thisyear); + + today = p->tm_mday; + thismonth = p->tm_mon; + thisyear = p->tm_year+1900; + } + + /* We only check every two minutes */ + sleep(120); + } +} + +/* EOF */ diff --git a/src/monitord/monitord.h b/src/monitord/monitord.h new file mode 100755 index 0000000..18e97e5 --- /dev/null +++ b/src/monitord/monitord.h @@ -0,0 +1,54 @@ +/* @(#) $Id: monitord.h,v 1.7 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _MONITORD_H +#define _MONITORD_H + +#ifndef ARGV0 + #define ARGV0 "ossec-monitord" +#endif + +typedef struct _monitor_config +{ + short int day_wait; + short int compress; + short int sign; + short int monitor_agents; + int a_queue; + + char **agents; +}monitor_config; + + +/** Prototypes **/ + +/* Main monitord */ +void Monitord(); + +/*manage_files */ +void manage_files(int cday, int cmon, int cyear); + +/* monitor_agents */ +void monitor_agents(); + +/* Sign a log */ +void OS_SignLog(char *logfile, char *logfile_old, int log_missing); + +/* Compress log */ +void OS_CompressLog(char *logfile); + + +/* Global variables */ +monitor_config mond; + + +#endif diff --git a/src/monitord/report.c b/src/monitord/report.c new file mode 100755 index 0000000..bddeb89 --- /dev/null +++ b/src/monitord/report.c @@ -0,0 +1,199 @@ +/* @(#) $Id: report.c,v 1.4 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + + + +/* ossec-reportd - Runs manual reports. */ +void report_help() +{ + printf("\nOSSEC HIDS %s: Generate reports (via stdin).\n", ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-f Filter the results.\n"); + printf("\t-r Show related entries.\n"); + printf("\t-n Creates a description for the report.\n"); + printf("Examples:\n"); + printf("\t-f group authentication success (to filter on login success).\n"); + printf("\t-f level 10 (to filter on level >= 10).\n"); + printf("\t-f group authentication -r user srcip (to show the srcip for all users).\n"); + exit(1); +} + + + +int main(int argc, char **argv) +{ + int c, test_config = 0; + int uid=0,gid=0; + char *dir = DEFAULTDIR; + char *user = USER; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTCPATH; + + char *filter_by = NULL; + char *filter_value = NULL; + + char *related_of = NULL; + char *related_values = NULL; + report_filter r_filter; + + + /* Setting the name */ + OS_SetName(ARGV0); + + r_filter.group = NULL; + r_filter.rule = NULL; + r_filter.level = NULL; + r_filter.location = NULL; + + r_filter.related_group = 0; + r_filter.related_rule = 0; + r_filter.related_level = 0; + r_filter.related_location = 0; + r_filter.related_srcip = 0; + r_filter.related_user = 0; + + r_filter.report_name = NULL; + + while((c = getopt(argc, argv, "Vdhtu:g:D:c:f:v:n:r:")) != -1) + { + switch(c){ + case 'V': + print_version(); + break; + case 'h': + report_help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'n': + if(!optarg) + ErrorExit("%s: -n needs an argument",ARGV0); + r_filter.report_name = optarg; + break; + case 'r': + if(!optarg || !argv[optind]) + ErrorExit("%s: -r needs two argument",ARGV0); + related_of = optarg; + related_values = argv[optind]; + + if(os_report_configfilter(related_of, related_values, + &r_filter, REPORT_RELATED) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, "user argument"); + } + optind++; + break; + case 'f': + if(!optarg) + ErrorExit("%s: -f needs two argument",ARGV0); + filter_by = optarg; + filter_value = argv[optind]; + + if(os_report_configfilter(filter_by, filter_value, + &r_filter, REPORT_FILTER) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, "user argument"); + } + optind++; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user=optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group=optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir=optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + report_help(ARGV0); + break; + } + + } + + /* Starting daemon */ + debug1(STARTED_MSG,ARGV0); + + /* Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + ErrorExit(USER_ERROR,ARGV0,user,group); + + + + /* Exit here if test config is set */ + if(test_config) + exit(0); + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + nowChroot(); + + + + /* Changing user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + debug1(PRIVSEP_MSG,ARGV0,dir,user); + + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + + /* Creating PID files */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR,ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* the real stuff now */ + os_ReportdStart(&r_filter); + exit(0); +} + + +/* EOF */ diff --git a/src/monitord/sign_log.c b/src/monitord/sign_log.c new file mode 100755 index 0000000..27adb2f --- /dev/null +++ b/src/monitord/sign_log.c @@ -0,0 +1,103 @@ +/* @(#) $Id: sign_log.c,v 1.8 2009/06/24 17:06:27 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/sha1/sha1_op.h" + + +/* Signs a log file */ +void OS_SignLog(char *logfile, char *logfile_old, int log_missing) +{ + os_md5 mf_sum; + os_md5 mf_sum_old; + + os_sha1 sf_sum; + os_sha1 sf_sum_old; + + char logfilesum[OS_FLSIZE +1]; + char logfilesum_old[OS_FLSIZE +1]; + + FILE *fp; + + + /* Clearing the memory */ + memset(logfilesum, '\0', OS_FLSIZE +1); + memset(logfilesum_old, '\0', OS_FLSIZE +1); + + + /* Setting the umask */ + umask(0027); + + + /* Creating the checksum file names */ + snprintf(logfilesum, OS_FLSIZE, "%s.sum", logfile); + snprintf(logfilesum_old, OS_FLSIZE, "%s.sum", logfile_old); + + + /* generating md5 of the old file */ + if(OS_MD5_File(logfilesum_old, mf_sum_old) < 0) + { + merror("%s: No previous md5 checksum found: '%s'. " + "Starting over.", ARGV0, logfilesum_old); + strncpy(mf_sum_old, "none", 6); + } + + /* generating sha1 of the old file. */ + if(OS_SHA1_File(logfilesum_old, sf_sum_old) < 0) + { + merror("%s: No previous sha1 checksum found: '%s'. " + "Starting over.", ARGV0, logfilesum_old); + strncpy(sf_sum_old, "none", 6); + } + + + /* Generating md5 of the current file */ + if(OS_MD5_File(logfile, mf_sum) < 0) + { + if(log_missing) + merror("%s: File '%s' not found. MD5 checksum skipped.", + ARGV0, logfile); + strncpy(mf_sum, "none", 6); + } + + /* Generating sha1 of the current file */ + if(OS_SHA1_File(logfile, sf_sum) < 0) + { + if(log_missing) + merror("%s: File '%s' not found. SHA1 checksum skipped.", + ARGV0, logfile); + strncpy(sf_sum, "none", 6); + } + + + fp = fopen(logfilesum, "w"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, logfilesum); + return; + } + + + fprintf(fp, "Current checksum:\n"); + fprintf(fp, "MD5 (%s) = %s\n", logfile, mf_sum); + fprintf(fp, "SHA1 (%s) = %s\n\n", logfile, sf_sum); + + fprintf(fp, "Chained checksum:\n"); + fprintf(fp, "MD5 (%s) = %s\n", logfilesum_old, mf_sum_old); + fprintf(fp, "SHA1 (%s) = %s\n\n", logfilesum_old, sf_sum_old); + fclose(fp); + + return; +} + + +/* EOF */ diff --git a/src/os_crypto/Makefile b/src/os_crypto/Makefile new file mode 100755 index 0000000..ee2b1cc --- /dev/null +++ b/src/os_crypto/Makefile @@ -0,0 +1,23 @@ +# Makefile for os_crypto +# Daniel B. Cid || + +PT=../ +NAME=os_crypto + +include ../Config.Make + +os_crypto: + @cd blowfish; make + @cd md5; make + @cd sha1; make + @cd md5_sha1; make + @cd shared; make + ar cru os_crypto.a blowfish/bf_op.o blowfish/bf_skey.o blowfish/bf_enc.o md5/md5_op.o md5/md5.o sha1/sha1_op.o md5_sha1/md5_sha1_op.o shared/*.o + ranlib os_crypto.a +clean: + @cd blowfish; make clean + @cd md5; make clean; + @cd sha1; make clean; + @cd md5_sha1; make clean; + @cd shared; make clean; + rm -f *.a diff --git a/src/os_crypto/blowfish/Makefile b/src/os_crypto/blowfish/Makefile new file mode 100755 index 0000000..f309e5e --- /dev/null +++ b/src/os_crypto/blowfish/Makefile @@ -0,0 +1,24 @@ +# Makefile for os_crypto blowfish +# Daniel B. Cid || + +PT=../../ + +NAME=blowfish_op + +include ../../Config.Make + +SRCS = bf_op.c bf_skey.c bf_enc.c + +bf_OBJS = bf_op.o bf_skey.o bf_enc.o + + +bf: + $(CC) $(CFLAGS) -c $(SRCS) + ar cru bf_op.a $(bf_OBJS) + ranlib bf_op.a + +main: + $(CC) $(CFLAGS) -o main main.c bf_op.a + +clean: + rm -f *.o *.a diff --git a/src/os_crypto/blowfish/bf_enc.c b/src/os_crypto/blowfish/bf_enc.c new file mode 100755 index 0000000..bbe5b05 --- /dev/null +++ b/src/os_crypto/blowfish/bf_enc.c @@ -0,0 +1,306 @@ +/* crypto/bf/bf_enc.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "blowfish.h" +#include "bf_locl.h" + +/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' + * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20) +#error If you set BF_ROUNDS to some value other than 16 or 20, you will have \ +to modify the code. +#endif + +void BF_encrypt(BF_LONG *data, const BF_KEY *key) + { +#ifndef BF_PTR2 + register BF_LONG l,r; + register const BF_LONG *p,*s; + + p=key->P; + s= &(key->S[0]); + l=data[0]; + r=data[1]; + + l^=p[0]; + BF_ENC(r,l,s,p[ 1]); + BF_ENC(l,r,s,p[ 2]); + BF_ENC(r,l,s,p[ 3]); + BF_ENC(l,r,s,p[ 4]); + BF_ENC(r,l,s,p[ 5]); + BF_ENC(l,r,s,p[ 6]); + BF_ENC(r,l,s,p[ 7]); + BF_ENC(l,r,s,p[ 8]); + BF_ENC(r,l,s,p[ 9]); + BF_ENC(l,r,s,p[10]); + BF_ENC(r,l,s,p[11]); + BF_ENC(l,r,s,p[12]); + BF_ENC(r,l,s,p[13]); + BF_ENC(l,r,s,p[14]); + BF_ENC(r,l,s,p[15]); + BF_ENC(l,r,s,p[16]); +#if BF_ROUNDS == 20 + BF_ENC(r,l,s,p[17]); + BF_ENC(l,r,s,p[18]); + BF_ENC(r,l,s,p[19]); + BF_ENC(l,r,s,p[20]); +#endif + r^=p[BF_ROUNDS+1]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#else + register BF_LONG l,r,t,*k; + + l=data[0]; + r=data[1]; + k=(BF_LONG*)key; + + l^=k[0]; + BF_ENC(r,l,k, 1); + BF_ENC(l,r,k, 2); + BF_ENC(r,l,k, 3); + BF_ENC(l,r,k, 4); + BF_ENC(r,l,k, 5); + BF_ENC(l,r,k, 6); + BF_ENC(r,l,k, 7); + BF_ENC(l,r,k, 8); + BF_ENC(r,l,k, 9); + BF_ENC(l,r,k,10); + BF_ENC(r,l,k,11); + BF_ENC(l,r,k,12); + BF_ENC(r,l,k,13); + BF_ENC(l,r,k,14); + BF_ENC(r,l,k,15); + BF_ENC(l,r,k,16); +#if BF_ROUNDS == 20 + BF_ENC(r,l,k,17); + BF_ENC(l,r,k,18); + BF_ENC(r,l,k,19); + BF_ENC(l,r,k,20); +#endif + r^=k[BF_ROUNDS+1]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#endif + } + +#ifndef BF_DEFAULT_OPTIONS + +void BF_decrypt(BF_LONG *data, const BF_KEY *key) + { +#ifndef BF_PTR2 + register const BF_LONG *p,*s; + register BF_LONG l,r; + + p=key->P; + s= &(key->S[0]); + l=data[0]; + r=data[1]; + + l^=p[BF_ROUNDS+1]; +#if BF_ROUNDS == 20 + BF_ENC(r,l,s,p[20]); + BF_ENC(l,r,s,p[19]); + BF_ENC(r,l,s,p[18]); + BF_ENC(l,r,s,p[17]); +#endif + BF_ENC(r,l,s,p[16]); + BF_ENC(l,r,s,p[15]); + BF_ENC(r,l,s,p[14]); + BF_ENC(l,r,s,p[13]); + BF_ENC(r,l,s,p[12]); + BF_ENC(l,r,s,p[11]); + BF_ENC(r,l,s,p[10]); + BF_ENC(l,r,s,p[ 9]); + BF_ENC(r,l,s,p[ 8]); + BF_ENC(l,r,s,p[ 7]); + BF_ENC(r,l,s,p[ 6]); + BF_ENC(l,r,s,p[ 5]); + BF_ENC(r,l,s,p[ 4]); + BF_ENC(l,r,s,p[ 3]); + BF_ENC(r,l,s,p[ 2]); + BF_ENC(l,r,s,p[ 1]); + r^=p[0]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#else + register BF_LONG l,r,t,*k; + + l=data[0]; + r=data[1]; + k=(BF_LONG *)key; + + l^=k[BF_ROUNDS+1]; +#if BF_ROUNDS == 20 + BF_ENC(r,l,k,20); + BF_ENC(l,r,k,19); + BF_ENC(r,l,k,18); + BF_ENC(l,r,k,17); +#endif + BF_ENC(r,l,k,16); + BF_ENC(l,r,k,15); + BF_ENC(r,l,k,14); + BF_ENC(l,r,k,13); + BF_ENC(r,l,k,12); + BF_ENC(l,r,k,11); + BF_ENC(r,l,k,10); + BF_ENC(l,r,k, 9); + BF_ENC(r,l,k, 8); + BF_ENC(l,r,k, 7); + BF_ENC(r,l,k, 6); + BF_ENC(l,r,k, 5); + BF_ENC(r,l,k, 4); + BF_ENC(l,r,k, 3); + BF_ENC(r,l,k, 2); + BF_ENC(l,r,k, 1); + r^=k[0]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#endif + } + +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int encrypt) + { + register BF_LONG tin0,tin1; + register BF_LONG tout0,tout1,xor0,xor1; + register long l=length; + BF_LONG tin[2]; + + if (encrypt) + { + n2l(ivec,tout0); + n2l(ivec,tout1); + ivec-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + BF_encrypt(tin,schedule); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + if (l != -8) + { + n2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + BF_encrypt(tin,schedule); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + l2n(tout0,ivec); + l2n(tout1,ivec); + } + else + { + n2l(ivec,xor0); + n2l(ivec,xor1); + ivec-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + BF_decrypt(tin,schedule); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2n(tout0,out); + l2n(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + BF_decrypt(tin,schedule); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2nn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + l2n(xor0,ivec); + l2n(xor1,ivec); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +#endif diff --git a/src/os_crypto/blowfish/bf_locl.h b/src/os_crypto/blowfish/bf_locl.h new file mode 100755 index 0000000..0567cb5 --- /dev/null +++ b/src/os_crypto/blowfish/bf_locl.h @@ -0,0 +1,228 @@ +/* Modified to work without OPENSSL. + * os_crypto (www.ossec.net/c/os_crypto) + * Daniel B. Cid, danielcid@gmail.com + */ + +/* crypto/bf/bf_locl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BF_LOCL_H +#define HEADER_BF_LOCL_H + +/* Only include if OPENSSL is present */ +#ifdef USE_OPENSSL +#include /* BF_PTR, BF_PTR2 */ +#endif + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* This is actually a big endian algorithm, the most significant byte + * is used to lookup array 0 */ + +#if defined(BF_PTR2) + +/* + * This is basically a special Intel version. Point is that Intel + * doesn't have many registers, but offers a reach choice of addressing + * modes. So we spare some registers by directly traversing BF_KEY + * structure and hiring the most decorated addressing mode. The code + * generated by EGCS is *perfectly* competitive with assembler + * implementation! + */ +#define BF_ENC(LL,R,KEY,Pi) (\ + LL^=KEY[Pi], \ + t= KEY[BF_ROUNDS+2 + 0 + ((R>>24)&0xFF)], \ + t+= KEY[BF_ROUNDS+2 + 256 + ((R>>16)&0xFF)], \ + t^= KEY[BF_ROUNDS+2 + 512 + ((R>>8 )&0xFF)], \ + t+= KEY[BF_ROUNDS+2 + 768 + ((R )&0xFF)], \ + LL^=t \ + ) + +#elif defined(BF_PTR) + +#ifndef BF_LONG_LOG2 +#define BF_LONG_LOG2 2 /* default to BF_LONG being 32 bits */ +#endif +#define BF_M (0xFF<>BF_i)&BF_M gets folded into a single instruction, namely + * rlwinm. So let'em double-check if their compiler does it. + */ + +#define BF_ENC(LL,R,S,P) ( \ + LL^=P, \ + LL^= (((*(BF_LONG *)((unsigned char *)&(S[ 0])+((R>>BF_0)&BF_M))+ \ + *(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \ + *(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \ + *(BF_LONG *)((unsigned char *)&(S[768])+((R<>24)&0xff)] + \ + S[0x0100+((int)(R>>16)&0xff)])^ \ + S[0x0200+((int)(R>> 8)&0xff)])+ \ + S[0x0300+((int)(R )&0xff)])&0xffffffffL \ + ) +#endif + +#endif diff --git a/src/os_crypto/blowfish/bf_op.c b/src/os_crypto/blowfish/bf_op.c new file mode 100755 index 0000000..fe81831 --- /dev/null +++ b/src/os_crypto/blowfish/bf_op.c @@ -0,0 +1,47 @@ +/* $OSSEC, os_crypto/blowfish_op.c, v0.2, 2005/09/17, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* v0.2 (2005/09/17): uchar fixes + * v0.1 (2005/01/29) + */ + +/* OS_crypto/blowfish Library. + * APIs for many crypto operations. + */ + +#include +#include +#include + +#include "blowfish.h" + +#include "bf_op.h" + +typedef unsigned char uchar; + +int OS_BF_Str(char *input, char *output, char *charkey, + long size, short int action) +{ + BF_KEY key; + static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; + unsigned char iv[8]; + + memcpy(iv,cbc_iv,sizeof(iv)); + + BF_set_key(&key, strlen(charkey), (uchar *)charkey); + + BF_cbc_encrypt((uchar *)input, (uchar *)output, size, + &key, iv, action); + + return(1); +} + +/* EOF */ diff --git a/src/os_crypto/blowfish/bf_op.h b/src/os_crypto/blowfish/bf_op.h new file mode 100755 index 0000000..13b9518 --- /dev/null +++ b/src/os_crypto/blowfish/bf_op.h @@ -0,0 +1,29 @@ +/* $OSSEC, os_crypto/bf_op.h, v0.1, 2004/08/09, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* OS_crypto/blowfish Library. + * APIs for many crypto operations. + */ + +#ifndef __BF_OP_H + +#define __BF_OP_H + +#define OS_ENCRYPT 1 +#define OS_DECRYPT 0 + + +int OS_BF_Str(char * input, char *output, char *charkey, + long size, short int action); + +#endif + +/* EOF */ diff --git a/src/os_crypto/blowfish/bf_pi.h b/src/os_crypto/blowfish/bf_pi.h new file mode 100755 index 0000000..9949513 --- /dev/null +++ b/src/os_crypto/blowfish/bf_pi.h @@ -0,0 +1,325 @@ +/* crypto/bf/bf_pi.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +static const BF_KEY bf_init= { + { + 0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, + 0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, + 0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL, + 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L, + 0x9216d5d9L, 0x8979fb1b + },{ + 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, + 0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, + 0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L, + 0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL, + 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, + 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, + 0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL, + 0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL, + 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L, + 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, + 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, + 0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, + 0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL, + 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L, + 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, + 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, + 0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L, + 0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L, + 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL, + 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, + 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, + 0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, + 0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L, + 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL, + 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, + 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, + 0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, + 0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L, + 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL, + 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, + 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, + 0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, + 0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L, + 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL, + 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, + 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, + 0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, + 0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L, + 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL, + 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, + 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, + 0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, + 0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L, + 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L, + 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, + 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, + 0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, + 0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL, + 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL, + 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, + 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, + 0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, + 0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L, + 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL, + 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, + 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, + 0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, + 0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L, + 0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L, + 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, + 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, + 0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, + 0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L, + 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL, + 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, + 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, + 0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, + 0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL, + 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L, + 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, + 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, + 0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, + 0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L, + 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L, + 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, + 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, + 0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L, + 0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L, + 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L, + 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, + 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, + 0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL, + 0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL, + 0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L, + 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, + 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, + 0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, + 0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL, + 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL, + 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, + 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, + 0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, + 0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL, + 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL, + 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, + 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, + 0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, + 0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L, + 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L, + 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, + 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, + 0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, + 0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L, + 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL, + 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, + 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, + 0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L, + 0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L, + 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L, + 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, + 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, + 0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, + 0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L, + 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L, + 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, + 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, + 0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, + 0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L, + 0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L, + 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, + 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, + 0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, + 0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L, + 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL, + 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, + 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, + 0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, + 0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L, + 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L, + 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, + 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, + 0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L, + 0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L, + 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L, + 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, + 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, + 0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, + 0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L, + 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L, + 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, + 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, + 0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, + 0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L, + 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL, + 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, + 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, + 0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L, + 0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL, + 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L, + 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, + 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, + 0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, + 0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L, + 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L, + 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, + 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, + 0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, + 0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL, + 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L, + 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, + 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, + 0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, + 0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL, + 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL, + 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, + 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, + 0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, + 0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL, + 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL, + 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, + 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, + 0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L, + 0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L, + 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L, + 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, + 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, + 0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, + 0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L, + 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L, + 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, + 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, + 0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, + 0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L, + 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L, + 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, + 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, + 0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, + 0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL, + 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L, + 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, + 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, + 0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L, + 0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL, + 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL, + 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, + 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, + 0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, + 0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L, + 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L, + 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, + 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, + 0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, + 0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L, + 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L, + 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, + 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, + 0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, + 0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL, + 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL, + 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, + 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, + 0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, + 0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL, + 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L, + 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, + 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, + 0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L, + 0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L, + 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L, + 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, + 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, + 0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, + 0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L, + 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L, + 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, + 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, + 0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, + 0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L, + 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L, + 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, + 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, + 0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, + 0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L, + 0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL, + 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, + 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, + 0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, + 0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L, + 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L, + 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, + 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, + 0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, + 0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL, + 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L, + 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, + 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, + 0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L, + 0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL, + 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L, + 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, + 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, + 0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L, + 0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL, + 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L, + 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, + 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, + } + }; + diff --git a/src/os_crypto/blowfish/bf_skey.c b/src/os_crypto/blowfish/bf_skey.c new file mode 100755 index 0000000..d3cba58 --- /dev/null +++ b/src/os_crypto/blowfish/bf_skey.c @@ -0,0 +1,116 @@ +/* crypto/bf/bf_skey.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "blowfish.h" +#include "bf_locl.h" +#include "bf_pi.h" + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data) + { + int i; + BF_LONG *p,ri,in[2]; + const unsigned char *d,*end; + + + memcpy(key,&bf_init,sizeof(BF_KEY)); + p=key->P; + + if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4; + + d=data; + end= &(data[len]); + for (i=0; i<(BF_ROUNDS+2); i++) + { + ri= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + p[i]^=ri; + } + + in[0]=0L; + in[1]=0L; + for (i=0; i<(BF_ROUNDS+2); i+=2) + { + BF_encrypt(in,key); + p[i ]=in[0]; + p[i+1]=in[1]; + } + + p=key->S; + for (i=0; i<4*256; i+=2) + { + BF_encrypt(in,key); + p[i ]=in[0]; + p[i+1]=in[1]; + } + } + diff --git a/src/os_crypto/blowfish/blowfish.h b/src/os_crypto/blowfish/blowfish.h new file mode 100755 index 0000000..ad6ce95 --- /dev/null +++ b/src/os_crypto/blowfish/blowfish.h @@ -0,0 +1,127 @@ +/* crypto/bf/blowfish.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BLOWFISH_H +#define HEADER_BLOWFISH_H + +/* #include */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_BF +#error BF is disabled. +#endif + +#define BF_ENCRYPT 1 +#define BF_DECRYPT 0 + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! BF_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! BF_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__) +#define BF_LONG unsigned long +#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +#define BF_LONG unsigned long +#define BF_LONG_LOG2 3 +/* + * _CRAY note. I could declare short, but I have no idea what impact + * does it have on performance on none-T3E machines. I could declare + * int, but at least on C90 sizeof(int) can be chosen at compile time. + * So I've chosen long... + * + */ +#else +#define BF_LONG unsigned int +#endif + +#define BF_ROUNDS 16 +#define BF_BLOCK 8 + +typedef struct bf_key_st + { + BF_LONG P[BF_ROUNDS+2]; + BF_LONG S[4*256]; + } BF_KEY; + + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); + +void BF_encrypt(BF_LONG *data,const BF_KEY *key); +void BF_decrypt(BF_LONG *data,const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num); +const char *BF_options(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os_crypto/blowfish/main.c b/src/os_crypto/blowfish/main.c new file mode 100755 index 0000000..0b34a02 --- /dev/null +++ b/src/os_crypto/blowfish/main.c @@ -0,0 +1,45 @@ +#include +#include +#include + +#include "bf_op.h" + + +int main(int argc, char ** argv) +{ + int i; + char output[1024]; + char output2[1024]; + + memset(output, '\0', 1024); + memset(output2, '\0', 1024); + + if(argc < 3) + { + printf("%s: string key\n", argv[0]); + exit(1); + } + + if((strlen(argv[1]) > 1020) || (strlen(argv[2]) > 512)) + { + printf("%s: size err\n", argv[0]); + exit(1); + } + + /* Encrypt */ + OS_BF_Str(argv[1], output, argv[2], strlen(argv[1]), OS_ENCRYPT); + + /* Decript */ + OS_BF_Str(output, output2, argv[2], strlen(argv[1]), OS_DECRYPT); + + printf("finished.\n"); + printf("input: '%s'\n",argv[1]); + printf("crpt: "); + for(i=0;i <= strlen(argv[1]);i++) + { + printf("%d", output[i]); + } + printf("\n"); + printf("output2: '%s'\n",output2); + return(0); +} diff --git a/src/os_crypto/md5/Makefile b/src/os_crypto/md5/Makefile new file mode 100755 index 0000000..14abd4e --- /dev/null +++ b/src/os_crypto/md5/Makefile @@ -0,0 +1,21 @@ +# Makefile for os_crypto md5 +# Daniel B. Cid || + +PT=../../ +NAME=md5_op + +include ../../Config.Make + +SRCS = md5.c md5_op.c +md5_OBJS = md5_op.o md5.o + + +md5: + $(CC) $(CFLAGS) -c $(SRCS) + ar cru md5_op.a $(md5_OBJS) + ranlib md5_op.a +main: + $(CC) $(CFLAGS) -o main main.c md5_op.a + +clean: + rm -f *.o *.a main diff --git a/src/os_crypto/md5/main.c b/src/os_crypto/md5/main.c new file mode 100755 index 0000000..8265fa6 --- /dev/null +++ b/src/os_crypto/md5/main.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "md5_op.h" + +void usage(char **argv) +{ + printf("%s file str\n%s str string\n",argv[0],argv[0]); + exit(1); +} + +/* make main to compile (after the make md5) + * Example of the md5 API use + * Daniel B. Cid, dcid@ossec.net + */ +int main(int argc, char ** argv) +{ + os_md5 filesum; + + if(argc < 3) + usage(argv); + + + if(strcmp(argv[1],"file") == 0) + { + OS_MD5_File(argv[2], filesum); + } + + else if(strcmp(argv[1],"str") == 0) + { + OS_MD5_Str(argv[2], filesum); + } + + else + usage(argv); + + printf("MD5Sum for \"%s\" is: %s\n",argv[2],filesum); + return(0); +} + +/* EOF */ diff --git a/src/os_crypto/md5/md5.c b/src/os_crypto/md5/md5.c new file mode 100755 index 0000000..f2eb619 --- /dev/null +++ b/src/os_crypto/md5/md5.c @@ -0,0 +1,263 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include /* for memcpy() */ +#include + +#include "md5.h" + +/* Checking for endiannes */ +#ifdef __BYTE_ORDER +#if __BYTE_ORDER == __BIG_ENDIAN + #define HIGHFIRST +#endif /* BIG ENDIAN */ +#endif /* byte order */ + + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/src/os_crypto/md5/md5.h b/src/os_crypto/md5/md5.h new file mode 100755 index 0000000..24aa178 --- /dev/null +++ b/src/os_crypto/md5/md5.h @@ -0,0 +1,58 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + + +#ifndef MD5_H +#define MD5_H + +#include +#if defined SOLARIS +typedef uint32_t u_int32_t; +typedef uint16_t u_int16_t; +typedef uint8_t u_int8_t; +#endif + +#if defined HPUX +typedef uint32_t u_int32_t; +typedef uint16_t u_int16_t; +typedef uint8_t u_int8_t; +#endif + +#ifdef WIN32 +typedef unsigned int u_int32_t; +#endif + +typedef u_int32_t uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); +void MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !MD5_H */ diff --git a/src/os_crypto/md5/md5_op.c b/src/os_crypto/md5/md5_op.c new file mode 100755 index 0000000..fdd9958 --- /dev/null +++ b/src/os_crypto/md5/md5_op.c @@ -0,0 +1,88 @@ +/* $OSSEC, os_crypto/md5_op.c, v0.2, 2005/09/17, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* v0.2 (2005/09/17): char fixes (signal) + * v0.1 (2004/08/09) + */ + +/* OS_crypto/md5 Library. + * APIs for many crypto operations. + */ + + +#include +#include +#include "md5.h" + +int OS_MD5_File(char * fname, char * output) +{ + FILE *fp; + MD5_CTX ctx; + unsigned char buf[1024 +1]; + unsigned char digest[16]; + int n; + + memset(output,0, 33); + buf[1024] = '\0'; + + fp = fopen(fname,"r"); + if(!fp) + { + return(-1); + } + + MD5Init(&ctx); + while((n = fread(buf, 1, sizeof(buf) -1, fp)) > 0) + { + buf[n] = '\0'; + MD5Update(&ctx,buf,n); + } + + MD5Final(digest, &ctx); + + for(n = 0;n < 16; n++) + { + snprintf(output, 3, "%02x", digest[n]); + output+=2; + } + + /* Closing it */ + fclose(fp); + + return(0); +} + +/* EOF */ +int OS_MD5_Str(char * str, char * output) +{ + unsigned char digest[16]; + + int n; + + MD5_CTX ctx; + + MD5Init(&ctx); + + MD5Update(&ctx,(unsigned char *)str,strlen(str)); + + MD5Final(digest, &ctx); + + output[32] = '\0'; + for(n = 0;n < 16;n++) + { + snprintf(output, 3, "%02x", digest[n]); + output+=2; + } + + return(0); +} + +/* EOF */ diff --git a/src/os_crypto/md5/md5_op.h b/src/os_crypto/md5/md5_op.h new file mode 100755 index 0000000..3af94d7 --- /dev/null +++ b/src/os_crypto/md5/md5_op.h @@ -0,0 +1,28 @@ +/* $OSSEC, os_crypto/md5_op.h, v0.1, 2004/08/09, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* OS_crypto/md5 Library. + * APIs for many crypto operations. + */ + +#ifndef __MD5_OP_H + +#define __MD5_OP_H + +typedef char os_md5[33]; + +int OS_MD5_File(char *fname, char * output); + +int OS_MD5_Str(char * str, char * output); + +#endif + +/* EOF */ diff --git a/src/os_crypto/md5_sha1/Makefile b/src/os_crypto/md5_sha1/Makefile new file mode 100755 index 0000000..f048f7b --- /dev/null +++ b/src/os_crypto/md5_sha1/Makefile @@ -0,0 +1,21 @@ +# Makefile for os_crypto md5_sha1 +# Daniel B. Cid + +PT=../../ +NAME=md5_sha1_op + +include ../../Config.Make + +SRCS = ../md5/md5.c md5_sha1_op.c +md5_OBJS = md5_sha1_op.o ../md5/md5.o + + +md5: + $(CC) $(CFLAGS) -c $(SRCS) + ar cru md5_op.a $(md5_OBJS) + ranlib md5_op.a +main: + $(CC) $(CFLAGS) -o main main.c md5_op.a + +clean: + rm -f *.o *.a main diff --git a/src/os_crypto/md5_sha1/main.c b/src/os_crypto/md5_sha1/main.c new file mode 100755 index 0000000..71e3965 --- /dev/null +++ b/src/os_crypto/md5_sha1/main.c @@ -0,0 +1,40 @@ +#include +#include +#include + +#include "../md5/md5_op.h" +#include "../sha1/sha1_op.h" +#include "md5_sha1_op.h" + +void usage(char **argv) +{ + printf("%s file str\n%s str string\n",argv[0],argv[0]); + exit(1); +} + +/* make main to compile (after the make md5) + * Example of the md5 API use + * Daniel B. Cid, dcid@ossec.net + */ +int main(int argc, char ** argv) +{ + os_md5 filesum1; + os_sha1 filesum2; + + if(argc < 3) + usage(argv); + + + if(strcmp(argv[1],"file") == 0) + { + OS_MD5_SHA1_File(argv[2], filesum1, filesum2); + } + + else + usage(argv); + + printf("MD5Sha1Sum for \"%s\" is: %s - %s\n",argv[2], filesum1, filesum2); + return(0); +} + +/* EOF */ diff --git a/src/os_crypto/md5_sha1/md5_sha1_op.c b/src/os_crypto/md5_sha1/md5_sha1_op.c new file mode 100755 index 0000000..d38e542 --- /dev/null +++ b/src/os_crypto/md5_sha1/md5_sha1_op.c @@ -0,0 +1,83 @@ +/* @(#) $Id: md5_sha1_op.c,v 1.3 2009/06/24 17:06:28 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include "md5_sha1_op.h" + +#include "../md5/md5.h" +#include "../sha1/sha.h" + + + +int OS_MD5_SHA1_File(char * fname, char *md5output, char *sha1output) +{ + int n; + FILE *fp; + unsigned char buf[2048 +2]; + unsigned char sha1_digest[SHA_DIGEST_LENGTH]; + unsigned char md5_digest[16]; + + SHA_CTX sha1_ctx; + MD5_CTX md5_ctx; + + + /* Clearing the memory. */ + md5output[0] = '\0'; + sha1output[0] = '\0'; + buf[2048 +1] = '\0'; + + fp = fopen(fname,"r"); + if(!fp) + return(-1); + + + /* Initializing both hashes */ + MD5Init(&md5_ctx); + SHA1_Init(&sha1_ctx); + + + /* Updating for each one. */ + while((n = fread(buf, 1, 2048, fp)) > 0) + { + buf[n] = '\0'; + SHA1_Update(&sha1_ctx, buf, (unsigned long)n); + MD5Update(&md5_ctx, buf, n); + } + + SHA1_Final(&(sha1_digest[0]), &sha1_ctx); + MD5Final(md5_digest, &md5_ctx); + + + /* Setting output for md5. */ + for(n = 0;n < 16; n++) + { + snprintf(md5output, 3, "%02x", md5_digest[n]); + md5output+=2; + } + + /* Setting output for sha1. */ + for (n = 0; n + + +PT=../../ +NAME=sha1_op + +include ../../Config.Make + +SRCS = sha1_op.c +sha1_OBJS = sha1_op.o + + +sha1: + $(CC) $(CFLAGS) -c $(SRCS) + ar cru sha1_op.a $(sha1_OBJS) + ranlib sha1_op.a +main: + $(CC) $(CFLAGS) -o main main.c sha1_op.a + +clean: + rm -f *.o *.a main diff --git a/src/os_crypto/sha1/main.c b/src/os_crypto/sha1/main.c new file mode 100755 index 0000000..4373f47 --- /dev/null +++ b/src/os_crypto/sha1/main.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#include "sha1_op.h" + +void usage(char **argv) +{ + printf("%s file\n", argv[0]); + exit(1); +} + +/* make main to compile (after the make md5) + * Example of the md5 API use + * Daniel B. Cid, dcid@ossec.net + */ +int main(int argc, char ** argv) +{ + os_sha1 filesum; + + if(argc < 2) + usage(argv); + + + if(OS_SHA1_File(argv[1], filesum) == 0) + { + printf("SHA1Sum for \"%s\" is: %s\n",argv[1],filesum); + } + else + { + printf("SHA1Sum for \"%s\" failed\n", argv[1]); + } + return(0); +} + +/* EOF */ diff --git a/src/os_crypto/sha1/md32_common.h b/src/os_crypto/sha1/md32_common.h new file mode 100755 index 0000000..0081ec5 --- /dev/null +++ b/src/os_crypto/sha1/md32_common.h @@ -0,0 +1,634 @@ +/* @(#) $Id: md32_common.h,v 1.2 2007/09/22 03:29:13 dcid Exp $ */ +/* Included on ossec */ + +/* crypto/md32_common.h */ +/* ==================================================================== + * Copyright (c) 1999-2002 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at lest 32 bit wide, if it's wider, then + * HASH_LONG_LOG2 *has to* be defined along + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * HASH_LONG data[HASH_LBLOCK]; + * unsigned int num; + * ... + * } HASH_CTX; + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_HOST_ORDER + * name of "block" function treating *aligned* input message + * in host byte order, implemented externally. + * HASH_BLOCK_DATA_ORDER + * name of "block" function treating *unaligned* input message + * in original (data) byte order, implemented externally (it + * actually is optional if data and host are of the same + * "endianess"). + * HASH_MAKE_STRING + * macro convering context variables to an ASCII hash string. + * + * Optional macros: + * + * B_ENDIAN or L_ENDIAN + * defines host byte-order. + * HASH_LONG_LOG2 + * defaults to 2 if not states otherwise. + * HASH_LBLOCK + * assumed to be HASH_CBLOCK/4 if not stated otherwise. + * HASH_BLOCK_DATA_ORDER_ALIGNED + * alternative "block" function capable of treating + * aligned input message in original (data) order, + * implemented externally. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_LONG_LOG2 MD5_LONG_LOG2 + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_LBLOCK MD5_LBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_HOST_ORDER md5_block_host_order + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + * + * + */ + + +#ifndef _MD32_COMMON__H +#define _MD32_COMMON__H + + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +#error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +#error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +#error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +#error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +#error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +#error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_HOST_ORDER +#error "HASH_BLOCK_HOST_ORDER must be defined!" +#endif + +#if 0 +/* + * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED + * isn't defined. + */ +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#ifndef HASH_LBLOCK +#define HASH_LBLOCK (HASH_CBLOCK/4) +#endif + +#ifndef HASH_LONG_LOG2 +#define HASH_LONG_LOG2 2 +#endif + +/* + * Engage compiler specific rotate intrinsic function if available. + */ +#undef ROTATE +#ifndef PEDANTIC +# if defined(_MSC_VER) || defined(__ICC) +# define ROTATE(a,n) _lrotl(a,n) +# elif defined(__MWERKS__) +# if defined(__POWERPC__) +# define ROTATE(a,n) __rlwinm(a,n,0,31) +# elif defined(__MC68K__) + /* Motorola specific tweak. */ +# define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) +# else +# define ROTATE(a,n) __rol(a,n) +# endif +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) + /* + * Some GNU C inline assembler templates. Note that these are + * rotates by *constant* number of bits! But that's exactly + * what we need here... + * + */ +# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "roll %1,%0" \ + : "=r"(ret) \ + : "I"(n), "0"(a) \ + : "cc"); \ + ret; \ + }) +# elif defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "rlwinm %0,%1,%2,0,31" \ + : "=r"(ret) \ + : "r"(a), "I"(n)); \ + ret; \ + }) +# endif +# endif +#endif /* PEDANTIC */ + +#if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */ +/* A nice byte order reversal from Wei Dai */ +#ifdef ROTATE +/* 5 instructions with rotate instruction, else 9 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \ + ) +#else +/* 6 instructions with rotate instruction, else 8 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \ + ROTATE(l,16) \ + ) +/* + * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... + * It's rewritten as above for two reasons: + * - RISCs aren't good at long constants and have to explicitely + * compose 'em with several (well, usually 2) instructions in a + * register before performing the actual operation and (as you + * already realized:-) having same constant should inspire the + * compiler to permanently allocate the only register for it; + * - most modern CPUs have two ALUs, but usually only one has + * circuitry for shifts:-( this minor tweak inspires compiler + * to schedule shift instructions in a better way... + * + * + */ +#endif +#endif + +#ifndef ROTATE +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* + * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED + * and HASH_BLOCK_HOST_ORDER ought to be the same if input data + * and host are of the same "endianess". It's possible to mask + * this with blank #define HASH_BLOCK_DATA_ORDER though... + * + * + */ +#if defined(B_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# endif +#elif defined(L_ENDIAN) +# if defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# endif +#endif + +#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#ifndef PEDANTIC +# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +# if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \ + (defined(__x86_64) || defined(__x86_64__)) + /* + * This gives ~30-40% performance improvement in SHA-256 compiled + * with gcc [on P4]. Well, first macro to be frank. We can pull + * this trick on x86* platforms only, because these CPUs can fetch + * unaligned data without raising an exception. + */ +# define HOST_c2l(c,l) ({ unsigned int r=*((const unsigned int *)(c)); \ + asm ("bswapl %0":"=r"(r):"0"(r)); \ + (c)+=4; (l)=r; }) +# define HOST_l2c(l,c) ({ unsigned int r=(l); \ + asm ("bswapl %0":"=r"(r):"0"(r)); \ + *((unsigned int *)(c))=r; (c)+=4; r; }) +# endif +# endif +#endif + +#ifndef HOST_c2l +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ), \ + l) +#endif +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } } +#ifndef HOST_l2c +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) +#endif + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# ifndef B_ENDIAN + /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */ +# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l) +# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l) +# endif +#endif + +#ifndef HOST_c2l +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24), \ + l) +#endif +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } } +#ifndef HOST_l2c +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) +#endif + +#endif + +/* + * Time for some action:-) + */ + +int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len) + { + const unsigned char *data=data_; + register HASH_LONG * p; + register HASH_LONG l; + size_t sw,sc,ew,ec; + + if (len==0) return 1; + + l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); /* might cause compiler warning on 16-bit */ + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= HASH_CBLOCK) + { + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; swnum); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=(unsigned int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + if (sc) + l=p[sw]; + HOST_p_c2l(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { + HOST_c2l(data,l); p[sw]=l; + } + if (ec) + { + HOST_c2l_p(data,l,ec); p[sw]=l; + } + } + return 1; + } + } + + sw=len/HASH_CBLOCK; + if (sw > 0) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + /* + * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined + * only if sizeof(HASH_LONG)==4. + */ + if ((((size_t)data)%4) == 0) + { + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(const HASH_LONG *)data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } + else +#if !defined(HASH_BLOCK_DATA_ORDER) + while (sw--) + { + memcpy (p=c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); + data+=HASH_CBLOCK; + len-=HASH_CBLOCK; + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + { + HASH_BLOCK_DATA_ORDER(c,data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } +#endif + } + + if (len!=0) + { + p = c->data; + c->num = len; + ew=len>>2; /* words to copy */ + ec=len&0x03; + for (; ew; ew--,p++) + { + HOST_c2l(data,l); *p=l; + } + HOST_c2l_p(data,l,ec); + *p=l; + } + return 1; + } + + +void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + if ((((size_t)data)%4) == 0) + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(const HASH_LONG *)data,1); + else +#if !defined(HASH_BLOCK_DATA_ORDER) + { + memcpy (c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + HASH_BLOCK_DATA_ORDER (c,data,1); +#endif + } + + +int HASH_FINAL (unsigned char *md, HASH_CTX *c) + { + register HASH_LONG *p; + register unsigned long l; + register int i,j; + static const unsigned char end[4]={0x80,0x00,0x00,0x00}; + const unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + i=c->num>>2; + j=c->num&0x03; + +#if 0 + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + * Many thanks to Alex Tang for pickup this + * 'potential bug' */ +#ifdef PURIFY + if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */ +#endif + l=p[i]; +#else + l = (j==0) ? 0 : p[i]; +#endif + HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ + + if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ + { + if (iNh; + p[HASH_LBLOCK-1]=c->Nl; +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + p[HASH_LBLOCK-2]=c->Nl; + p[HASH_LBLOCK-1]=c->Nh; +#endif + HASH_BLOCK_HOST_ORDER (c,p,1); + +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c,md); +#endif + + c->num=0; + /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack + * but I'm not worried :-) + OPENSSL_cleanse((void *)c,sizeof(HASH_CTX)); + */ + return 1; + } + +#ifndef MD32_REG_T +#define MD32_REG_T long +/* + * This comment was originaly written for MD5, which is why it + * discusses A-D. But it basically applies to all 32-bit digests, + * which is why it was moved to common header file. + * + * In case you wonder why A-D are declared as long and not + * as MD5_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + * + * Apparently there're LP64 compilers that generate better + * code if A-D are declared int. Most notably GCC-x86_64 + * generates better code. + * + */ +#endif + + +#endif /* _MD32_COMMON__H */ diff --git a/src/os_crypto/sha1/sha.h b/src/os_crypto/sha1/sha.h new file mode 100755 index 0000000..4079cb4 --- /dev/null +++ b/src/os_crypto/sha1/sha.h @@ -0,0 +1,104 @@ +/* @(#) $Id: sha.h,v 1.1 2006/07/12 18:28:29 dcid Exp $ */ +/* Included on ossec */ + + +/* crypto/sha/sha.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SHA_H +#define HEADER_SHA_H + + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! SHA_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(__LP32__) +#define SHA_LONG unsigned long +#elif defined(__ILP64__) +#define SHA_LONG unsigned long +#define SHA_LONG_LOG2 3 +#else +#define SHA_LONG unsigned int +#endif + +#define SHA_LBLOCK 16 +#define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a + * contiguous array of 32 bit + * wide big-endian values. */ +#define SHA_LAST_BLOCK (SHA_CBLOCK-8) +#define SHA_DIGEST_LENGTH 20 + +typedef struct SHAstate_st + { + SHA_LONG h0,h1,h2,h3,h4; + SHA_LONG Nl,Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num; + } SHA_CTX; + +int SHA1_Init(SHA_CTX *c); +int SHA1_Update(SHA_CTX *c, const void *data, size_t len); +int SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); + +#endif diff --git a/src/os_crypto/sha1/sha1_op.c b/src/os_crypto/sha1/sha1_op.c new file mode 100755 index 0000000..3b1ad04 --- /dev/null +++ b/src/os_crypto/sha1/sha1_op.c @@ -0,0 +1,68 @@ +/* @(#) $Id: sha1_op.c,v 1.7 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include "sha1_op.h" + +/* Openssl sha1 + * Only use if open ssl is not available. +#ifndef USE_OPENSSL +#include "sha.h" +#include "sha_locl.h" +#else +#include +#endif +*/ + +#include "sha_locl.h" + + + +int OS_SHA1_File(char * fname, char * output) +{ + SHA_CTX c; + FILE *fp; + unsigned char buf[2048 +2]; + unsigned char md[SHA_DIGEST_LENGTH]; + int n; + + memset(output,0, 65); + buf[2049] = '\0'; + + fp = fopen(fname,"r"); + if(!fp) + return(-1); + + SHA1_Init(&c); + while((n = fread(buf, 1, 2048, fp)) > 0) + { + buf[n] = '\0'; + SHA1_Update(&c,buf,(unsigned long)n); + } + + SHA1_Final(&(md[0]),&c); + + for (n=0; n +#include + +#include "sha.h" + +#define SHA_1 +#ifndef SHA_LONG_LOG2 +#define SHA_LONG_LOG2 2 /* default to 32 bits */ +#endif + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_LONG SHA_LONG +#define HASH_LONG_LOG2 SHA_LONG_LOG2 +#define HASH_CTX SHA_CTX +#define HASH_CBLOCK SHA_CBLOCK +#define HASH_LBLOCK SHA_LBLOCK +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->h0; HOST_l2c(ll,(s)); \ + ll=(c)->h1; HOST_l2c(ll,(s)); \ + ll=(c)->h2; HOST_l2c(ll,(s)); \ + ll=(c)->h3; HOST_l2c(ll,(s)); \ + ll=(c)->h4; HOST_l2c(ll,(s)); \ + } while (0) + +#if defined(SHA_0) + +# define HASH_UPDATE SHA_Update +# define HASH_TRANSFORM SHA_Transform +# define HASH_FINAL SHA_Final +# define HASH_INIT SHA_Init +# define HASH_BLOCK_HOST_ORDER sha_block_host_order +# define HASH_BLOCK_DATA_ORDER sha_block_data_order +# define Xupdate(a,ix,ia,ib,ic,id) (ix=(a)=(ia^ib^ic^id)) + + void sha_block_host_order (SHA_CTX *c, const void *p,size_t num); + void sha_block_data_order (SHA_CTX *c, const void *p,size_t num); + +#elif defined(SHA_1) + +# define HASH_UPDATE SHA1_Update +# define HASH_TRANSFORM SHA1_Transform +# define HASH_FINAL SHA1_Final +# define HASH_INIT SHA1_Init +# define HASH_BLOCK_HOST_ORDER sha1_block_host_order +# define HASH_BLOCK_DATA_ORDER sha1_block_data_order +# if defined(__MWERKS__) && defined(__MC68K__) + /* Metrowerks for Motorola fails otherwise:-( */ +# define Xupdate(a,ix,ia,ib,ic,id) do { (a)=(ia^ib^ic^id); \ + ix=(a)=ROTATE((a),1); \ + } while (0) +# else +# define Xupdate(a,ix,ia,ib,ic,id) ( (a)=(ia^ib^ic^id), \ + ix=(a)=ROTATE((a),1) \ + ) +# endif + +# ifdef SHA1_ASM +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) +# if !defined(B_ENDIAN) +# define sha1_block_host_order sha1_block_asm_host_order +# define DONT_IMPLEMENT_BLOCK_HOST_ORDER +# define sha1_block_data_order sha1_block_asm_data_order +# define DONT_IMPLEMENT_BLOCK_DATA_ORDER +# define HASH_BLOCK_DATA_ORDER_ALIGNED sha1_block_asm_data_order +# endif +# elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) +# define sha1_block_host_order sha1_block_asm_host_order +# define DONT_IMPLEMENT_BLOCK_HOST_ORDER +# define sha1_block_data_order sha1_block_asm_data_order +# define DONT_IMPLEMENT_BLOCK_DATA_ORDER +# endif +# endif + void sha1_block_host_order (SHA_CTX *c, const void *p,size_t num); + void sha1_block_data_order (SHA_CTX *c, const void *p,size_t num); + +#else +# error "Either SHA_0 or SHA_1 must be defined." +#endif + +#include "md32_common.h" + +#define INIT_DATA_h0 0x67452301UL +#define INIT_DATA_h1 0xefcdab89UL +#define INIT_DATA_h2 0x98badcfeUL +#define INIT_DATA_h3 0x10325476UL +#define INIT_DATA_h4 0xc3d2e1f0UL + +int HASH_INIT (SHA_CTX *c) + { + c->h0=INIT_DATA_h0; + c->h1=INIT_DATA_h1; + c->h2=INIT_DATA_h2; + c->h3=INIT_DATA_h3; + c->h4=INIT_DATA_h4; + c->Nl=0; + c->Nh=0; + c->num=0; + return 1; + } + +#define K_00_19 0x5a827999UL +#define K_20_39 0x6ed9eba1UL +#define K_40_59 0x8f1bbcdcUL +#define K_60_79 0xca62c1d6UL + +/* As pointed out by Wei Dai , F() below can be + * simplified to the code in F_00_19. Wei attributes these optimisations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) + * I've just become aware of another tweak to be made, again from Wei Dai, + * in F_40_59, (x&a)|(y&a) -> (x|y)&a + */ +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#ifndef OPENSSL_SMALL_FOOTPRINT + +#define BODY_00_15(i,a,b,c,d,e,f,xi) \ + (f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ + (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#ifdef X +#undef X +#endif +#ifndef MD32_XARRAY + /* + * Originally X was an array. As it's automatic it's natural + * to expect RISC compiler to accomodate at least part of it in + * the register bank, isn't it? Unfortunately not all compilers + * "find" this expectation reasonable:-( On order to make such + * compilers generate better code I replace X[] with a bunch of + * X0, X1, etc. See the function body below... + * + */ +# define X(i) XX##i +#else + /* + * However! Some compilers (most notably HP C) get overwhelmed by + * that many local variables so that we have to have the way to + * fall down to the original behavior. + */ +# define X(i) XX[i] +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER +void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, size_t num) + { + const SHA_LONG *W=d; + register unsigned MD32_REG_T A,B,C,D,E,T; +#ifndef MD32_XARRAY + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +#else + SHA_LONG XX[16]; +#endif + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + BODY_00_15( 0,A,B,C,D,E,T,W[ 0]); + BODY_00_15( 1,T,A,B,C,D,E,W[ 1]); + BODY_00_15( 2,E,T,A,B,C,D,W[ 2]); + BODY_00_15( 3,D,E,T,A,B,C,W[ 3]); + BODY_00_15( 4,C,D,E,T,A,B,W[ 4]); + BODY_00_15( 5,B,C,D,E,T,A,W[ 5]); + BODY_00_15( 6,A,B,C,D,E,T,W[ 6]); + BODY_00_15( 7,T,A,B,C,D,E,W[ 7]); + BODY_00_15( 8,E,T,A,B,C,D,W[ 8]); + BODY_00_15( 9,D,E,T,A,B,C,W[ 9]); + BODY_00_15(10,C,D,E,T,A,B,W[10]); + BODY_00_15(11,B,C,D,E,T,A,W[11]); + BODY_00_15(12,A,B,C,D,E,T,W[12]); + BODY_00_15(13,T,A,B,C,D,E,W[13]); + BODY_00_15(14,E,T,A,B,C,D,W[14]); + BODY_00_15(15,D,E,T,A,B,C,W[15]); + + BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]); + BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]); + BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]); + BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0)); + + BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1)); + BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2)); + BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3)); + BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4)); + BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5)); + BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6)); + BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7)); + BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8)); + BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9)); + BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10)); + BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11)); + BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12)); + + BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); + BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); + BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); + BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); + BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); + BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); + BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); + BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); + + BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); + BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); + BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); + BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); + BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); + BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); + BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); + BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); + BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); + BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); + BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); + BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); + BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); + BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); + BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); + BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); + + BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); + BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); + BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); + BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); + BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); + BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); + BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); + BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); + BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); + BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); + BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); + BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); + BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); + BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); + BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); + BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); + BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); + BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); + BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); + BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + if (--num == 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=SHA_LBLOCK; + } + } +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER +void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, size_t num) + { + const unsigned char *data=p; + register unsigned MD32_REG_T A,B,C,D,E,T,l; +#ifndef MD32_XARRAY + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +#else + SHA_LONG XX[16]; +#endif + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + + HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + BODY_00_15( 0,A,B,C,D,E,T,X( 0)); HOST_c2l(data,l); X( 2)=l; + BODY_00_15( 1,T,A,B,C,D,E,X( 1)); HOST_c2l(data,l); X( 3)=l; + BODY_00_15( 2,E,T,A,B,C,D,X( 2)); HOST_c2l(data,l); X( 4)=l; + BODY_00_15( 3,D,E,T,A,B,C,X( 3)); HOST_c2l(data,l); X( 5)=l; + BODY_00_15( 4,C,D,E,T,A,B,X( 4)); HOST_c2l(data,l); X( 6)=l; + BODY_00_15( 5,B,C,D,E,T,A,X( 5)); HOST_c2l(data,l); X( 7)=l; + BODY_00_15( 6,A,B,C,D,E,T,X( 6)); HOST_c2l(data,l); X( 8)=l; + BODY_00_15( 7,T,A,B,C,D,E,X( 7)); HOST_c2l(data,l); X( 9)=l; + BODY_00_15( 8,E,T,A,B,C,D,X( 8)); HOST_c2l(data,l); X(10)=l; + BODY_00_15( 9,D,E,T,A,B,C,X( 9)); HOST_c2l(data,l); X(11)=l; + BODY_00_15(10,C,D,E,T,A,B,X(10)); HOST_c2l(data,l); X(12)=l; + BODY_00_15(11,B,C,D,E,T,A,X(11)); HOST_c2l(data,l); X(13)=l; + BODY_00_15(12,A,B,C,D,E,T,X(12)); HOST_c2l(data,l); X(14)=l; + BODY_00_15(13,T,A,B,C,D,E,X(13)); HOST_c2l(data,l); X(15)=l; + BODY_00_15(14,E,T,A,B,C,D,X(14)); + BODY_00_15(15,D,E,T,A,B,C,X(15)); + + BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13)); + BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14)); + BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15)); + BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0)); + + BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1)); + BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2)); + BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3)); + BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4)); + BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5)); + BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6)); + BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7)); + BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8)); + BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9)); + BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10)); + BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11)); + BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12)); + + BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); + BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); + BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); + BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); + BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); + BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); + BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); + BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); + + BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); + BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); + BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); + BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); + BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); + BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); + BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); + BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); + BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); + BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); + BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); + BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); + BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); + BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); + BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); + BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); + + BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); + BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); + BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); + BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); + BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); + BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); + BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); + BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); + BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); + BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); + BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); + BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); + BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); + BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); + BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); + BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); + BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); + BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); + BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); + BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + if (--num == 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + } + } +#endif + +#else /* OPENSSL_SMALL_FOOTPRINT */ + +#define BODY_00_15(xi) do { \ + T=E+K_00_19+F_00_19(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T+xi; } while(0) + +#define BODY_16_19(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T+=E+K_00_19+F_00_19(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T; } while(0) + +#define BODY_20_39(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T+=E+K_20_39+F_20_39(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T; } while(0) + +#define BODY_40_59(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T+=E+K_40_59+F_40_59(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T; } while(0) + +#define BODY_60_79(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T=E+K_60_79+F_60_79(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T+xa; } while(0) + +#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER +void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, size_t num) + { + const SHA_LONG *W=d; + register unsigned MD32_REG_T A,B,C,D,E,T; + int i; + SHA_LONG X[16]; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + for (i=0;i<16;i++) + { X[i]=W[i]; BODY_00_15(X[i]); } + for (i=0;i<4;i++) + { BODY_16_19(X[i], X[i+2], X[i+8], X[(i+13)&15]); } + for (;i<24;i++) + { BODY_20_39(X[i&15], X[(i+2)&15], X[(i+8)&15],X[(i+13)&15]); } + for (i=0;i<20;i++) + { BODY_40_59(X[(i+8)&15],X[(i+10)&15],X[i&15], X[(i+5)&15]); } + for (i=4;i<24;i++) + { BODY_60_79(X[(i+8)&15],X[(i+10)&15],X[i&15], X[(i+5)&15]); } + + c->h0=(c->h0+A)&0xffffffffL; + c->h1=(c->h1+B)&0xffffffffL; + c->h2=(c->h2+C)&0xffffffffL; + c->h3=(c->h3+D)&0xffffffffL; + c->h4=(c->h4+E)&0xffffffffL; + + if (--num == 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=SHA_LBLOCK; + } + } +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER +void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, size_t num) + { + const unsigned char *data=p; + register unsigned MD32_REG_T A,B,C,D,E,T,l; + int i; + SHA_LONG X[16]; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + for (i=0;i<16;i++) + { HOST_c2l(data,l); X[i]=l; BODY_00_15(X[i]); } + for (i=0;i<4;i++) + { BODY_16_19(X[i], X[i+2], X[i+8], X[(i+13)&15]); } + for (;i<24;i++) + { BODY_20_39(X[i&15], X[(i+2)&15], X[(i+8)&15],X[(i+13)&15]); } + for (i=0;i<20;i++) + { BODY_40_59(X[(i+8)&15],X[(i+10)&15],X[i&15], X[(i+5)&15]); } + for (i=4;i<24;i++) + { BODY_60_79(X[(i+8)&15],X[(i+10)&15],X[i&15], X[(i+5)&15]); } + + c->h0=(c->h0+A)&0xffffffffL; + c->h1=(c->h1+B)&0xffffffffL; + c->h2=(c->h2+C)&0xffffffffL; + c->h3=(c->h3+D)&0xffffffffL; + c->h4=(c->h4+E)&0xffffffffL; + + if (--num == 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + } + } +#endif + +#endif + + +#endif /* _SHA_LOCL__H */ diff --git a/src/os_crypto/shared/Makefile b/src/os_crypto/shared/Makefile new file mode 100755 index 0000000..b236abf --- /dev/null +++ b/src/os_crypto/shared/Makefile @@ -0,0 +1,18 @@ +# Makefile for os_crypto shared +# Daniel B. Cid || + +PT=../../ +NAME=shared + +include ../../Config.Make + +SRCS = *.c +OBJS = *.o + + +shared: + $(CC) $(CFLAGS) -c $(SRCS) + ar cru shared.a $(OBJS) + ranlib shared.a +clean: + ${CLEAN} diff --git a/src/os_crypto/shared/keys.c b/src/os_crypto/shared/keys.c new file mode 100755 index 0000000..9e6d7e7 --- /dev/null +++ b/src/os_crypto/shared/keys.c @@ -0,0 +1,511 @@ +/* @(#) $Id: keys.c,v 1.10 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#include "headers/shared.h" +#include "headers/sec.h" + +#include "os_zlib/os_zlib.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/blowfish/bf_op.h" + + + +/* __memclear: Clears keys entries. + */ +void __memclear(char *id, char *name, char *ip, char *key, int size) +{ + memset(id,'\0', size); + memset(name,'\0', size); + memset(key,'\0', size); + memset(ip,'\0', size); +} + + +/* __chash: Creates the final key. + */ +void __chash(keystore *keys, char *id, char *name, char *ip, char *key) +{ + os_md5 filesum1; + os_md5 filesum2; + + char *tmp_str; + char _finalstr[KEYSIZE]; + + + /* Allocating for the whole structure */ + keys->keyentries =(keyentry **)realloc(keys->keyentries, + (keys->keysize+2)*sizeof(keyentry *)); + if(!keys->keyentries) + { + ErrorExit(MEM_ERROR, __local_name); + } + os_calloc(1, sizeof(keyentry), keys->keyentries[keys->keysize]); + + + /* Setting configured values for id */ + os_strdup(id, keys->keyentries[keys->keysize]->id); + OSHash_Add(keys->keyhash_id, + keys->keyentries[keys->keysize]->id, + keys->keyentries[keys->keysize]); + + + /* agent ip */ + os_calloc(1, sizeof(os_ip), keys->keyentries[keys->keysize]->ip); + if(OS_IsValidIP(ip, keys->keyentries[keys->keysize]->ip) == 0) + { + ErrorExit(INVALID_IP, __local_name, ip); + } + + /* We need to remove the "/" from the cidr */ + if((tmp_str = strchr(keys->keyentries[keys->keysize]->ip->ip, '/')) != NULL) + { + *tmp_str = '\0'; + } + OSHash_Add(keys->keyhash_ip, + keys->keyentries[keys->keysize]->ip->ip, + keys->keyentries[keys->keysize]); + + + /* agent name */ + os_strdup(name, keys->keyentries[keys->keysize]->name); + + /* Initializing the variables */ + keys->keyentries[keys->keysize]->rcvd = 0; + keys->keyentries[keys->keysize]->local = 0; + keys->keyentries[keys->keysize]->keyid = keys->keysize; + keys->keyentries[keys->keysize]->global = 0; + keys->keyentries[keys->keysize]->fp = NULL; + + + + /** Generating final symmetric key **/ + + /* MD5 from name, id and key */ + OS_MD5_Str(name, filesum1); + OS_MD5_Str(id, filesum2); + + + /* Generating new filesum1 */ + snprintf(_finalstr, sizeof(_finalstr)-1, "%s%s", filesum1, filesum2); + + + /* Using just half of the first md5 (name/id) */ + OS_MD5_Str(_finalstr, filesum1); + filesum1[15] = '\0'; + filesum1[16] = '\0'; + + + /* Second md is just the key */ + OS_MD5_Str(key, filesum2); + + + /* Generating final key */ + memset(_finalstr,'\0', sizeof(_finalstr)); + snprintf(_finalstr, 49, "%s%s", filesum2, filesum1); + + + /* Final key is 48 * 4 = 192bits */ + os_strdup(_finalstr, keys->keyentries[keys->keysize]->key); + + + /* Cleaning final string from memory */ + memset(_finalstr,'\0', sizeof(_finalstr)); + + + /* ready for next */ + keys->keysize++; + + + return; +} + + +/* int OS_CheckKeys(): + * Checks if the authentication key file is present + */ +int OS_CheckKeys() +{ + FILE *fp; + + if(File_DateofChange(KEYSFILE_PATH) < 0) + { + merror(NO_AUTHFILE, __local_name, KEYSFILE_PATH); + merror(NO_REM_CONN, __local_name); + return(0); + } + + fp = fopen(KEYSFILE_PATH, "r"); + if(!fp) + { + /* We can leave from here */ + merror(FOPEN_ERROR, __local_name, KEYSFILE_PATH); + merror(NO_AUTHFILE, __local_name, KEYSFILE_PATH); + merror(NO_REM_CONN, __local_name); + return(0); + } + + fclose(fp); + + + /* Authentication keys are present */ + return(1); +} + + +/* void OS_ReadKeys(keystore *keys) + * Read the authentication keys. + */ +void OS_ReadKeys(keystore *keys) +{ + FILE *fp; + + char buffer[OS_BUFFER_SIZE +1]; + + char name[KEYSIZE +1]; + char ip[KEYSIZE +1]; + char id[KEYSIZE +1]; + char key[KEYSIZE +1]; + + + /* Checking if the keys file is present and we can read it. */ + if((keys->file_change = File_DateofChange(KEYS_FILE)) < 0) + { + merror(NO_AUTHFILE, __local_name, KEYS_FILE); + ErrorExit(NO_REM_CONN, __local_name); + } + fp = fopen(KEYS_FILE,"r"); + if(!fp) + { + /* We can leave from here */ + merror(FOPEN_ERROR, __local_name, KEYS_FILE); + ErrorExit(NO_REM_CONN, __local_name); + } + + + /* Initilizing hashes */ + keys->keyhash_id = OSHash_Create(); + keys->keyhash_ip = OSHash_Create(); + if(!keys->keyhash_id || !keys->keyhash_ip) + { + ErrorExit(MEM_ERROR, __local_name); + } + + + /* Initializing structure */ + keys->keyentries = NULL; + keys->keysize = 0; + + + /* Zeroing the buffers */ + __memclear(id, name, ip, key, KEYSIZE +1); + memset(buffer, '\0', OS_BUFFER_SIZE +1); + + + /* Reading each line. + * lines are divided as "id name ip key" + */ + while(fgets(buffer, OS_BUFFER_SIZE, fp) != NULL) + { + char *tmp_str; + char *valid_str; + + if((buffer[0] == '#') || (buffer[0] == ' ')) + continue; + + + /* Getting ID */ + valid_str = buffer; + tmp_str = strchr(buffer, ' '); + if(!tmp_str) + { + merror(INVALID_KEY, __local_name, buffer); + continue; + } + + *tmp_str = '\0'; + tmp_str++; + strncpy(id, valid_str, KEYSIZE -1); + + /* Removed entry. */ + if(*tmp_str == '#') + { + continue; + } + + /* Getting name */ + valid_str = tmp_str; + tmp_str = strchr(tmp_str, ' '); + if(!tmp_str) + { + merror(INVALID_KEY, __local_name, buffer); + } + + *tmp_str = '\0'; + tmp_str++; + strncpy(name, valid_str, KEYSIZE -1); + + + /* Getting ip address */ + valid_str = tmp_str; + tmp_str = strchr(tmp_str, ' '); + if(!tmp_str) + { + merror(INVALID_KEY, __local_name, buffer); + } + + *tmp_str = '\0'; + tmp_str++; + strncpy(ip, valid_str, KEYSIZE -1); + + + /* Getting key */ + valid_str = tmp_str; + tmp_str = strchr(tmp_str, '\n'); + if(tmp_str) + { + *tmp_str = '\0'; + } + + strncpy(key, valid_str, KEYSIZE -1); + + + /* Generating the key hash */ + __chash(keys, id, name, ip, key); + + + /* Clearing the memory */ + __memclear(id, name, ip, key, KEYSIZE +1); + + + /* Checking for maximum agent size */ + if(keys->keysize >= (MAX_AGENTS -2)) + { + merror(AG_MAX_ERROR, __local_name, MAX_AGENTS -2); + ErrorExit(CONFIG_ERROR, __local_name, KEYS_FILE); + } + + continue; + } + + + /* Closing key file. */ + fclose(fp); + + + /* clear one last time before leaving */ + __memclear(id, name, ip, key, KEYSIZE +1); + + + /* Checking if there is any agent available */ + if(keys->keysize == 0) + { + ErrorExit(NO_REM_CONN, __local_name); + } + + + /* Adding additional entry for sender == keysize */ + os_calloc(1, sizeof(keyentry), keys->keyentries[keys->keysize]); + + + return; +} + + +/* void __keysfree() + * Frees the auth keys. + */ +void OS_FreeKeys(keystore *keys) +{ + int i = 0; + int _keysize = 0; + void *hashid; + void *haship; + + _keysize = keys->keysize; + hashid = keys->keyhash_id; + haship = keys->keyhash_ip; + + + /* Zeroing the entries. */ + keys->keysize = 0; + keys->keyhash_id =NULL; + keys->keyhash_ip = NULL; + + + /* Sleeping to give time to other threads to stop using them. */ + sleep(1); + + + /* Freeing the hashes */ + OSHash_Free(hashid); + OSHash_Free(haship); + + + for(i = 0; i<= _keysize; i++) + { + if(keys->keyentries[i]) + { + if(keys->keyentries[i]->ip) + { + free(keys->keyentries[i]->ip->ip); + free(keys->keyentries[i]->ip); + } + + if(keys->keyentries[i]->id) + free(keys->keyentries[i]->id); + + if(keys->keyentries[i]->key) + free(keys->keyentries[i]->key); + + if(keys->keyentries[i]->name) + free(keys->keyentries[i]->name); + + /* Closing counter */ + if(keys->keyentries[i]->fp) + fclose(keys->keyentries[i]->fp); + + free(keys->keyentries[i]); + keys->keyentries[i] = NULL; + } + } + + /* Freeing structure */ + free(keys->keyentries); + keys->keyentries = NULL; + keys->keysize = 0; +} + + +/* int OS_CheckUpdateKeys(keystore *keys) + * Checks if key changed. + */ +int OS_CheckUpdateKeys(keystore *keys) +{ + if(keys->file_change != File_DateofChange(KEYS_FILE)) + { + return(1); + } + return(0); +} + + +/* OS_UpdateKeys(keystore *keys) + * Update the keys if changed. + */ +int OS_UpdateKeys(keystore *keys) +{ + if(keys->file_change != File_DateofChange(KEYS_FILE)) + { + merror(ENCFILE_CHANGED, __local_name); + debug1("%s: DEBUG: Freekeys", __local_name); + + OS_FreeKeys(keys); + debug1("%s: DEBUG: OS_ReadKeys", __local_name); + + /* Reading keys */ + verbose(ENC_READ, __local_name); + + + OS_ReadKeys(keys); + debug1("%s: DEBUG: OS_StartCounter", __local_name); + + OS_StartCounter(keys); + debug1("%s: DEBUG: OS_UpdateKeys completed", __local_name); + + return(1); + } + return(0); +} + + +/* OS_IsAllowedIP() + * Checks if an IP address is allowed to connect. + */ +int OS_IsAllowedIP(keystore *keys, char *srcip) +{ + keyentry *entry; + + if(srcip == NULL) + return(-1); + + entry = OSHash_Get(keys->keyhash_ip, srcip); + if(entry) + { + return(entry->keyid); + } + + return(-1); +} + + +/* int OS_IsAllowedName + * Checks if the agent name is valid. + */ +int OS_IsAllowedName(keystore *keys, char *name) +{ + int i = 0; + + for(i = 0; i < keys->keysize; i++) + { + if(strcmp(keys->keyentries[i]->name, name) == 0) + return(i); + } + + return(-1); +} + + +/* OS_IsAllowedID + */ +int OS_IsAllowedID(keystore *keys, char *id) +{ + keyentry *entry; + + if(id == NULL) + return(-1); + + entry = OSHash_Get(keys->keyhash_id, id); + if(entry) + { + return(entry->keyid); + } + return(-1); +} + + +/* int OS_IsAllowedDynamicID -- Used for dynamic ip addresses. + */ +int OS_IsAllowedDynamicID(keystore *keys, char *id, char *srcip) +{ + keyentry *entry; + + if(id == NULL) + return(-1); + + entry = OSHash_Get(keys->keyhash_id, id); + if(entry) + { + if(OS_IPFound(srcip, entry->ip)) + { + return(entry->keyid); + } + } + + return(-1); +} + + +/* EOF */ diff --git a/src/os_crypto/shared/msgs.c b/src/os_crypto/shared/msgs.c new file mode 100755 index 0000000..6d22a09 --- /dev/null +++ b/src/os_crypto/shared/msgs.c @@ -0,0 +1,584 @@ +/* @(#) $Id: msgs.c,v 1.10 2009/08/10 14:27:37 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#include "shared.h" +#include "headers/sec.h" + +#include "os_zlib/os_zlib.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/blowfish/bf_op.h" + + +/** Sending counts **/ +unsigned int global_count = 0; +unsigned int local_count = 0; + + +/** Average compression rates **/ +int evt_count = 0; +int rcv_count = 0; +unsigned int c_orig_size = 0; +unsigned int c_comp_size = 0; + + +/** Static variables (read from define file) **/ +int _s_comp_print = 0; +int _s_recv_flush = 0; + +int _s_verify_counter = 1; + + +/** OS_StartCounter. + * Read counters for each agent. + */ +void OS_StartCounter(keystore *keys) +{ + int i; + char rids_file[OS_FLSIZE +1]; + + rids_file[OS_FLSIZE] = '\0'; + + + debug1("%s: OS_StartCounter: keysize: %d", __local_name, keys->keysize); + + + /* Starting receiving counter */ + for(i = 0; i<=keys->keysize; i++) + { + /* On i == keysize, we deal with the + * sender counter. + */ + if(i == keys->keysize) + { + snprintf(rids_file, OS_FLSIZE, "%s/%s", + RIDS_DIR, + SENDER_COUNTER); + } + else + { + snprintf(rids_file, OS_FLSIZE, "%s/%s", + RIDS_DIR, + keys->keyentries[i]->id); + } + + keys->keyentries[i]->fp = fopen(rids_file, "r+"); + + /* If nothing is there, try to open as write only */ + if(!keys->keyentries[i]->fp) + { + keys->keyentries[i]->fp = fopen(rids_file, "w"); + if(!keys->keyentries[i]->fp) + { + int my_error = errno; + + /* Just in case we run out of file descriptiors */ + if((keys->keyentries[i -1]->fp) && (i > 10)) + { + fclose(keys->keyentries[i -1]->fp); + + if(keys->keyentries[i -2]->fp) + { + fclose(keys->keyentries[i -2]->fp); + } + } + + merror("%s: Unable to open agent file. errno: %d", + __local_name, my_error); + ErrorExit(FOPEN_ERROR, __local_name, rids_file); + } + } + else + { + unsigned int g_c = 0, l_c = 0; + if(fscanf(keys->keyentries[i]->fp,"%u:%u", &g_c, &l_c) != 2) + { + if(i == keys->keysize) + { + verbose("%s: INFO: No previous sender counter.", __local_name); + } + else + { + verbose("%s: INFO: No previous counter available for '%s'.", + __local_name, + keys->keyentries[i]->name); + } + + g_c = 0; + l_c = 0; + } + + if(i == keys->keysize) + { + verbose("%s: INFO: Assigning sender counter: %d:%d", + __local_name, g_c, l_c); + global_count = g_c; + local_count = l_c; + } + else + { + verbose("%s: INFO: Assigning counter for agent %s: '%d:%d'.", + __local_name, keys->keyentries[i]->name, g_c, l_c); + + keys->keyentries[i]->global = g_c; + keys->keyentries[i]->local = l_c; + } + } + } + + debug2("%s: DEBUG: Stored counter.", __local_name); + + /* Getting counter values */ + if(_s_recv_flush == 0) + { + _s_recv_flush = getDefine_Int("remoted", + "recv_counter_flush", + 10, 999999); + } + + /* Average printout values */ + if(_s_comp_print == 0) + { + _s_comp_print = getDefine_Int("remoted", + "comp_average_printout", + 10, 999999); + } + + + _s_verify_counter = getDefine_Int("remoted", "verify_msg_id" , 0, 1); +} + + + +/** OS_RemoveCounter(char *id) + * Remove the ID counter. + */ +void OS_RemoveCounter(char *id) +{ + char rids_file[OS_FLSIZE +1]; + snprintf(rids_file, OS_FLSIZE, "%s/%s",RIDS_DIR, id); + unlink(rids_file); +} + + +/** StoreSenderCounter((keystore *keys, int global, int local) + * Store sender counter. + */ +void StoreSenderCounter(keystore *keys, int global, int local) +{ + /* Writting at the beginning of the file */ + fseek(keys->keyentries[keys->keysize]->fp, 0, SEEK_SET); + fprintf(keys->keyentries[keys->keysize]->fp, "%u:%u:", global, local); +} + + +/* StoreCount(keystore *keys, int id, int global, int local) + * Store the global and local count of events. + */ +void StoreCounter(keystore *keys, int id, int global, int local) +{ + /* Writting at the beginning of the file */ + fseek(keys->keyentries[id]->fp, 0, SEEK_SET); + fprintf(keys->keyentries[id]->fp, "%u:%u:", global, local); +} + + +/* CheckSum v0.1: 2005/02/15 + * Verify the checksum of the message. + * Returns NULL on error or the message on success. + */ +char *CheckSum(char *msg) +{ + os_md5 recvd_sum; + os_md5 checksum; + + + /* Better way */ + strncpy(recvd_sum,msg,32); + recvd_sum[32]='\0'; + + msg+=32; + + OS_MD5_Str(msg, checksum); + if(strncmp(checksum,recvd_sum,32) != 0) + { + return(NULL); + } + + return(msg); +} + + + +/* ReadSecMSG v0.2: 2005/02/10 */ +char *ReadSecMSG(keystore *keys, char *buffer, char *cleartext, + int id, int buffer_size) +{ + int cmp_size; + unsigned int msg_global; + unsigned int msg_local; + + char *f_msg; + + + if(*buffer == ':') + { + buffer++; + } + else + { + merror(ENCFORMAT_ERROR, __local_name, keys->keyentries[id]->ip->ip); + return(NULL); + } + + /* Decrypting message */ + if(!OS_BF_Str(buffer, cleartext, keys->keyentries[id]->key, + buffer_size, OS_DECRYPT)) + { + merror(ENCKEY_ERROR, __local_name, keys->keyentries[id]->ip->ip); + return(NULL); + } + + + /* Compressed */ + else if(cleartext[0] == '!') + { + cleartext[buffer_size] = '\0'; + cleartext++; + buffer_size--; + + /* Removing padding */ + while(*cleartext == '!') + { + cleartext++; + buffer_size--; + } + + /* Uncompressing */ + cmp_size = os_uncompress(cleartext, buffer, buffer_size, OS_MAXSTR); + if(!cmp_size) + { + merror(UNCOMPRESS_ERR, __local_name); + return(NULL); + } + + /* Checking checksum */ + f_msg = CheckSum(buffer); + if(f_msg == NULL) + { + merror(ENCSUM_ERROR, __local_name, keys->keyentries[id]->ip->ip); + return(NULL); + } + + /* Removing random */ + f_msg+=5; + + + /* Checking count -- protecting against replay attacks */ + msg_global = atoi(f_msg); + f_msg+=10; + + /* Checking for the right message format */ + if(*f_msg != ':') + { + merror(ENCFORMAT_ERROR, __local_name,keys->keyentries[id]->ip->ip); + return(NULL); + } + f_msg++; + + msg_local = atoi(f_msg); + f_msg+=5; + + + /* Returning the message if we don't need to verify the counbter. */ + if(!_s_verify_counter) + { + /* Updating currently counts */ + keys->keyentries[id]->global = msg_global; + keys->keyentries[id]->local = msg_local; + if(rcv_count >= _s_recv_flush) + { + StoreCounter(keys, id, msg_global, msg_local); + rcv_count = 0; + } + rcv_count++; + return(f_msg); + } + + + if((msg_global > keys->keyentries[id]->global)|| + ((msg_global == keys->keyentries[id]->global) && + (msg_local > keys->keyentries[id]->local))) + { + /* Updating currently counts */ + keys->keyentries[id]->global = msg_global; + keys->keyentries[id]->local = msg_local; + + if(rcv_count >= _s_recv_flush) + { + StoreCounter(keys, id, msg_global, msg_local); + rcv_count = 0; + } + rcv_count++; + return(f_msg); + } + + + /* Checking if it is a duplicated message */ + if(msg_global == keys->keyentries[id]->global) + { + return(NULL); + } + + + /* Warn about duplicated messages */ + merror("%s: WARN: Duplicate error: global: %d, local: %d, " + "saved global: %d, saved local:%d", + __local_name, + msg_global, + msg_local, + keys->keyentries[id]->global, + keys->keyentries[id]->local); + + merror(ENCTIME_ERROR, __local_name, keys->keyentries[id]->name); + return(NULL); + } + + /* Old format */ + else if(cleartext[0] == ':') + { + int msg_count; + time_t msg_time; + + /* Closing string */ + cleartext[buffer_size] = '\0'; + + + /* Checking checksum */ + cleartext++; + f_msg = CheckSum(cleartext); + if(f_msg == NULL) + { + merror(ENCSUM_ERROR, __local_name, keys->keyentries[id]->ip->ip); + return(NULL); + } + + + /* Checking time -- protecting against replay attacks */ + msg_time = atoi(f_msg); + f_msg+=11; + + msg_count = atoi(f_msg); + f_msg+=5; + + + /* Returning the message if we don't need to verify the counbter. */ + if(!_s_verify_counter) + { + /* Updating currently counts */ + keys->keyentries[id]->global = msg_time; + keys->keyentries[id]->local = msg_local; + + f_msg = strchr(f_msg, ':'); + if(f_msg) + { + f_msg++; + return(f_msg); + } + } + + + if((msg_time > keys->keyentries[id]->global) || + ((msg_time == keys->keyentries[id]->global)&& + (msg_count > keys->keyentries[id]->local))) + { + /* Updating currently time and count */ + keys->keyentries[id]->global = msg_time; + keys->keyentries[id]->local = msg_count; + + f_msg = strchr(f_msg, ':'); + if(f_msg) + { + f_msg++; + return(f_msg); + } + } + + /* Checking if it is a duplicated message */ + if((msg_count == keys->keyentries[id]->local) && + (msg_time == keys->keyentries[id]->global)) + { + return(NULL); + } + + + /* Warn about duplicated message */ + merror("%s: WARN: Duplicate error: msg_count: %d, time: %d, " + "saved count: %d, saved_time:%d", + __local_name, + msg_count, + (int)msg_time, + keys->keyentries[id]->local, + keys->keyentries[id]->global); + + merror(ENCTIME_ERROR, __local_name, keys->keyentries[id]->name); + return(NULL); + } + + merror(ENCFORMAT_ERROR, __local_name, keys->keyentries[id]->ip->ip); + return(NULL); +} + + + +/* Creat a encrypted message. + * Returns the size of it + */ +int CreateSecMSG(keystore *keys, char *msg, char *msg_encrypted, int id) +{ + int bfsize; + int msg_size; + int cmp_size; + + u_int16_t rand1; + + char _tmpmsg[OS_MAXSTR + 2]; + char _finmsg[OS_MAXSTR + 2]; + + os_md5 md5sum; + + msg_size = strlen(msg); + + + /* Checking for invalid msg sizes */ + if((msg_size > (OS_MAXSTR - OS_HEADER_SIZE))||(msg_size < 1)) + { + merror(ENCSIZE_ERROR, __local_name, msg); + return(0); + } + + /* Random number */ + rand1 = (u_int16_t)random(); + + + _tmpmsg[OS_MAXSTR +1] = '\0'; + _finmsg[OS_MAXSTR +1] = '\0'; + msg_encrypted[OS_MAXSTR] = '\0'; + + + /* Increasing local and global counters */ + if(local_count >= 9997) + { + local_count = 0; + global_count++; + } + local_count++; + + + snprintf(_tmpmsg, OS_MAXSTR,"%05hu%010u:%04hu:%s", + rand1, global_count, local_count, + msg); + + + /* Generating md5sum of the unencrypted string */ + OS_MD5_Str(_tmpmsg, md5sum); + + + + /* Generating final msg to be compressed */ + snprintf(_finmsg, OS_MAXSTR,"%s%s",md5sum,_tmpmsg); + msg_size = strlen(_finmsg); + + + /* Compressing message. + * We assing the first 8 bytes for padding. + */ + cmp_size = os_compress(_finmsg, _tmpmsg + 8, msg_size, OS_MAXSTR - 12); + if(!cmp_size) + { + merror(COMPRESS_ERR, __local_name, _finmsg); + return(0); + } + cmp_size++; + + /* Padding the message (needs to be div by 8) */ + bfsize = 8 - (cmp_size % 8); + if(bfsize == 8) + bfsize = 0; + + _tmpmsg[0] = '!'; + _tmpmsg[1] = '!'; + _tmpmsg[2] = '!'; + _tmpmsg[3] = '!'; + _tmpmsg[4] = '!'; + _tmpmsg[5] = '!'; + _tmpmsg[6] = '!'; + _tmpmsg[7] = '!'; + + cmp_size+=bfsize; + + + /* Getting average sizes */ + c_orig_size+= msg_size; + c_comp_size+= cmp_size; + if(evt_count > _s_comp_print) + { + verbose("%s: INFO: Event count after '%u': %u->%u (%d%%)", __local_name, + evt_count, + c_orig_size, + c_comp_size, + (c_comp_size * 100)/c_orig_size); + evt_count = 0; + c_orig_size = 0; + c_comp_size = 0; + } + evt_count++; + + /* If the ip is dynamic (not single host, append agent id + * to the message. + */ + if(!isSingleHost(keys->keyentries[id]->ip) && isAgent) + { + snprintf(msg_encrypted, 16, "!%s!:", keys->keyentries[id]->id); + msg_size = strlen(msg_encrypted); + } + else + { + /* Setting beginning of the message */ + msg_encrypted[0] = ':'; + msg_size = 1; + } + + + /* msg_size is the ammount of non-encrypted message + * appended to the buffer. On dynamic ips, it will + * include the agent id. + */ + + /* Encrypting everything */ + OS_BF_Str(_tmpmsg + (7 - bfsize), msg_encrypted + msg_size, + keys->keyentries[id]->key, + cmp_size, + OS_ENCRYPT); + + + /* Storing before leaving */ + StoreSenderCounter(keys, global_count, local_count); + + return(cmp_size + msg_size); +} + + +/* EOF */ diff --git a/src/os_csyslogd/Makefile b/src/os_csyslogd/Makefile new file mode 100755 index 0000000..2d910b2 --- /dev/null +++ b/src/os_csyslogd/Makefile @@ -0,0 +1,19 @@ +# Makefile for client-syslog +# Daniel B. Cid + +PT=../ +NAME=ossec-csyslogd + + +include ../Config.Make +LOCAL = *.c + + +OBJS = ${OS_CONFIG} ${OS_SHARED} ${OS_NET} ${OS_REGEX} ${OS_XML} + +default: + ${CC} ${CFLAGS} ${OS_LINK} ${LOCAL} ${OBJS} -o ${NAME} +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/os_csyslogd/alert.c b/src/os_csyslogd/alert.c new file mode 100755 index 0000000..6d38990 --- /dev/null +++ b/src/os_csyslogd/alert.c @@ -0,0 +1,171 @@ +/* @(#) $Id: alert.c,v 1.5 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "csyslogd.h" +#include "config/config.h" +#include "os_net/os_net.h" + + + + + +/** int OS_Alert_SendSyslog + * Sends an alert via syslog. + * Returns 1 on success or 0 on error. + */ +int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config) +{ + char *tstamp; + char user_msg[256]; + char srcip_msg[256]; + + char syslog_msg[OS_SIZE_2048 +1]; + + + /* Invalid socket. */ + if(syslog_config->socket < 0) + { + return(0); + } + + + /* Clearing the memory before insert */ + memset(syslog_msg, '\0', OS_SIZE_2048 +1); + + + /* Looking if location is set */ + if(syslog_config->location) + { + if(!OSMatch_Execute(al_data->location, + strlen(al_data->location), + syslog_config->location)) + { + return(0); + } + } + + + /* Looking for the level */ + if(syslog_config->level) + { + if(al_data->level < syslog_config->level) + { + return(0); + } + } + + + /* Looking for rule id */ + if(syslog_config->rule_id) + { + int id_i = 0; + while(syslog_config->rule_id[id_i] != 0) + { + if(syslog_config->rule_id[id_i] == al_data->rule) + { + break; + } + id_i++; + } + + + /* If we found, id is going to be a valid rule */ + if(!syslog_config->rule_id[id_i]) + { + return(0); + } + } + + + /* Looking for the group */ + if(syslog_config->group) + { + if(!OSMatch_Execute(al_data->group, + strlen(al_data->group), + syslog_config->group)) + { + return(0); + } + } + + + /* Fixing the timestamp to be syslog compatible. + * We have 2008 Jul 10 10:11:23 + * Should be: Jul 10 10:11:23 + */ + tstamp = al_data->date; + if(strlen(al_data->date) > 14) + { + tstamp+=5; + + /* Fixing first digit if the day is < 10 */ + if(tstamp[4] == '0') + tstamp[4] = ' '; + } + + + /* Adding source ip. */ + if(!al_data->srcip || + ((al_data->srcip[0] == '(') && + (al_data->srcip[1] == 'n') && + (al_data->srcip[2] == 'o'))) + { + srcip_msg[0] = '\0'; + } + else + { + snprintf(srcip_msg, 255, " srcip: %s;", al_data->srcip); + } + + + /* Adding username. */ + if(!al_data->user || + ((al_data->user[0] == '(') && + (al_data->user[1] == 'n') && + (al_data->user[2] == 'o'))) + { + user_msg[0] = '\0'; + } + else + { + snprintf(user_msg, 255, " user: %s;", al_data->user); + } + + + /* Inserting data */ + if(syslog_config->format == DEFAULT_CSYSLOG) + { + /* Building syslog message. */ + snprintf(syslog_msg, OS_SIZE_2048, + "<%d>%s %s ossec: Alert Level: %d; Rule: %d - %s; " + "Location: %s;%s%s %s", + syslog_config->priority, tstamp, __shost, + al_data->level, al_data->rule, al_data->comment, + al_data->location, + + /* Source ip. */ + srcip_msg, + user_msg, + al_data->log[0]); + } + + + OS_SendUDPbySize(syslog_config->socket, strlen(syslog_msg), syslog_msg); + + return(1); +} + + +/* EOF */ diff --git a/src/os_csyslogd/config.c b/src/os_csyslogd/config.c new file mode 100755 index 0000000..fbeb54e --- /dev/null +++ b/src/os_csyslogd/config.c @@ -0,0 +1,50 @@ +/* @(#) $Id: config.c,v 1.2 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "csyslogd.h" +#include "config/global-config.h" +#include "config/config.h" + + +/** void *OS_SyslogConf(int test_config, char *cfgfile, + SyslogConfig **syslog_config) + * Reads configuration. + */ +void *OS_ReadSyslogConf(int test_config, char *cfgfile, + SyslogConfig **syslog_config) +{ + int modules = 0; + GeneralConfig gen_config; + + + /* Modules for the configuration */ + modules|= CSYSLOGD; + gen_config.data = syslog_config; + + + /* Reading configuration */ + if(ReadConfig(modules, cfgfile, &gen_config, NULL) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfgfile); + return(NULL); + } + + + syslog_config = gen_config.data; + + return(syslog_config); +} + +/* EOF */ diff --git a/src/os_csyslogd/csyslogd.c b/src/os_csyslogd/csyslogd.c new file mode 100755 index 0000000..7622133 --- /dev/null +++ b/src/os_csyslogd/csyslogd.c @@ -0,0 +1,96 @@ +/* @(#) $Id: csyslogd.c,v 1.3 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#include "csyslogd.h" +#include "os_net/os_net.h" + + + +/* OS_SyslogD: Monitor the alerts and sends them via syslog. + * Only return in case of error. + */ +void OS_CSyslogD(SyslogConfig **syslog_config) +{ + int s = 0; + time_t tm; + struct tm *p; + + file_queue *fileq; + alert_data *al_data; + + + /* Getting currently time before starting */ + tm = time(NULL); + p = localtime(&tm); + + + /* Initating file queue - to read the alerts */ + os_calloc(1, sizeof(file_queue), fileq); + Init_FileQueue(fileq, p, 0); + + + /* Connecting to syslog. */ + s = 0; + while(syslog_config[s]) + { + syslog_config[s]->socket = OS_ConnectUDP(syslog_config[s]->port, + syslog_config[s]->server); + if(syslog_config[s]->socket < 0) + { + merror(CONNS_ERROR, ARGV0, syslog_config[s]->server); + } + else + { + merror("%s: INFO: Forwarding alerts via syslog to: '%s:%d'.", + ARGV0, syslog_config[s]->server, syslog_config[s]->port); + } + + s++; + } + + + + /* Infinite loop reading the alerts and inserting them. */ + while(1) + { + tm = time(NULL); + p = localtime(&tm); + + + /* Get message if available (timeout of 5 seconds) */ + al_data = Read_FileMon(fileq, p, 5); + if(!al_data) + { + continue; + } + + + + /* Sending via syslog */ + s = 0; + while(syslog_config[s]) + { + OS_Alert_SendSyslog(al_data, syslog_config[s]); + s++; + } + + + /* Clearing the memory */ + FreeAlertData(al_data); + } +} + +/* EOF */ diff --git a/src/os_csyslogd/csyslogd.h b/src/os_csyslogd/csyslogd.h new file mode 100755 index 0000000..08bb9b9 --- /dev/null +++ b/src/os_csyslogd/csyslogd.h @@ -0,0 +1,45 @@ +/* @(#) $Id: csyslogd.h,v 1.2 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef _CSYSLOGD_H +#define _CSYSLOGD_H + + +#include "config/csyslogd-config.h" + + +/** Prototypes **/ + +/* Read syslog config */ +void *OS_ReadSyslogConf(int test_config, char *cfgfile, + SyslogConfig **sys_config); + + +/* Send alerts via syslog */ +int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config); + + +/* Database inserting main function */ +void OS_CSyslogD(SyslogConfig **syslog_config); + + + +/** Global vars **/ + +/* System hostname */ +char __shost[512]; + + +#endif diff --git a/src/os_csyslogd/main.c b/src/os_csyslogd/main.c new file mode 100755 index 0000000..1f9f420 --- /dev/null +++ b/src/os_csyslogd/main.c @@ -0,0 +1,188 @@ +/* @(#) $Id: main.c,v 1.4 2009/11/18 19:07:40 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "csyslogd.h" + + + +int main(int argc, char **argv) +{ + int c, test_config = 0,run_foreground = 0; + int uid = 0,gid = 0; + + /* Using MAILUSER (read only) */ + char *dir = DEFAULTDIR; + char *user = MAILUSER; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTCPATH; + + + /* Database Structure */ + SyslogConfig **syslog_config = NULL; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "vVdhtfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'v': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user=optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group=optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir=optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + + /* Starting daemon */ + debug1(STARTED_MSG, ARGV0); + + + /* Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Reading configuration */ + syslog_config = OS_ReadSyslogConf(test_config, cfg, syslog_config); + + + /* Getting servers hostname */ + memset(__shost, '\0', 512); + if(gethostname(__shost, 512 -1) != 0) + { + ErrorExit("%s: ERROR: gethostname() failed", ARGV0); + } + else + { + char *ltmp; + + /* Remove domain part if available */ + ltmp = strchr(__shost, '.'); + if(ltmp) + *ltmp = '\0'; + } + + + /* Exit here if test config is set */ + if(test_config) + exit(0); + + + if (!run_foreground) + { + /* Going on daemon mode */ + nowDaemon(); + goDaemon(); + } + + + + /* Not configured */ + if(!syslog_config || !syslog_config[0]) + { + verbose("%s: INFO: Remote syslog server not configured. " + "Clean exit.", ARGV0); + exit(0); + } + + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + + /* Now on chroot */ + nowChroot(); + + + + /* Changing user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + /* Basic start up completed. */ + debug1(PRIVSEP_MSG,ARGV0,dir,user); + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + /* Creating PID files */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR, ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* the real daemon now */ + OS_CSyslogD(syslog_config); + exit(0); +} + + +/* EOF */ diff --git a/src/os_dbd/Makefile b/src/os_dbd/Makefile new file mode 100755 index 0000000..7b7f44b --- /dev/null +++ b/src/os_dbd/Makefile @@ -0,0 +1,26 @@ +# Makefile for dbd +# Daniel B. Cid + +PT=../ +NAME=ossec-dbd + +# Uncomment the following if you know what you are doing. +#DBFLAGS=-I/usr/local/include/mysql -L/usr/local/lib/mysql -lmysqlclient + +include ../Config.Make + +LOCAL = *.c + + +# Getting database cflags + + +OBJS = ${OS_CONFIG} ${OS_SHARED} ${OS_NET} ${OS_REGEX} ${OS_XML} + +default: + @echo "Compiling DB support with: ${DBCHECK}" + ${CC} ${CFLAGS} ${OS_LINK} ${DBFLAGS} ${CDB} ${LOCAL} ${OBJS} -o ${NAME} +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/os_dbd/README b/src/os_dbd/README new file mode 100644 index 0000000..129e60f --- /dev/null +++ b/src/os_dbd/README @@ -0,0 +1,47 @@ +# Simple readme with some query examples. +# Examples for MySQL and PostgreSQL + + +1- View all rules: + +> SELECT rule_id, level, description FROM signature; + + +2- View all categories (groups) + +> SELECT * FROM category; + + +3- View all categories of a specific rule (1002 for example): + +> SELECT rule_id, cat_name from category, signature_category_mapping WHERE rule_id = 1002 AND signature_category_mapping.cat_id = category.cat_id; + + +4- View all alerts (without data): + +> SELECT * FROM alert; + + +5- View all alerts (with IP as string): + +> SELECT rule_id, timestamp, INET_ATON(src_ip) srcip from alert; + + +6- View all alerts, including locations (IP as string and time as string): + +MySQL: +>SELECT FROM_UNIXTIME(timestamp) time, rule_id,location.name location, INET_NTOA(src_ip) srcip, full_log FROM alert,location, data WHERE location.id = alert.location_id AND data.id = alert.id AND data.server_id = alert.server_id; + +PostgreSQL: +>SELECT to_timestamp(timestamp), rule_id, location.name, full_log FROM alert,location, data WHERE location.id = alert.location_id AND data.id = alert.id AND data.server_id = alert.server_id; + +Output: + ++---------------------+---------+---------------------------+--------------+--------------------------------------------------------------------------------------------------+ +| time | rule_id | location | srcip | full_log | ++---------------------+---------+---------------------------+--------------+--------------------------------------------------------------------------------------------------+ +| 2007-08-18 00:28:49 | 1002 | enigma->/var/log/messages | 0.0.0.0 | Aug 18 00:28:49 enigma dcid: Segmentation Fault 1q2 | +| 2007-08-18 00:38:06 | 5715 | enigma->/var/log/authlog | 192.168.2.10 | Aug 18 00:38:02 enigma sshd[24284]: Accepted password for dcid from 192.168.2.10 port 34631 ssh2 | +| 2007-08-18 00:38:21 | 5715 | enigma->/var/log/authlog | 192.168.2.10 | Aug 18 00:38:15 enigma sshd[20749]: Accepted password for dcid from 192.168.2.10 port 35755 ssh2 | ++---------------------+---------+---------------------------+--------------+--------------------------------------------------------------------------------------------------+ + diff --git a/src/os_dbd/alert.c b/src/os_dbd/alert.c new file mode 100755 index 0000000..56fd1a3 --- /dev/null +++ b/src/os_dbd/alert.c @@ -0,0 +1,218 @@ +/* @(#) $Id: alert.c,v 1.8 2009/06/24 17:06:29 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "dbd.h" +#include "config/config.h" +#include "rules_op.h" + + + +/** int OS_SelectMaxID(DBConfig *db_config) + * Selects the maximum ID from the alert table. + * Returns 0 if not found. + */ +int OS_SelectMaxID(DBConfig *db_config) +{ + int result = 0; + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT MAX(id) FROM " + "alert WHERE server_id = '%u'", + db_config->server_id); + + + /* Checking return code. */ + result = osdb_query_select(db_config->conn, sql_query); + + return(result); +} + + +/** int __DBSelectLocation(char *locaton, DBConfig *db_config) + * Selects the location ID from the db. + * Returns 0 if not found. + */ +int __DBSelectLocation(char *location, DBConfig *db_config) +{ + int result = 0; + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT id FROM " + "location WHERE name = '%s' AND server_id = '%d' " + "LIMIT 1", + location, db_config->server_id); + + + /* Checking return code. */ + result = osdb_query_select(db_config->conn, sql_query); + + return(result); +} + + +/** int __DBInsertLocation(char *location, DBConfig *db_config) + * Inserts location in to the db. + */ +int __DBInsertLocation(char *location, DBConfig *db_config) +{ + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "INSERT INTO " + "location(server_id, name) " + "VALUES ('%u', '%s')", + db_config->server_id, location); + + + /* Checking return code. */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + + return(0); +} + + + +/** int OS_Alert_InsertDB(DBConfig *db_config) + * Insert alert into to the db. + * Returns 1 on success or 0 on error. + */ +int OS_Alert_InsertDB(alert_data *al_data, DBConfig *db_config) +{ + unsigned int s_ip = 0, d_ip = 0, location_id = 0; + int *loc_id; + char sql_query[OS_SIZE_2048 +1]; + + + /* Clearing the memory before insert */ + memset(sql_query, '\0', OS_SIZE_2048 +1); + + + /* Converting srcip to int */ + if(al_data->srcip) + { + struct in_addr net; + + /* Extracting ip address */ + if(inet_aton(al_data->srcip, &net)) + { + s_ip = net.s_addr; + } + } + d_ip = 0; + + + /* Escaping strings */ + osdb_escapestr(al_data->user); + osdb_escapestr(al_data->log[0]); + + + /* We first need to insert the location */ + loc_id = OSHash_Get(db_config->location_hash, al_data->location); + + + /* If we dont have location id, we must select and/or insert in the db */ + if(!loc_id) + { + location_id = __DBSelectLocation(al_data->location, db_config); + if(location_id == 0) + { + /* Insert it */ + __DBInsertLocation(al_data->location, db_config); + location_id = __DBSelectLocation(al_data->location, db_config); + } + + if(!location_id) + { + merror("%s: Unable to insert location: '%s'.", + ARGV0, al_data->location); + return(0); + } + + + /* Adding to hash */ + os_calloc(1, sizeof(int), loc_id); + *loc_id = location_id; + OSHash_Add(db_config->location_hash, al_data->location, loc_id); + } + + + /* Inserting data */ + if(db_config->db_type == POSTGDB) + { + /* On postgres we need to escape the user field. */ + snprintf(sql_query, OS_SIZE_2048, + "INSERT INTO " + "data(id, server_id, \"user\", full_log) " + "VALUES ('%u', '%u', '%s', '%s') ", + db_config->alert_id, db_config->server_id, + al_data->user, al_data->log[0]); + } + else + { + snprintf(sql_query, OS_SIZE_2048, + "INSERT INTO " + "data(id, server_id, user, full_log) " + "VALUES ('%u', '%u', '%s', '%s') ", + db_config->alert_id, db_config->server_id, + al_data->user, al_data->log[0]); + } + + + /* Inserting into the db */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + + + + /* Generating final SQL */ + snprintf(sql_query, OS_SIZE_2048, + "INSERT INTO " + "alert(id,server_id,rule_id,timestamp,location_id,src_ip) " + "VALUES ('%u', '%u', '%u','%u', '%u', '%lu')", + db_config->alert_id, db_config->server_id, al_data->rule, + (unsigned int)time(0), *loc_id, (unsigned long)ntohl(s_ip)); + + + /* Inserting into the db */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + + + db_config->alert_id++; + return(1); +} + + +/* EOF */ diff --git a/src/os_dbd/config.c b/src/os_dbd/config.c new file mode 100755 index 0000000..fed44dd --- /dev/null +++ b/src/os_dbd/config.c @@ -0,0 +1,140 @@ +/* @(#) $Id: config.c,v 1.9 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "dbd.h" +#include "config/global-config.h" +#include "config/config.h" + + +/** int OS_ReadDBConf(int test_config, char *cfgfile, DBConfig *db_config) + * Reads database configuration. + */ +int OS_ReadDBConf(int test_config, char *cfgfile, DBConfig *db_config) +{ + int modules = 0; + _Config *tmp_config; + + + /* Modules for the configuration */ + modules|= CDBD; + modules|= CRULES; + + + /* Allocating config just to get the rules. */ + os_calloc(1, sizeof(_Config), tmp_config); + + + /* Clearing configuration variables */ + tmp_config->includes = NULL; + db_config->includes = NULL; + db_config->host = NULL; + db_config->user = NULL; + db_config->pass = NULL; + db_config->db = NULL; + db_config->port = 0; + db_config->sock = NULL; + db_config->db_type = 0; + db_config->maxreconnect = 0; + + + /* Reading configuration */ + if(ReadConfig(modules, cfgfile, tmp_config, db_config) < 0) + return(OS_INVALID); + + + /* Here, we assign the rules to db_config and free the rest + * of the Config. + */ + db_config->includes = tmp_config->includes; + free(tmp_config); + + + /* Checking if dbd isn't supposed to run. */ + if(!db_config->host && + !db_config->user && + !db_config->pass && + !db_config->db && + !db_config->sock && + !db_config->port && + !db_config->db_type) + { + return(0); + } + + + /* Checking for a valid config. */ + if(!db_config->host || + !db_config->user || + !db_config->pass || + !db_config->db || + !db_config->db_type) + { + merror(DB_MISS_CONFIG, ARGV0); + return(OS_INVALID); + } + + osdb_connect = NULL; + + /* Assigning the proper location for the function calls */ + #ifdef UMYSQL + if(db_config->db_type == MYSQLDB) + { + osdb_connect = mysql_osdb_connect; + osdb_query_insert = mysql_osdb_query_insert; + osdb_query_select = mysql_osdb_query_select; + osdb_close = mysql_osdb_close; + } + #endif + + #ifdef UPOSTGRES + if(db_config->db_type == POSTGDB) + { + osdb_connect = postgresql_osdb_connect; + osdb_query_insert = postgresql_osdb_query_insert; + osdb_query_select = postgresql_osdb_query_select; + osdb_close = postgresql_osdb_close; + } + #endif + + + + /* Checking for config errros (moving from config.c). + */ + if(db_config->db_type == MYSQLDB) + { + #ifndef UMYSQL + merror(DB_COMPILED, ARGV0, "mysql"); + return(OS_INVALID); + #endif + } + else if(db_config->db_type == POSTGDB) + { + #ifndef UPOSTGRES + merror(DB_COMPILED, ARGV0, "postgresql"); + return(OS_INVALID); + #endif + } + + + if(osdb_connect == NULL) + { + merror("%s: Invalid DB configuration (Internal error?). ", ARGV0); + return(OS_INVALID); + } + + return(1); +} + +/* EOF */ diff --git a/src/os_dbd/db_op.c b/src/os_dbd/db_op.c new file mode 100755 index 0000000..81eb76b --- /dev/null +++ b/src/os_dbd/db_op.c @@ -0,0 +1,446 @@ +/* @(#) $Id: db_op.c,v 1.17 2009/12/01 01:49:55 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Common lib for dealing with databases */ + + +#include "dbd.h" + +/* Using Mysql */ +#ifdef UMYSQL +#include +#endif + +/* Using PostgreSQL */ +#ifdef UPOSTGRES +#include +#endif + + + +/* Config pointer */ +DBConfig *db_config_pt = NULL; + + + +/** void osdb_escapestr + * Escapes a null terminated string before inserting into the database. + * We built a white list of allowed characters at insert_map. Everything + * not allowed will become spaces. + */ +void osdb_escapestr(char *str) +{ + if(!str) + { + return; + } + + while(*str) + { + if(*str == '\'') + { + *str = '`'; + } + else if(*str == '\\') + { + *str = '/'; + } + else if(insert_map[(unsigned char)*str] != '\001') + { + *str = ' '; + } + str++; + } + + /* It can not end with \\ */ + if(*(str -1) == '\\') + { + *(str-1) = '\0'; + } +} + + + +/** void osdb_checkerror() + * Checks for errors and handle it appropriately. + */ +void osdb_checkerror() +{ + int sleep_time = 2; + if(!db_config_pt || db_config_pt->error_count > 20) + { + ErrorExit(DB_MAINERROR, ARGV0); + } + + + /* If error count is too large, we try to reconnect. */ + if(db_config_pt->error_count > 0) + { + int i = 0; + if(db_config_pt->conn) + { + osdb_close(db_config_pt->conn); + db_config_pt->conn = NULL; + } + + while(i <= db_config_pt->maxreconnect) + { + merror(DB_ATTEMPT, ARGV0); + db_config_pt->conn = osdb_connect(db_config_pt->host, + db_config_pt->user, + db_config_pt->pass, + db_config_pt->db, + db_config_pt->port, + db_config_pt->sock); + + /* If we were able to reconnect, keep going. */ + if(db_config_pt->conn) + { + break; + } + sleep(sleep_time); + sleep_time *= 2; + i++; + } + + + /* If we weren't able to connect, exit */ + if(!db_config_pt->conn) + { + ErrorExit(DB_MAINERROR, ARGV0); + } + + + verbose("%s: Connected to database '%s' at '%s'.", + ARGV0, db_config_pt->db, db_config_pt->host); + + } +} + + +/** void osdb_seterror() + * Sets the error counter. + */ +void osdb_seterror() +{ + db_config_pt->error_count++; + osdb_checkerror(); +} + + +/** void osdb_setconfig(DBConfig *db_config) + * Creates an internal pointer to the db configuration. + */ +void osdb_setconfig(DBConfig *db_config) +{ + db_config_pt = db_config; +} + + + +/** MySQL calls **/ +#ifdef UMYSQL + + +/* Create the database connection. + * Returns NULL on error + */ +void *mysql_osdb_connect(char *host, char *user, char *pass, char *db, + int port, char *sock) +{ + MYSQL *conn; + conn = mysql_init(NULL); + if (conn == NULL) + { + merror(DBINIT_ERROR, ARGV0); + return(NULL); + } + + + /* If host is 127.0.0.1 or localhost, use tcp socket */ + if((strcmp(host, "127.0.0.1") == 0) || + (strcmp(host, "localhost") == 0)) + { + if(sock != NULL) + { + mysql_options(conn, MYSQL_OPT_NAMED_PIPE, NULL); + } + else + { + unsigned int p_type = MYSQL_PROTOCOL_TCP; + mysql_options(conn, MYSQL_OPT_PROTOCOL, (char *)&p_type); + } + } + if(mysql_real_connect(conn, host, user, pass, db, + port, sock, 0) == NULL) + { + merror(DBCONN_ERROR, ARGV0, host, db, mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + return(conn); +} + + + +/* Closes the database connection. + */ +void *mysql_osdb_close(void *db_conn) +{ + merror(DB_CLOSING, ARGV0); + mysql_close(db_conn); + return(NULL); +} + + + +/** int mysql_osdb_query_insert(void *db_conn, char *query) + * Sends insert query to database. + */ +int mysql_osdb_query_insert(void *db_conn, char *query) +{ + if(mysql_query(db_conn, query) != 0) + { + /* failure; report error */ + merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn)); + osdb_seterror(); + return(0); + } + + return(1); +} + + + +/** int mysql_osdb_query_select(void *db_conn, char *query) + * Sends a select query to database. Returns the value of it. + * Returns 0 on error (not found). + */ +int mysql_osdb_query_select(void *db_conn, char *query) +{ + int result_int = 0; + MYSQL_RES *result_data; + MYSQL_ROW result_row; + + + /* Sending the query. It can not fail. */ + if(mysql_query(db_conn, query) != 0) + { + /* failure; report error */ + merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn)); + osdb_seterror(); + return(0); + } + + + /* Getting result */ + result_data = mysql_use_result(db_conn); + if(result_data == NULL) + { + /* failure; report error */ + merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn)); + osdb_seterror(); + return(0); + } + + + /* Getting row. We only care about the first result. */ + result_row = mysql_fetch_row(result_data); + if(result_row && (result_row[0] != NULL)) + { + result_int = atoi(result_row[0]); + } + + + mysql_free_result(result_data); + + + return(result_int); +} +#endif +/** End of MYSQL calls **/ + + + + +/** PostGRES Calls **/ +#if defined UPOSTGRES + + +/** void *postgresql_osdb_connect(char *host, char *user, char *pass, char *db) + * Create the PostgreSQL database connection. + * Return NULL on error + */ +void *postgresql_osdb_connect(char *host, char *user, char *pass, char *db, + int port, char *sock) +{ + PGconn *conn; + + + conn = PQsetdbLogin(host, NULL, NULL, NULL, db, user, pass); + if(PQstatus(conn) == CONNECTION_BAD) + { + merror(DBCONN_ERROR, ARGV0, host, db, PQerrorMessage(conn)); + PQfinish(conn); + return(NULL); + } + + return(conn); +} + + + +/** void postgresql_osdb_close(void *db_conn) + * Terminates db connection. + */ +void *postgresql_osdb_close(void *db_conn) +{ + merror(DB_CLOSING, ARGV0); + PQfinish(db_conn); + return(NULL); +} + + + +/** int postgresql_osdb_query_insert(void *db_conn, char *query) + * Sends insert query to database. + */ +int postgresql_osdb_query_insert(void *db_conn, char *query) +{ + PGresult *result; + + + result = PQexec(db_conn,query); + if(!result) + { + merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn)); + osdb_seterror(); + return(0); + } + + + if(PQresultStatus(result) != PGRES_COMMAND_OK) + { + merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn)); + PQclear(result); + osdb_seterror(); + return(0); + } + + + PQclear(result); + return(1); +} + + + +/** int postgresql_osdb_query_select(void *db_conn, char *query) + * Sends a select query to database. Returns the value of it. + * Returns 0 on error (not found). + */ +int postgresql_osdb_query_select(void *db_conn, char *query) +{ + int result_int = 0; + PGresult *result; + + result = PQexec(db_conn,query); + if(!result) + { + merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn)); + osdb_seterror(); + return(0); + } + + if((PQresultStatus(result) == PGRES_TUPLES_OK)) + { + if(PQntuples(result) == 1) + { + result_int = atoi(PQgetvalue(result,0,0)); + } + } + else + { + merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn)); + osdb_seterror(); + return(0); + } + + + /* Clear result */ + PQclear(result); + + + return(result_int); +} +/** End of PostGRES calls **/ +#endif + + + +/* Everything else when db is not defined. */ +#if !defined(UPOSTGRES) && !defined(UMYSQL) + + + +void *none_osdb_connect(char *host, char *user, char *pass, char *db, + int port, char *sock) +{ + char *tmp; + + + /* Just to avoid warnings. */ + tmp = host; tmp = user; tmp = pass; tmp = db; + + + merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0); + return(NULL); +} +void *none_osdb_close(void *db_conn) +{ + void *tmp; + + tmp = db_conn; + merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0); + return(NULL); +} +void *none_osdb_query_insert(void *db_conn, char *query) +{ + void *tmp; + + tmp = db_conn; tmp = query; + + merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0); + return(0); +} +void *none_osdb_query_select(void *db_conn, char *query) +{ + void *tmp; + + tmp = db_conn; tmp = query; + + merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0); + return(0); +} + + + + +/** End of not defined db calls **/ +#endif + + + +/* EOF */ diff --git a/src/os_dbd/db_op.h b/src/os_dbd/db_op.h new file mode 100755 index 0000000..e8b3552 --- /dev/null +++ b/src/os_dbd/db_op.h @@ -0,0 +1,92 @@ +/* @(#) $Id: db_op.h,v 1.7 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* Common API for dealing with databases */ + + +#ifndef _OS_DBOP_H +#define _OS_DBOP_H + + +/* Connects to the database */ +void *(*osdb_connect)(char *host, char *user, char *pass, char *db, int port, char *sock); +void *mysql_osdb_connect(char *host, char *user, char *pass, char *db, int port, char *sock); +void *postgresql_osdb_connect(char *host, char *user, char *pass, char *db, int port, char *sock); + +/* Sends insert query to the database */ +int (* osdb_query_insert)(void *db_conn, char *query); +int mysql_osdb_query_insert(void *db_conn, char *query); +int postgresql_osdb_query_insert(void *db_conn, char *query); + +/* Sends select query to the database */ +int (* osdb_query_select)(void *db_conn, char *query); +int mysql_osdb_query_select(void *db_conn, char *query); +int postgresql_osdb_query_select(void *db_conn, char *query); + +/* Closes connection to the database */ +void *(*osdb_close)(void *db_conn); +void *mysql_osdb_close(void *db_conn); +void *postgresql_osdb_close(void *db_conn); + + +/* escape strings before inserting. */ +void osdb_escapestr(char *str); + + +/* Allowed characters */ +/* Insert charmap. + * Available chars: a-z, A-Z, 0-9, -, _, ., %, $, @, (, ), +, *, / + * Basically: 040-046 (oct) + * 050-176 (oct) + */ +static const unsigned char insert_map[] = +{ + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\047', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', +}; + + +#endif + +/* EOF */ diff --git a/src/os_dbd/dbd.c b/src/os_dbd/dbd.c new file mode 100755 index 0000000..c62c0ac --- /dev/null +++ b/src/os_dbd/dbd.c @@ -0,0 +1,88 @@ +/* @(#) $Id: dbd.c,v 1.6 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef DBD + #define DBD +#endif + +#ifndef ARGV0 + #define ARGV0 "ossec-dbd" +#endif + +#include "shared.h" +#include "dbd.h" + + + +/* OS_DBD: Monitor the alerts and insert them into the database. + * Only return in case of error. + */ +void OS_DBD(DBConfig *db_config) +{ + time_t tm; + struct tm *p; + + file_queue *fileq; + alert_data *al_data; + + + /* Getting currently time before starting */ + tm = time(NULL); + p = localtime(&tm); + + + /* Initating file queue - to read the alerts */ + os_calloc(1, sizeof(file_queue), fileq); + Init_FileQueue(fileq, p, 0); + + + /* Creating location hash */ + db_config->location_hash = OSHash_Create(); + if(!db_config->location_hash) + { + ErrorExit(MEM_ERROR, ARGV0); + } + + + /* Getting maximum ID */ + db_config->alert_id = OS_SelectMaxID(db_config); + db_config->alert_id++; + + + /* Infinite loop reading the alerts and inserting them. */ + while(1) + { + tm = time(NULL); + p = localtime(&tm); + + + /* Get message if available (timeout of 5 seconds) */ + al_data = Read_FileMon(fileq, p, 5); + if(!al_data) + { + continue; + } + + + /* Inserting into the db */ + OS_Alert_InsertDB(al_data, db_config); + + + /* Clearing the memory */ + FreeAlertData(al_data); + } +} + +/* EOF */ diff --git a/src/os_dbd/dbd.h b/src/os_dbd/dbd.h new file mode 100755 index 0000000..17d7150 --- /dev/null +++ b/src/os_dbd/dbd.h @@ -0,0 +1,62 @@ +/* @(#) $Id: dbd.h,v 1.6 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef _DBD_H +#define _DBD_H + + +#include "shared.h" +#include "db_op.h" +#include "config/dbd-config.h" + + +/** Prototypes **/ + +/* Read database config */ +int OS_ReadDBConf(int test_config, char *cfgfile, DBConfig *db_config); + + +/* Inserts server info to the db. */ +int OS_Server_ReadInsertDB(void *db_config); + + +/* Insert rules in to the database */ +int OS_InsertRulesDB(DBConfig *db_config); + + +/* Get maximum ID */ +int OS_SelectMaxID(DBConfig *db_config); + + +/* Insert alerts in to the database */ +int OS_Alert_InsertDB(alert_data *al_data, DBConfig *db_config); + + +/* Database inserting main function */ +void OS_DBD(DBConfig *db_config); + + +/* Setting config pointer for osbd_op */ +void osdb_setconfig(DBConfig *db_config); + + + +/** Global vars **/ + +/* System hostname */ +char __shost[512]; + + +#endif diff --git a/src/os_dbd/dbmake.sh b/src/os_dbd/dbmake.sh new file mode 100755 index 0000000..b3cbce3 --- /dev/null +++ b/src/os_dbd/dbmake.sh @@ -0,0 +1,135 @@ +#!/bin/sh + + +MI="" +ML="" +PI="" +PL="" + + +# Looking for mysql +ls "`which mysql 2>/dev/null`" > /dev/null 2>&1 +if [ $? = 0 ]; then + + # Checking if mysql_config is installed to use it. + mysql_config --port > /dev/null 2>&1 + if [ $? = 0 ]; then + MI=`mysql_config --cflags` + ML=`mysql_config --libs` + fi + + + # Checking on a few dirs if mysql_config is not there. + for i in /usr /usr/local $1 + do + for j in $i/include/mysql/mysql.h $i/include/mysql.h + do + ls $j > /dev/null 2>&1 + if [ $? = 0 ]; then + if [ "X$MI" = "X" ]; then + MI="-I `dirname $j`"; + fi + break; + fi + done + + for j in $i/lib/mysql $i/lib64/mysql + do + ls $j > /dev/null 2>&1 + if [ $? = 0 ]; then + if [ "X$ML" = "X" ]; then + ML="-L $j -lmysqlclient"; + fi + break + fi + done + done +fi + + +# Looking for postgresql +ls "`which psql 2>/dev/null`" > /dev/null 2>&1 +if [ $? = 0 ]; then + + # Checking if pg_config is installed to use it. + pg_config --version > /dev/null 2>&1 + if [ $? = 0 ]; then + PGID=`pg_config --includedir` + PGPI=`pg_config --pkgincludedir` + PGLD=`pg_config --libdir` + PGLI=`pg_config --pkglibdir` + PI="${PGID} -I${PGPI}" + PL="-L${PGLD} -L${PGLI}" + fi + + for i in /usr /usr/local /usr/local/pgsql /usr/pgsql /usr/postgresql $1 + do + for j in $i/include/pgsql/libpq-fe.h $i/include/libpq-fe.h $i/include/postgresql/libpq-fe.h + do + ls $j > /dev/null 2>&1 + if [ $? = 0 ]; then + if [ "X$PI" = "X" ]; then + PI=`dirname $j`; + fi + break; + fi + done + + for j in $i/lib/pgsql $i/lib/postgresql $i/lib64/pgsql $i/lib64/postgresql + do + ls $j > /dev/null 2>&1 + if [ $? = 0 ]; then + if [ "X$PL" = "X" ]; then + PG_MAIN=`dirname $j`; + PL="-L$j -L${PG_MAIN}"; + fi + break + fi + done + done +fi + + + + +# Printing error if mysql is not found +if [ "X$MI" = "X" -a "X$ML" = "X" ]; then + echo "" >&2 + echo "Error: MySQL client libraries not installed." >&2 + echo "" >&2 +fi + +# Printing error if postgresql is not found +if [ "X$PI" = "X" -a "X$PL" = "X" ]; then + echo "" >&2 + echo "Error: PostgreSQL client libraries not installed." >&2 + echo "" >&2 +fi + + +# Final cflags -- can not be empty. +if [ "X$MI" = "X" -o "X$ML" = "X" ]; then + MYSQL_FINAL="" +else + echo "Info: Compiled with MySQL support." >&2 + MYSQL_FINAL="$MI $ML -DDBD -DUMYSQL" +fi + +# For postgresql +if [ "X$PI" = "X" -o "X$PL" = "X" ]; then + POSTGRES_FINAL="" +else + echo "Info: Compiled with PostgreSQL support." >&2 + POSTGRES_FINAL="-I$PI $PL -lpq -DDBD -DUPOSTGRES" +fi + + +if [ "X${MYSQL_FINAL}" = "X" -a "X${POSTGRES_FINAL}" = "X" ]; then + echo "Error: DB libraries not installed." >&2 + exit 1; +fi + +echo "${MYSQL_FINAL} ${POSTGRES_FINAL}" + +exit 0; + diff --git a/src/os_dbd/main.c b/src/os_dbd/main.c new file mode 100755 index 0000000..d674e33 --- /dev/null +++ b/src/os_dbd/main.c @@ -0,0 +1,269 @@ +/* @(#) $Id: main.c,v 1.17 2009/11/18 19:07:40 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef DBD + #define DBD +#endif + +#ifndef ARGV0 + #define ARGV0 "ossec-dbd" +#endif + +#include "shared.h" +#include "dbd.h" + + +/* Prints information regarding enabled databases */ +void db_info() +{ + print_out(" "); + print_out("%s %s - %s", __name, __version, __author); + + #ifdef UMYSQL + print_out("Compiled with MySQL support."); + #endif + + #ifdef UPOSTGRES + print_out("Compiled with PostgreSQL support."); + #endif + + #if !defined(UMYSQL) && !defined(UPOSTGRES) + print_out("Compiled without any Database support."); + #endif + + print_out(" "); + print_out("%s",__license); + + exit(1); +} + + + +int main(int argc, char **argv) +{ + int c, test_config = 0, run_foreground = 0; + int uid = 0,gid = 0; + + /* Using MAILUSER (read only) */ + char *dir = DEFAULTDIR; + char *user = MAILUSER; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTCPATH; + + + /* Database Structure */ + DBConfig db_config; + db_config.error_count = 0; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "vVdhtfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + db_info(); + break; + case 'v': + db_info(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user=optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group=optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir=optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + + /* Starting daemon */ + debug1(STARTED_MSG, ARGV0); + + + /* Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Reading configuration */ + if((c = OS_ReadDBConf(test_config, cfg, &db_config)) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* Exit here if test config is set */ + if(test_config) + exit(0); + + + if(!run_foreground) + { + /* Going on daemon mode */ + nowDaemon(); + goDaemon(); + } + + + + /* Not configured */ + if(c == 0) + { + verbose("%s: Database not configured. Clean exit.", ARGV0); + exit(0); + } + + + /* Maybe disable this debug? */ + debug1("%s: DEBUG: Connecting to '%s', using '%s', '%s', '%s', %d,'%s'.", + ARGV0, db_config.host, db_config.user, + db_config.pass, db_config.db,db_config.port,db_config.sock); + + + /* Setting config pointer */ + osdb_setconfig(&db_config); + + + /* Getting maximum reconned attempts */ + db_config.maxreconnect = getDefine_Int("dbd", + "reconnect_attempts", 1, 9999); + + + /* Connecting to the database */ + c = 0; + while(c <= (db_config.maxreconnect * 10)) + { + db_config.conn = osdb_connect(db_config.host, db_config.user, + db_config.pass, db_config.db, + db_config.port,db_config.sock); + + /* If we are able to reconnect, keep going */ + if(db_config.conn) + { + break; + } + + c++; + sleep(c * 60); + + } + + + /* If after the maxreconnect attempts, it still didn't work, exit here. */ + if(!db_config.conn) + { + merror(DB_CONFIGERR, ARGV0); + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* We must notify that we connected -- easy debugging */ + verbose("%s: Connected to database '%s' at '%s'.", + ARGV0, db_config.db, db_config.host); + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + + /* Now on chroot */ + nowChroot(); + + + /* Inserting server info into the db */ + db_config.server_id = OS_Server_ReadInsertDB(&db_config); + if(db_config.server_id <= 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* Read rules and insert into the db */ + if(OS_InsertRulesDB(&db_config) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* Changing user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + /* Basic start up completed. */ + debug1(PRIVSEP_MSG,ARGV0,dir,user); + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + /* Creating PID files */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR,ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* the real daemon now */ + OS_DBD(&db_config); + exit(0); +} + + +/* EOF */ diff --git a/src/os_dbd/mysql.schema b/src/os_dbd/mysql.schema new file mode 100644 index 0000000..c8fa067 --- /dev/null +++ b/src/os_dbd/mysql.schema @@ -0,0 +1,97 @@ +# @(#) $Id: mysql.schema,v 1.8 2009/06/24 17:06:30 dcid Exp $ */ +# +# Copyright (C) 2009 Trend Micro Inc. +# All rights reserved. +# +# This program is a free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 3) as published by the FSF - Free Software +# Foundation. +# +# License details at the LICENSE file included with OSSEC or +# online at: http://www.ossec.net/en/licensing.html + + +CREATE TABLE category + ( + cat_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, + cat_name VARCHAR(32) NOT NULL UNIQUE, + PRIMARY KEY (cat_id), + INDEX (cat_name) + ); + +CREATE TABLE signature + ( + id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, + rule_id MEDIUMINT UNSIGNED NOT NULL UNIQUE, + level TINYINT UNSIGNED, + description VARCHAR(255) NOT NULL, + PRIMARY KEY (id), + INDEX (level), + INDEX (rule_id) + ); + +CREATE TABLE signature_category_mapping + ( + id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, + rule_id MEDIUMINT UNSIGNED NOT NULL, + cat_id SMALLINT UNSIGNED NOT NULL, + PRIMARY KEY (id, rule_id, cat_id) + ); + +CREATE TABLE server + ( + id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, + last_contact INT UNSIGNED NOT NULL, + version VARCHAR(32) NOT NULL, + hostname VARCHAR(64) NOT NULL UNIQUE, + information VARCHAR(128) NOT NULL, + PRIMARY KEY (id) + ); + +CREATE TABLE agent + ( + id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, + server_id SMALLINT UNSIGNED NOT NULL, + last_contact INT UNSIGNED NOT NULL, + ip_address INT UNSIGNED NOT NULL, + version VARCHAR(32) NOT NULL, + name VARCHAR(64) NOT NULL, + information VARCHAR(128) NOT NULL, + PRIMARY KEY (id, server_id) + ); + +CREATE TABLE location + ( + id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, + server_id SMALLINT UNSIGNED NOT NULL, + name VARCHAR(128) NOT NULL, + PRIMARY KEY (id, server_id) + ); + +CREATE TABLE data + ( + id INT UNSIGNED NOT NULL, + server_id SMALLINT UNSIGNED NOT NULL, + user TEXT NOT NULL, + full_log TEXT NOT NULL, + PRIMARY KEY (id, server_id) + ); + +CREATE TABLE alert + ( + id INT UNSIGNED NOT NULL, + server_id SMALLINT UNSIGNED NOT NULL, + rule_id MEDIUMINT UNSIGNED NOT NULL, + timestamp INT UNSIGNED NOT NULL, + location_id SMALLINT UNSIGNED NOT NULL, + src_ip INT UNSIGNED, + dst_ip INT UNSIGNED, + src_port SMALLINT UNSIGNED, + dst_port SMALLINT UNSIGNED, + PRIMARY KEY (id, server_id), + INDEX time (timestamp), + INDEX (rule_id), + INDEX (src_ip) + ); + diff --git a/src/os_dbd/postgresql.schema b/src/os_dbd/postgresql.schema new file mode 100644 index 0000000..6544d95 --- /dev/null +++ b/src/os_dbd/postgresql.schema @@ -0,0 +1,100 @@ +-- @(#) $Id: postgresql.schema,v 1.4 2009/06/24 17:06:30 dcid Exp $ */ +-- +-- Copyright (C) 2009 Trend Micro Inc. +-- All rights reserved. +-- +-- This program is a free software; you can redistribute it +-- and/or modify it under the terms of the GNU General Public +-- License (version 3) as published by the FSF - Free Software +-- Foundation. +-- +-- License details at the LICENSE file included with OSSEC or +-- online at: http://www.ossec.net/en/licensing.html + + +BEGIN; + +CREATE TABLE category + ( + cat_id SERIAL NOT NULL, + cat_name VARCHAR(32) NOT NULL UNIQUE, + PRIMARY KEY (cat_id) + ); +CREATE INDEX cat_name ON category (cat_name); + +CREATE TABLE signature + ( + id SERIAL NOT NULL, + rule_id INT8 NOT NULL UNIQUE, + level INT4, + description VARCHAR(255) NOT NULL, + PRIMARY KEY (id) + ); +CREATE INDEX level ON signature (level); +CREATE INDEX rule_id ON signature (rule_id); + +CREATE TABLE signature_category_mapping + ( + id SERIAL NOT NULL, + rule_id INT8 NOT NULL, + cat_id INT4 NOT NULL, + PRIMARY KEY (id, rule_id, cat_id) + ); + +CREATE TABLE server + ( + id SERIAL NOT NULL, + last_contact INT8 NOT NULL, + version VARCHAR(32) NOT NULL, + hostname VARCHAR(64) NOT NULL UNIQUE, + information VARCHAR(128) NOT NULL, + PRIMARY KEY (id) + ); + +CREATE TABLE agent + ( + id SERIAL NOT NULL, + server_id INT8 NOT NULL, + last_contact INT8 NOT NULL, + ip_address INT8 NOT NULL, + version VARCHAR(32) NOT NULL, + name VARCHAR(64) NOT NULL, + information VARCHAR(128) NOT NULL, + PRIMARY KEY (id, server_id) + ); + +CREATE TABLE location + ( + id SERIAL NOT NULL, + server_id INT8 NOT NULL, + name VARCHAR(128) NOT NULL, + PRIMARY KEY (id, server_id) + ); + +CREATE TABLE data + ( + id INT8 NOT NULL, + server_id INT4 NOT NULL, + "user" TEXT NOT NULL, + full_log TEXT NOT NULL, + PRIMARY KEY (id, server_id) + ); + +CREATE TABLE alert + ( + id INT8 NOT NULL, + server_id INT4 NOT NULL, + rule_id INT8 NOT NULL, + timestamp INT8 NOT NULL, + location_id INT4 NOT NULL, + src_ip INT8, + dst_ip INT8, + src_port INT4, + dst_port INT4, + PRIMARY KEY (id, server_id) + ); +CREATE INDEX time on alert(timestamp); +CREATE INDEX ruleid on alert(rule_id); +CREATE INDEX src_ip on alert(src_ip); + +COMMIT; diff --git a/src/os_dbd/rules.c b/src/os_dbd/rules.c new file mode 100755 index 0000000..a451423 --- /dev/null +++ b/src/os_dbd/rules.c @@ -0,0 +1,318 @@ +/* @(#) $Id: rules.c,v 1.9 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "dbd.h" +#include "config/config.h" +#include "rules_op.h" + + + +/** int __Groups_SelectGroup(char *group, DBConfig *db_config) + * Select group (categories) from to the db. + * Returns 0 if not found. + */ +int __Groups_SelectGroup(char *group, DBConfig *db_config) +{ + int result = 0; + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT cat_id FROM " + "category WHERE cat_name = '%s'", + group); + + + /* Checking return code. */ + result = osdb_query_select(db_config->conn, sql_query); + + return(result); +} + + +/** int __Groups_InsertGroup(char *group, DBConfig *db_config) + * Insert group (categories) in to the db. + */ +int __Groups_InsertGroup(char *group, DBConfig *db_config) +{ + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "INSERT INTO " + "category(cat_name) " + "VALUES ('%s')", + group); + + + /* Checking return code. */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + + return(0); +} + + +/** int __Groups_SelectGroupMapping() + * Select group (categories) from to the db. + * Returns 0 if not found. + */ +int __Groups_SelectGroupMapping(int cat_id, int rule_id, DBConfig *db_config) +{ + int result = 0; + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT id FROM signature_category_mapping " + "WHERE cat_id = '%u' AND rule_id = '%u'", + cat_id, rule_id); + + + /* Checking return code. */ + result = osdb_query_select(db_config->conn, sql_query); + + return(result); +} + + +/** int __Groups_InsertGroup(int cat_id, int rule_id, DBConfig *db_config) + * Insert group (categories) in to the db. + */ +int __Groups_InsertGroupMapping(int cat_id, int rule_id, DBConfig *db_config) +{ + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "INSERT INTO " + "signature_category_mapping(cat_id, rule_id) " + "VALUES ('%u', '%u')", + cat_id, rule_id); + + + /* Checking return code. */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + + return(0); +} + + + +/** void _Groups_ReadInsertDB(RuleInfo *rule, DBConfig *db_config) + * Insert groups (categories) in to the db. + */ +void _Groups_ReadInsertDB(RuleInfo *rule, DBConfig *db_config) +{ + /* We must insert each group separately. */ + int cat_id; + char *tmp_group; + char *tmp_str; + + + debug1("%s: DEBUG: entering _Groups_ReadInsertDB", ARGV0); + + + /* If group is null, just return */ + if(rule->group == NULL) + { + return; + } + + tmp_str = strchr(rule->group, ','); + tmp_group = rule->group; + + + /* Groups are separated by comma */ + while(tmp_group) + { + if(tmp_str) + { + *tmp_str = '\0'; + tmp_str++; + } + + /* Removing white spaces */ + while(*tmp_group == ' ') + tmp_group++; + + + /* Checking for empty group */ + if(*tmp_group == '\0') + { + tmp_group = tmp_str; + if(tmp_group) + { + tmp_str = strchr(tmp_group, ','); + } + continue; + } + + cat_id = __Groups_SelectGroup(tmp_group, db_config); + + + /* We firt check if we have this group in the db already. + * If not, we add it. + */ + if(cat_id == 0) + { + __Groups_InsertGroup(tmp_group, db_config); + cat_id = __Groups_SelectGroup(tmp_group, db_config); + } + + + /* If our cat_id is valid (not zero), we need to insert + * the mapping between the category and the rule. */ + if(cat_id != 0) + { + /* But, we first check if the mapping is already not there. */ + if(!__Groups_SelectGroupMapping(cat_id, rule->sigid, db_config)) + { + /* If not, we add it */ + __Groups_InsertGroupMapping(cat_id, rule->sigid, db_config); + } + } + + + /* Getting next category */ + tmp_group = tmp_str; + if(tmp_group) + { + tmp_str = strchr(tmp_group, ','); + } + } + + return; +} + + + +/** void *_Rules_ReadInsertDB(RuleInfo *rule, void *db_config) + * Insert rules in to the db. + */ +void *_Rules_ReadInsertDB(RuleInfo *rule, void *db_config) +{ + DBConfig *dbc = (DBConfig *)db_config; + char sql_query[OS_SIZE_1024]; + memset(sql_query, '\0', OS_SIZE_1024); + + + /* Escaping strings */ + osdb_escapestr(rule->group); + osdb_escapestr(rule->comment); + + + /* Checking level limit */ + if(rule->level > 20) + rule->level = 20; + if(rule->level < 0) + rule->level = 0; + + + debug1("%s: DEBUG: entering _Rules_ReadInsertDB()", ARGV0); + + + /* Checking rule limit */ + if(rule->sigid < 0 || rule->sigid > 9999999) + { + merror("%s: Invalid rule id: %u", ARGV0, rule->sigid); + return(NULL); + } + + + /* Inserting group into the signature mapping */ + _Groups_ReadInsertDB(rule, db_config); + + + + debug2("%s: DEBUG: Inserting: %d", ARGV0, rule->sigid); + + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT id FROM signature " + "where rule_id = %u", + rule->sigid); + + if(osdb_query_select(dbc->conn, sql_query) == 0) + { + snprintf(sql_query, OS_SIZE_1024 -1, + "INSERT INTO " + "signature(rule_id, level, description) " + "VALUES ('%u','%u','%s')", + rule->sigid, rule->level, rule->comment); + } + else + { + snprintf(sql_query, OS_SIZE_1024 -1, + "UPDATE signature SET level='%u',description='%s' " + "WHERE rule_id='%u'", + rule->level, rule->comment,rule->sigid); + } + + + /* Checking return code. */ + if(!osdb_query_insert(dbc->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + + return(NULL); +} + + +int OS_InsertRulesDB(DBConfig *db_config) +{ + char **rulesfiles; + + rulesfiles = db_config->includes; + while(rulesfiles && *rulesfiles) + { + debug1("%s: Reading rules file: '%s'", ARGV0, *rulesfiles); + + if(OS_ReadXMLRules(*rulesfiles, _Rules_ReadInsertDB, db_config) < 0) + { + merror(RULES_ERROR, ARGV0, *rulesfiles); + return(-1); + } + + free(*rulesfiles); + rulesfiles++; + } + + free(db_config->includes); + db_config->includes = NULL; + + + return(0); +} + + +/* EOF */ diff --git a/src/os_dbd/server.c b/src/os_dbd/server.c new file mode 100755 index 0000000..79b5037 --- /dev/null +++ b/src/os_dbd/server.c @@ -0,0 +1,147 @@ +/* @(#) $Id: server.c,v 1.7 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "dbd.h" +#include "config/config.h" +#include "rules_op.h" + + +/** int __DBSelectServer(char *server, DBConfig *db_config) + * Selects the server ID from the db. + * Returns 0 if not found. + */ +int __DBSelectServer(char *server, DBConfig *db_config) +{ + int result = 0; + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + + /* Generating SQL */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT id FROM " + "server WHERE hostname = '%s'", + server); + + + /* Checking return code. */ + result = osdb_query_select(db_config->conn, sql_query); + + return(result); +} + + +/** int __DBInsertServer(char *server, char *info, DBConfig *db_config) + * Inserts server in to the db. + */ +int __DBInsertServer(char *server, char *info, DBConfig *db_config) +{ + char sql_query[OS_SIZE_1024]; + + memset(sql_query, '\0', OS_SIZE_1024); + + /* Checking if the server is present */ + snprintf(sql_query, OS_SIZE_1024 -1, + "SELECT id from server where hostname = '%s'", + server); + + /* If not present, we insert */ + if(osdb_query_select(db_config->conn, sql_query) == 0) + { + snprintf(sql_query, OS_SIZE_1024 -1, + "INSERT INTO " + "server(last_contact, version, hostname, information) " + "VALUES ('%u', '%s', '%s', '%s')", + (unsigned int)time(0), __version, server, info); + + /* Checking return code. */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + } + + /* If it is, we update it */ + else + { + + snprintf(sql_query, OS_SIZE_1024 -1, + "UPDATE server SET " + "last_contact='%u',version='%s',information='%s' " + "WHERE hostname = '%s'", + (unsigned int)time(0), __version, info, server); + + /* Checking return code. */ + if(!osdb_query_insert(db_config->conn, sql_query)) + { + merror(DB_GENERROR, ARGV0); + } + } + + return(0); +} + + + +/** int OS_Server_ReadInsertDB(void *db_config) + * Insert server info to the db. + * Returns server ID or 0 on error. + */ +int OS_Server_ReadInsertDB(void *db_config) +{ + int server_id = 0; + char *info; + + + debug1("%s: DEBUG: entering OS_Server_ReadInsertDB()", ARGV0); + + + /* Getting servers hostname */ + memset(__shost, '\0', 512); + if(gethostname(__shost, 512 -1) != 0) + { + merror("%s: Error: gethostname() failed", ARGV0); + return(0); + } + + + /* Getting system uname */ + info = getuname(); + if(!info) + { + merror(MEM_ERROR, ARGV0); + return(0); + } + + + /* Escaping strings */ + osdb_escapestr(info); + osdb_escapestr(__shost); + + + /* Inserting server */ + __DBInsertServer(__shost, info, (DBConfig *)db_config); + + + /* Getting server id */ + server_id = __DBSelectServer(__shost, (DBConfig *)db_config); + + + return(server_id); +} + + +/* EOF */ diff --git a/src/os_execd/Makefile b/src/os_execd/Makefile new file mode 100755 index 0000000..eb71c0a --- /dev/null +++ b/src/os_execd/Makefile @@ -0,0 +1,19 @@ +# Makefile for execd +# Daniel B. Cid || + +PT=../ +NAME=ossec-execd + +include ../Config.Make + +LOCAL = execd.c exec.c config.c + +OBJS = ${OS_SHARED} ${OS_NET} ${OS_REGEX} ${OS_XML} + +addclient: + ${CC} ${CFLAGS} ${OS_LINK} ${LOCAL} ${OBJS} -o ${NAME} + ${CC} ${CFLAGS} -c ${LOCAL} +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/os_execd/config.c b/src/os_execd/config.c new file mode 100755 index 0000000..c49ba78 --- /dev/null +++ b/src/os_execd/config.c @@ -0,0 +1,63 @@ +/* @(#) $Id: config.c,v 1.14 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + + +/* ExecdConfig v0.1, 2006/03/24 + * Read the config file + */ +int ExecdConfig(char * cfgfile) +{ + #ifdef WIN32 + int is_disabled = 1; + #else + int is_disabled = 0; + #endif + char *(xmlf[]) = {"ossec_config", "active-response", "disabled", NULL}; + char *disable_entry; + + OS_XML xml; + + + /* Reading XML file */ + if(OS_ReadXML(cfgfile,&xml) < 0) + { + ErrorExit(XML_ERROR, ARGV0, cfgfile, xml.err, xml.err_line); + } + + /* We do not validate the xml in here. It is done by other processes */ + disable_entry = OS_GetOneContentforElement(&xml, xmlf); + if(disable_entry) + { + if(strcmp(disable_entry, "yes") == 0) + { + is_disabled = 1; + } + else if(strcmp(disable_entry, "no") == 0) + { + is_disabled = 0; + } + else + { + merror(XML_VALUEERR, ARGV0, + "disabled", + disable_entry); + return(-1); + } + } + + OS_ClearXML(&xml); + return(is_disabled); +} + +/* EOF */ diff --git a/src/os_execd/exec.c b/src/os_execd/exec.c new file mode 100755 index 0000000..8f033f5 --- /dev/null +++ b/src/os_execd/exec.c @@ -0,0 +1,275 @@ +/* @(#) $Id: exec.c,v 1.20 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "os_regex/os_regex.h" +#include "execd.h" + +char exec_names[MAX_AR +1][OS_FLSIZE +1]; +char exec_cmd[MAX_AR +1][OS_FLSIZE +1]; +int exec_timeout[MAX_AR +1]; +int exec_size = 0; +int f_time_reading = 1; + + +/** int ReadExecConfig() v0.1: + * Reads the shared exec config. + * Returns 1 on success or 0 on failure. + * Format of the file is 'name - command - timeout' + */ +int ReadExecConfig() +{ + int i = 0, j = 0, dup_entry = 0; + FILE *fp; + FILE *process_file; + char buffer[OS_MAXSTR +1]; + + /* Cleaning up */ + for(i = 0;i <= exec_size+1; i++) + { + memset(exec_names[i], '\0', OS_FLSIZE +1); + memset(exec_cmd[i], '\0', OS_FLSIZE +1); + exec_timeout[i] = 0; + } + exec_size = 0; + + + /* Opening file */ + fp = fopen(DEFAULTARPATH, "r"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, DEFAULTARPATH); + return(0); + } + + + /* Reading config */ + while(fgets(buffer, OS_MAXSTR, fp) != NULL) + { + char *str_pt; + char *tmp_str; + + str_pt = buffer; + + /* Cleaning up the buffer */ + tmp_str = strchr(buffer, ' '); + if(!tmp_str) + { + merror(EXEC_INV_CONF, ARGV0, DEFAULTARPATH); + continue; + } + *tmp_str = '\0'; + tmp_str++; + + + /* Searching for ' ' and - */ + if(*tmp_str == '-') + { + tmp_str+=2; + } + else + { + merror(EXEC_INV_CONF, ARGV0, DEFAULTARPATH); + continue; + } + + + + /* Setting the name */ + strncpy(exec_names[exec_size], str_pt, OS_FLSIZE); + exec_names[exec_size][OS_FLSIZE] = '\0'; + + + str_pt = tmp_str; + + tmp_str = strchr(tmp_str, ' '); + if(!tmp_str) + { + merror(EXEC_INV_CONF, ARGV0, DEFAULTARPATH); + continue; + } + *tmp_str = '\0'; + + + /* Writting the full command path */ + snprintf(exec_cmd[exec_size], OS_FLSIZE, + "%s/%s", + AR_BINDIRPATH, + str_pt); + process_file = fopen(exec_cmd[exec_size], "r"); + if(!process_file) + { + if(f_time_reading) + { + verbose("%s: INFO: Active response command not present: '%s'. " + "Not using it on this system.", + ARGV0, exec_cmd[exec_size]); + } + + exec_cmd[exec_size][0] = '\0'; + } + else + { + fclose(process_file); + } + + + /* Searching for ' ' and - */ + tmp_str++; + if(*tmp_str == '-') + { + tmp_str+=2; + } + else + { + merror(EXEC_INV_CONF, ARGV0, DEFAULTARPATH); + continue; + } + + + str_pt = tmp_str; + tmp_str = strchr(tmp_str, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + + /* Getting the exec timeout */ + exec_timeout[exec_size] = atoi(str_pt); + + + /* Checking if name is duplicated. */ + dup_entry = 0; + for(j = 0; j< exec_size; j++) + { + if(strcmp(exec_names[j], exec_names[exec_size]) == 0) + { + if(exec_cmd[j][0] == '\0') + { + strncpy(exec_cmd[j], exec_cmd[exec_size], OS_FLSIZE); + exec_cmd[j][OS_FLSIZE] = '\0'; + dup_entry = 1; + break; + } + else if(exec_cmd[exec_size][0] == '\0') + { + dup_entry = 1; + } + } + } + + if(dup_entry) + { + exec_cmd[exec_size][0] = '\0'; + exec_names[exec_size][0] = '\0'; + exec_timeout[exec_size] = 0; + } + else + { + exec_size++; + } + } + + fclose(fp); + f_time_reading = 0; + + return(1); +} + + + +/** char *GetCommandbyName(char *name, int *timeout) v0.2 + * Returns a pointer to the command name (full path) + * Returns NULL if name cannot be found + * If timeout is not NULL, write the timeout for that + * command to it. + */ +char *GetCommandbyName(char *name, int *timeout) +{ + int i = 0; + + for(;i < exec_size; i++) + { + if(strcmp(name, exec_names[i]) == 0) + { + *timeout = exec_timeout[i]; + return(exec_cmd[i]); + } + } + + return(NULL); +} + + +/** void ExecCmd(char **cmd, char *extra_data) v0.1 + * Execute command given. Must be a argv** NULL terminated. + * Void. Prints error to log message in case of problems. + */ +void ExecCmd(char **cmd) +{ + #ifndef WIN32 + pid_t pid; + + + /* Forking and leaving it running */ + pid = fork(); + if(pid == 0) + { + if(execv(*cmd, cmd) < 0) + { + merror(EXEC_CMDERROR, ARGV0, *cmd, strerror(errno)); + exit(1); + } + + exit(0); + } + + #endif + + return; +} + + +void ExecCmd_Win32(char *cmd) +{ + /* Windows code now. */ + #ifdef WIN32 + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + if(!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, + &si, &pi)) + { + merror("%s: ERROR: Unable to create active response process. ", ARGV0); + return; + } + + + /* Wait until process exits. */ + WaitForSingleObject(pi.hProcess, INFINITE ); + + /* Close process and thread */ + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + + + #endif + + return; +} + + +/* EOF */ diff --git a/src/os_execd/execd.c b/src/os_execd/execd.c new file mode 100755 index 0000000..e84b68b --- /dev/null +++ b/src/os_execd/execd.c @@ -0,0 +1,556 @@ +/* @(#) $Id: execd.c,v 1.39 2009/11/18 19:07:41 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "list_op.h" +#include "os_regex/os_regex.h" +#include "os_net/os_net.h" + +#include "execd.h" + + + +/* Timeout data structure */ +typedef struct _timeout_data +{ + time_t time_of_addition; + int time_to_block; + char **command; +}timeout_data; + + +/* Timeout list */ +OSList *timeout_list; +OSListNode *timeout_node; + + + +/** + * Shudowns execd properly. + */ +void execd_shutdown() +{ + /* Removing pending active responses. */ + merror(EXEC_SHUTDOWN, ARGV0); + + timeout_node = OSList_GetFirstNode(timeout_list); + while(timeout_node) + { + timeout_data *list_entry; + + list_entry = (timeout_data *)timeout_node->data; + + ExecCmd(list_entry->command); + + /* Delete currently node - already sets the pointer to next */ + OSList_DeleteCurrentlyNode(timeout_list); + timeout_node = OSList_GetCurrentlyNode(timeout_list); + } + + #ifndef WIN32 + HandleSIG(); + #endif + +} + + +#ifndef WIN32 + +/** int main(int argc, char **argv) v0.1 + */ +int main(int argc, char **argv) +{ + int c; + int test_config = 0,run_foreground = 0; + int gid = 0,m_queue = 0; + + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTARPATH; + char *xmlcfg = DEFAULTCPATH; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument.",ARGV0); + group = optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument.",ARGV0); + dir = optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument.",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + + + /* Check if the group given are valid */ + gid = Privsep_GetGroup(group); + if(gid < 0) + ErrorExit(USER_ERROR,ARGV0,"",group); + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* Reading config */ + if((c = ExecdConfig(xmlcfg)) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, xmlcfg); + } + + + /* Exit if test_config */ + if(test_config) + exit(0); + + + /* Signal manipulation */ + StartSIG2(ARGV0, execd_shutdown); + + + if (!run_foreground) + { + /* Going daemon */ + nowDaemon(); + goDaemon(); + } + + + /* Active response disabled */ + if(c == 1) + { + verbose(EXEC_DISABLED, ARGV0); + exit(0); + } + + /* Creating the PID file */ + if(CreatePID(ARGV0, getpid()) < 0) + merror(PID_ERROR, ARGV0); + + + /* Starting queue (exec queue) */ + if((m_queue = StartMQ(EXECQUEUEPATH,READ)) < 0) + ErrorExit(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno)); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* The real daemon Now */ + ExecdStart(m_queue); + + exit(0); +} + + +#endif + + + +/** void FreeTimeoutEntry(timeout_data *timeout_entry) v0.1 + * Free the timeout entry. Must be called after popping it + * from the timeout list + */ +void FreeTimeoutEntry(void *timeout_entry_pt) +{ + timeout_data *timeout_entry; + char **tmp_str; + + timeout_entry = (timeout_data *)timeout_entry_pt; + + if(!timeout_entry) + { + return; + } + + tmp_str = timeout_entry->command; + + /* Clearing the command arguments */ + if(tmp_str) + { + while(*tmp_str) + { + os_free(*tmp_str); + *tmp_str = NULL; + tmp_str++; + } + os_free(timeout_entry->command); + timeout_entry->command = NULL; + } + + os_free(timeout_entry); + timeout_entry = NULL; + + return; +} + + +#ifndef WIN32 + + +/** void ExecdStart(int q) v0.2 + * Main function on the execd. Does all the data receiving ,etc. + */ +void ExecdStart(int q) +{ + int i, childcount = 0; + time_t curr_time; + + char buffer[OS_MAXSTR + 1]; + char *tmp_msg = NULL; + char *name; + char *command; + char *cmd_args[MAX_ARGS +2]; + + + /* Select */ + fd_set fdset; + struct timeval socket_timeout; + + + /* Clearing the buffer */ + memset(buffer, '\0', OS_MAXSTR +1); + + + /* Initializing the cmd arguments */ + for(i = 0; i<= MAX_ARGS +1; i++) + { + cmd_args[i] = NULL; + } + + + /* Creating list for timeout */ + timeout_list = OSList_Create(); + if(!timeout_list) + { + ErrorExit(LIST_ERROR, ARGV0); + } + + + /* Main loop. */ + while(1) + { + int timeout_value; + int added_before = 0; + + char **timeout_args; + timeout_data *timeout_entry; + + + /* Cleaning up any child. */ + while (childcount) + { + int wp; + wp = waitpid((pid_t) -1, NULL, WNOHANG); + if (wp < 0) + { + merror(WAITPID_ERROR, ARGV0); + } + + /* if = 0, we still need to wait for the child process */ + else if (wp == 0) + { + break; + } + /* Child completed if wp > 0 */ + else + { + childcount--; + } + } + + + /* Getting currently time */ + curr_time = time(0); + + + /* Checking if there is any timeouted command to execute. */ + timeout_node = OSList_GetFirstNode(timeout_list); + while(timeout_node) + { + timeout_data *list_entry; + + list_entry = (timeout_data *)timeout_node->data; + + /* Timeouted */ + if((curr_time - list_entry->time_of_addition) > + list_entry->time_to_block) + { + ExecCmd(list_entry->command); + + /* Deletecurrently node already sets the pointer to next */ + OSList_DeleteCurrentlyNode(timeout_list); + timeout_node = OSList_GetCurrentlyNode(timeout_list); + + /* Clearing the memory */ + FreeTimeoutEntry(list_entry); + + childcount++; + } + + else + { + timeout_node = OSList_GetNextNode(timeout_list); + } + } + + + /* Setting timeout to EXECD_TIMEOUT */ + socket_timeout.tv_sec = EXECD_TIMEOUT; + socket_timeout.tv_usec= 0; + + + + /* Setting FD values */ + FD_ZERO(&fdset); + FD_SET(q, &fdset); + + /* Adding timeout */ + if(select(q+1, &fdset, NULL, NULL, &socket_timeout) == 0) + { + /* Timeout .. */ + continue; + } + + + /* Checking for error */ + if(!FD_ISSET(q, &fdset)) + { + merror(SELECT_ERROR, ARGV0); + continue; + } + + + /* Receiving the message */ + if(recv(q, buffer, OS_MAXSTR, 0) == -1) + { + merror(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno)); + continue; + } + + + /* Currently time */ + curr_time = time(0); + + + /* Getting application name */ + name = buffer; + + + /* Zeroing the name */ + tmp_msg = strchr(buffer, ' '); + if(!tmp_msg) + { + merror(EXECD_INV_MSG, ARGV0, buffer); + continue; + } + *tmp_msg = '\0'; + tmp_msg++; + + + /* Getting the command to execute (valid name) */ + command = GetCommandbyName(name, &timeout_value); + if(!command) + { + ReadExecConfig(); + command = GetCommandbyName(name, &timeout_value); + if(!command) + { + merror(EXEC_INV_NAME, ARGV0, name); + continue; + } + } + + + /* Command not present. */ + if(command[0] == '\0') + continue; + + + /* Allocating memory for the timeout argument */ + os_calloc(MAX_ARGS+2, sizeof(char *), timeout_args); + + + /* Adding initial variables to the cmd_arg and to the timeout cmd */ + cmd_args[0] = command; + cmd_args[1] = ADD_ENTRY; + os_strdup(command, timeout_args[0]); + os_strdup(DELETE_ENTRY, timeout_args[1]); + + cmd_args[2] = NULL; + timeout_args[2] = NULL; + + + /* Getting the arguments. */ + i = 2; + while(i < (MAX_ARGS -1)) + { + cmd_args[i] = tmp_msg; + cmd_args[i+1] = NULL; + + tmp_msg = strchr(tmp_msg, ' '); + if(!tmp_msg) + { + timeout_args[i] = strdup(cmd_args[i]); + timeout_args[i+1] = NULL; + break; + } + *tmp_msg = '\0'; + tmp_msg++; + + timeout_args[i] = strdup(cmd_args[i]); + timeout_args[i+1] = NULL; + + i++; + } + + + /* Check this command was already executed. */ + timeout_node = OSList_GetFirstNode(timeout_list); + added_before = 0; + + + /* Checking for the username and ip argument */ + if(!timeout_args[2] || !timeout_args[3]) + { + added_before = 1; + merror("%s: Invalid number of arguments.", ARGV0); + } + + while(timeout_node) + { + timeout_data *list_entry; + + list_entry = (timeout_data *)timeout_node->data; + if((strcmp(list_entry->command[3], timeout_args[3]) == 0) && + (strcmp(list_entry->command[0], timeout_args[0]) == 0)) + { + /* Means we executed this command before + * and we don't need to add it again. + */ + added_before = 1; + + + /* updating the timeout */ + list_entry->time_of_addition = curr_time; + break; + } + + /* Continue with the next entry in timeout list*/ + timeout_node = OSList_GetNextNode(timeout_list); + } + + + /* If it wasn't added before, do it now */ + if(!added_before) + { + /* executing command */ + ExecCmd(cmd_args); + + /* We don't need to add to the list if the timeout_value == 0 */ + if(timeout_value) + { + /* Creating the timeout entry */ + os_calloc(1, sizeof(timeout_data), timeout_entry); + timeout_entry->command = timeout_args; + timeout_entry->time_of_addition = curr_time; + timeout_entry->time_to_block = timeout_value; + + + /* Adding command to the timeout list */ + if(!OSList_AddData(timeout_list, timeout_entry)) + { + merror(LIST_ADD_ERROR, ARGV0); + FreeTimeoutEntry(timeout_entry); + } + } + + /* If no timeout, we still need to free it in here */ + else + { + char **ss_ta = timeout_args; + while(*timeout_args) + { + os_free(*timeout_args); + *timeout_args = NULL; + timeout_args++; + } + os_free(ss_ta); + } + + childcount++; + } + + /* We didn't add it to the timeout list */ + else + { + char **ss_ta = timeout_args; + + /* Clear the timeout arguments */ + while(*timeout_args) + { + os_free(*timeout_args); + *timeout_args = NULL; + timeout_args++; + } + + os_free(ss_ta); + } + + /* Some cleanup */ + while(i > 0) + { + cmd_args[i] = NULL; + i--; + } + } +} + + +#endif + +/* EOF */ diff --git a/src/os_execd/execd.h b/src/os_execd/execd.h new file mode 100755 index 0000000..e26bb5c --- /dev/null +++ b/src/os_execd/execd.h @@ -0,0 +1,67 @@ +/* @(#) $Id: execd.h,v 1.12 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * More details at the LICENSE file included with OSSEC or + * online at http://www.ossec.net/en/licensing.html . + */ + + +#ifndef _EXECD_H + +#ifndef ARGV0 +#define ARGV0 "ossec-execd" +#endif + + +/* Add/delete arguments for the commands */ +#define ADD_ENTRY "add" +#define DELETE_ENTRY "delete" + + +/* Maximum number of active responses active */ +#define MAX_AR 64 + + +/* Maximum number of command arguments */ +#define MAX_ARGS 32 + + +/* Execd select timeout -- in seconds */ +#define EXECD_TIMEOUT 90 + + + +/** Function prototypes **/ + +void ExecdStart(int queue); + +void WinExecdRun(char *exec_msg); + +int ReadExecConfig(); + +char *GetCommandbyName(char *name, int *timeout); + +void ExecCmd(char **cmd); + +void ExecCmd_Win32(char *cmd); + +int ExecdConfig(char * cfgfile); + +int WinExecd_Start(); + +void WinTimeoutRun(int timeout); + +void FreeTimeoutEntry(void *timeout_entry); + + + +#define _EXECD_H + +#endif diff --git a/src/os_execd/win_execd.c b/src/os_execd/win_execd.c new file mode 100755 index 0000000..3a02ffe --- /dev/null +++ b/src/os_execd/win_execd.c @@ -0,0 +1,331 @@ +/* @(#) $Id: win_execd.c,v 1.4 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifdef WIN32 + +#include "shared.h" +#include "list_op.h" +#include "os_regex/os_regex.h" +#include "os_net/os_net.h" + +#include "execd.h" + + +#ifdef ARGV0 + #undef ARGV0 +#endif + +#define ARGV0 "ossec-execd" + + + + +/* Timeout data structure */ +typedef struct _timeout_data +{ + time_t time_of_addition; + int time_to_block; + char **command; +}timeout_data; + + +/* Timeout list */ +OSList *timeout_list; +OSListNode *timeout_node; + + + + +/** int main(int argc, char **argv) v0.1 + */ +int WinExecd_Start() +{ + int c; + int test_config = 0; + + char *xmlcfg = DEFAULTCPATH; + + + + /* Reading config */ + if((c = ExecdConfig(xmlcfg)) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, xmlcfg); + } + + + /* Exit if test_config */ + if(test_config) + return(0); + + + /* Active response disabled */ + if(c == 1) + { + verbose(EXEC_DISABLED, ARGV0); + return(0); + } + + + /* Creating list for timeout */ + timeout_list = OSList_Create(); + if(!timeout_list) + { + ErrorExit(LIST_ERROR, ARGV0); + } + + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, getpid()); + + + return(1); +} + + + +void WinTimeoutRun(int curr_time) +{ + /* Checking if there is any timeouted command to execute. */ + timeout_node = OSList_GetFirstNode(timeout_list); + while(timeout_node) + { + timeout_data *list_entry; + + list_entry = (timeout_data *)timeout_node->data; + + /* Timeouted */ + if((curr_time - list_entry->time_of_addition) > + list_entry->time_to_block) + { + ExecCmd_Win32(list_entry->command[0]); + + /* Deletecurrently node already sets the pointer to next */ + OSList_DeleteCurrentlyNode(timeout_list); + timeout_node = OSList_GetCurrentlyNode(timeout_list); + + /* Clearing the memory */ + FreeTimeoutEntry(list_entry); + } + + else + { + timeout_node = OSList_GetNextNode(timeout_list); + } + } +} + + + +/** void WinExecdRun(char *exec_msg) + */ +void WinExecdRun(char *exec_msg) +{ + time_t curr_time; + + int i,j; + int timeout_value; + int added_before = 0; + + char **timeout_args; + + + char *tmp_msg = NULL; + char *name; + char *command; + char *cmd_user; + char *cmd_ip; + char buffer[OS_MAXSTR + 1]; + + + timeout_data *timeout_entry; + + + + + /* Currently time */ + curr_time = time(0); + + + /* Getting application name */ + name = exec_msg; + + + /* Zeroing the name */ + tmp_msg = strchr(exec_msg, ' '); + if(!tmp_msg) + { + merror(EXECD_INV_MSG, ARGV0, exec_msg); + return; + } + *tmp_msg = '\0'; + tmp_msg++; + + + /* Getting user. */ + cmd_user = tmp_msg; + tmp_msg = strchr(tmp_msg, ' '); + if(!tmp_msg) + { + merror(EXECD_INV_MSG, ARGV0, cmd_user); + return; + } + *tmp_msg = '\0'; + tmp_msg++; + + + /* Getting ip. */ + cmd_ip = tmp_msg; + tmp_msg = strchr(tmp_msg, ' '); + if(!tmp_msg) + { + merror(EXECD_INV_MSG, ARGV0, cmd_ip); + return; + } + *tmp_msg = '\0'; + tmp_msg++; + + + /* Getting the command to execute (valid name) */ + command = GetCommandbyName(name, &timeout_value); + if(!command) + { + ReadExecConfig(); + command = GetCommandbyName(name, &timeout_value); + if(!command) + { + merror(EXEC_INV_NAME, ARGV0, name); + return; + } + } + + + /* Command not present. */ + if(command[0] == '\0') + return; + + + /* Allocating memory for the timeout argument */ + os_calloc(MAX_ARGS+2, sizeof(char *), timeout_args); + + + /* Adding initial variables to the timeout cmd */ + snprintf(buffer, OS_MAXSTR, "\"%s\" %s \"%s\" \"%s\" \"%s\"", + command, DELETE_ENTRY, cmd_user, cmd_ip, tmp_msg); + os_strdup(buffer, timeout_args[0]); + timeout_args[1] = NULL; + + + + /* Getting size for the strncmp */ + i = 0, j = 0; + while(buffer[i] != '\0') + { + if(buffer[i] == ' ') + j++; + + i++; + if(j == 4) + break; + } + + + /* Check this command was already executed. */ + timeout_node = OSList_GetFirstNode(timeout_list); + added_before = 0; + + + while(timeout_node) + { + timeout_data *list_entry; + + list_entry = (timeout_data *)timeout_node->data; + if(strncmp(list_entry->command[0], timeout_args[0], i) == 0) + { + /* Means we executed this command before + * and we don't need to add it again. + */ + added_before = 1; + + + /* updating the timeout */ + list_entry->time_of_addition = curr_time; + break; + } + + /* Continue with the next entry in timeout list*/ + timeout_node = OSList_GetNextNode(timeout_list); + } + + + /* If it wasn't added before, do it now */ + if(!added_before) + { + snprintf(buffer, OS_MAXSTR, "\"%s\" %s \"%s\" \"%s\" \"%s\"", command, + ADD_ENTRY, cmd_user, cmd_ip, tmp_msg); + /* executing command */ + + ExecCmd_Win32(buffer); + + /* We don't need to add to the list if the timeout_value == 0 */ + if(timeout_value) + { + /* Creating the timeout entry */ + os_calloc(1, sizeof(timeout_data), timeout_entry); + timeout_entry->command = timeout_args; + timeout_entry->time_of_addition = curr_time; + timeout_entry->time_to_block = timeout_value; + + + /* Adding command to the timeout list */ + if(!OSList_AddData(timeout_list, timeout_entry)) + { + merror(LIST_ADD_ERROR, ARGV0); + FreeTimeoutEntry(timeout_entry); + } + } + + /* If no timeout, we still need to free it in here */ + else + { + char **ss_ta = timeout_args; + while(*timeout_args) + { + os_free(*timeout_args); + *timeout_args = NULL; + timeout_args++; + } + os_free(ss_ta); + } + } + + /* We didn't add it to the timeout list */ + else + { + char **ss_ta = timeout_args; + + /* Clear the timeout arguments */ + while(*timeout_args) + { + os_free(*timeout_args); + *timeout_args = NULL; + timeout_args++; + } + + os_free(ss_ta); + } +} + +#endif + +/* EOF */ diff --git a/src/os_maild/Makefile b/src/os_maild/Makefile new file mode 100755 index 0000000..d9e1b7f --- /dev/null +++ b/src/os_maild/Makefile @@ -0,0 +1,18 @@ +# Makefile for maild +# Daniel B. Cid + +PT=../ +NAME=ossec-maild + +include ../Config.Make + +LOCAL = maild.c config.c os_maild_client.c sendmail.c mail_list.c + +OBJS = ${OS_CONFIG} ${OS_SHARED} ${OS_NET} ${OS_REGEX} ${OS_XML} + +maild: + ${CC} ${CFLAGS} ${OS_LINK} ${LOCAL} ${OBJS} -o ${NAME} +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/os_maild/config.c b/src/os_maild/config.c new file mode 100755 index 0000000..6a0194e --- /dev/null +++ b/src/os_maild/config.c @@ -0,0 +1,58 @@ +/* @(#) $Id: config.c,v 1.13 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" + +#include "maild.h" +#include "config/config.h" + + +/* MailConf v0.1: 2005/04/01 + * Reads the Mail configuration + */ +int MailConf(int test_config, char *cfgfile, MailConfig *Mail) +{ + int modules = 0; + + modules|= CMAIL; + + Mail->to = NULL; + Mail->from = NULL; + Mail->smtpserver = NULL; + Mail->mn = 0; + Mail->priority = 0; + Mail->maxperhour = 12; + Mail->gran_to = NULL; + Mail->gran_id = NULL; + Mail->gran_level = NULL; + Mail->gran_location = NULL; + Mail->gran_group = NULL; + Mail->gran_set = NULL; + Mail->gran_format = NULL; + Mail->groupping = 1; + Mail->strict_checking = 0; + + if(ReadConfig(modules, cfgfile, NULL, Mail) < 0) + return(OS_INVALID); + + if(!Mail->mn) + { + if(!test_config) + { + verbose(MAIL_DIS, ARGV0); + } + exit(0); + } + + return(0); +} + +/* EOF */ diff --git a/src/os_maild/mail_list.c b/src/os_maild/mail_list.c new file mode 100755 index 0000000..7537428 --- /dev/null +++ b/src/os_maild/mail_list.c @@ -0,0 +1,166 @@ +/* @(#) $Id: mail_list.c,v 1.6 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "headers/debug_op.h" +#include "maild.h" +#include "mail_list.h" + +#include "error_messages/error_messages.h" + +MailNode *n_node; +MailNode *lastnode; + +int _memoryused = 0; +int _memorymaxsize = 0; + + +/* Create the Mail List */ +void OS_CreateMailList(int maxsize) +{ + n_node = NULL; + + _memorymaxsize = maxsize; + + _memoryused = 0; + + return; +} + +/* check last mail */ +MailNode *OS_CheckLastMail() +{ + return(lastnode); +} + +/* Get the last Mail -- or first node */ +MailNode *OS_PopLastMail() +{ + + MailNode *oldlast; + + oldlast = lastnode; + + if(lastnode == NULL) + { + n_node = NULL; + return(NULL); + } + + _memoryused--; + + lastnode = lastnode->prev; + + /* Remove the last */ + return(oldlast); +} + + +void FreeMailMsg(MailMsg *ml) +{ + if(ml == NULL) + return; + + if(ml->subject) + free(ml->subject); + + if(ml->body) + free(ml->body); + + free(ml); +} + + +/* Free mail node */ +void FreeMail(MailNode *ml) +{ + if(ml == NULL) + return; + if(ml->mail->subject) + free(ml->mail->subject); + + if(ml->mail->body) + free(ml->mail->body); + + free(ml->mail); + free(ml); +} + + +/* Add an email to the list -- always to the begining */ +void OS_AddMailtoList(MailMsg *ml) +{ + MailNode *tmp_node = n_node; + + if(tmp_node) + { + MailNode *new_node; + new_node = (MailNode *)calloc(1,sizeof(MailNode)); + + if(new_node == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + /* Always adding to the beginning of the list + * The new node will become the first node and + * new_node->next will be the previous first node + */ + new_node->next = tmp_node; + new_node->prev = NULL; + tmp_node->prev = new_node; + + n_node = new_node; + + /* Adding the event to the node */ + new_node->mail = ml; + + _memoryused++; + + /* Need to remove the last node */ + if(_memoryused > _memorymaxsize) + { + MailNode *oldlast; + + oldlast = lastnode; + lastnode = lastnode->prev; + + /* free last node */ + FreeMail(oldlast); + + _memoryused--; + } + } + + else + { + /* Adding first node */ + n_node = (MailNode *)calloc(1,sizeof(MailNode)); + if(n_node == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + n_node->prev = NULL; + n_node->next = NULL; + n_node->mail = ml; + + lastnode = n_node; + } + + return; +} + +/* EOF */ diff --git a/src/os_maild/mail_list.h b/src/os_maild/mail_list.h new file mode 100755 index 0000000..4e62132 --- /dev/null +++ b/src/os_maild/mail_list.h @@ -0,0 +1,46 @@ +/* @(#) $Id: mail_list.h,v 1.6 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef _MAILIST__H +#define _MAILIST__H + + +/* Events List structure */ +typedef struct _MailNode +{ + MailMsg *mail; + struct _MailNode *next; + struct _MailNode *prev; +}MailNode; + + +/* Add an email to the list */ +void OS_AddMailtoList(MailMsg *ml); + +/* Return the last event from the Event list + * removing it from there + */ +MailNode *OS_PopLastMail(); + +/* Returns a pointer to the last email, not removing it */ +MailNode *OS_CheckLastMail(); + +/* Create the mail list. Maxsize must be specified */ +void OS_CreateMailList(int maxsize); + +/* Free an email node */ +void FreeMail(MailNode *ml); + +/* Free email msg */ +void FreeMailMsg(MailMsg *ml); + +#endif diff --git a/src/os_maild/maild.c b/src/os_maild/maild.c new file mode 100755 index 0000000..0e2a506 --- /dev/null +++ b/src/os_maild/maild.c @@ -0,0 +1,474 @@ +/* @(#) $Id: maild.c,v 1.34 2009/11/18 19:07:41 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef MAILD + #define MAILD +#endif + +#ifndef ARGV0 + #define ARGV0 "ossec-maild" +#endif + +#include "shared.h" +#include "maild.h" +#include "mail_list.h" + + +void OS_Run(MailConfig *mail); + +int main(int argc, char **argv) +{ + int c, test_config = 0,run_foreground = 0; + int uid = 0,gid = 0; + char *dir = DEFAULTDIR; + char *user = MAILUSER; + char *group = GROUPGLOBAL; + char *cfg = DEFAULTCPATH; + + /* Mail Structure */ + MailConfig mail; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user=optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group=optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir=optarg; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + + } + + /* Starting daemon */ + debug1(STARTED_MSG,ARGV0); + + /*Check if the user/group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + ErrorExit(USER_ERROR,ARGV0,user,group); + + + /* Reading configuration */ + if(MailConf(test_config, cfg, &mail) < 0) + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + + + /* Reading internal options */ + mail.strict_checking = getDefine_Int("maild", + "strict_checking", + 0, 1); + + /* Get groupping */ + mail.groupping = getDefine_Int("maild", + "groupping", + 0, 1); + + /* Getting subject type */ + mail.subject_full = getDefine_Int("maild", + "full_subject", + 0, 1); + + + /* Exit here if test config is set */ + if(test_config) + exit(0); + + + if(!run_foreground) + { + nowDaemon(); + goDaemon(); + } + + + /* Privilege separation */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR,ARGV0,group); + + + /* chrooting */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + nowChroot(); + + + + /* Changing user */ + if(Privsep_SetUser(uid) < 0) + ErrorExit(SETUID_ERROR,ARGV0,user); + + + debug1(PRIVSEP_MSG,ARGV0,dir,user); + + + + /* Signal manipulation */ + StartSIG(ARGV0); + + + + /* Creating PID files */ + if(CreatePID(ARGV0, getpid()) < 0) + ErrorExit(PID_ERROR, ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* the real daemon now */ + OS_Run(&mail); + exit(0); +} + + +/* OS_Run: Read the queue and send the appropriate alerts. + * not supposed to return.. + */ +void OS_Run(MailConfig *mail) +{ + MailMsg *msg; + MailMsg *s_msg = NULL; + MailMsg *msg_sms = NULL; + + time_t tm; + struct tm *p; + + int i = 0; + int mailtosend = 0; + int childcount = 0; + int today = 0; + int thishour = 0; + + int n_errs = 0; + + file_queue *fileq; + + + /* Getting currently time before starting */ + tm = time(NULL); + p = localtime(&tm); + today = p->tm_mday; + thishour = p->tm_hour; + + + /* Init file queue */ + i = 0; + i |= CRALERT_MAIL_SET; + os_calloc(1, sizeof(file_queue), fileq); + Init_FileQueue(fileq, p, i); + + + /* Creating the list */ + OS_CreateMailList(MAIL_LIST_SIZE); + + + /* Setting default timeout */ + mail_timeout = DEFAULT_TIMEOUT; + + + /* Clearing global vars */ + _g_subject_level = 0; + memset(_g_subject, '\0', SUBJECT_SIZE +2); + + + while(1) + { + tm = time(NULL); + p = localtime(&tm); + + + /* SMS messages are sent without delay */ + if(msg_sms) + { + pid_t pid; + + pid = fork(); + + if(pid < 0) + { + merror("%s: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno)); + merror(FORK_ERROR, ARGV0); + sleep(30); + continue; + } + else if (pid == 0) + { + if(OS_Sendsms(mail, p, msg_sms) < 0) + merror(SNDMAIL_ERROR, ARGV0, mail->smtpserver); + + exit(0); + } + + + /* Freeing sms structure */ + FreeMailMsg(msg_sms); + msg_sms = NULL; + + + /* Increasing child count */ + childcount++; + } + + + /* If mail_timeout == NEXTMAIL_TIMEOUT, we will try to get + * more messages, before sending anything + */ + if((mail_timeout == NEXTMAIL_TIMEOUT) && (p->tm_hour == thishour)) + { + /* getting more messages */ + } + + + /* Hour changed. Send all supressed mails */ + else if(((mailtosend < mail->maxperhour) && (mailtosend != 0))|| + ((p->tm_hour != thishour) && (childcount < MAXCHILDPROCESS))) + { + MailNode *mailmsg; + pid_t pid; + + /* Checking if we have anything to sent */ + mailmsg = OS_CheckLastMail(); + if(mailmsg == NULL) + { + /* dont fork in here */ + goto snd_check_hour; + } + + pid = fork(); + if(pid < 0) + { + merror("%s: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno)); + merror(FORK_ERROR, ARGV0); + sleep(30); + continue; + } + else if (pid == 0) + { + if(OS_Sendmail(mail, p) < 0) + merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); + + exit(0); + } + + /* Cleaning the memory */ + mailmsg = OS_PopLastMail(); + do + { + FreeMail(mailmsg); + mailmsg = OS_PopLastMail(); + }while(mailmsg); + + + /* Increasing child count */ + childcount++; + + + /* Clearing global vars */ + _g_subject[0] = '\0'; + _g_subject[SUBJECT_SIZE -1] = '\0'; + _g_subject_level = 0; + + + /* Cleaning up set values */ + if(mail->gran_to) + { + i = 0; + while(mail->gran_to[i] != NULL) + { + if(s_msg && mail->gran_set[i] == DONOTGROUP) + { + mail->gran_set[i] = FULL_FORMAT; + } + else + { + mail->gran_set[i] = 0; + } + i++; + } + } + + snd_check_hour: + /* If we sent everything */ + if(p->tm_hour != thishour) + { + thishour = p->tm_hour; + + mailtosend = 0; + } + } + + /* Saved message for the do_not_group option. + */ + if(s_msg) + { + /* We need to set the remaining do no group to + * full format. + */ + if(mail->gran_to) + { + i = 0; + while(mail->gran_to[i] != NULL) + { + if(mail->gran_set[i] == DONOTGROUP) + { + mail->gran_set[i] = FULL_FORMAT; + } + i++; + } + } + + OS_AddMailtoList(s_msg); + + s_msg = NULL; + mailtosend++; + continue; + } + + + /* Receive message from queue */ + if((msg = OS_RecvMailQ(fileq, p, mail, &msg_sms)) != NULL) + { + /* If the e-mail priority is do_not_group, we first will + * flush all previous entries and then send it. + * We use s_msg to hold the pointer to the message + * while we flush it. + */ + if(mail->priority == DONOTGROUP) + { + s_msg = msg; + } + else + { + OS_AddMailtoList(msg); + } + + + /* Change timeout to see if any new message is coming shortly */ + if(mail->groupping) + { + /* If priority is set, send email now */ + if(mail->priority) + { + mail_timeout = DEFAULT_TIMEOUT; + + /* If do_not_group is set, we do not increase the + * list count in here. + */ + if(mail->priority != DONOTGROUP) + { + mailtosend++; + } + } + else + { + /* 5 seconds only */ + mail_timeout = NEXTMAIL_TIMEOUT; + } + } + else + { + /* Send message by itself */ + mailtosend++; + } + } + else + { + if(mail_timeout == NEXTMAIL_TIMEOUT) + { + mailtosend++; + + /* Default timeout */ + mail_timeout = DEFAULT_TIMEOUT; + } + } + + + /* Waiting for the childs .. */ + while (childcount) + { + int wp; + int p_status; + wp = waitpid((pid_t) -1, &p_status, WNOHANG); + if (wp < 0) + { + merror(WAITPID_ERROR, ARGV0); + n_errs++; + } + + /* if = 0, we still need to wait for the child process */ + else if (wp == 0) + break; + else + { + if(p_status != 0) + { + merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); + n_errs++; + } + childcount--; + } + + /* Too many errors */ + if(n_errs > 6) + { + merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); + exit(1); + } + } + + } +} + +/* EOF */ diff --git a/src/os_maild/maild.h b/src/os_maild/maild.h new file mode 100755 index 0000000..43a5709 --- /dev/null +++ b/src/os_maild/maild.h @@ -0,0 +1,80 @@ +/* @(#) $Id: maild.h,v 1.23 2009/06/24 17:06:30 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifndef _MAILD_H +#define _MAILD_H + +#define MAIL_LIST_SIZE 96 /* Max number of emails to be saved */ +#define MAXCHILDPROCESS 6 /* Maximum simultaneos childs */ + +/* Each timeout is x * 5 */ +#define NEXTMAIL_TIMEOUT 2 /* Time to check for next msg - 5 */ +#define DEFAULT_TIMEOUT 18 /* socket read timeout - 18 (*5)*/ +#define SUBJECT_SIZE 128 /* Maximum subject size */ + + /* Maximum body size */ +#define BODY_SIZE OS_MAXSTR + OS_SIZE_1024 + +#define SMS_SUBJECT "OSSEC %d - %d - %s" +#define MAIL_SUBJECT "OSSEC Notification - %s - Alert level %d" +#define MAIL_SUBJECT_FULL "OSSEC Alert - %s - Level %d - %s" + +/* Full subject without ossec in the name */ +#ifdef CLEANFULL +#define MAIL_SUBJECT_FULL2 "%d - %s - %s" +#endif + +#define MAIL_BODY "\r\nOSSEC HIDS Notification.\r\n" \ + "%s\r\n\r\n" \ + "Received From: %s\r\n" \ + "Rule: %d fired (level %d) -> \"%s\"\r\n" \ + "Portion of the log(s):\r\n\r\n%s\r\n" \ + "\r\n\r\n --END OF NOTIFICATION\r\n\r\n\r\n" + + +/* Mail msg structure */ +typedef struct _MailMsg +{ + char *subject; + char *body; +}MailMsg; + +#include "shared.h" +#include "config/mail-config.h" + + +/* Config function */ +int MailConf(int test_config, char *cfgfile, MailConfig *Mail); + + +/* Receive the e-mail message */ +MailMsg *OS_RecvMailQ(file_queue *fileq, struct tm *p, MailConfig *mail, + MailMsg **msg_sms); + +/* Sends an email */ +int OS_Sendmail(MailConfig *mail, struct tm *p); +int OS_Sendsms(MailConfig *mail, struct tm *p, MailMsg *sms_msg); + + +/* Mail timeout used by the file-queue */ +int mail_timeout; + + +/* Global var for highest level on mail subjects */ +int _g_subject_level; +char _g_subject[SUBJECT_SIZE +2]; + + +#endif diff --git a/src/os_maild/os_maild_client.c b/src/os_maild/os_maild_client.c new file mode 100755 index 0000000..118d2e6 --- /dev/null +++ b/src/os_maild/os_maild_client.c @@ -0,0 +1,288 @@ +/* @(#) $Id: os_maild_client.c,v 1.22 2009/06/24 17:06:31 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "maild.h" + + +/* OS_RecvMailQ, + * v0.1, 2005/03/15 + * Receive a Message on the Mail queue + * v0,2: Using the new file-queue. + */ +MailMsg *OS_RecvMailQ(file_queue *fileq, struct tm *p, + MailConfig *Mail, MailMsg **msg_sms) +{ + int i = 0, body_size = OS_MAXSTR -3, log_size, sms_set = 0,donotgroup = 0; + char logs[OS_MAXSTR + 1]; + char *subject_host; + + MailMsg *mail; + alert_data *al_data; + + Mail->priority = 0; + + + /* Get message if available */ + al_data = Read_FileMon(fileq, p, mail_timeout); + if(!al_data) + return(NULL); + + + /* If e-mail came correctly, generate the e-mail body/subject */ + os_calloc(1,sizeof(MailMsg), mail); + os_calloc(BODY_SIZE, sizeof(char), mail->body); + os_calloc(SUBJECT_SIZE, sizeof(char), mail->subject); + + + /* Generating the logs */ + logs[0] = '\0'; + logs[OS_MAXSTR] = '\0'; + + while(al_data->log[i]) + { + log_size = strlen(al_data->log[i]) + 4; + + /* If size left is small than the size of the log, stop it */ + if(body_size <= log_size) + { + break; + } + + strncat(logs, al_data->log[i], body_size); + strncat(logs, "\r\n", body_size); + body_size -= log_size; + i++; + } + + + /* Subject */ + subject_host = strchr(al_data->location, '>'); + if(subject_host) + { + subject_host--; + *subject_host = '\0'; + } + + /* We have two subject options - full and normal */ + if(Mail->subject_full) + { + /* Option for a clean full subject (without ossec in the name) */ + #ifdef CLEANFULL + snprintf(mail->subject, SUBJECT_SIZE -1, MAIL_SUBJECT_FULL2, + al_data->level, + al_data->comment, + al_data->location); + #else + snprintf(mail->subject, SUBJECT_SIZE -1, MAIL_SUBJECT_FULL, + al_data->location, + al_data->level, + al_data->comment); + #endif + } + else + { + snprintf(mail->subject, SUBJECT_SIZE -1, MAIL_SUBJECT, + al_data->location, + al_data->level); + } + + + /* fixing subject back */ + if(subject_host) + { + *subject_host = '-'; + } + + + /* Body */ + snprintf(mail->body, BODY_SIZE -1, MAIL_BODY, + al_data->date, + al_data->location, + al_data->rule, + al_data->level, + al_data->comment, + logs); + + + /* Checking for granular email configs */ + if(Mail->gran_to) + { + i = 0; + while(Mail->gran_to[i] != NULL) + { + int gr_set = 0; + + /* Looking if location is set */ + if(Mail->gran_location[i]) + { + if(OSMatch_Execute(al_data->location, + strlen(al_data->location), + Mail->gran_location[i])) + { + gr_set = 1; + } + else + { + i++; + continue; + } + } + + /* Looking for the level */ + if(Mail->gran_level[i]) + { + if(al_data->level >= Mail->gran_level[i]) + { + gr_set = 1; + } + else + { + i++; + continue; + } + } + + + /* Looking for rule id */ + if(Mail->gran_id[i]) + { + int id_i = 0; + while(Mail->gran_id[i][id_i] != 0) + { + if(Mail->gran_id[i][id_i] == al_data->rule) + { + break; + } + id_i++; + } + + /* If we found, id is going to be a valid rule */ + if(Mail->gran_id[i][id_i]) + { + gr_set = 1; + } + else + { + i++; + continue; + } + } + + + /* Looking for the group */ + if(Mail->gran_group[i]) + { + if(OSMatch_Execute(al_data->group, + strlen(al_data->group), + Mail->gran_group[i])) + { + gr_set = 1; + } + else + { + i++; + continue; + } + } + + + /* If we got in here, it is because everything + * matched. Set this e-mail to be used. + */ + if(gr_set) + { + if(Mail->gran_format[i] == SMS_FORMAT) + { + Mail->gran_set[i] = SMS_FORMAT; + + /* Setting the SMS flag */ + sms_set = 1; + } + else + { + /* Options */ + if(Mail->gran_format[i] == FORWARD_NOW) + { + Mail->priority = 1; + Mail->gran_set[i] = FULL_FORMAT; + } + else if(Mail->gran_format[i] == DONOTGROUP) + { + Mail->priority = DONOTGROUP; + Mail->gran_set[i] = DONOTGROUP; + donotgroup = 1; + } + else + { + Mail->gran_set[i] = FULL_FORMAT; + } + } + } + i++; + } + } + + + /* If DONOTGROUP is set, we can't assign the new subject */ + if(!donotgroup) + { + /* Getting highest level for alert */ + if(_g_subject[0] != '\0') + { + if(_g_subject_level < al_data->level) + { + strncpy(_g_subject, mail->subject, SUBJECT_SIZE); + _g_subject_level = al_data->level; + } + } + else + { + strncpy(_g_subject, mail->subject, SUBJECT_SIZE); + _g_subject_level = al_data->level; + } + } + + + /* If sms is set, create the sms output */ + if(sms_set) + { + MailMsg *msg_sms_tmp; + + /* Allocate memory for sms */ + os_calloc(1,sizeof(MailMsg), msg_sms_tmp); + os_calloc(BODY_SIZE, sizeof(char), msg_sms_tmp->body); + os_calloc(SUBJECT_SIZE, sizeof(char), msg_sms_tmp->subject); + + snprintf(msg_sms_tmp->subject, SUBJECT_SIZE -1, SMS_SUBJECT, + al_data->level, + al_data->rule, + al_data->comment); + + + strncpy(msg_sms_tmp->body, logs, 128); + msg_sms_tmp->body[127] = '\0'; + + /* Assigning msg_sms */ + *msg_sms = msg_sms_tmp; + } + + + + /* Clearing the memory */ + FreeAlertData(al_data); + + + return(mail); + +} +/* EOF */ diff --git a/src/os_maild/sendmail.c b/src/os_maild/sendmail.c new file mode 100755 index 0000000..39c5d8b --- /dev/null +++ b/src/os_maild/sendmail.c @@ -0,0 +1,594 @@ +/* @(#) $Id: sendmail.c,v 1.30 2009/06/24 17:06:31 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Basic e-mailing operations */ + + +#include "shared.h" +#include "os_net/os_net.h" +#include "maild.h" +#include "mail_list.h" + + +/* Return codes (from SMTP server) */ +#define VALIDBANNER "220" +#define VALIDMAIL "250" +#define VALIDDATA "354" + + +/* Default values use to connect */ +#define SMTP_DEFAULT_PORT 25 +#define HELOMSG "Helo notify.ossec.net\r\n" +#define MAILFROM "Mail From: <%s>\r\n" +#define RCPTTO "Rcpt To: <%s>\r\n" +#define DATAMSG "DATA\r\n" +#define FROM "From: OSSEC HIDS <%s>\r\n" +#define TO "To: <%s>\r\n" +#define CC "Cc: <%s>\r\n" +#define SUBJECT "Subject: %s\r\n" +#define ENDDATA "\r\n.\r\n" +#define QUITMSG "QUIT\r\n" + + +/* Error messages - Can be translated */ +#define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error" +#define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server" +#define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server" +#define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server" +#define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'." +#define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server" +#define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server" + + +#define MAIL_DEBUG_FLAG 0 +#define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z) + + +/* OS_Sendsms. + */ +int OS_Sendsms(MailConfig *mail, struct tm *p, MailMsg *sms_msg) +{ + int socket, i = 0, final_to_sz; + char *msg; + char snd_msg[128]; + char final_to[512]; + + + /* Connecting to the smtp server */ + socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver); + if(socket < 0) + { + return(socket); + } + + + /* Receiving the banner */ + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDBANNER, msg))) + { + merror(BANNER_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, ""); + free(msg); + + + + /* Sending HELO message */ + OS_SendTCP(socket,HELOMSG); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + if(msg) + { + /* Ugly fix warning :) */ + /* In some cases (with virus scans in the middle) + * we may get two banners. Check for that in here. + */ + if(OS_Match(VALIDBANNER, msg)) + { + free(msg); + + /* Try again */ + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null"); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + } + else + { + merror("%s:%s",HELO_ERROR,msg); + free(msg); + close(socket); + return(OS_INVALID); + } + } + else + { + merror("%s:%s",HELO_ERROR,"null"); + close(socket); + return(OS_INVALID); + } + } + + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg); + free(msg); + + + /* Building "Mail from" msg */ + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, MAILFROM, mail->from); + OS_SendTCP(socket, snd_msg); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror(FROM_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); + free(msg); + + + /* Additional RCPT to */ + final_to[0] = '\0'; + final_to_sz = sizeof(final_to) -2; + + if(mail->gran_to) + { + i = 0; + while(mail->gran_to[i] != NULL) + { + if(mail->gran_set[i] != SMS_FORMAT) + { + i++; + continue; + } + + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, RCPTTO, mail->gran_to[i]); + OS_SendTCP(socket, snd_msg); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror(TO_ERROR, mail->gran_to[i]); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); + free(msg); + + + /* Creating header for to */ + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, TO, mail->gran_to[i]); + strncat(final_to, snd_msg, final_to_sz); + final_to_sz -= strlen(snd_msg) +2; + + i++; + continue; + } + } + + + /* Sending the "DATA" msg */ + OS_SendTCP(socket,DATAMSG); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDDATA, msg))) + { + merror(DATA_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg); + free(msg); + + + /* Building "From" and "To" in the e-mail header */ + OS_SendTCP(socket, final_to); + + + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, FROM, mail->from); + OS_SendTCP(socket, snd_msg); + + + /* Sending date */ + memset(snd_msg,'\0',128); + + + /* Solaris doesn't have the "%z", so we set the timezone to 0. */ + #ifdef SOLARIS + strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p); + #else + strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p); + #endif + + OS_SendTCP(socket,snd_msg); + + + /* Sending subject */ + memset(snd_msg,'\0',128); + snprintf(snd_msg, 127, SUBJECT, sms_msg->subject); + OS_SendTCP(socket,snd_msg); + + + + /* Sending body */ + OS_SendTCP(socket, sms_msg->body); + + + /* Sending end of data \r\n.\r\n */ + OS_SendTCP(socket,ENDDATA); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))) + { + merror(END_DATA_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + /* Checking msg in here, since it may be null */ + if(msg) + free(msg); + + + /* quitting and closing socket */ + OS_SendTCP(socket,QUITMSG); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + + if(msg) + free(msg); + + memset(snd_msg,'\0',128); + + + /* Returning 0 (success) */ + close(socket); + + return(0); +} + + + +/* OS_Sendmail v0.1: 2005/03/18 + */ +int OS_Sendmail(MailConfig *mail, struct tm *p) +{ + int socket,i=0; + char *msg; + char snd_msg[128]; + char additional_to[512]; + + MailNode *mailmsg; + + additional_to[0] = '\0'; + + /* If there is no sms message, we attempt to get from the + * email list. + */ + mailmsg = OS_PopLastMail(); + + if(mailmsg == NULL) + { + merror("%s: No email to be sent. Inconsistent state.",ARGV0); + } + + + /* Connecting to the smtp server */ + socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver); + if(socket < 0) + { + return(socket); + } + + + /* Receiving the banner */ + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDBANNER, msg))) + { + merror(BANNER_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, ""); + free(msg); + + + + /* Sending HELO message */ + OS_SendTCP(socket,HELOMSG); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + if(msg) + { + /* Ugly fix warning :) */ + /* In some cases (with virus scans in the middle) + * we may get two banners. Check for that in here. + */ + if(OS_Match(VALIDBANNER, msg)) + { + free(msg); + + /* Try again */ + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null"); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + } + else + { + merror("%s:%s",HELO_ERROR,msg); + free(msg); + close(socket); + return(OS_INVALID); + } + } + else + { + merror("%s:%s",HELO_ERROR,"null"); + close(socket); + return(OS_INVALID); + } + } + + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg); + free(msg); + + + /* Building "Mail from" msg */ + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, MAILFROM, mail->from); + OS_SendTCP(socket, snd_msg); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror(FROM_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); + free(msg); + + + /* Building "RCPT TO" msg */ + while(1) + { + if(mail->to[i] == NULL) + { + if(i == 0) + { + merror(INTERNAL_ERROR); + close(socket); + return(OS_INVALID); + } + break; + } + memset(snd_msg,'\0',128); + snprintf(snd_msg,127,RCPTTO, mail->to[i++]); + OS_SendTCP(socket,snd_msg); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror(TO_ERROR, mail->to[i -1]); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); + free(msg); + } + + + /* Additional RCPT to */ + if(mail->gran_to) + { + i = 0; + while(mail->gran_to[i] != NULL) + { + if(mail->gran_set[i] != FULL_FORMAT) + { + i++; + continue; + } + + memset(snd_msg,'\0',128); + snprintf(snd_msg,127,RCPTTO, mail->gran_to[i]); + OS_SendTCP(socket,snd_msg); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) + { + merror(TO_ERROR, mail->gran_to[i]); + if(msg) + free(msg); + + i++; + continue; + } + + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); + free(msg); + i++; + continue; + } + } + + + /* Sending the "DATA" msg */ + OS_SendTCP(socket,DATAMSG); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if((msg == NULL)||(!OS_Match(VALIDDATA, msg))) + { + merror(DATA_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg); + free(msg); + + + /* Building "From" and "To" in the e-mail header */ + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, TO, mail->to[0]); + OS_SendTCP(socket, snd_msg); + + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, FROM, mail->from); + OS_SendTCP(socket, snd_msg); + + + /* Adding CCs */ + if(mail->to[1]) + { + i = 1; + while(1) + { + if(mail->to[i] == NULL) + { + break; + } + + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, TO, mail->to[i]); + OS_SendTCP(socket,snd_msg); + + i++; + } + } + + + /* More CCs - from granular options */ + if(mail->gran_to) + { + i = 0; + while(mail->gran_to[i] != NULL) + { + if(mail->gran_set[i] != FULL_FORMAT) + { + i++; + continue; + } + + memset(snd_msg,'\0',128); + snprintf(snd_msg,127, TO, mail->gran_to[i]); + OS_SendTCP(socket, snd_msg); + i++; + continue; + } + } + + + /* Sending date */ + memset(snd_msg,'\0',128); + + + /* Solaris doesn't have the "%z", so we set the timezone to 0. */ + #ifdef SOLARIS + strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p); + #else + strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p); + #endif + + OS_SendTCP(socket,snd_msg); + + + /* Sending subject */ + memset(snd_msg,'\0',128); + + + /* Checking if global subject is available */ + if((_g_subject_level != 0) && (_g_subject[0] != '\0')) + { + snprintf(snd_msg, 127, SUBJECT, _g_subject); + + /* Clearing global values */ + _g_subject[0] = '\0'; + _g_subject_level = 0; + } + else + { + snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject); + } + OS_SendTCP(socket,snd_msg); + + + + /* Sending body */ + + /* Sending multiple emails together if we have to */ + do + { + OS_SendTCP(socket, mailmsg->mail->body); + mailmsg = OS_PopLastMail(); + }while(mailmsg); + + + /* Sending end of data \r\n.\r\n */ + OS_SendTCP(socket,ENDDATA); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))) + { + merror(END_DATA_ERROR); + if(msg) + free(msg); + close(socket); + return(OS_INVALID); + } + /* Checking msg in here, since it may be null */ + if(msg) + free(msg); + + + /* quitting and closing socket */ + OS_SendTCP(socket,QUITMSG); + msg = OS_RecvTCP(socket, OS_SIZE_1024); + + if(msg) + free(msg); + + memset(snd_msg,'\0',128); + + + /* Returning 0 (success) */ + close(socket); + + return(0); +} +/* EOF */ diff --git a/src/os_net/COPYRIGHT b/src/os_net/COPYRIGHT new file mode 100755 index 0000000..8e92190 --- /dev/null +++ b/src/os_net/COPYRIGHT @@ -0,0 +1,9 @@ +Copyright (C) 2009 Trend Micro Inc. + All rights reserved. + This program is a free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License (version 3) as published by the FSF - Free Software + Foundation + +OSSEC, os_net library. +Available at http://www.ossec.net/ diff --git a/src/os_net/Makefile b/src/os_net/Makefile new file mode 100755 index 0000000..72b3a82 --- /dev/null +++ b/src/os_net/Makefile @@ -0,0 +1,18 @@ +# Makefile for os_net +# Daniel B. Cid || + +PT=../ +NAME=os_net + +include ../Config.Make + +SRCS = os_net.c +OBJS = os_net.o + +net: + $(CC) $(CFLAGS) -c $(SRCS) + ar cru os_net.a ${OBJS} + ranlib os_net.a + +clean: + ${CLEAN} diff --git a/src/os_net/VERSION b/src/os_net/VERSION new file mode 100755 index 0000000..be58634 --- /dev/null +++ b/src/os_net/VERSION @@ -0,0 +1 @@ +0.3 diff --git a/src/os_net/os_err.h b/src/os_net/os_err.h new file mode 100755 index 0000000..36964e1 --- /dev/null +++ b/src/os_net/os_err.h @@ -0,0 +1,35 @@ +/* @(#) $Id: os_err.h,v 1.7 2009/06/24 17:06:31 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Basic err codes + * + */ + +#ifndef __OS_ERR /* Definition of the __OS_ERR */ +#define __OS_ERR + +#define OS_SUCCESS 0 /* Success */ +#define OS_INVALID -1 /* Invalid entry */ +#define OS_NOTFOUND -2 /* Entry not found */ +#define OS_FILERR -3 /* Error in the file */ +#define OS_SIZELIM -4 /* Size limit problem */ +#define OS_CFGERR -5 /* Configuration error */ +#define OS_SOCKTERR -6 /* Socket error */ +#define OS_MISVALUE -7 /* There are values missing */ +#define OS_CONNERR -8 /* Connection failed */ +#define OS_UNDEF -9 /* Uknown error */ +#define OS_MEMERR -10 /* Memory Error */ +#define OS_SOCKBUSY -11 /* Busy socket -- try again */ + +#define OS_ENDFILE -20 /* End of file */ +#define OS_FINISH -21 /* Finished this task */ + +#endif /* __OS_ERR */ diff --git a/src/os_net/os_net.c b/src/os_net/os_net.c new file mode 100755 index 0000000..7ec960f --- /dev/null +++ b/src/os_net/os_net.c @@ -0,0 +1,508 @@ +/* @(#) $Id: os_net.c,v 1.34 2009/06/24 17:06:31 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + +/* OS_net Library. + * APIs for many network operations. + */ + + + + +#include "shared.h" +#include "os_net.h" + + +struct sockaddr_in _c; /* Client socket */ +socklen_t _cl; /* Client socket length */ + + +/* Unix socket -- not for windows */ +#ifndef WIN32 +struct sockaddr_un n_us; +socklen_t us_l = sizeof(n_us); + +/* UNIX SOCKET */ +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +#endif /* Sun_LEN */ + +#else +int ENOBUFS = 0; +#endif /* WIN32*/ + + +/* OS_Bindport v 0.2, 2005/02/11 + * Bind a specific port + * v0.2: Added REUSEADDR. + */ +int OS_Bindport(unsigned int _port, unsigned int _proto, char *_ip) +{ + int ossock; + struct sockaddr_in server; + + + if(_proto == IPPROTO_UDP) + { + if((ossock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + return OS_SOCKTERR; + } + } + else if(_proto == IPPROTO_TCP) + { + int flag = 1; + if((ossock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + { + return(int)(OS_SOCKTERR); + } + + if(setsockopt(ossock, SOL_SOCKET, SO_REUSEADDR, + (char *)&flag, sizeof(flag)) < 0) + { + return(OS_SOCKTERR); + } + } + else + { + return(OS_INVALID); + } + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons( _port ); + + if((_ip == NULL)||(_ip[0] == '\0')) + server.sin_addr.s_addr = htonl(INADDR_ANY); + else + server.sin_addr.s_addr = inet_addr(_ip); + + if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0) + { + return(OS_SOCKTERR); + } + + if(_proto == IPPROTO_TCP) + { + if(listen(ossock, 32) < 0) + { + return(OS_SOCKTERR); + } + } + + + _cl = sizeof(_c); + return(ossock); +} + + +/* OS_Bindporttcp v 0.1 + * Bind a TCP port, using the OS_Bindport + */ +int OS_Bindporttcp(unsigned int _port, char *_ip) +{ + return(OS_Bindport(_port, IPPROTO_TCP, _ip)); +} + + +/* OS_Bindportudp v 0.1 + * Bind a UDP port, using the OS_Bindport + */ +int OS_Bindportudp(unsigned int _port, char *_ip) +{ + return(OS_Bindport(_port, IPPROTO_UDP, _ip)); +} + +#ifndef WIN32 +/* OS_BindUnixDomain v0.1, 2004/07/29 + * Bind to a Unix domain, using DGRAM sockets + */ +int OS_BindUnixDomain(char * path, int mode, int max_msg_size) +{ + int len; + int ossock = 0; + socklen_t optlen = sizeof(len); + + /* Making sure the path isn't there */ + unlink(path); + + memset(&n_us, 0, sizeof(n_us)); + n_us.sun_family = AF_UNIX; + strncpy(n_us.sun_path, path, sizeof(n_us.sun_path)-1); + + if((ossock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + return(OS_SOCKTERR); + + if(bind(ossock, (struct sockaddr *)&n_us, SUN_LEN(&n_us)) < 0) + { + close(ossock); + return(OS_SOCKTERR); + } + + /* Changing permissions */ + chmod(path,mode); + + + /* Getting current maximum size */ + if(getsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1) + return(OS_SOCKTERR); + + + /* Setting socket opt */ + if(len < max_msg_size) + { + len = max_msg_size; + setsockopt(ossock, SOL_SOCKET, SO_RCVBUF, &len, optlen); + } + + return(ossock); +} + +/* OS_ConnectUnixDomain v0.1, 2004/07/29 + * Open a client Unix domain socket + * ("/tmp/lala-socket",0666)); + * + */ +int OS_ConnectUnixDomain(char * path, int max_msg_size) +{ + int len; + int ossock = 0; + socklen_t optlen = sizeof(len); + + memset(&n_us, 0, sizeof(n_us)); + + n_us.sun_family = AF_UNIX; + + /* Setting up path */ + strncpy(n_us.sun_path,path,sizeof(n_us.sun_path)-1); + + if((ossock = socket(AF_UNIX, SOCK_DGRAM,0)) < 0) + return(OS_SOCKTERR); + + + /* Connecting to the UNIX domain. + * We can use "send" after that + */ + if(connect(ossock,(struct sockaddr *)&n_us,SUN_LEN(&n_us)) < 0) + return(OS_SOCKTERR); + + + /* Getting current maximum size */ + if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1) + return(OS_SOCKTERR); + + + /* Setting maximum message size */ + if(len < max_msg_size) + { + len = max_msg_size; + setsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, optlen); + } + + + /* Returning the socket */ + return(ossock); +} + + +int OS_getsocketsize(int ossock) +{ + int len = 0; + socklen_t optlen = sizeof(len); + + /* Getting current maximum size */ + if(getsockopt(ossock, SOL_SOCKET, SO_SNDBUF, &len, &optlen) == -1) + return(OS_SOCKTERR); + + return(len); +} + +#endif + +/* OS_Connect v 0.1, 2004/07/21 + * Open a TCP/UDP client socket + */ +int OS_Connect(unsigned int _port, unsigned int protocol, char *_ip) +{ + int ossock; + struct sockaddr_in server; + + if(protocol == IPPROTO_TCP) + { + if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) + return(OS_SOCKTERR); + } + else if(protocol == IPPROTO_UDP) + { + if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) + return(OS_SOCKTERR); + } + else + return(OS_INVALID); + + _cl = sizeof(server); + + memset(&server, 0, _cl); + server.sin_family = AF_INET; + server.sin_port = htons( _port ); + + if((_ip == NULL)||(_ip[0] == '\0')) + return(OS_INVALID); + + server.sin_addr.s_addr = inet_addr(_ip); + + if(connect(ossock,(struct sockaddr *)&server, _cl) < 0) + return(OS_SOCKTERR); + + return(ossock); +} + + +/* OS_ConnectTCP, v0.1 + * Open a TCP socket + */ +int OS_ConnectTCP(unsigned int _port, char *_ip) +{ + return(OS_Connect(_port, IPPROTO_TCP,_ip)); +} + + +/* OS_ConnectUDP, v0.1 + * Open a UDP socket + */ +int OS_ConnectUDP(unsigned int _port, char *_ip) +{ + return(OS_Connect(_port, IPPROTO_UDP,_ip)); +} + +/* OS_SendTCP v0.1, 2004/07/21 + * Send a TCP packet (in a open socket) + */ +int OS_SendTCP(int socket, char *msg) +{ + if((send(socket, msg, strlen(msg),0)) <= 0) + return (OS_SOCKTERR); + + return(0); +} + +/* OS_SendTCPbySize v0.1, 2004/07/21 + * Send a TCP packet (in a open socket) of a specific size + */ +int OS_SendTCPbySize(int socket, int size, char *msg) +{ + if((send(socket, msg, size, 0)) < size) + return (OS_SOCKTERR); + + return(0); +} + + +/* OS_SendUDPbySize v0.1, 2004/07/21 + * Send a UDP packet (in a open socket) of a specific size + */ +int OS_SendUDPbySize(int socket, int size, char *msg) +{ + int i = 0; + + /* Maximum attempts is 5 */ + while((send(socket,msg,size,0)) < 0) + { + if((errno != ENOBUFS) || (i >= 5)) + { + return(OS_SOCKTERR); + } + + i++; + merror("%s: INFO: Remote socket busy, waiting %d s.", __local_name, i); + sleep(i); + } + + return(0); +} + + + +/* OS_AcceptTCP v0.1, 2005/01/28 + * Accept a TCP connection + */ +int OS_AcceptTCP(int socket, char *srcip, int addrsize) +{ + int clientsocket; + struct sockaddr_in _nc; + socklen_t _ncl; + + memset(&_nc, 0, sizeof(_nc)); + _ncl = sizeof(_nc); + + if((clientsocket = accept(socket, (struct sockaddr *) &_nc, + &_ncl)) < 0) + return(-1); + + strncpy(srcip, inet_ntoa(_nc.sin_addr),addrsize -1); + srcip[addrsize -1]='\0'; + + return(clientsocket); +} + + +/* OS_RecvTCP v0.1, 2004/07/21 + * Receive a TCP packet (in a open socket) + */ +char *OS_RecvTCP(int socket, int sizet) +{ + char *ret; + + int retsize=0; + + ret = (char *) calloc((sizet), sizeof(char)); + if(ret == NULL) + return(NULL); + + if((retsize = recv(socket, ret, sizet-1,0)) <= 0) + return(NULL); + + return(ret); +} + + +/* OS_RecvTCPBuffer v0.1, 2004/07/21 + * Receive a TCP packet (in a open socket) + */ +int OS_RecvTCPBuffer(int socket, char *buffer, int sizet) +{ + int retsize = 0; + + while(!retsize) + { + retsize = recv(socket, buffer, sizet -1, 0); + if(retsize > 0) + { + buffer[retsize] = '\0'; + return(0); + } + return(-1); + } + return(-1); +} + + + + +/* OS_RecvUDP v 0.1, 2004/07/20 + * Receive a UDP packet + */ +char *OS_RecvUDP(int socket, int sizet) +{ + char *ret; + + ret = (char *) calloc((sizet), sizeof(char)); + if(ret == NULL) + return(NULL); + + if((recvfrom(socket,ret,sizet-1,0,(struct sockaddr *)&_c,&_cl))<0) + return(NULL); + + return(ret); +} + + +/* OS_RecvConnUDP v0.1 + * Receives a message from a connected UDP socket + */ +int OS_RecvConnUDP(int socket, char *buffer, int buffer_size) +{ + int recv_b; + + recv_b = recv(socket, buffer, buffer_size, 0); + if(recv_b < 0) + return(0); + + return(recv_b); +} + + +#ifndef WIN32 +/* OS_RecvUnix, v0.1, 2004/07/29 + * Receive a message using a Unix socket + */ +int OS_RecvUnix(int socket, int sizet, char *ret) +{ + ssize_t recvd; + if((recvd = recvfrom(socket, ret, sizet -1, 0, + (struct sockaddr*)&n_us,&us_l)) < 0) + return(0); + + ret[recvd] = '\0'; + return((int)recvd); +} + + +/* OS_SendUnix, v0.1, 2004/07/29 + * Send a message using a Unix socket. + * Returns the OS_SOCKETERR if it + */ +int OS_SendUnix(int socket, char * msg, int size) +{ + if(size == 0) + size = strlen(msg)+1; + + if(send(socket, msg, size,0) < size) + { + if(errno == ENOBUFS) + return(OS_SOCKBUSY); + + return(OS_SOCKTERR); + } + + return(OS_SUCCESS); +} +#endif + + +/* OS_GetHost, v0.1, 2005/01/181 + * Calls gethostbyname (tries x attempts) + */ +char *OS_GetHost(char *host, int attempts) +{ + int i = 0; + int sz; + + char *ip; + struct hostent *h; + + if(host == NULL) + return(NULL); + + while(i <= attempts) + { + if((h = gethostbyname(host)) == NULL) + { + sleep(i++); + continue; + } + + sz = strlen(inet_ntoa(*((struct in_addr *)h->h_addr)))+1; + if((ip = (char *) calloc(sz, sizeof(char))) == NULL) + return(NULL); + + strncpy(ip,inet_ntoa(*((struct in_addr *)h->h_addr)), sz-1); + + return(ip); + } + + return(NULL); +} + +/* EOF */ diff --git a/src/os_net/os_net.h b/src/os_net/os_net.h new file mode 100755 index 0000000..68da2eb --- /dev/null +++ b/src/os_net/os_net.h @@ -0,0 +1,84 @@ +/* @(#) $Id: os_net.h,v 1.12 2009/06/24 17:06:31 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* OS_net Library. + * APIs for many network operations. + */ + +#ifndef __OS_NET_H + +#define __OS_NET_H + + +/* OS_Bindport* + * Bind a specific port (protocol and a ip). + * If the IP is not set, it is going to use ADDR_ANY + * Return the socket. + */ +int OS_Bindporttcp(unsigned int _port, char *_ip); +int OS_Bindportudp(unsigned int _port, char *_ip); + +/* OS_BindUnixDomain + * Bind to a specific file, using the "mode" permissions in + * a Unix Domain socket. + */ +int OS_BindUnixDomain(char * path, int mode, int max_msg_size); +int OS_ConnectUnixDomain(char * path, int max_msg_size); +int OS_getsocketsize(int ossock); + + +/* OS_Connect + * Connect to a TCP/UDP socket + */ +int OS_ConnectTCP(unsigned int _port, char *_ip); +int OS_ConnectUDP(unsigned int _port, char *_ip); + +/* OS_RecvUDP + * Receive a UDP packet. Return NULL if failed + */ +char *OS_RecvUDP(int socket, int sizet); +int OS_RecvConnUDP(int socket, char *buffer, int buffer_size); + + +/* OS_RecvUnix + * Receive a message via a Unix socket + */ +int OS_RecvUnix(int socket, int sizet, char *ret); + + +/* OS_RecvTCP + * Receive a TCP packet + */ +int OS_AcceptTCP(int socket, char *srcip, int addrsize); +char *OS_RecvTCP(int socket, int sizet); +int OS_RecvTCPBuffer(int socket, char *buffer, int sizet); + + +/* OS_SendTCP + * Send a TCP/UDP/UnixSocket packet (in a open socket) + */ +int OS_SendTCP(int socket, char *msg); +int OS_SendTCPbySize(int socket, int size, char *msg); + +int OS_SendUnix(int socket, char * msg, int size); + +int OS_SendUDP(int socket, char *msg); +int OS_SendUDPbySize(int socket, int size, char *msg); + + +/* OS_GetHost + * Calls gethostbyname + */ +char *OS_GetHost(char *host, int attempts); + +#endif + +/* EOF */ diff --git a/src/os_regex/COPYRIGHT b/src/os_regex/COPYRIGHT new file mode 100755 index 0000000..4394e65 --- /dev/null +++ b/src/os_regex/COPYRIGHT @@ -0,0 +1,9 @@ +Copyright (C) 2009 Trend Micro Inc. + All right reserved. + This program is a free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License (version 3) as published by the FSF - Free Software + Foundation + +OSSEC, os_regex library. +Available at http://www.ossec.net/ diff --git a/src/os_regex/Makefile b/src/os_regex/Makefile new file mode 100755 index 0000000..9e37d47 --- /dev/null +++ b/src/os_regex/Makefile @@ -0,0 +1,22 @@ +# Makefile for os_regex +# Daniel B. Cid || + +PT=../ +NAME=os_regex + +include ../Config.Make + +SRCS = *.c +OBJS = *.o + +regex: + $(CC) $(CFLAGS) -c $(SRCS) -Wall + ar cru os_regex.a ${OBJS} + ranlib os_regex.a + +main: + $(CC) $(CFLAGS) -o main main.c os_regex.a + +clean: + ${CLEAN} + rm -f main diff --git a/src/os_regex/README b/src/os_regex/README new file mode 100755 index 0000000..f91ed51 --- /dev/null +++ b/src/os_regex/README @@ -0,0 +1,36 @@ +OSSEC os_regex 0.3 +Copyright (c) 2004,2005,2006 Daniel B. Cid + + + += OSSEC, os_regex Library. = + + +Fast and simple library for regular expressions in C. + +This library is designed to be simple, but support +the most common regular expressions. It was design +with intrusion detection systems in mind, where having +all options is not crucial, but speed is. + + +The following expressions are supported: + \w -> A-Z, a-z, 0-9 characters + \d -> 0-9 characters + \s -> For spaces " " + \p -> ()*+,-.:;<=>?[] (pontuation characters) + \W -> For anything not \w + \D -> For anything not \d + \S -> For anything not \s + \. -> For anything + + +Each regular expression can be followed by: + + + -> To match one or more times (eg \w+ or \d+) + * -> To match zero or more times (eg \w* or \p*) + + +We also support the "^" to match at the beginning of the text, +'$" to match at the end of the text and "|" to have multiple +expressions. diff --git a/src/os_regex/VERSION b/src/os_regex/VERSION new file mode 100755 index 0000000..be58634 --- /dev/null +++ b/src/os_regex/VERSION @@ -0,0 +1 @@ +0.3 diff --git a/src/os_regex/examples/Makefile b/src/os_regex/examples/Makefile new file mode 100755 index 0000000..c5ab6f4 --- /dev/null +++ b/src/os_regex/examples/Makefile @@ -0,0 +1,9 @@ +# Makefile for os_regex tests + +maketest: + $(CC) -o regex regex.c ../os_regex.a -I../ -Wall + $(CC) -o match match.c ../os_regex.a -I../ -Wall + $(CC) -o regex_str regex_str.c ../os_regex.a -I../ -Wall + +clean: + -rm regex regex_str *.core diff --git a/src/os_regex/examples/match.c b/src/os_regex/examples/match.c new file mode 100755 index 0000000..d63ffe7 --- /dev/null +++ b/src/os_regex/examples/match.c @@ -0,0 +1,28 @@ +/* Copyright by Daniel B. Cid (2005) + * Under the public domain. It is just an example. + * Some examples of the usage for the os_regex library. + */ + +#include +#include +#include +#include "os_regex.h" + +int main(int argc,char **argv) +{ + + if(argc != 3) + { + printf("%s regex word\n",argv[0]); + exit(1); + } + + printf("for MATCH: "); + if(OS_Match2(argv[1],argv[2])) + printf("TRUE\n"); + else + printf("FALSE\n"); + + return(0); +} +/* EOF */ diff --git a/src/os_regex/examples/regex.c b/src/os_regex/examples/regex.c new file mode 100755 index 0000000..6200e33 --- /dev/null +++ b/src/os_regex/examples/regex.c @@ -0,0 +1,28 @@ +/* Copyright by Daniel B. Cid (2005) + * Under the public domain. It is just an example. + * Some examples of the usage for the os_regex library. + */ + +#include +#include +#include +#include "os_regex.h" + +int main(int argc,char **argv) +{ + + if(argc != 3) + { + printf("%s regex word\n",argv[0]); + exit(1); + } + + printf("for REGEX: "); + if(OS_Regex(argv[1],argv[2])) + printf("TRUE\n"); + else + printf("FALSE\n"); + + return(0); +} +/* EOF */ diff --git a/src/os_regex/examples/regex_str.c b/src/os_regex/examples/regex_str.c new file mode 100755 index 0000000..c28346f --- /dev/null +++ b/src/os_regex/examples/regex_str.c @@ -0,0 +1,75 @@ +/* Copyright by Daniel B. Cid (2005, 2006) + * Under the public domain. It is just an example. + * Some examples of usage for the os_regex library. + */ + +#include +#include +#include + +/* Must be included */ +#include "os_regex.h" + +int main(int argc,char **argv) +{ + int r_code = 0; + char **ret; + + /* OSRegex structure */ + OSRegex reg; + + /* checking for arguments */ + if(argc != 3) + { + printf("%s regex string\n",argv[0]); + exit(1); + } + + + /* If the compilation failed, we don't need to free anything. + * We are passing the OS_RETURN_SUBSTRING because we wan't the + * substrings back. + */ + if(OSRegex_Compile(argv[1], ®, OS_RETURN_SUBSTRING)) + { + char *retv; + /* If the execution succeeds, the substrings will be + * at reg.sub_strings + */ + if((retv = OSRegex_Execute(argv[2], ®))) + { + int sub_size = 0; + r_code = 1; + + /* next pt */ + printf("next pt: '%s'\n", retv); + /* Assigning reg.sub_strings to ret */ + ret = reg.sub_strings; + + printf("substrings:\n"); + while(*ret) + { + printf(" %d: !%s!\n", sub_size, *ret); + sub_size++; ret++; + } + + /* We must free the substrings */ + OSRegex_FreeSubStrings(®); + } + else + { + printf("Error: Didn't match.\n"); + } + + OSRegex_FreePattern(®); + } + + /* Compilation error */ + else + { + printf("Error: Regex Compile Error: %d\n", reg.error); + } + + return(r_code); +} +/* EOF */ diff --git a/src/os_regex/examples/run.sh b/src/os_regex/examples/run.sh new file mode 100755 index 0000000..aae2e3f --- /dev/null +++ b/src/os_regex/examples/run.sh @@ -0,0 +1,10 @@ +make +perl ./validate.pl "./match" tests/true.tests FALSE +perl ./validate.pl "./match" tests/false.tests TRUE +perl ./validate.pl "./newmatch" tests/true.tests FALSE +perl ./validate.pl "./newmatch" tests/false.tests TRUE +perl ./validate.pl "./regex" tests/true.tests FALSE +perl ./validate.pl "./regex" tests/false.tests TRUE +perl ./validate.pl "./regex" tests/true.regex FALSE +perl ./validate.pl "./regex" tests/false.regex TRUE +perl ./validate.pl "./regex_str" tests/str.regex FALSE diff --git a/src/os_regex/examples/tests/false.regex b/src/os_regex/examples/tests/false.regex new file mode 100755 index 0000000..a963632 --- /dev/null +++ b/src/os_regex/examples/tests/false.regex @@ -0,0 +1,8 @@ +"\w+\s+\w+\d+\s\$" "a aa11 " +"^\s+\s l" " lala" +"test123test\d+" "test123test" +"test123test\d+\$" "test123test" +"(lalala" "lalala" +"test123(\d)" "test123a" +"\(test)" "test" +"(\w+)(\d+)" "1 1" diff --git a/src/os_regex/examples/tests/false.tests b/src/os_regex/examples/tests/false.tests new file mode 100755 index 0000000..0d9d64c --- /dev/null +++ b/src/os_regex/examples/tests/false.tests @@ -0,0 +1,13 @@ +"abc" "abb" +"^ab" " ab" +"test" "tes" +"abcd" "abc" +"abbb" "abb" +"abbbbbbbb" "abbbbbbb" +"a|b|c| " "def" +"lala$" "lalalalalal" +"^ab$" "abc" +"zzzz$" "zzzzzzzzzzzz " +"^bin$|^shell$" "bina" +"^bin$|^shell$" "shella" +"^bin$|^shell$" "ashell" diff --git a/src/os_regex/examples/tests/str.regex b/src/os_regex/examples/tests/str.regex new file mode 100755 index 0000000..96bba0a --- /dev/null +++ b/src/os_regex/examples/tests/str.regex @@ -0,0 +1,6 @@ +"123(\w+\s+)abc" "123sdf abc" +"123(\w+\s+)abc" "abc123sdf abc" +"123 (\d+.\d.\d.\d\d*\d*)" "123 45.6.5.567" +"from (\S*\d+.\d+.\d+.\d\d*\d*)" "sshd[21576]: Illegal user web14 from ::ffff:212.227.60.55" +"^sshd[\d+]: Accepted \S+ for (\S+) from (\S+) port " "sshd[21405]: Accepted password for root from 192.1.1.1 port 6023" +": \((\S+)@(\S+)\) [" "pure-ftpd: (?@enigma.lab.ossec.net) [INFO] New connection from enigma.lab.ossec.net" diff --git a/src/os_regex/examples/tests/true.regex b/src/os_regex/examples/tests/true.regex new file mode 100755 index 0000000..4981582 --- /dev/null +++ b/src/os_regex/examples/tests/true.regex @@ -0,0 +1,27 @@ +"\s+123" " 123" +"\s*123" "123" +"\s123" " 123" +"\w+\s+\w+" "a 1" +"\w+\d+\w+\s+" "ab12fb12fd12 " +"^\s*\w\s*\w+" "a l a a" +"\w+\s+\w+\d+\s\$" "a aa11 " +"^su\S*: BAD su" "su: BAD SU dcid to root on /dev/ttyp0" +"^su\s*: BAD su" "su: BAD SU dcid to root on /dev/ttyp0" +"^abc\sabc" "abc abcd" +"^abc\s\s*abc" "abc abcd" +"^\s+\sl" " lala" +"^\s*\sl" " lala" +"^\s\s+l" " lala" +"^\s+\s l" " lala" +"^\s*\s lal\w\$" " lala" +"test123test\d+\$" "test123test123" +"^kernel: \S+ \.+ SRC=\S+ DST=\S+ \.+ PROTO=\w+ SPT=\d+ DPT=\d+ " "kernel: IPTABLE IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:00:03:93:db:2e:b4:08:00 SRC=10.4.11.40 DST=255.255.255.255 LEN=180 TOS=0x00 PREC=0x00 TTL=64 ID=4753 PROTO=UDP SPT=49320 DPT=2222 LEN=160" +"test (\w+)la" "test abclala" +"(\w+) (\w+)" "wofl wofl" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:469:3] ICMP PING NMAP [Classification: Attempted Information Leak] [Priority: 2]: {ICMP} 10.4.12.26 -> 10.4.10.231" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:408:5] ICMP Echo Reply [Classification: Misc Activity] [Priority: 3]: {ICMP} 10.4.10.231 -> 10.4.12.26" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:1420:11] SNMP trap tcp [Classification: Attempted Information Leak] [Priority: 2]: {TCP} 10.4.12.26:37020 -> 10.4.10.231:162" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:1420:11] SNMP trap tcp [Classification: Attempted Information Leak] [Priority: 2]: {TCP} 10.4.12.26:37021 -> 10.4.10.231:162" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:590:12] RPC portmap ypserv request UDP [Classification: Decode of an RPC Query] [Priority: 2]: {UDP} 10.4.11.94:669 -> 10.4.3.20:111" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:590:12] RPC portmap ypserv request UDP [Classification: Decode of an RPC Query] [Priority: 2]: {UDP} 10.4.11.94:670 -> 10.4.3.20:111" +"^\S+ [(\d+:\d+:\d+)] \.+ (\d+.\d+.\d+.\d+)\p*\d* -> (\d+.\d+.\d+.\d+)\p*" "snort: [1:1421:11] SNMP AgentX/tcp request [Classification: Attempted Information Leak] [Priority: 2]: {TCP} 10.4.12.26:37020 -> 10.4.10.231:705" diff --git a/src/os_regex/examples/tests/true.tests b/src/os_regex/examples/tests/true.tests new file mode 100755 index 0000000..0bb68d3 --- /dev/null +++ b/src/os_regex/examples/tests/true.tests @@ -0,0 +1,28 @@ +"abc" "abcd" +"abcd" "abcd" +"a" "a" +"a" "aa" +"^a" "ab" +"test" "testa" +"test" "testest" +"lalaila" "lalalalaila" +"abc|cde" "cde" +"^aa|ee|ii|oo|uu" "dfgdsii" +"Abc" "abc" +"ZBE" "zbe" +"ABC" "ABc" +"^A" "a" +"a|E" "abcdef" +"daniel" "daniel" +"DANIeL" "daNIel" +"^abc " "abc " +"ddd|eee|fff|ggg|ggg|hhh|iii" "iii" +"kwo|fe|fw|wfW|edW|dwDF|WdW|dw|d|^la" "la" +"^a" "a" +"^ab$" "ab" +"c$" "c" +"c$" "lalalalac" +"^bin$|^shell$" "bin" +"^bin$|^shell$" "shell" +"^bin$|^shell$|^ftp$" "shell" +"^bin$|^shell$|^ftp$" "ftp" diff --git a/src/os_regex/examples/validate.pl b/src/os_regex/examples/validate.pl new file mode 100755 index 0000000..3a925c6 --- /dev/null +++ b/src/os_regex/examples/validate.pl @@ -0,0 +1,37 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +if(@ARGV < 2) +{ + die "$0 file error_msg\n"; +} + +my ($prog, $file,$msg) = (@ARGV); + +open(FILE,$file) || die "Error opening file: $file\n"; + +if(! -f $prog) +{ + die "File $prog not present\n"; +} + +while() +{ + my $line = $_; + print "running: $prog $line\n"; + my $result = `$prog $line`; + if($result =~ /$msg/) + { + print $result; + print "\t ** $line **\n"; + ; + } + else + { + print $result; + } +} + +# EOF diff --git a/src/os_regex/os_match.c b/src/os_regex/os_match.c new file mode 100755 index 0000000..4de0e75 --- /dev/null +++ b/src/os_regex/os_match.c @@ -0,0 +1,47 @@ +/* $OSSEC, os_regex.c, v0.4, 2006/01/02, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" + + +/** int OS_Match2(char *pattern, char *str) v0.4 + * + * This function is a wrapper around the compile/execute + * functions. It should only be used when the pattern is + * only going to be used once. + * Returns 1 on success or 0 on failure. + */ +int OS_Match2(char *pattern, char *str) +{ + int r_code = 0; + OSMatch reg; + + /* If the compilation failed, we don't need to free anything */ + if(OSMatch_Compile(pattern, ®, 0)) + { + if(OSMatch_Execute(str,strlen(str), ®)) + { + r_code = 1; + } + + OSMatch_FreePattern(®); + } + + return(r_code); +} + + +/* EOF */ diff --git a/src/os_regex/os_match_compile.c b/src/os_regex/os_match_compile.c new file mode 100755 index 0000000..8521b3f --- /dev/null +++ b/src/os_regex/os_match_compile.c @@ -0,0 +1,228 @@ +/* $OSSEC, os_match_compile.c, v0.1, 2006/04/17, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + +/* Prototype fo the _OsMatch */ +int _OS_Match(char *pattern, char *str, int str_len, int size); +int _os_strncmp(char *pattern, char *str, int str_len, int size); +int _os_strcmp_last(char *pattern, char *str, int str_len, int size); +int _os_strcmp(char *pattern, char *str, int str_len, int size); +int _os_strmatch(char *pattern, char *str, int str_len, int size); + + +/** int OSMatch_Compile(char *pattern, OSMatch *reg, int flags) v0.1 + * Compile a pattern to be used later. + * Allowed flags are: + * - OS_CASE_SENSITIVE + * Returns 1 on success or 0 on error. + * The error code is set on reg->error. + */ +int OSMatch_Compile(char *pattern, OSMatch *reg, int flags) +{ + int i = 0; + int count = 0; + int end_of_string = 0; + + char *pt; + char *new_str; + char *new_str_free = NULL; + + + /* Checking for references not initialized */ + if(reg == NULL) + { + return(0); + } + + + /* Initializing OSRegex structure */ + reg->error = 0; + reg->patterns = NULL; + reg->size = NULL; + + + /* The pattern can't be null */ + if(pattern == NULL) + { + reg->error = OS_REGEX_PATTERN_NULL; + goto compile_error; + } + + + /* Maximum size of the pattern */ + if(strlen(pattern) > OS_PATTERN_MAXSIZE) + { + reg->error = OS_REGEX_MAXSIZE; + goto compile_error; + } + + + /* Duping the pattern for our internal work */ + new_str = strdup(pattern); + if(!new_str) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + new_str_free = new_str; + pt = new_str; + + + /* Getting the number of sub patterns */ + while(*pt != '\0') + { + /* The pattern must be always lower case if + * case sensitive is set + */ + if(!(flags & OS_CASE_SENSITIVE)) + { + *pt = charmap[(uchar)*pt]; + } + + /* Number of sub patterns */ + if(*pt == OR) + { + count++; + } + pt++; + } + + + /* For the last pattern */ + count++; + reg->patterns = calloc(count +1, sizeof(char *)); + reg->size = calloc(count +1, sizeof(int)); + reg->match_fp = calloc(count +1, sizeof(void *)); + + + /* Memory allocation error check */ + if(!reg->patterns || !reg->size || !reg->match_fp) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + + + /* Initializing each sub pattern */ + for(i = 0; i<=count; i++) + { + reg->patterns[i] = NULL; + reg->match_fp[i] = NULL; + reg->size[i] = 0; + } + i = 0; + + + /* Reassigning pt to the beginning of the string */ + pt = new_str; + + + /* Getting the sub patterns */ + do + { + if((*pt == OR) || (*pt == '\0')) + { + if(*pt == '\0') + { + end_of_string = 1; + } + + *pt = '\0'; + + /* Dupping the string */ + if(*new_str == BEGINREGEX) + reg->patterns[i] = strdup(new_str +1); + else + reg->patterns[i] = strdup(new_str); + + /* Memory error */ + if(!reg->patterns[i]) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + + + /* If the string has ^ and $ */ + if((*new_str == BEGINREGEX) && (*(pt -1) == ENDREGEX)) + { + reg->match_fp[i] = _os_strcmp; + reg->size[i] = strlen(reg->patterns[i]) -1; + reg->patterns[i][reg->size[i]] = '\0'; + } + else if(strlen(new_str) == 0) + { + reg->match_fp[i] = _os_strmatch; + reg->size[i] = 0; + } + + /* String only has $ */ + else if(*(pt -1) == ENDREGEX) + { + reg->match_fp[i] = _os_strcmp_last; + reg->size[i] = strlen(reg->patterns[i]) -1; + reg->patterns[i][reg->size[i]] = '\0'; + } + + /* If string starts with ^, use strncmp */ + else if(*new_str == BEGINREGEX) + { + reg->match_fp[i] = _os_strncmp; + reg->size[i] = strlen(reg->patterns[i]); + } + else + { + reg->match_fp[i] = _OS_Match; + reg->size[i] = strlen(reg->patterns[i]); + } + + if(end_of_string) + { + break; + } + + new_str = ++pt; + i++; + continue; + } + pt++; + + }while(!end_of_string); + + + /* Success return */ + free(new_str_free); + return(1); + + + /* Error handling */ + compile_error: + + if(new_str_free) + { + free(new_str_free); + } + + OSMatch_FreePattern(reg); + + return(0); +} + + +/* EOF */ diff --git a/src/os_regex/os_match_execute.c b/src/os_regex/os_match_execute.c new file mode 100755 index 0000000..70f3184 --- /dev/null +++ b/src/os_regex/os_match_execute.c @@ -0,0 +1,133 @@ +/* $OSSEC, os_match_execute.c, v0.1, 2006/04/18, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + + +/** Internal matching **/ +int _OS_Match(char *pattern, char *str, int str_len, int size) +{ + int i = 0,j; + char *pt = pattern; + + size = str_len - size; + + /* Look to match the first pattern */ + do + { + /* Match */ + if(charmap[(uchar)str[i]] == *pt) + { + pt++; + j = i+1; + + while(*pt != '\0') + { + if(str[j] == '\0') + return(FALSE); + + else if(*pt != charmap[(uchar)str[j]]) + { + pt = pattern; + goto nnext; + } + j++;pt++; + } + return(TRUE); + nnext: + continue; + } + }while(++i <= size); + + return(FALSE); +} + + +/** Internal matching **/ +int _os_strncmp(char *pattern, char *str, int str_len, int size) +{ + if(strncasecmp(pattern, str, size) == 0) + return(TRUE); + + return(FALSE); +} + +/** Internal matching **/ +int _os_strcmp(char *pattern, char *str, int str_len, int size) +{ + if(strcasecmp(pattern, str) == 0) + return(TRUE); + + return(FALSE); +} + +int _os_strmatch(char *pattern, char *str, int str_len, int size) +{ + return(TRUE); +} + + +/** Internal matching **/ +int _os_strcmp_last(char *pattern, char *str, int str_len, int size) +{ + /* Size of the string must be bigger */ + if((str_len - size) < 0) + return(FALSE); + + if(strcasecmp(pattern, str + (str_len - size)) == 0) + return(TRUE); + + return(FALSE); +} + + +/** int OSMatch_Execute(char *str, int str_len, OSMatch *reg) v0.1 + * Compare an already compiled pattern with + * a not NULL string. + * Returns 1 on success or 0 on error. + * The error code is set on reg->error. + */ +int OSMatch_Execute(char *str, int str_len, OSMatch *reg) +{ + short int i = 0; + + /* The string can't be NULL */ + if(str == NULL) + { + reg->error = OS_REGEX_STR_NULL; + return(0); + } + + + /* Looping on all sub patterns */ + while(reg->patterns[i]) + { + if(reg->match_fp[i](reg->patterns[i], + str, + str_len, + reg->size[i]) == TRUE) + { + return(1); + } + i++; + } + + return(0); +} + + +/* EOF */ diff --git a/src/os_regex/os_match_free_pattern.c b/src/os_regex/os_match_free_pattern.c new file mode 100755 index 0000000..095f8c9 --- /dev/null +++ b/src/os_regex/os_match_free_pattern.c @@ -0,0 +1,52 @@ +/* $OSSEC, os_match_free_pattern.c, v0.1, 2006/04/18, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + + +/** int OSMatch_FreePattern(OSMatch *reg) v0.1 + * Release all the memory created by the compilation/executation + * phases. + * Returns void. + */ +void OSMatch_FreePattern(OSMatch *reg) +{ + /* Freeing the patterns */ + if(reg->patterns) + { + char **pattern = reg->patterns; + while(*pattern) + { + if(*pattern) + free(*pattern); + pattern++; + } + + free(reg->patterns); + free(reg->size); + free(reg->match_fp); + + reg->patterns = NULL; + reg->size = NULL; + reg->match_fp = NULL; + } + + return; +} + + +/* EOF */ diff --git a/src/os_regex/os_regex.c b/src/os_regex/os_regex.c new file mode 100755 index 0000000..2e89fab --- /dev/null +++ b/src/os_regex/os_regex.c @@ -0,0 +1,47 @@ +/* $OSSEC, os_regex.c, v0.4, 2006/01/02, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" + + +/** int OS_Regex(char *pattern, char *str) v0.4 + * + * This function is a wrapper around the compile/execute + * functions. It should only be used when the pattern is + * only going to be used once. + * Returns 1 on success or 0 on failure. + */ +int OS_Regex(char *pattern, char *str) +{ + int r_code = 0; + OSRegex reg; + + /* If the compilation failed, we don't need to free anything */ + if(OSRegex_Compile(pattern, ®, 0)) + { + if(OSRegex_Execute(str, ®)) + { + r_code = 1; + } + + OSRegex_FreePattern(®); + } + + return(r_code); +} + + +/* EOF */ diff --git a/src/os_regex/os_regex.h b/src/os_regex/os_regex.h new file mode 100755 index 0000000..71e17af --- /dev/null +++ b/src/os_regex/os_regex.h @@ -0,0 +1,189 @@ +/* $OSSEC, os_regex.h, v0.3, 2005/04/05, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* See README for details */ + + +#ifndef __OS_REGEX_H +#define __OS_REGEX_H + + +/* OSRegex_Compile flags */ +#define OS_RETURN_SUBSTRING 0000200 +#define OS_CASE_SENSITIVE 0000400 + + +/* Pattern maximum size */ +#define OS_PATTERN_MAXSIZE 2048 + + +/* Error codes */ +#define OS_REGEX_REG_NULL 1 +#define OS_REGEX_PATTERN_NULL 2 +#define OS_REGEX_MAXSIZE 3 +#define OS_REGEX_OUTOFMEMORY 4 +#define OS_REGEX_STR_NULL 5 +#define OS_REGEX_BADREGEX 6 +#define OS_REGEX_BADPARENTHESIS 7 +#define OS_REGEX_NO_MATCH 8 + + +/* OSRegex structure */ +typedef struct _OSRegex +{ + int error; + int *flags; + char **patterns; + char **sub_strings; + char ***prts_closure; + char ***prts_str; +}OSRegex; + + +/* OSmatch structure */ +typedef struct _OSMatch +{ + int error; + int *size; + char **patterns; + int (**match_fp)(char *str, char *str2, int str_len, int size); +}OSMatch; + + +/*** Prototypes ***/ + + +/** int OSRegex_Compile(char *pattern, OSRegex *reg, int flags) v0.1 + * Compile a regular expression to be used later. + * Allowed flags are: + * - OS_CASE_SENSITIVE + * - OS_RETURN_SUBSTRING + * Returns 1 on success or 0 on error. + * The error code is set on reg->error. + */ +int OSRegex_Compile(char *pattern, OSRegex *reg, int flags); + + +/** char *OSRegex_Execute(char *str, OSRegex *reg) v0.1 + * Compare an already compiled regular expression with + * a not NULL string. + * Returns end of str on success or NULL on error. + * The error code is set on reg->error. + */ +char *OSRegex_Execute(char *str, OSRegex *reg); + + +/** int OSRegex_FreePattern(SRegex *reg) v0.1 + * Release all the memory created by the compilation/executation + * phases. + * Returns void. + */ +void OSRegex_FreePattern(OSRegex *reg); + + +/** int OSRegex_FreeSubStrings(OSRegex *reg) v0.1 + * Release all the memory created to store the sub strings. + * Returns void. + */ +void OSRegex_FreeSubStrings(OSRegex *reg); + + +/** int OS_Regex(char *pattern, char *str) v0.4 + * This function is a wrapper around the compile/execute + * functions. It should only be used when the pattern is + * only going to be used once. + * Returns 1 on success or 0 on failure. + */ +int OS_Regex(char *pattern, char *str); + + + +/** int OSMatch_Compile(char *pattern, OSMatch *reg, int flags) v0.1 + * Compile a pattern to be used later. + * Allowed flags are: + * - OS_CASE_SENSITIVE + * Returns 1 on success or 0 on error. + * The error code is set on reg->error. + */ +int OSMatch_Compile(char *pattern, OSMatch *reg, int flags); + + +/** int OSMatch_Execute(char *str, int str_len, OSMatch *reg) v0.1 + * Compare an already compiled pattern with + * a not NULL string. + * Returns 1 on success or 0 on error. + * The error code is set on reg->error. + */ +int OSMatch_Execute(char *str, int str_len, OSMatch *reg); + + +/** int OSMatch_FreePattern(OSMatch *reg) v0.1 + * Release all the memory created by the compilation/executation + * phases. + * Returns void. + */ +void OSMatch_FreePattern(OSMatch *reg); + + +int OS_Match2(char *pattern, char *str); + + +/* OS_WordMatch v0.3: + * Searches for pattern in the string + */ +int OS_WordMatch(char *pattern, char *str); +#define OS_Match OS_WordMatch + + +/** char **OS_StrBreak(char match, char *str, int size) v0.2 + * Split a string into multiples pieces, divided by a char "match". + * Returns a NULL terminated array on success or NULL on error. + */ +char **OS_StrBreak(char match, char *str, int size); + + +/** int OS_StrHowClosedMatch(char *str1, char *str2) v0.1 + * Returns the number of characters that both strings + * have in similar (start at the beginning of them). + */ +int OS_StrHowClosedMatch(char *str1, char *str2); + + +/** Inline prototypes **/ + + +/** int OS_StrStartsWith(char *str, char *pattern) v0.1 + * Verifies if a string starts with the provided pattern. + * Returns 1 on success or 0 on failure. + */ +#include +#define startswith(x,y) (strncmp(x,y,strlen(y)) == 0?1:0) +#define OS_StrStartsWith startswith + + +/** int OS_StrIsNum(char *str) v0.1 + * Checks if a specific string is numeric (like "129544") + */ +int OS_StrIsNum(char *str); + + +/** int isValidChar(char c) + * Checks if a specified char is in the following range: + * a-z, A-Z, 0-9, _-. + */ +#include "os_regex_maps.h" +#define isValidChar(x) (hostname_map[(unsigned char)x]) + + +#endif + + +/* EOF */ diff --git a/src/os_regex/os_regex_compile.c b/src/os_regex/os_regex_compile.c new file mode 100755 index 0000000..c5f1ea5 --- /dev/null +++ b/src/os_regex/os_regex_compile.c @@ -0,0 +1,374 @@ +/* $OSSEC, os_regex_compile.c, v0.1, 2006/01/02, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + + +/** int OSRegex_Compile(char *pattern, OSRegex *reg, int flags) v0.1 + * Compile a regular expression to be used later. + * Allowed flags are: + * - OS_CASE_SENSITIVE + * - OS_RETURN_SUBSTRING + * Returns 1 on success or 0 on error. + * The error code is set on reg->error. + */ +int OSRegex_Compile(char *pattern, OSRegex *reg, int flags) +{ + int i = 0; + int count = 0; + int end_of_string = 0; + int parenthesis = 0; + int prts_size = 0; + int max_prts_size = 0; + + char *pt; + char *new_str; + char *new_str_free = NULL; + + + /* Checking for references not initialized */ + if(reg == NULL) + { + return(0); + } + + + /* Initializing OSRegex structure */ + reg->error = 0; + reg->patterns = NULL; + reg->flags = NULL; + reg->prts_closure = NULL; + reg->prts_str = NULL; + reg->sub_strings = NULL; + + + + /* The pattern can't be null */ + if(pattern == NULL) + { + reg->error = OS_REGEX_PATTERN_NULL; + goto compile_error; + } + + /* Maximum size of the pattern */ + if(strlen(pattern) > OS_PATTERN_MAXSIZE) + { + reg->error = OS_REGEX_MAXSIZE; + goto compile_error; + } + + + /* Duping the pattern for our internal work */ + new_str = strdup(pattern); + if(!new_str) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + new_str_free = new_str; + pt = new_str; + + + /* Getting the number of sub patterns */ + do + { + if(*pt == BACKSLASH) + { + pt++; + if(!((*pt == 'w') || + (*pt == 'W') || + (*pt == 's') || + (*pt == 'S') || + (*pt == 'd') || + (*pt == 'D') || + (*pt == '.') || + (*pt == '(') || + (*pt == ')') || + (*pt == 'p') || + (*pt == 't') || + (*pt == '$') || + (*pt == '|') || + (*pt == '<') || + (*pt == '\\'))) + { + reg->error = OS_REGEX_BADREGEX; + goto compile_error; + } + + /* Giving the new values for each regex */ + switch(*pt) + { + case 'd': *pt = 1;break; + case 'w': *pt = 2;break; + case 's': *pt = 3;break; + case 'p': *pt = 4;break; + case '(': *pt = 5;break; + case ')': *pt = 6;break; + case '\\':*pt = 7;break; + case 'D': *pt = 8;break; + case 'W': *pt = 9;break; + case 'S': *pt = 10;break; + case '.': *pt = 11;break; + case 't': *pt = 12;break; + case '$': *pt = 13;break; + case '|': *pt = 14;break; + case '<': *pt = 15;break; + } + pt++; + + continue; + } + else if(*pt == '(') + { + parenthesis++; + } + else if(*pt == ')') + { + /* Internally, open and closed are the same */ + *pt = '('; + parenthesis--; + prts_size++; + } + + /* We only allow one level of parenthesis */ + if(parenthesis != 0 && parenthesis != 1) + { + reg->error = OS_REGEX_BADPARENTHESIS; + goto compile_error; + } + + /* The pattern must be always lower case if + * case sensitive is set + */ + if(!(flags & OS_CASE_SENSITIVE)) + { + *pt = charmap[(uchar)*pt]; + } + + if(*pt == OR) + { + /* Each sub pattern must be closed on parenthesis */ + if(parenthesis != 0) + { + reg->error = OS_REGEX_BADPARENTHESIS; + goto compile_error; + } + count++; + } + pt++; + }while(*pt != '\0'); + + + /* After the whole pattern is read, the parenthesis must all be closed */ + if(parenthesis != 0) + { + reg->error = OS_REGEX_BADPARENTHESIS; + goto compile_error; + } + + + /* Allocating the memory for the sub patterns */ + count++; + reg->patterns = calloc(count +1, sizeof(char *)); + reg->flags = calloc(count +1, sizeof(int)); + + + /* For the substrings */ + if((prts_size > 0) && (flags & OS_RETURN_SUBSTRING)) + { + reg->prts_closure = calloc(count +1, sizeof(char **)); + reg->prts_str = calloc(count +1, sizeof(char **)); + if(!reg->prts_closure || !reg->prts_str) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + } + + + /* Memory allocation error check */ + if(!reg->patterns || !reg->flags) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + + /* Initializing each sub pattern */ + for(i = 0; i<=count; i++) + { + reg->patterns[i] = NULL; + reg->flags[i] = 0; + + /* The parenthesis closure if set */ + if(reg->prts_closure) + { + reg->prts_closure[i] = NULL; + reg->prts_str[i] = NULL; + } + } + i = 0; + + + /* Reassigning pt to the beginning of the string */ + pt = new_str; + + + /* Getting the sub patterns */ + do + { + if((*pt == OR) || (*pt == '\0')) + { + if(*pt == '\0') + { + end_of_string = 1; + } + + *pt = '\0'; + + /* If string starts with ^, set the BEGIN SET flag */ + if(*new_str == BEGINREGEX) + { + new_str++; + reg->flags[i]|=BEGIN_SET; + } + + /* If string ends with $, set the END_SET flag */ + if(*(pt-1) == ENDREGEX) + { + *(pt-1) = '\0'; + reg->flags[i]|=END_SET; + } + + reg->patterns[i] = strdup(new_str); + + if(!reg->patterns[i]) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + + } + + + /* Setting the parenthesis closures */ + /* The parenthesis closure if set */ + if(reg->prts_closure) + { + int tmp_int = 0; + char *tmp_str; + + + /* search the whole pattern for parenthesis */ + prts_size = 0; + + /* First loop we get the number of parenthesis. + * We allocate the memory and loop again setting + * the parenthesis closures. + */ + tmp_str = reg->patterns[i]; + while(*tmp_str != '\0') + { + if(prts(*tmp_str)) + { + prts_size++; + } + tmp_str++; + } + + /* Getting the maximum number of parenthesis for + * all sub strings. We need that to set up the maximum + * number of substrings to be returned. + */ + if(max_prts_size < prts_size) + { + max_prts_size = prts_size; + } + + /* Allocating the memory */ + reg->prts_closure[i] = calloc(prts_size + 1, sizeof(char *)); + reg->prts_str[i] = calloc(prts_size + 1, sizeof(char *)); + if((reg->prts_closure[i] == NULL)||(reg->prts_str[i] == NULL)) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + + /* Next loop to set the closures */ + tmp_str = reg->patterns[i]; + while(*tmp_str != '\0') + { + if(prts(*tmp_str)) + { + if(tmp_int >= prts_size) + { + reg->error = OS_REGEX_BADPARENTHESIS; + goto compile_error; + } + + /* Setting to the pointer to the string */ + reg->prts_closure[i][tmp_int] = tmp_str; + reg->prts_str[i][tmp_int] = NULL; + + tmp_int++; + } + + tmp_str++; + } + } + + + if(end_of_string) + { + break; + } + + new_str = ++pt; + i++; + continue; + } + pt++; + + }while(!end_of_string); + + /* Allocating sub string for the maximum number of parenthesis */ + reg->sub_strings = calloc(max_prts_size + 1, sizeof(char *)); + if(reg->sub_strings == NULL) + { + reg->error = OS_REGEX_OUTOFMEMORY; + goto compile_error; + } + + /* Success return */ + free(new_str_free); + return(1); + + + /* Error handling */ + compile_error: + + if(new_str_free) + { + free(new_str_free); + } + + OSRegex_FreePattern(reg); + + return(0); +} + + +/* EOF */ diff --git a/src/os_regex/os_regex_execute.c b/src/os_regex/os_regex_execute.c new file mode 100755 index 0000000..0839493 --- /dev/null +++ b/src/os_regex/os_regex_execute.c @@ -0,0 +1,497 @@ +/* $OSSEC, os_regex.c, v0.3, 2005/04/05, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + + +/** Internal prototypes **/ +char *_OS_Regex(char *pattern, char *str, char **prts_closure, + char **prts_str, int flags); + + + +/** char *OSRegex_Execute(char *str, OSRegex *reg) v0.1 + * Compare an already compiled regular expression with + * a not NULL string. + * Returns the end of the string on success or NULL on error. + * The error code is set on reg->error. + */ +char *OSRegex_Execute(char *str, OSRegex *reg) +{ + char *ret; + int i = 0; + + /* The string can't be NULL */ + if(str == NULL) + { + reg->error = OS_REGEX_STR_NULL; + return(0); + } + + + /* If we need the sub strings */ + if(reg->prts_closure) + { + int j = 0, k = 0, str_char = 0; + + /* Looping on all sub patterns */ + while(reg->patterns[i]) + { + /* Cleaning the prts_str */ + while(reg->prts_closure[i][j]) + { + reg->prts_str[i][j] = NULL; + j++; + } + + if((ret = _OS_Regex(reg->patterns[i], str, reg->prts_closure[i], + reg->prts_str[i], reg->flags[i]))) + { + j = 0; + + /* We must always have the open and the close */ + while(reg->prts_str[i][j] && reg->prts_str[i][j+1]) + { + str_char = reg->prts_str[i][j+1][0]; + + reg->prts_str[i][j+1][0] = '\0'; + + reg->sub_strings[k] = strdup(reg->prts_str[i][j]); + if(!reg->sub_strings[k]) + { + OSRegex_FreeSubStrings(reg); + return(NULL); + } + + /* Set the next one to null */ + reg->prts_str[i][j+1][0] = str_char; + k++; + reg->sub_strings[k] = NULL; + + /* Go two by two */ + j+=2; + } + + return(ret); + } + i++; + } + + return(0); + + } + + /* If we don't need the sub strings */ + + /* Looping on all sub patterns */ + while(reg->patterns[i]) + { + if((ret = _OS_Regex(reg->patterns[i], str, NULL, NULL, reg->flags[i]))) + { + return(ret); + } + i++; + } + + return(NULL); +} + +#define PRTS(x) ((prts(*x) && x++) || 1) +#define ENDOFFILE(x) ( PRTS(x) && (*x == '\0')) + +/** int _OS_Regex(char *pattern, char *str, char **prts_closure, + char **prts_str, int flags) v0.1 + * Perform the pattern matching on the pattern/string provided. + * Returns 1 on success and 0 on failure. + * If prts_closure is set, the parenthesis locations will be + * written on prts_str (which must not be NULL) + */ +char *_OS_Regex(char *pattern, char *str, char **prts_closure, + char **prts_str, int flags) +{ + char *r_code = NULL; + + int ok_here; + int _regex_matched = 0; + + int prts_int; + + char *st = str; + char *st_error = NULL; + + char *pt = pattern; + char *next_pt; + + char *pt_error[4] = {NULL, NULL, NULL, NULL}; + char *pt_error_str[4]; + + + /* Will loop the whole string, trying to find a match */ + do + { + switch(*pt) + { + case '\0': + if(!(flags & END_SET) || (flags & END_SET && (*st == '\0'))) + return(r_code); + break; + + /* If it is a parenthesis do not match against the character */ + case '(': + /* Find the closure for the parenthesis */ + if(prts_closure) + { + prts_int = 0; + while(prts_closure[prts_int]) + { + if(prts_closure[prts_int] == pt) + { + prts_str[prts_int] = st; + break; + } + prts_int++; + } + } + + pt++; + if(*pt == '\0') + { + if(!(flags & END_SET) || (flags & END_SET && (*st == '\0'))) + return(r_code); + } + break; + } + + /* If it starts on Backslash (future regex) */ + if(*pt == BACKSLASH) + { + if(Regex((uchar)*(pt+1), (uchar)*st)) + { + next_pt = pt+2; + + /* If we don't have a '+' or '*', we should skip + * searching using this pattern. + */ + if(!isPlus(*next_pt)) + { + pt = next_pt; + if(!st_error) + { + /* If st_error is not set, we need to set it here. + * In case of error in the matching later, we need + * to continue from here (it will be incremented in + * the while loop) + */ + st_error = st; + } + r_code = st; + continue; + } + + /* If it is a '*', we need to set the _regex_matched + * for the first pattern even. + */ + if(*next_pt == '*') + { + _regex_matched = 1; + } + + + /* If our regex matches and we have a "+" set, we will + * try the next one to see if it matches. If yes, we + * can jump to it, but saving our currently location + * in case of error. + * _regex_matched will set set to true after the first + * round of matches + */ + if(_regex_matched) + { + next_pt++; + ok_here = -1; + + /* If it is a parenthesis, jump to the next and write + * the location down if 'ok_here >= 0' + */ + if(prts(*next_pt)) + { + next_pt++; + } + + if(*next_pt == '\0') + { + ok_here = 1; + } + else if(*next_pt == BACKSLASH) + { + if(Regex((uchar)*(next_pt+1), (uchar)*st)) + { + /* If the next one does not have + * a '+' or '*', we can set it as + * being read and continue. + */ + if(!isPlus(*(next_pt+2))) + { + ok_here = 2; + } + else + { + ok_here = 0; + } + } + } + else if(*next_pt == charmap[(uchar)*st]) + { + _regex_matched = 0; + ok_here = 1; + } + + /* If the next character matches in here */ + if(ok_here >= 0) + { + if(prts_closure && prts(*(next_pt - 1))) + { + prts_int = 0; + while(prts_closure[prts_int]) + { + if(prts_closure[prts_int] == (next_pt -1)) + { + if(*(st+1) == '\0') + prts_str[prts_int] = st+1; + else + prts_str[prts_int] = st; + break; + } + prts_int++; + } + } + + + /* If next_pt == \0, return the r_code */ + if(*next_pt == '\0') + { + continue; + } + + + /* Each "if" will increment the amount + * necessary for the next pattern in ok_here + */ + if(ok_here) + next_pt+=ok_here; + + + if(!pt_error[0]) + { + pt_error[0] = pt; + pt_error_str[0] = st; + } + else if(!pt_error[1]) + { + pt_error[1] = pt; + pt_error_str[1] = st; + } + else if(!pt_error[2]) + { + pt_error[2] = pt; + pt_error_str[2] = st; + + } + else if(!pt_error[3]) + { + pt_error[3] = pt; + pt_error_str[3] = st; + } + + pt = next_pt; + } + } + else + { + next_pt++; + + /* If it is a parenthesis, mark the location */ + if(prts_closure && prts(*next_pt)) + { + prts_int = 0; + while(prts_closure[prts_int]) + { + if(prts_closure[prts_int] == next_pt) + { + if(*(st+1) == '\0') + prts_str[prts_int] = st +1; + else + prts_str[prts_int] = st; + break; + } + prts_int++; + } + next_pt++; + } + + _regex_matched = 1; + } + + r_code = st; + continue; + } + + else if((*(pt+3) == '\0') && (_regex_matched == 1)&&(r_code)) + { + r_code = st; + if(!(flags & END_SET) || (flags & END_SET && (*st == '\0'))) + return(r_code); + } + + /* If we didn't match regex, but _regex_matched == 1, jump + * to the next available pattern + */ + else if((*(pt+2) == '+') && (_regex_matched == 1)) + { + pt+=3; + st--; + _regex_matched = 0; + continue; + } + /* We may not match with '*' */ + else if(*(pt+2) == '*') + { + pt+=3; + st--; + r_code = st; + _regex_matched = 0; + continue; + } + + _regex_matched = 0; + } + else if(*pt == charmap[(uchar)*st]) + { + pt++; + if(!st_error) + { + /* If st_error is not set, we need to set it here. + * In case of error in the matching later, we need + * to continue from here (it will be incremented in + * the while loop) + */ + st_error = st; + } + r_code = st; + continue; + } + + /* Error Handling */ + if(pt_error[3]) + { + pt = pt_error[3]; + st = pt_error_str[3]; + pt_error[3] = NULL; + continue; + } + else if(pt_error[2]) + { + pt = pt_error[2]; + st = pt_error_str[2]; + pt_error[2] = NULL; + continue; + } + else if(pt_error[1]) + { + pt = pt_error[1]; + st = pt_error_str[1]; + pt_error[1] = NULL; + continue; + } + else if(pt_error[0]) + { + pt = pt_error[0]; + st = pt_error_str[0]; + pt_error[0] = NULL; + continue; + } + else if(flags & BEGIN_SET) + { + /* If we get an error and the "^" option is + * set, we can return "not matched" in here. + */ + return(NULL); + } + else if(st_error) + { + st = st_error; + st_error = NULL; + } + pt = pattern; + r_code = NULL; + + }while(*(++st) != '\0'); + + + /* Matching for a possible last parenthesis */ + if(prts_closure) + { + while(!prts(*pt) && *pt != '\0') + { + if(*pt == BACKSLASH && *(pt+2) == '*') + pt+=3; + else + break; + } + + if(prts(*pt)) + { + prts_int = 0; + while(prts_closure[prts_int]) + { + if(prts_closure[prts_int] == pt) + { + prts_str[prts_int] = st; + break; + } + prts_int++; + } + } + } + + /* Cleaning up */ + if(ENDOFFILE(pt) || + (*pt == BACKSLASH && + _regex_matched && + (pt+=2) && + isPlus(*pt) && + (pt++) && + ((ENDOFFILE(pt)) || + ((*pt == BACKSLASH) && + (pt+=2) && + (*pt == '*') && + (pt++) && + (ENDOFFILE(pt)) ))) || + (*pt == BACKSLASH && + (pt+=2) && + (*pt == '*') && + (pt++) && + ENDOFFILE(pt)) + ) + { + return(r_code); + } + + return(NULL); +} + + +/* EOF */ diff --git a/src/os_regex/os_regex_free_pattern.c b/src/os_regex/os_regex_free_pattern.c new file mode 100755 index 0000000..2cfa00e --- /dev/null +++ b/src/os_regex/os_regex_free_pattern.c @@ -0,0 +1,86 @@ +/* $OSSEC, os_regex_free_pattern.c, v0.1, 2006/01/02, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + + +/** int OSRegex_FreePattern(SRegex *reg) v0.1 + * Release all the memory created by the compilation/executation + * phases. + * Returns void. + */ +void OSRegex_FreePattern(OSRegex *reg) +{ + int i = 0; + + /* Freeing the patterns */ + if(reg->patterns) + { + char **pattern = reg->patterns; + while(*pattern) + { + if(*pattern) + free(*pattern); + pattern++; + } + + free(reg->patterns); + free(reg->flags); + + reg->patterns = NULL; + reg->flags = NULL; + } + + /* Freeing the closure */ + if(reg->prts_closure) + { + i = 0; + while(reg->prts_closure[i]) + { + free(reg->prts_closure[i]); + i++; + } + free(reg->prts_closure); + reg->prts_closure = NULL; + } + + /* Freeing the str */ + if(reg->prts_str) + { + i = 0; + while(reg->prts_str[i]) + { + free(reg->prts_str[i]); + i++; + } + free(reg->prts_str); + reg->prts_str = NULL; + } + + /* Freeing the sub strings */ + if(reg->sub_strings) + { + OSRegex_FreeSubStrings(reg); + free(reg->sub_strings); + reg->sub_strings = NULL; + } + + return; +} + + +/* EOF */ diff --git a/src/os_regex/os_regex_free_substrings.c b/src/os_regex/os_regex_free_substrings.c new file mode 100755 index 0000000..e2cfcd2 --- /dev/null +++ b/src/os_regex/os_regex_free_substrings.c @@ -0,0 +1,43 @@ +/* $OSSEC, os_regex_free_substrings.c, v0.1, 2006/01/02, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include + +#include "os_regex.h" +#include "os_regex_internal.h" + + +/** int OSRegex_FreeSubStrings(OSRegex *reg) v0.1 + * Release all the memory created to store the sub strings. + * Returns void. + */ +void OSRegex_FreeSubStrings(OSRegex *reg) +{ + int i = 0; + + /* Freeing the sub strings */ + if(reg->sub_strings) + { + while(reg->sub_strings[i]) + { + free(reg->sub_strings[i]); + reg->sub_strings[i] = NULL; + i++; + } + } + return; +} + + +/* EOF */ diff --git a/src/os_regex/os_regex_internal.h b/src/os_regex/os_regex_internal.h new file mode 100755 index 0000000..0186950 --- /dev/null +++ b/src/os_regex/os_regex_internal.h @@ -0,0 +1,710 @@ +/* $OSSEC, os_regex_internal.h, v0.3, 2005/04/05, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + */ + + +#ifndef __OS_INTERNAL_H +#define __OS_INTERNAL_H + + +/* + * Defining some caracters to be used. +*/ +#define BACKSLASH '\\' +#define ENDSTR '\0' +#define ENDLINE '\n' +#define BEGINREGEX '^' +#define ENDREGEX '$' +#define OR '|' +#define AND '&' + +#define TRUE 1 +#define FALSE 0 + + +/* Pattern flags */ +#define BEGIN_SET 0000200 +#define END_SET 0000400 + + +/* uchar */ +typedef unsigned char uchar; + + +/* _IsD Returns 1 if it is a number */ +#define _IsD(x) ((x >= 48) && (x <= 57)) + + +/* Is it a character ? + * a-z or A-Z or 0-9 + * Returns 1 if true + */ +#define _IsW(x) ((x >= 48 && x <= 57 )|| \ + (x >= 65 && x <= 90 )|| \ + (x >= 97 && x <= 122)) + + +/* Is it a ' ' (blank) + * Ascii 32 + * Returns 1 if true + */ +#define _IsS(x) (x == 32) + + +/* Check for parenthesis */ +#define prts(x) (x == '(') + + +/* Is it '+' or '*' + * Returns 1 on success + */ +#define isPlus(x) ((x == '+') || (x == '*')) + + +/* True char */ +#define TRUECHAR 1 + + +/* Is "y" a valid "x"?. + * Returns 1 on success + */ +#define Regex(x,y) (regexmap[x][y] == TRUECHAR) +#define Regex2(x,y) (x == 'd' && y >= 48 && y <= 57)|| \ + (x == 's' && y == 32)|| \ + ((x == 'p') && \ + ((y >= 40 && y <= 46)|| \ + (y >= 58 && y <= 63)))|| \ + ((x == 'w') && \ + ((y == '_')|| \ + (y >= 48 && y <= 57)|| \ + (y >= 65 && y <= 90)|| \ + (y >= 97 && y <= 122)))|| \ + (x == '.')|| \ + ((x == '\\') && (y == '\\'))|| \ + ((x == 'n') && (y == '\n'))|| \ + (x == 'S' && y != 32)|| \ + (x == 'D' && (y < 48 || y > 57))|| \ + (x == 'W' && (y < 48 || y > 122 || \ + (y > 57 && y <65)||(y > 90 && y< 97))) + + +/* Charmap for case insensitive search */ +static const uchar charmap[] = { + '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }; + + + +/* Regex mapping + * 0 = none + * 1 = \d + * 2 = \w + * 3 = \s + * 4 = \p + * 5 = \( + * 6 = \) + * 7 = \\ + * 8 = \D + * 9 = \W + * 10 = \S + * 11 = \. + * 12 = \t + * 13 = \$ + * 14 = | + * 15 = < + */ +static const uchar regexmap[][256] = +{ + { + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\000', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + { + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\000', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\001', '\056', '\057', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\072', '\073', '\074', '\075', '\076', '\077', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\133', '\134', '\135', '\136', '\001', + '\140', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + }, + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\001', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\001', '\001', '\001', '\001', '\001', '\001', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\001', '\000', '\001', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + { + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\001', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + }, + { + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\001', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + }, + { + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\001', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + }, + { + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + }, + { + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\001', '\001', '\001', '\001', '\000', + '\001', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', + '\000', '\000', '\000', '\001', '\001', '\001', '\001', '\000', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + }, + { + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\000', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + }, + { + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + }, + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\001', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\012', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\001', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\012', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\001', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + + + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\012', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\001', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', + }, + + +}; + + +#endif + + +/* EOF */ diff --git a/src/os_regex/os_regex_maps.h b/src/os_regex/os_regex_maps.h new file mode 100644 index 0000000..117332d --- /dev/null +++ b/src/os_regex/os_regex_maps.h @@ -0,0 +1,61 @@ +/* @(#) $Id: os_regex_maps.h,v 1.6 2009/06/24 17:06:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + */ + + +#ifndef __OS_REGEX_MAPS_H +#define __OS_REGEX_MAPS_H + + + +/* Hostname charmap. + * Available chars: a-z, A-Z, 0-9, -, _, ., @ / + */ +static const unsigned char hostname_map[] = + { + '\000', '\000', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\001', '\001', '\052', '\053', '\054', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\072', '\073', '\074', '\075', '\076', '\077', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\133', '\134', '\135', '\136', '\001', + '\140', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\001', '\001', '\001', '\001', '\001', + '\001', '\001', '\001', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + }; + + +#endif + + +/* EOF */ diff --git a/src/os_regex/os_regex_match.c b/src/os_regex/os_regex_match.c new file mode 100755 index 0000000..8094133 --- /dev/null +++ b/src/os_regex/os_regex_match.c @@ -0,0 +1,135 @@ +/* $OSSEC, os_regex_match.c, v0.3, 2005/06/09, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include +#include "os_regex_internal.h" + +/* Algorithm: + * Go as faster as you can :) + * + * Supports: + * '|' to separate multiple OR patterns + * '^' to match the begining of a string + */ + + +/** Prototypes **/ +int _InternalMatch(char *pattern, char *str,int count); + + +/* OS_WordMatch v0.3: + * Searches for pattern in the string + */ +int OS_WordMatch(char *pattern, char *str) +{ + int count = 0; + + if(*pattern == '\0') + return(FALSE); + + do + { + if(pattern[count] == '|') + { + /* If we match '|' , search with + * we have so far. + */ + if(_InternalMatch(pattern, str, count)) + { + return(TRUE); + } + else + { + pattern += count+1; + count = 0; + continue; + } + } + + count++; + + }while(pattern[count] != '\0'); + + /* Last check until end of string */ + return(_InternalMatch(pattern, str,count)); +} + +/* Internal match function */ +int _InternalMatch(char *pattern, char *str, int pattern_size) +{ + uchar *pt = (uchar *)pattern; + uchar *st = (uchar *)str; + + uchar last_char = pattern[pattern_size]; + + + /* Return true for some odd expressions */ + if(*pattern == '\0') + return(TRUE); + + + /* If '^' specified, just do a strncasecmp */ + else if(*pattern == '^') + { + pattern++; + pattern_size --; + + /* Compare two string */ + if(strncasecmp(pattern,str,pattern_size) == 0) + return(TRUE); + return(FALSE); + } + + + /* Null line */ + else if(*st == '\0') + return(FALSE); + + + /* Look to match the first pattern */ + do + { + /* Match */ + if(charmap[*st] == charmap[*pt]) + { + str = (char *)st++; + pt++; + + while(*pt != last_char) + { + if(*st == '\0') + return(FALSE); + + else if(charmap[*pt] != charmap[*st]) + goto error; + + st++;pt++; + } + + /* Return here if pt == last_char */ + return(TRUE); + + error: + st = (uchar *)str; + pt = (uchar *)pattern; + + } + + st++; + }while(*st != '\0'); + + return(FALSE); +} +/* EOF */ diff --git a/src/os_regex/os_regex_str.c b/src/os_regex/os_regex_str.c new file mode 100755 index 0000000..13b46ca --- /dev/null +++ b/src/os_regex/os_regex_str.c @@ -0,0 +1,74 @@ +/* $OSSEC, os_regex_str.c, v0.1, 2005/12/29, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include "os_regex_internal.h" + + +/** int OS_StrIsNum(char *str) v0.1 + * Checks if a specific string is numeric (like "129544") + */ +int OS_StrIsNum(char *str) +{ + if(str == NULL) + return(FALSE); + + while(*str != '\0') + { + if(!_IsD(*str)) + return(FALSE); /* 0 */ + str++; + } + + return(TRUE); +} + + +/** int OS_StrHowClosedMatch(char *str1, char *str2) v0.1 + * Returns the number of characters that both strings + * have in similar. + */ +int OS_StrHowClosedMatch(char *str1, char *str2) +{ + int count = 0; + + /* They don't match if any of them is null */ + if(!str1 || !str2) + { + return(0); + } + + do + { + if(str1[count] != str2[count]) + { + break; + } + + count++; + }while((str1[count] != '\0') && (str2[count] != '\0')); + + return(count); +} + + + +/** int OS_StrStartsWith(char *str, char *pattern) v0.1 + * Verifies if a string starts with the provided pattern. + * Returns 1 on success or 0 on failure. + */ +#define startswith(x,y) (strncmp(x,y,strlen(y)) == 0?1:0) +#define OS_StrStartsWith startswith + +/* EOF */ diff --git a/src/os_regex/os_regex_strbreak.c b/src/os_regex/os_regex_strbreak.c new file mode 100755 index 0000000..e8a4228 --- /dev/null +++ b/src/os_regex/os_regex_strbreak.c @@ -0,0 +1,120 @@ +/* $OSSEC, os_regex_strbreak.c, v0.3, 2005/04/05, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include "os_regex_internal.h" + + +/** char **OS_StrBreak(char match, char *str, int size) v0.2 + * Split a string into multiples pieces, divided by a char "match". + * Returns a NULL terminated array on success or NULL on error. + */ +char **OS_StrBreak(char match, char *str, int size) +{ + int count = 0; + int i = 0; + + char *tmp_str = str; + + char **ret; + + /* We can't do anything if str is null or size <= 0 */ + if((str == NULL)||(size <= 0)) + return(NULL); + + ret = (char **)calloc(size+1, sizeof(char *)); + + if(ret == NULL) + { + /* Memory error. Should provice a better way to detect it */ + return(NULL); + } + + /* Allocating memory to null */ + while(i <= size) + { + ret[i] = NULL; + i++; + } + i = 0; + + /* */ + while(*str != '\0') + { + i++; + if((count < size-1)&&(*str == match)) + { + ret[count] = (char *)calloc(i,sizeof(char)); + + if(ret[count] == NULL) + { + goto error; + } + + /* Copying the string */ + ret[count][i-1] = '\0'; + strncpy(ret[count],tmp_str,i-1); + + tmp_str = ++str; + count++; + i=0; + + continue; + } + str++; + } /* leave from here when *str == \0 */ + + + /* Just do it if count < size */ + if(count < size) + { + ret[count] = (char *)calloc(i+1,sizeof(char)); + + if(ret[count] == NULL) + { + goto error; + } + + /* Copying the string */ + ret[count][i] = '\0'; + strncpy(ret[count],tmp_str,i); + + count++; + + /* Making sure it is null terminated */ + ret[count] = NULL; + + return(ret); + } + + /* We shouldn't get to this point + * Just let "error" handle that + */ + + error: + i = 0; + + /* Deallocating the memory whe can */ + while(i < count) + { + free(ret[i]); + i++; + } + + free(ret); + return(NULL); + +} + +/* EOF */ diff --git a/src/os_xml/COPYRIGHT b/src/os_xml/COPYRIGHT new file mode 100755 index 0000000..764fbc6 --- /dev/null +++ b/src/os_xml/COPYRIGHT @@ -0,0 +1,9 @@ +Copyright (C) 2009 Trend Micro Inc. + All rights reserved. + This program is a free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License (version 3) as published by the FSF - Free Software + Foundation + +OSSEC, os_xml library. +Available at http://www.ossec.net diff --git a/src/os_xml/Makefile b/src/os_xml/Makefile new file mode 100755 index 0000000..6edf2c0 --- /dev/null +++ b/src/os_xml/Makefile @@ -0,0 +1,18 @@ +# Makefile for os_xml +# Daniel B. Cid || + +PT = ../ +NAME = os_xml + +include ../Config.Make + +SRCS = os_xml.c os_xml_access.c os_xml_node_access.c os_xml_variables.c os_xml_writer.c +OBJS = os_xml.o os_xml_access.o os_xml_node_access.o os_xml_variables.o os_xml_writer.o + +xml: + $(CC) -DXML_VAR=\"var\" $(CFLAGS) -c $(SRCS) + ar cru os_xml.a ${OBJS} + ranlib os_xml.a + +clean: + ${CLEAN} diff --git a/src/os_xml/README b/src/os_xml/README new file mode 100755 index 0000000..12fc42e --- /dev/null +++ b/src/os_xml/README @@ -0,0 +1,21 @@ +== OSSEC, os_xml "library" == +Copyright (C) 2009 Trend Micro Inc. + +This "library" is a set of very simple functions to read +a XML configuration file. + +It can only read XML, not write. I did not test it on very +complex XML files, so I don't know if it will work. + +Any question, comment or suggestion, please contact me +at dcid@ossec.net or daniel@underlinux.com.br. + +The latest version of this library is available at +http://www.ossec.net/ + +== Examples == + +The file examples/main.c shows some examples (reading example.xml) on +how to use the "os_xml" to read an XML file. Basically, you only need to +start your XML" by calling the ReadXML function (the file as argument) +and use the other supplied functions to read the structure it creates. diff --git a/src/os_xml/VERSION b/src/os_xml/VERSION new file mode 100755 index 0000000..be58634 --- /dev/null +++ b/src/os_xml/VERSION @@ -0,0 +1 @@ +0.3 diff --git a/src/os_xml/examples/mem_test.c b/src/os_xml/examples/mem_test.c new file mode 100755 index 0000000..437eb3d --- /dev/null +++ b/src/os_xml/examples/mem_test.c @@ -0,0 +1,67 @@ +#include +#include +#include + +#include "os_xml.h" + +int main(int argc, char ** argv) +{ + OS_XML xml; + xml_node **node=NULL; + int i = 0; + + if(argc < 2) + { + printf("usage: %s file\n",argv[0]); + return(-1); + } + + while(1) + { + usleep(10); + printf("."); + fflush(stdout); + + if(OS_ReadXML(argv[1],&xml) < 0) + { + printf("Error reading XML!%s\n",xml.err); + return(1); + } + + node = OS_GetElementsbyNode(&xml,NULL); + if(node == NULL) + { + printf("error reading xml\n"); + return(1); + } + + i = 0; + + while(node[i]) + { + xml_node **cnode = NULL; + int j=0; + cnode = OS_GetElementsbyNode(&xml,node[i]); + if(cnode == NULL) + { + i++; + continue; + } + while(cnode[j]) + { + /* */ + j++; + } + + OS_ClearNode(cnode); + i++; + } + + OS_ClearNode(node); + + node = NULL; + + OS_ClearXML(&xml); + } + return(0); +} diff --git a/src/os_xml/examples/test.c b/src/os_xml/examples/test.c new file mode 100755 index 0000000..89369d5 --- /dev/null +++ b/src/os_xml/examples/test.c @@ -0,0 +1,88 @@ +#include +#include +#include + +#include "os_xml.h" + +int main(int argc, char ** argv) +{ + int i = 0; + OS_XML xml; + XML_NODE node = NULL; + + + /* File name must be given */ + if(argc < 2) + { + printf("Usage: %s file\n",argv[0]); + return(-1); + } + + + /* Reading the XML. Printing error and line number */ + if(OS_ReadXML(argv[1],&xml) < 0) + { + printf("OS_ReadXML error: %s, line :%d\n",xml.err, xml.err_line); + return(1); + } + + if(OS_ApplyVariables(&xml) != 0) + { + printf("OS_ReadXML error: Applying variables: %s\n", xml.err); + return(1); + } + + /* Getting all nodes */ + node = OS_GetElementsbyNode(&xml,NULL); + if(node == NULL) + { + printf("OS_GetElementsbyNode error: %s, line: %d\n", xml.err, xml.err_line); + return(1); + } + + i = 0; + + while(node[i]) + { + int j = 0; + XML_NODE cnode; + + cnode = OS_GetElementsbyNode(&xml, node[i]); + if(cnode == NULL) + { + i++; + continue; + } + + while(cnode[j]) + { + printf("Element: %s -> %s\n", + cnode[j]->element, + cnode[j]->content); + if(cnode[j]->attributes && cnode[j]->values) + { + int k = 0; + while(cnode[j]->attributes[k]) + { + printf("attr %s:%s\n", + cnode[j]->attributes[k], + cnode[j]->values[k]); + k++; + } + } + j++; + } + + OS_ClearNode(cnode); + i++; + } + + /* Clearing the nodes */ + OS_ClearNode(node); + + node = NULL; + + OS_ClearXML(&xml); + + return(0); +} diff --git a/src/os_xml/examples/test.xml b/src/os_xml/examples/test.xml new file mode 100755 index 0000000..cc8ed34 --- /dev/null +++ b/src/os_xml/examples/test.xml @@ -0,0 +1,46 @@ +xx +my name is daniel +xx2 +Davi Alves Cid +Liliane Cid + + + + + $lala + + lele + + + + $lala + $lala2 + $lala + PARA $lala2,$lala ola $davi|$lili$lala.$lala OIIIIII + lala-abc + + + + + yes please \< lala + + + + + content1 + content2 + + + + content3lala \< lala\< + content4 + content5 + content51 + content52 + + content6 + + diff --git a/src/os_xml/os_xml.c b/src/os_xml/os_xml.c new file mode 100755 index 0000000..befa457 --- /dev/null +++ b/src/os_xml/os_xml.c @@ -0,0 +1,556 @@ +/* $OSSEC, os_xml.c, v0.3, 2005/02/11, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* os_xml Library. + */ + + + +#include "shared.h" + +#include "os_xml.h" + +#define _R_CONFS '<' +#define _R_CONFE '>' +#define _R_EQUAL '=' +#define _R_COM '!' +#define _R_VAR '$' + +#define OPEN 51 +#define CLOSE 52 + +#define LEOF -2 + +/* Internal functions */ +int _oscomment(FILE *fp); +int _writecontent(char *str, unsigned int size, int parent, OS_XML *_lxml); +int _writememory(char *str, short int type, unsigned int size, + int parent, OS_XML *_lxml); +int _checkmemory(char *str,OS_XML *_lxml); +int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml); +int _getattributes(FILE *fp,int parent,OS_XML *_lxml); + +void xml_error(OS_XML *_lxml, const char *msg,...) __attribute__((format(printf, 2, 3))); + +/* Currently line */ +int _line; + +/* Local fgetc */ +int _xml_fgetc(FILE *fp) +{ + int c; + c = fgetc(fp); + + if(c == '\n') /* add new line */ + _line++; + + return(c); +} + +#define FGETC(fp) _xml_fgetc(fp) + +void xml_error(OS_XML *_lxml, const char *msg,...) +{ +#ifdef DEBUG + time_t tm; + struct tm *p; +#endif + + va_list args; + va_start(args,msg); + +#ifdef DEBUG + tm = time(NULL); + p = localtime(&tm); + fprintf(stderr,"%d/%d/%d %d:%d:%d (LINE: %d)",p->tm_year+1900,p->tm_mon, + p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,_line); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n\n"); +#endif + + memset(_lxml->err,'\0', 128); + vsnprintf(_lxml->err,127,msg,args); + va_end(args); + _lxml->err_line = _line; +} + + + +/* OS_ClearXML v0.1 + * Clear the memory used by the XML + */ +void OS_ClearXML(OS_XML *_lxml) +{ + int i; + for(i=0;i<_lxml->cur;i++) + { + if(_lxml->el[i]) + free(_lxml->el[i]); + if(_lxml->ct[i]) + free(_lxml->ct[i]); + } + _lxml->cur = 0; + _lxml->err_line = 0; + free(_lxml->el); + free(_lxml->ct); + free(_lxml->rl); + free(_lxml->tp); + free(_lxml->ck); + free(_lxml->ln); + memset(_lxml->err,'\0', 128); + + return; + +} + + +/* OS_ReadXML v0.1 + * Read a XML file and generate the necessary structs. + */ +int OS_ReadXML(char *file, OS_XML *_lxml) +{ + int r,i; + FILE *fp; + + fp = fopen(file,"r"); + if(!fp) + { + xml_error(_lxml, "XMLERR: File '%s' not found.",file); + return(-2); + } + + _lxml->cur = 0; + _lxml->fol = 0; + _lxml->el = NULL; + _lxml->ct = NULL; + _lxml->tp = NULL; + _lxml->rl = NULL; + _lxml->ck = NULL; + _lxml->ln = NULL; + + _lxml->err_line = 0; + memset(_lxml->err,'\0',128); + + /* Zeroing the line */ + _line = 1; + + if((r = _ReadElem(fp,0,0,_lxml)) < 0) /* First position */ + { + if(r != LEOF) + { + fclose(fp); + return(-1); + } + } + + for(i=0;i<_lxml->cur;i++) + { + if(_lxml->ck[i] == 0) + { + xml_error(_lxml,"XMLERR: Element '%s' not closed\n", _lxml->el[i]); + fclose(fp); + return(-1); + } + } + + fclose(fp); + return(0); +} + + +int _oscomment(FILE *fp) +{ + int c; + if((c = fgetc(fp)) == _R_COM) + { + while((c=FGETC(fp)) != EOF) + { + if(c == _R_COM) + { + if((c=fgetc(fp)) == _R_CONFE) + return(1); + ungetc(c,fp); + } + else if(c == '-') /* W3C way of finish comments */ + { + if((c = FGETC(fp)) == '-') + { + if((c = fgetc(fp)) == _R_CONFE) + return(1); + ungetc(c,fp); + } + ungetc(c,fp); + } + else + continue; + } + return(-1); + } + else + ungetc(c,fp); + return(0); +} + + +int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml) +{ + int c; + unsigned int count = 0; + unsigned int _currentlycont = 0; + short int location = -1; + + char prevv = 0; + char elem[XML_MAXSIZE +1]; + char cont[XML_MAXSIZE +1]; + char closedelem[XML_MAXSIZE +1]; + + + + memset(elem,'\0',XML_MAXSIZE +1); + memset(cont,'\0',XML_MAXSIZE +1); + memset(closedelem,'\0',XML_MAXSIZE +1); + + while((c=FGETC(fp)) != EOF) + { + if(c == '\\') + prevv = c; + else if(prevv == '\\') + { + if(c != _R_CONFS) + prevv = 0; + } + + + /* Max size */ + if(count >= XML_MAXSIZE) + { + xml_error(_lxml,"XML ERR: String overflow. Exiting."); + return(-1); + } + + + /* Checking for comments */ + if(c == _R_CONFS) + { + int r = 0; + if((r = _oscomment(fp)) < 0) + { + xml_error(_lxml,"XML ERR: Comment not closed. Bad XML."); + return(-1); + } + else if(r == 1) + continue; + } + + /* real checking */ + if((location == -1) && (prevv == 0)) + { + if(c == _R_CONFS) + { + if((c=fgetc(fp)) == '/') + { + xml_error(_lxml,"XML ERR: Bad formed XML. Element " + "not opened"); + return(-1); + } + else + ungetc(c,fp); + location = 0; + } + else + continue; + } + + else if((location == 0) && ((c == _R_CONFE) || (c == ' '))) + { + int _ge = 0; + int _ga = 0; + elem[count]='\0'; + + /* Removing the / at the end of the element name */ + if(elem[count -1] == '/') + { + _ge = '/'; + elem[count -1] = '\0'; + } + + _writememory(elem, XML_ELEM, count+1, parent, _lxml); + _currentlycont=_lxml->cur-1; + if(c == ' ') + { + if((_ga = _getattributes(fp,parent,_lxml)) < 0) + return(-1); + } + + /* If the element is closed already (finished in />) */ + if((_ge == '/') || (_ga == '/')) + { + _writecontent("\0", 2, _currentlycont,_lxml); + _lxml->ck[_currentlycont] = 1; + _currentlycont = 0; + count = 0; + location = -1; + + memset(elem,'\0',XML_MAXSIZE); + memset(closedelem,'\0',XML_MAXSIZE); + memset(cont,'\0',XML_MAXSIZE); + + if(parent > 0) + return(0); + } + else + { + count = 0; + location = 1; + } + } + + else if((location == 2) &&(c == _R_CONFE)) + { + closedelem[count]='\0'; + if(strcmp(closedelem,elem) != 0) + { + xml_error(_lxml,"XML ERR: Element not closed: %s",elem); + return(-1); + } + _writecontent(cont,strlen(cont)+1,_currentlycont,_lxml); + _lxml->ck[_currentlycont]=1; + memset(elem,'\0',XML_MAXSIZE); + memset(closedelem,'\0',XML_MAXSIZE); + memset(cont,'\0',XML_MAXSIZE); + _currentlycont = 0; + count = 0; + location = -1; + if(parent > 0) + return(0); + } + else if((location == 1) && (c == _R_CONFS) && (prevv == 0)) + { + if((c=fgetc(fp)) == '/') + { + cont[count] = '\0'; + count = 0; + location = 2; + } + else + { + ungetc(c,fp); + ungetc(_R_CONFS,fp); + + if(_ReadElem(fp,position+1,parent+1,_lxml)< 0) + { + return(-1); + } + count=0; + } + } + else + { + if(location == 0) + elem[count++] = c; + else if(location == 1) + cont[count++] = c; + else if(location == 2) + closedelem[count++] = c; + + if((_R_CONFS == c) && (prevv != 0)) + { + prevv = 0; + } + } + } + if(location == -1) + return(LEOF); + + xml_error(_lxml,"XML ERR: End of file and some elements were not closed"); + return(-1); +} + +int _writememory(char *str, short int type, unsigned int size, + int parent, OS_XML *_lxml) +{ + /* Allocating for the element */ + _lxml->el = (char **)realloc(_lxml->el,(_lxml->cur+1)*sizeof(char *)); + _lxml->el[_lxml->cur]=(char *)calloc(size,sizeof(char)); + strncpy(_lxml->el[_lxml->cur],str,size-1); + + /* Allocating for the content */ + _lxml->ct = (char **)realloc(_lxml->ct,(_lxml->cur+1)*sizeof(char *)); + + /* Allocating for the type */ + _lxml->tp = realloc(_lxml->tp,(_lxml->cur+1)*sizeof(int)); + _lxml->tp[_lxml->cur] = type; + + /* Allocating for the relation */ + _lxml->rl = realloc(_lxml->rl,(_lxml->cur+1)*sizeof(int)); + _lxml->rl[_lxml->cur] = parent; + + /* Allocating for the "check" */ + _lxml->ck = realloc(_lxml->ck,(_lxml->cur+1)*sizeof(int)); + _lxml->ck[_lxml->cur] = 0; + + /* Allocating for the line */ + _lxml->ln = realloc(_lxml->ln,(_lxml->cur+1)*sizeof(int)); + _lxml->ln[_lxml->cur] = _line; + + /* Attributes does not need to be closed */ + if(type == XML_ATTR) + _lxml->ck[_lxml->cur] = 1; + + /* Checking if it is a variable */ + if(strcasecmp(XML_VAR,str) == 0) + { + _lxml->tp[_lxml->cur] = XML_VARIABLE_BEGIN; + } + + _lxml->cur++; + return(0); +} + +int _writecontent(char *str, unsigned int size, int parent, OS_XML *_lxml) +{ + _lxml->ct[parent]=(char *)calloc(size,sizeof(char)); + strncpy(_lxml->ct[parent],str,size-1); + + return(0); +} + + +int _checkmemory(char *str,OS_XML *_lxml) +{ + int i; + for(i=0;i<_lxml->cur;i++) + { + if(_lxml->ck[i] == 0) + { + if(strcmp(str,_lxml->el[i]) == 0) + { + _lxml->ck[i] = 1; + return(0); + } + else + continue; + } + } + return(-1); +} + +/* getattributes (Internal function): v0.1: 2005/03/03 + * Read the attributes of an element + */ +int _getattributes(FILE *fp,int parent,OS_XML *_lxml) +{ + int location = 0; + int count = 0; + int c; + int c_to_match = 0; + + char attr[XML_MAXSIZE+1]; + char value[XML_MAXSIZE+1]; + + memset(attr,'\0',XML_MAXSIZE+1); + memset(value,'\0',XML_MAXSIZE+1); + + while((c=FGETC(fp)) != EOF) + { + if(count >= XML_MAXSIZE) + { + attr[count-1] = '\0'; + xml_error(_lxml, + "XMLERR: Overflow attempt at attribute '%s'.",attr); + return(-1); + } + + else if((c == _R_CONFE) || (c == '/')) + { + if((location == 1)||((location == 0)&&(count > 0))) + { + xml_error(_lxml, "XMLERR: Attribute '%s' not closed.", + attr); + return(-1); + } + else if(c == '/') + return(c); + else + return(0); + } + else if((location == 0)&&(c == '=')) + { + attr[count]='\0'; + c = FGETC(fp); + if((c != '"')&&(c != '\'')) + { + unsigned short int _err=1; + if(c == ' ') + { + while((c=FGETC(fp))!= EOF) + { + if(c == ' ') + continue; + else if((c == '"')||(c == '\'')) + { + _err = 0; + break; + } + else + break; + } + } + if(_err != 0){ + xml_error(_lxml, + "XMLERR: Attribute '%s' not followed by a \" or \'." + ,attr); + return(-1); } + } + + c_to_match = c; + location = 1; + count = 0; + } + else if((location == 0)&&(c == ' ')) + continue; + + else if((location == 1)&&(c == c_to_match)) + { + value[count]='\0'; + + location = 0; + c_to_match = 0; + + _writememory(attr, XML_ATTR, strlen(attr)+1, + parent, _lxml); + _writecontent(value,count+1,_lxml->cur-1,_lxml); + c = FGETC(fp); + if(c == ' ') + return(_getattributes(fp,parent,_lxml)); + else if(c == _R_CONFE) + return(0); + else + { + xml_error(_lxml, + "XMLERR: Bad attribute closing for '%s'='%s'.", + attr,value); + return(-1); + } + count = 0; + } + else if(location == 0) + attr[count++]=c; + else if(location == 1) + value[count++]=c; + + } + + xml_error(_lxml, "XMLERR: End of file while reading an attribute."); + return(-1); +} + +/* EOF */ diff --git a/src/os_xml/os_xml.h b/src/os_xml/os_xml.h new file mode 100755 index 0000000..cb2d466 --- /dev/null +++ b/src/os_xml/os_xml.h @@ -0,0 +1,104 @@ +/* @(#) $Id: os_xml.h,v 1.8 2009/06/24 17:06:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* os_xml C Library. + */ + + +#ifndef __OS_XML_H +#define __OS_XML_H + +#ifndef XML_MAXSIZE + #define XML_MAXSIZE 2048 +#endif /* XML_MAXSIZE */ + +#ifndef XML_VAR + #define XML_VAR "xml_var" +#endif /* XML_VAR */ + +#define XML_ELEM 101 +#define XML_ATTR 102 +#define XML_VARIABLE_BEGIN '$' + +/* XML Node structure */ +typedef struct _xml_node +{ + int key; + int line; + char *element; + char *content; + char **attributes; + char **values; +}xml_node; + +/* XML structure */ +typedef struct _OS_XML +{ + int cur; /* Currently position (and last after reading) */ + int fol; /* Currently position for the xml_access */ + int *tp; /* Item type */ + int *rl; /* Relation in the XML */ + int *ck; /* If the item was closed or not */ + int *ln; /* Currently xml file line */ + int err_line; /* Line number of the possible error */ + char **ct; /* Content is stored */ + char **el; /* The element/attribute name is stored */ + char err[128]; /* Error messages are stored in here */ +}OS_XML; + +typedef xml_node ** XML_NODE; + +/* Start the XML structure reading a file */ +int OS_ReadXML(char *file, OS_XML *lxml); + +/* Clear the XML strucute memory */ +void OS_ClearXML(OS_XML *_lxml); + +/* clear a node */ +void OS_ClearNode(xml_node **node); + + +/* Functions to read the XML */ + +/* Return 1 if element_name is a root element */ +int OS_RootElementExist(OS_XML *_lxml, char *element_name); + +/* Return 1 if the element_name exists */ +int OS_ElementExist(OS_XML *_lxml, char **element_name); + +/* Return the elements "children" of the element_name */ +char **OS_GetElements(OS_XML *_lxml, char **element_name); + +/* Return the elements "children" of the element_name */ +xml_node **OS_GetElementsbyNode(OS_XML *_lxml, xml_node *node); + +/* Return the attributes of the element name */ +char **OS_GetAttributes(OS_XML *_lxml, char **element_name); + +/* Return one value from element_name */ +char *OS_GetOneContentforElement(OS_XML *_lxml, char **element_name); + +/* Return an array with the content of all entries of element_name */ +char **OS_GetElementContent(OS_XML *_lxml, char **element_name); + +/* Return an array with the contents of an element_nane */ +char **OS_GetContents(OS_XML *_lxml, char **element_name); + +/* Return the value of a specific attribute of the element_name */ +char *OS_GetAttributeContent(OS_XML *_lxml, char **element_name, + char *attribute_name); + +/* Apply the variables to the xml */ +int OS_ApplyVariables(OS_XML *_lxml); + +#endif + +/* EOF */ diff --git a/src/os_xml/os_xml_access.c b/src/os_xml/os_xml_access.c new file mode 100755 index 0000000..be5741f --- /dev/null +++ b/src/os_xml/os_xml_access.c @@ -0,0 +1,439 @@ +/* $OSSEC, os_xml_access.c, v0.3, 2005/02/11, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* os_xml C Library. + */ + + +#include +#include +#include + +#include "os_xml.h" + + +/* Internal functions */ +char **_GetElements(OS_XML *_lxml, char **element_name,int type); +char **_GetElementContent(OS_XML *_lxml, char **element_name, char *attr); + + +/* OS_ElementExist: v1.0: 2005/02/26 + * Check if a element exists + * The element_name must be NULL terminated (last char) + */ +int OS_ElementExist(OS_XML *_lxml, char **element_name) +{ + int i=0,j=0,matched=0,totalmatch=0; + + if(element_name == NULL) + return(0); + + for(i=0,j=0;i<_lxml->cur;i++) + { + if(element_name[j] == NULL) + j=0; + if((_lxml->tp[i] == XML_ELEM)&&(_lxml->rl[i] == j)) + { + if(strcmp(_lxml->el[i],element_name[j]) == 0) + { + j++; + matched=1; + if(element_name[j] == NULL) + { + j=0; + totalmatch++; + } + continue; + } + } + if((matched == 1) &&(j > _lxml->rl[i])&& + (_lxml->tp[i] == XML_ELEM)) + { + j=0; + matched=0; + } + } + return(totalmatch); +} + + +/* RootElementExist: v1.0: 2005/02/26 + * Check if a root element exists + */ +int OS_RootElementExist(OS_XML *_lxml, char *element_name) +{ + char *(elements[])={element_name,NULL}; + return(OS_ElementExist(_lxml,elements)); +} + + +/* GetAttributes: v.0.1: 2005/03/01 + * Get the attributes of the element_name + */ +char **OS_GetAttributes(OS_XML *_lxml, char **element_name) +{ + return(_GetElements(_lxml,element_name,XML_ATTR)); +} + + + + +/* GetElements: v0.1: 2005/03/01 + * Get the elements children of the element_name + */ +char **OS_GetElements(OS_XML *_lxml, char **element_name) +{ + return(_GetElements(_lxml, element_name,XML_ELEM)); +} + + + + +/* _GetElements: v0.1: 2005/03/01 + * Get the elements or attributes (internal use) + */ +char **_GetElements(OS_XML *_lxml, char **element_name,int type) +{ + int i=0,j=0,k=0,matched=0,ready=0,size=0; + char **ret=NULL; + + if((type == XML_ELEM) && (element_name == NULL)) + ready=1; + + for(i=0,j=0;i<_lxml->cur;i++) + { + if((ready != 1) &&(element_name[j] == NULL)) + { + if(matched ==1) + ready=1; + else + break; + } + + if(j > 16) + return(ret); + + if((ready == 1)&&(_lxml->tp[i] == type)) + { + if(((type == XML_ATTR)&&(_lxml->rl[i] == j-1) + &&(_lxml->el[i] != NULL))|| + ((type == XML_ELEM)&&(_lxml->rl[i] == j)&& + (_lxml->el[i] != NULL))) + { + int el_size = strlen(_lxml->el[i])+1; + size+=el_size; + ret = (char**)realloc(ret,(k+1)*sizeof(char *)); + if(ret == NULL) + return(NULL); + ret[k]=(char*)calloc(el_size,sizeof(char)); + if(ret[k] == NULL) + { + free(ret); + return(NULL); + } + strncpy(ret[k],_lxml->el[i],el_size-1); + k++; + } + } + + else if((_lxml->tp[i] == XML_ELEM)&&(_lxml->rl[i] == j)&& + (element_name[j] != NULL)) + { + if(strcmp(_lxml->el[i],element_name[j]) == 0) + { + j++; + matched=1; + continue; + } + } + + if(matched == 1) + { + if(((_lxml->tp[i]==XML_ATTR)&&(j > _lxml->rl[i]+1))|| + ((_lxml->tp[i] == XML_ELEM)&&(j > _lxml->rl[i]))) + { + j=0; + matched=0; + if(element_name == NULL) + ready=1; + else + ready=0; + } + } + } + if(ret ==NULL) + return(NULL); + + ret = (char**)realloc(ret,(k+1)*sizeof(char *)); + if(ret == NULL) + return(NULL); + ret[k]=NULL; + return(ret); +} + + + +/* OS_GetOneContentforElement: v0.1: 2005/03/01 + * Get one value for a specific element. + */ +char *OS_GetOneContentforElement(OS_XML *_lxml, char **element_name) +{ + int i = 1; + char *uniqret = NULL; + char **ret = NULL; + + _lxml->fol = 0; + ret = _GetElementContent(_lxml, element_name, NULL); + if(ret == NULL) + { + return(NULL); + } + + if(ret[0] != NULL) + { + uniqret = ret[0]; + } + + /* Freeing memory */ + while(ret[i]) + { + free(ret[i]); + ret[i] = NULL; + i++; + } + free(ret); + + return(uniqret); +} + + +/* OS_GetElementContent: v0.1: 2005/03/01 + * Get all values for a specific element + */ +char **OS_GetElementContent(OS_XML *_lxml, char **element_name) +{ + _lxml->fol=0; + return(_GetElementContent(_lxml, element_name, NULL)); +} + + +/* OS_GetContents: v0.1: 2005/03/01 + * Get the contents for a specific element + * Use element_name = NULL to start the state + */ +char **OS_GetContents(OS_XML *_lxml, char **element_name) +{ + if(element_name == NULL) + { + _lxml->fol = -1; + return(NULL); + } + return(_GetElementContent(_lxml, element_name, NULL)); +} + + + +/* OS_GetAttributeContent: v0.1: 2005/03/01 + * Get one value for a specific attribute + */ +char *OS_GetAttributeContent(OS_XML *_lxml, char **element_name, + char *attribute_name) +{ + int success = 0; + char *uniqret = NULL; + char **ret = NULL; + + _lxml->fol=0; + + ret = _GetElementContent(_lxml, element_name,attribute_name); + + if(ret == NULL) + return(NULL); + + if(ret[0] != NULL) + { + int retsize= strlen(ret[0])+1; + if((retsize < XML_MAXSIZE) && (retsize > 0)) + { + uniqret = (char *)calloc(retsize,sizeof(char)); + if(uniqret != NULL) + { + strncpy(uniqret, ret[0], retsize-1); + success = 1; + } + } + } + while(1) + { + if(*ret == NULL) + break; + free(*ret++); + } + if(success) + return(uniqret); + + return(NULL); +} + + +/* _GetElementContent: v0.1: 2005/03/01 + * Get the values for an element or attribute + */ +char **_GetElementContent(OS_XML *_lxml, char **element_name, char *attr) +{ + int i = 0,j = 0,k = 0,matched = 0; + char **ret = NULL; + + /* Element name can not be null. */ + if(element_name == NULL) + return(NULL); + + if(_lxml->fol == _lxml->cur) + { + _lxml->fol = 0; + return(NULL); + } + + if(_lxml->fol > 0) + { + for(i=_lxml->fol;i>=0;i--) + { + _lxml->fol = i; + if(_lxml->rl[i] == 0) + break; + } + i = _lxml->fol; + } + else + { + i = 0; + } + + + /* Looping through all nodes */ + for(j=0; i<_lxml->cur; i++) + { + if(element_name[j] == NULL) + { + if(matched !=1) + break; + } + + /* Setting maximum depth of 16. */ + if(j > 16) + return(NULL); + + + /* If the type is not an element and the relation doesn't match, + * keep going. + */ + if((_lxml->tp[i] != XML_ELEM) || (_lxml->rl[i] != j)) + { + /* If the node relation is higher than we currently xml + * node, zero the position and look at it again (i--). + */ + if(j > _lxml->rl[i]) + { + j = 0; + matched = 0; + i--; + } + else + { + continue; + } + } + + + /* If the element name matches what we are looking for. */ + else if(strcmp(_lxml->el[i], element_name[j]) == 0) + { + j++; + matched = 1; + + /* Get content if we are at the end of the array. */ + if(element_name[j] == NULL) + { + /* If we have an attribute to match. */ + if(attr != NULL) + { + int k=0; + for(k=i+1; k<_lxml->cur; k++) + { + if(_lxml->tp[k] == XML_ELEM) + { + break; + } + + if(strcmp(attr, _lxml->el[k]) == 0) + { + i = k; + break; + } + } + } + + if(_lxml->ct[i] != NULL) + { + /* Increasing the size of the array. */ + ret = (char**) realloc(ret,(k+2) * sizeof(char*)); + if(ret == NULL) + { + return(NULL); + } + + /* Adding new entry. */ + ret[k] = strdup(_lxml->ct[i]); + ret[k + 1] = NULL; + if(ret[k] == NULL) + { + free(ret); + return(NULL); + } + + matched = 1; + k++; + + if(attr != NULL) + { + break; + } + + else if(_lxml->fol != 0) + { + _lxml->fol = i+1; + break; + } + } + + /* Setting new array pointer. */ + if((i<_lxml->cur-1) && (_lxml->tp[i+1] == XML_ELEM)) + { + j = _lxml->rl[i+1]; + } + } + continue; + } + + if(j > _lxml->rl[i]) + { + j = 0; + matched = 0; + } + } + + if(ret == NULL) + return(NULL); + + return(ret); +} + +/* EOF */ diff --git a/src/os_xml/os_xml_node_access.c b/src/os_xml/os_xml_node_access.c new file mode 100755 index 0000000..7d986ca --- /dev/null +++ b/src/os_xml/os_xml_node_access.c @@ -0,0 +1,189 @@ +/* @(#) $Id: os_xml_node_access.c,v 1.6 2009/06/24 17:06:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* os_xml C Library. + * Available at http://www.ossec.net/ + */ + + +#include +#include +#include + +#include "os_xml.h" + + +/* OS_ClearNode v0,1 + * Clear the Node structure + */ +void OS_ClearNode(xml_node **node) +{ + if(node) + { + int i=0; + while(node[i]) + { + if(node[i]->element) + free(node[i]->element); + if(node[i]->content) + free(node[i]->content); + if(node[i]->attributes) + { + int j=0; + while(node[i]->attributes[j]) + { + free(node[i]->attributes[j]); + j++; + } + free(node[i]->attributes); + } + if(node[i]->values) + { + int j=0; + while(node[i]->values[j]) + { + free(node[i]->values[j]); + j++; + } + free(node[i]->values); + } + + node[i]->element=NULL; + node[i]->content=NULL; + node[i]->attributes=NULL; + node[i]->values=NULL; + free(node[i]); + node[i]=NULL; + i++; + } + free(node); + node=NULL; + } +} + + +/** xml_node **OS_GetElementsbyNode(OS_XML *_lxml, xml_node *node) + * Get the elements by node. + */ +xml_node **OS_GetElementsbyNode(OS_XML *_lxml, xml_node *node) +{ + int i,j,k=0; + xml_node **ret=NULL; + + if(node == NULL) + { + j = -1; + i = 0; + } + else + { + i = node->key; + j = _lxml->rl[i++]; + } + + + for(;i<_lxml->cur;i++) + { + if(_lxml->tp[i] == XML_ELEM) + { + if((_lxml->rl[i] == j+1) && (_lxml->el[i] != NULL)) + { + int l=i+1; + /* Allocating for xml_node ** */ + ret = (xml_node**)realloc(ret,(k+1)*sizeof(xml_node*)); + if(ret == NULL) + return(NULL); + + /* Allocating for the xml_node * */ + ret[k] = (xml_node *)calloc(1,sizeof(xml_node)); + if(ret[k] == NULL) + return(NULL); + + ret[k]->element = NULL; + ret[k]->content = NULL; + ret[k]->attributes = NULL; + ret[k]->values = NULL; + + /* Getting the element */ + ret[k]->element=strdup(_lxml->el[i]); + if(ret[k]->element == NULL) + { + free(ret); + return(NULL); + } + + /* Getting the content */ + if(_lxml->ct[i]) + { + ret[k]->content=strdup(_lxml->ct[i]); + if(ret[k]->content == NULL) + return(NULL); + } + /* Assigning the key */ + ret[k]->key = i; + + /* Getting attributes */ + while(l < _lxml->cur) + { + if((_lxml->tp[l] == XML_ATTR)&&(_lxml->rl[l] == j+1)&& + (_lxml->el[l]) && (_lxml->ct[l])) + { + ret[k]->attributes = + (char**)realloc(ret[k]->attributes, + (l-i+1)*sizeof(char*)); + ret[k]->values = + (char**)realloc(ret[k]->values, + (l-i+1)*sizeof(char*)); + if(!(ret[k]->attributes) || + !(ret[k]->values)) + return(NULL); + ret[k]->attributes[l-i-1]=strdup(_lxml->el[l]); + ret[k]->values[l-i-1] = strdup(_lxml->ct[l]); + if(!(ret[k]->attributes[l-i-1]) || + !(ret[k]->values[l-i-1])) + return(NULL); + l++; + } + else + { + break; + } + } + if(ret[k]->attributes) + { + ret[k]->attributes[l-i-1] = NULL; + ret[k]->values[l-i-1] = NULL; + } + k++; + continue; + } + } + if((_lxml->tp[i] == XML_ELEM)&&(j+1 > _lxml->rl[i])) + { + if(j == -1) + continue; + else + break; + } + } + + if(ret ==NULL) + return(NULL); + + ret = (xml_node **)realloc(ret,(k+1)*sizeof(xml_node *)); + if(ret == NULL) + return(NULL); + ret[k]=NULL; + return(ret); +} + + +/* EOF */ diff --git a/src/os_xml/os_xml_variables.c b/src/os_xml/os_xml_variables.c new file mode 100755 index 0000000..e474cda --- /dev/null +++ b/src/os_xml/os_xml_variables.c @@ -0,0 +1,293 @@ +/* $OSSEC, os_xml_node_variables.c, v0.3, 2005/04/12, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* os_xml C Library. + * Available at http://www.ossec.net/ + */ + + +#include +#include +#include + +#include "os_xml.h" + +int OS_ApplyVariables(OS_XML *_lxml) +{ + int i = 0,j = 0,s = 0; + char **var = NULL; + char **value = NULL; + + + /* No variables. */ + if(!_lxml->cur) + return(0); + + + /* Getting all variables */ + for(;i<_lxml->cur;i++) + { + if(_lxml->tp[i] == XML_VARIABLE_BEGIN) + { + int _found_var = 0; + + j = i+1; + for(;j<_lxml->cur;j++) + { + if(_lxml->rl[j] < _lxml->rl[i]) + break; + + else if(_lxml->tp[j] == XML_ATTR) + { + if((_lxml->el[j])&&(strcasecmp(_lxml->el[j],"name") == 0)) + { + if(!_lxml->ct[j]) + break; + + /* If not used, it will be cleaned latter */ + snprintf(_lxml->err, 128, "XML_ERR: Memory error"); + + var = (char**)realloc(var,(s+1)*sizeof(char *)); + if(var == NULL) + return (-1); + + var[s] = strdup(_lxml->ct[j]); + if(var[s] == NULL) + return(-1); + + /* Cleaning the lxml->err */ + strncpy(_lxml->err," ", 3); + + _found_var = 1; + break; + } + else + { + snprintf(_lxml->err, 128, + "XML_ERR: Only \"name\" is allowed" + " as an attribute for a variable"); + return(-1); + } + } + } /* Attribute FOR */ + + + if((_found_var == 0)||(!_lxml->ct[i])) + { + snprintf(_lxml->err,128, + "XML_ERR: Bad formed variable. No value set"); + return(-1); + } + + + snprintf(_lxml->err,128, "XML_ERR: Memory error"); + + value = (char**)realloc(value,(s+1)*sizeof(char *)); + if (value == NULL) + return(-1); + + value[s] = strdup(_lxml->ct[i]); + if(value[s] == NULL) + return(-1); + + strncpy(_lxml->err," ", 3); + s++; + } + } /* initial FOR to get the variables */ + + + /* No variable */ + if(s == 0) + return(0); + + + /* Looping again and modifying where found the variables */ + i = 0; + for(;i<_lxml->cur;i++) + { + if(((_lxml->tp[i] == XML_ELEM) || (_lxml->tp[i] == XML_ATTR))&& + (_lxml->ct[i])) + { + int tp = 0,init = 0,final = 0; + char *p = NULL; + char *p2= NULL; + char lvar[256]; /* MAX Var size */ + + + if(strlen(_lxml->ct[i]) <= 2) + continue; + + + /* Duplicating string */ + p = strdup(_lxml->ct[i]); + p2= p; + + if(p == NULL) + { + snprintf(_lxml->err, 128, "XML_ERR: Memory error"); + return(-1); + } + + + /* Reading the whole string */ + while(*p != '\0') + { + if(*p == XML_VARIABLE_BEGIN) + { + tp = 0; + p++; + memset(lvar, '\0', 256); + + while(1) + { + if((*p == XML_VARIABLE_BEGIN) + ||(*p == '\0') + ||(*p == '.') + ||(*p == '|') + ||(*p == ',') + ||(*p == ' ')) + { + lvar[tp]='\0'; + + final = init+tp; + + /* Looking for var */ + for(j=0; jct[i]) + + strlen(value[j]) - tp + 1; + + var_placeh = strdup(_lxml->ct[i]); + + free(_lxml->ct[i]); + + _lxml->ct[i] = (char*)calloc(tsize +2, + sizeof(char)); + + if(_lxml->ct[i] == NULL || var_placeh == NULL) + { + snprintf(_lxml->err,128, "XML_ERR: Memory " + "error"); + return(-1); + } + + + strncpy(_lxml->ct[i], var_placeh, tsize); + + + _lxml->ct[i][init] = '\0'; + strncat(_lxml->ct[i], value[j],tsize - init); + + + init = strlen(_lxml->ct[i]); + strncat(_lxml->ct[i], p, + tsize - strlen(_lxml->ct[i])); + + + free(var_placeh); + + break; + } + + /* Variale not found */ + if((j == s) && (strlen(lvar) >= 1)) + { + snprintf(_lxml->err,128, + "XML_ERR: Unknown variable" + ": %s", lvar); + return(-1); + } + else if(j == s) + { + init++; + } + + goto go_next; + } + + /* Maximum size for a variable */ + if(tp >= 255) + { + snprintf(_lxml->err,128, "XML_ERR: Invalid " + "variable size."); + return(-1); + + } + + lvar[tp] = *p; + tp++; + p++; + } + } /* IF XML_VAR_BEGIN */ + + p++; + init++; + + go_next: + continue; + + } /* WHILE END */ + + if(p2 != NULL) + { + free(p2); + p2 = NULL; + p = NULL; + } + } + } + + + /* Cleaning the variables */ + for(i=0;i' +#define _R_EQUAL '=' +#define _R_COM '!' +#define _R_VAR '$' + +#define OPEN 51 +#define CLOSE 52 + +#define LEOF -2 + +/* Internal functions */ +int _oswcomment(FILE *fp_in, FILE *fp_out); +int _WReadElem(FILE *fp_in, FILE *fp_out, int position, int parent, + char **node, char *value, int node_pos); + + +/* Currently line */ +int _line; + + +/* Local fgetc */ +int _xml_wfgetc(FILE *fp_in, FILE *fp_out) +{ + int c; + + /* Putting on fp_out, whatever we read */ + c = fgetc(fp_in); + if(c != EOF) + { + fputc(c, fp_out); + } + + if(c == '\n') /* add new line */ + _line++; + + return(c); +} + +#define FWGETC(fp_in, fp_out) _xml_wfgetc(fp_in, fp_out) + + + +/* OS_WriteXML + * Write an XML file, based on the input and values to change. + */ +int OS_WriteXML(char *infile, char *outfile, char **nodes, char *attr, + char *oldval, char *newval, int type) +{ + int r = 0; + int node_pos = 0; + FILE *fp_in; + FILE *fp_out; + + + /* Nodes and newval must be set. */ + if(!nodes || !newval) + { + return(XMLW_ERROR); + } + + /* Opening infile */ + fp_in = fopen(infile,"r"); + if(!fp_in) + { + return(XMLW_NOIN); + } + + + /* Opening out file */ + fp_out = fopen(outfile,"w"); + if(!fp_out) + { + fclose(fp_in); + return(XMLW_NOOUT); + } + + + if((r = _WReadElem(fp_in, fp_out, 0, 0, + nodes, newval, node_pos)) < 0) /* First position */ + { + fclose(fp_in); + fclose(fp_out); + return(XMLW_ERROR); + } + + /* We didn't find an entry, add at the end. */ + if(!oldval && r == 0) + { + int r = 0; + int rwidth = 0; + + fseek(fp_out, 0, SEEK_END); + fprintf(fp_out, "\n"); + + /* Printing each node. */ + while(nodes[r]) + { + fprintf(fp_out, "%*c<%s>", rwidth, ' ', nodes[r]); + r++; + rwidth += 3; + + if(nodes[r]) + fprintf(fp_out, "\n"); + } + + /* Printing val. */ + r--; + rwidth -=6; + fprintf(fp_out, "%s\n", newval, nodes[r]); + r--; + + + /* Closing each node. */ + while(r >= 0) + { + fprintf(fp_out, "%*c\n", rwidth, ' ', nodes[r]); + r--; + rwidth -= 3; + } + } + + fclose(fp_in); + fclose(fp_out); + return(0); +} + + + +/* Getting comments */ +int _oswcomment(FILE *fp_in, FILE *fp_out) +{ + int c; + if((c = fgetc(fp_in)) == _R_COM) + { + fputc(c, fp_out); + while((c = FWGETC(fp_in, fp_out)) != EOF) + { + if(c == _R_COM) + { + if((c=fgetc(fp_in)) == _R_CONFE) + { + fputc(c, fp_out); + return(1); + } + ungetc(c,fp_in); + } + else if(c == '-') /* W3C way of finish comments */ + { + if((c = fgetc(fp_in)) == '-') + { + fputc(c, fp_out); + if((c = fgetc(fp_in)) == _R_CONFE) + { + fputc(c, fp_out); + return(1); + } + ungetc(c,fp_in); + } + else + { + ungetc(c,fp_in); + } + } + else + { + continue; + } + } + return(-1); + } + else + { + ungetc(c,fp_in); + } + + return(0); +} + + + +int _WReadElem(FILE *fp_in, FILE *fp_out, + int position, int parent, char **nodes, char *val, int node_pos) +{ + int c; + int ret_code = 0; + unsigned int count = 0; + short int location = -1; + + char elem[XML_MAXSIZE +1]; + char cont[XML_MAXSIZE +1]; + char closedelem[XML_MAXSIZE +1]; + + memset(elem,'\0',XML_MAXSIZE +1); + memset(cont,'\0',XML_MAXSIZE +1); + memset(closedelem,'\0',XML_MAXSIZE +1); + + + while((c = FWGETC(fp_in, fp_out)) != EOF) + { + /* Max size */ + if(count >= XML_MAXSIZE) + { + return(-1); + } + + /* Checking for comments */ + if(c == _R_CONFS) + { + int r = 0; + if((r = _oswcomment(fp_in, fp_out)) < 0) + { + return(-1); + } + else if(r == 1) + { + continue; + } + } + + + /* Real checking */ + if(location == -1) + { + /* Must be the opening element */ + if(c == _R_CONFS) + { + if((c = fgetc(fp_in)) == '/') + { + return(-1); + } + else + { + ungetc(c,fp_in); + } + location = 0; + } + else + { + continue; + } + } + + + /* Looking for the closure */ + else if((location == 0) && ((c == _R_CONFE) || (c == ' '))) + { + int _ge = 0; + elem[count] = '\0'; + + + /* Removing the / at the end of the element name */ + if(elem[count -1] == '/') + { + _ge = '/'; + elem[count -1] = '\0'; + } + + + /* If we may have more attributes */ + if(c == ' ') + { + /* Writing the attributes */ + while((c = FWGETC(fp_in, fp_out)) != EOF) + { + if(c == _R_CONFE) + { + break; + } + } + } + + + /* If the element is closed already (finished in />) */ + if(_ge == '/') + { + count = 0; + location = -1; + + memset(elem,'\0',XML_MAXSIZE); + memset(closedelem,'\0',XML_MAXSIZE); + memset(cont,'\0',XML_MAXSIZE); + + if(parent > 0) + { + return(ret_code); + } + } + /* Location == means we are getting the content */ + else + { + count = 0; + location = 1; + } + + + /* Checking position of the node */ + if(node_pos > position) + { + node_pos = 0; + } + + /* Checking if the element name matches */ + if(node_pos == position && + nodes[node_pos] && strcmp(elem, nodes[node_pos]) == 0) + { + node_pos++; + + /* Latest node, printint value */ + if(!nodes[node_pos]) + { + ret_code = 1; + fprintf(fp_out, "%s", val); + + while((c = fgetc(fp_in)) != EOF) + { + if(c == _R_CONFS) + { + ungetc(c,fp_in); + break; + } + } + } + } + } + + else if((location == 2) &&(c == _R_CONFE)) + { + closedelem[count]='\0'; + if(strcmp(closedelem,elem) != 0) + { + return(-1); + } + + memset(elem,'\0',XML_MAXSIZE); + memset(closedelem,'\0',XML_MAXSIZE); + memset(cont,'\0',XML_MAXSIZE); + + count = 0; + location = -1; + if(parent > 0) + { + return(ret_code); + } + } + + /* If we are reading the element */ + else if((location == 1) &&(c == _R_CONFS)) + { + if((c=fgetc(fp_in)) == '/') + { + fputc(c, fp_out); + + cont[count] = '\0'; + count = 0; + location = 2; + } + else + { + int wret_code; + ungetc(c,fp_in); + ungetc(_R_CONFS,fp_in); + fseek(fp_out, -1, SEEK_CUR); + + if((wret_code = _WReadElem(fp_in, fp_out, position+1, parent+1, + nodes, val, node_pos))< 0) + { + return(-1); + } + + /* Setting final return code. */ + if(wret_code == 1) + { + ret_code = 1; + } + + count = 0; + } + } + else + { + if(location == 0) + { + elem[count++] = c; + } + else if(location == 1) + { + cont[count++] = c; + } + else if(location == 2) + { + closedelem[count++] = c; + } + } + } + + if(location == -1) + { + return(ret_code); + } + + + return(-1); +} + + + + +/* EOF */ diff --git a/src/os_xml/os_xml_writer.h b/src/os_xml/os_xml_writer.h new file mode 100755 index 0000000..5e3e938 --- /dev/null +++ b/src/os_xml/os_xml_writer.h @@ -0,0 +1,44 @@ +/* @(#) $Id: os_xml_writer.h,v 1.4 2009/06/24 17:06:32 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* os_xml C Library. + * Available at http://www.ossec.net/ + */ + + +#ifndef OS_XML_WRITER_H +#define OS_XML_WRITER_H + +#ifndef XML_MAXSIZE + #define XML_MAXSIZE 2048 +#endif /* XML_MAXSIZE */ + +#ifndef XML_VAR + #define XML_VAR "xml_var" +#endif /* XML_VAR */ + + +/* Error from writer */ +#define XMLW_ERROR 006 +#define XMLW_NOIN 007 +#define XMLW_NOOUT 010 + + +/* OS_WriteXML + * Write an XML file, based on the input and values to change. + */ +int OS_WriteXML(char *infile, char *outfile, char **nodes, char *attr, + char *oldval, char *newval, int type); + + +#endif + +/* EOF */ diff --git a/src/os_zlib/Makefile b/src/os_zlib/Makefile new file mode 100755 index 0000000..4cb175d --- /dev/null +++ b/src/os_zlib/Makefile @@ -0,0 +1,13 @@ +# Makefile for os_zlib tests. +# Daniel B. Cid +# http://www.ossec.net + +PT=../ +include $(PT)Config.Make + +OBJS = ${OS_SHARED} ${OS_ZLIB} + +me: + $(CC) $(CFLAGS) zlib-test.c $(OBJS) -o zlib-test +clean: + $(CLEAN) zlib-test diff --git a/src/os_zlib/os_zlib.c b/src/os_zlib/os_zlib.c new file mode 100755 index 0000000..9ad9516 --- /dev/null +++ b/src/os_zlib/os_zlib.c @@ -0,0 +1,51 @@ +/* @(#) $Id: os_zlib.c,v 1.7 2009/06/24 18:53:06 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" +#include "os_zlib.h" + +/* os_compress: Compress a string with zlib. */ +int os_compress(char *src, char *dst, int src_size, int dst_size) +{ + unsigned long int zl_dst = dst_size; + + /* We make sure to do not allow long sizes */ + if(compress2((unsigned char *)dst, + &zl_dst, + (unsigned char *)src, + (unsigned long int)src_size, 9) == Z_OK) + { + dst[zl_dst] = '\0'; + return(zl_dst); + } + + return(0); +} + + +/* os_uncompress: Uncompress a string with zlib. */ +int os_uncompress(char *src, char *dst, int src_size, int dst_size) +{ + unsigned long int zl_dst = dst_size; + + if(uncompress((unsigned char *)dst, + &zl_dst, + (unsigned char *)src, + (unsigned long int)src_size) == Z_OK) + { + dst[zl_dst] = '\0'; + return(zl_dst); + } + return(0); +} + + +/* EOF */ diff --git a/src/os_zlib/os_zlib.h b/src/os_zlib/os_zlib.h new file mode 100755 index 0000000..1f84568 --- /dev/null +++ b/src/os_zlib/os_zlib.h @@ -0,0 +1,26 @@ +/* @(#) $Id: os_zlib.h,v 1.5 2009/06/24 18:53:06 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __OS_ZLIB_H +#define __OS_ZLIB_H + +#include "zlib.h" + +/* os_compress: Compress a string with zlib. */ +int os_compress(char *src, char *dst, int src_size, int dst_size); + +/* os_uncompress: Uncompress a string with zlib. */ +int os_uncompress(char *src, char *dst, int src_size, int dst_size); + +#endif + +/* EOF */ diff --git a/src/os_zlib/zlib-test.c b/src/os_zlib/zlib-test.c new file mode 100755 index 0000000..6957eed --- /dev/null +++ b/src/os_zlib/zlib-test.c @@ -0,0 +1,69 @@ +/* @(#) $Id: zlib-test.c,v 1.5 2009/06/24 18:53:06 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "os_zlib.h" + +#ifndef ARGV0 + #define ARGV0 "zlib-test" +#endif + +/* Zlib test */ +int main(int argc, char **argv) +{ + int ret, srcsize, dstsize = 2010; + char dst[2048]; + char dst2[2048]; + + memset(dst, 0, 2048); + memset(dst2, 0, 2048); + + if(argc < 2) + { + printf("%s: string\n", argv[0]); + exit(1); + } + + srcsize = strlen(argv[1]); + if(srcsize > 2000) + { + printf("%s: string too large\n", argv[0]); + exit(1); + + } + + if((ret = os_compress(argv[1], dst, srcsize, dstsize))) + { + printf("Compressed, from %d->%d\n",srcsize, ret); + } + else + { + printf("FAILED compressing.\n"); + exit(1); + } + + /* Setting new srcsize for decompression */ + srcsize = ret; + + if((ret = os_uncompress(dst, dst2, srcsize, dstsize))) + { + printf("Uncompressed ok. String: '%s', size %d->%d\n", + dst2, srcsize, ret); + } + else + { + printf("FAILED uncompressing.\n"); + exit(1); + } + + return(0); +} diff --git a/src/remoted/COPYRIGHT b/src/remoted/COPYRIGHT new file mode 100755 index 0000000..ea4845c --- /dev/null +++ b/src/remoted/COPYRIGHT @@ -0,0 +1,13 @@ +Copyright (C) 2009 Trend Micro Inc. + All rights reserved. + This program is a free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License (version 3) as published by the FSF - Free Software + Foundation. + + License details at the LICENSE file included with OSSEC or + online at: http://www.ossec.net/en/licensing.html + + +OSSEC, logremote. +Available at http://www.ossec.net/ diff --git a/src/remoted/Makefile b/src/remoted/Makefile new file mode 100755 index 0000000..bbd9ade --- /dev/null +++ b/src/remoted/Makefile @@ -0,0 +1,18 @@ +# Makefile for remoted +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +PT=../ +NAME=ossec-remoted + +include ../Config.Make + +rlog_OBJS = *.c ${OS_CONFIG} ${OS_ZLIB} ${OS_CRYPTO} ${OS_SHARED} ${OS_NET} ${OS_XML} ${OS_REGEX} ${TEXTRA} + +remoted: + ${CC} ${CFLAGS} ${OS_LINK} ${rlog_OBJS} -o ${NAME} + +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/remoted/README b/src/remoted/README new file mode 100755 index 0000000..27886e1 --- /dev/null +++ b/src/remoted/README @@ -0,0 +1,24 @@ +How Remoted works: + +Three daemons (forked): + +-Secured (udp port 1514) +-Syslogd (udp port 514) +-Syslogd (tcp port 514) + + +-How secured works: + +-Three threads. + +-Main thread (remote receiver). + - Receives data from remote clients. + - If the data is a log, send to analysisd. + - If data is connection related, send to the manager thread + (by save_controlmsg). +-AR_Forward (local receiver). + - Receives data (active responses) locally from analysisd. + - Forward them to the configured agent. +-Manager (sends data to remote clients). + - Waits for messages from the main thread (wait_for_msgs). + diff --git a/src/remoted/VERSION b/src/remoted/VERSION new file mode 100755 index 0000000..7e32cd5 --- /dev/null +++ b/src/remoted/VERSION @@ -0,0 +1 @@ +1.3 diff --git a/src/remoted/ar-forward.c b/src/remoted/ar-forward.c new file mode 100755 index 0000000..c2035f3 --- /dev/null +++ b/src/remoted/ar-forward.c @@ -0,0 +1,200 @@ +/* @(#) $Id: ar-forward.c,v 1.27 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include + +#include "remoted.h" +#include "os_net/os_net.h" + + + +/** void *AR_Forward(void *arg) v0.1 + * Start of a new thread. Only returns + * on unrecoverable errors. + */ +void *AR_Forward(void *arg) +{ + int i = 0; + int arq = 0; + int agent_id = 0; + int ar_location = 0; + + char msg_to_send[OS_SIZE_1024 +1]; + + char msg[OS_SIZE_1024 +1]; + char *location = NULL; + char *ar_location_str = NULL; + char *ar_agent_id = NULL; + char *tmp_str = NULL; + + + /* Creating the unix queue */ + if((arq = StartMQ(ARQUEUE, READ)) < 0) + { + ErrorExit(QUEUE_ERROR, ARGV0, ARQUEUE, strerror(errno)); + } + + memset(msg, '\0', OS_SIZE_1024 +1); + + /* Daemon loop */ + while(1) + { + if(OS_RecvUnix(arq, OS_SIZE_1024, msg)) + { + /* Always zeroing the location */ + ar_location = 0; + + + /* Getting the location */ + location = msg; + + + /* Location is going to be the agent name */ + tmp_str = strchr(msg, ')'); + if(!tmp_str) + { + merror(EXECD_INV_MSG, ARGV0, msg); + continue; + } + *tmp_str = '\0'; + + + /* Going after the ')' and space */ + tmp_str += 2; + + + /* Extracting the source ip */ + tmp_str = strchr(tmp_str, ' '); + if(!tmp_str) + { + merror(EXECD_INV_MSG, ARGV0, msg); + continue; + } + tmp_str++; + location++; + + + /* Setting ar_location */ + ar_location_str = tmp_str; + if(*tmp_str == ALL_AGENTS_C) + { + ar_location|=ALL_AGENTS; + } + tmp_str++; + if(*tmp_str == REMOTE_AGENT_C) + { + ar_location|=REMOTE_AGENT; + } + else if(*tmp_str == NO_AR_C) + { + ar_location|=NO_AR_MSG; + } + tmp_str++; + if(*tmp_str == SPECIFIC_AGENT_C) + { + ar_location|=SPECIFIC_AGENT; + } + + + /*** Extracting the active response location ***/ + tmp_str = strchr(ar_location_str, ' '); + if(!tmp_str) + { + merror(EXECD_INV_MSG, ARGV0, msg); + continue; + } + *tmp_str = '\0'; + tmp_str++; + + + /*** Extracting the agent id */ + ar_agent_id = tmp_str; + tmp_str = strchr(tmp_str, ' '); + if(!tmp_str) + { + merror(EXECD_INV_MSG, ARGV0, msg); + continue; + } + *tmp_str = '\0'; + tmp_str++; + + + /*** Creating the new message ***/ + if(ar_location & NO_AR_MSG) + { + snprintf(msg_to_send, OS_SIZE_1024, "%s%s", + CONTROL_HEADER, + tmp_str); + } + else + { + snprintf(msg_to_send, OS_SIZE_1024, "%s%s%s", + CONTROL_HEADER, + EXECD_HEADER, + tmp_str); + } + + + /* Lock use of keys */ + key_lock(); + + + /* Sending to ALL agents */ + if(ar_location & ALL_AGENTS) + { + for(i = 0;i< keys.keysize; i++) + { + send_msg(i, msg_to_send); + } + } + + /* Send to the remote agent that generated the event */ + else if((ar_location & REMOTE_AGENT) && (location != NULL)) + { + agent_id = OS_IsAllowedName(&keys, location); + if(agent_id < 0) + { + key_unlock(); + merror(AR_NOAGENT_ERROR, ARGV0, location); + continue; + } + + send_msg(agent_id, msg_to_send); + } + + /* Send to a pre-defined agent */ + else if(ar_location & SPECIFIC_AGENT) + { + ar_location++; + + agent_id = OS_IsAllowedID(&keys, ar_agent_id); + + if(agent_id < 0) + { + key_unlock(); + merror(AR_NOAGENT_ERROR, ARGV0, ar_agent_id); + continue; + } + + send_msg(agent_id, msg_to_send); + } + + /* Lock use of keys */ + key_unlock(); + } + } +} + + + +/* EOF */ diff --git a/src/remoted/config.c b/src/remoted/config.c new file mode 100755 index 0000000..5b96b7d --- /dev/null +++ b/src/remoted/config.c @@ -0,0 +1,47 @@ +/* @(#) $Id: config.c,v 1.12 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + +#include "os_xml/os_xml.h" +#include "os_regex/os_regex.h" +#include "os_net/os_net.h" + +#include "remoted.h" +#include "config/config.h" + + +/* RemotedConfig v0.4, 2006/04/10 + * Read the config file (the remote access) + * v0.2: New OS_XML + * v0.3: Some improvements and cleanup + * v0.4: Move everything to the global config validator. + */ +int RemotedConfig(char *cfgfile, remoted *logr) +{ + int modules = 0; + + modules|= CREMOTE; + + logr->port = NULL; + logr->conn = NULL; + logr->allowips = NULL; + logr->denyips = NULL; + + if(ReadConfig(modules, cfgfile, logr, NULL) < 0) + return(OS_INVALID); + + return(1); +} + + +/* EOF */ diff --git a/src/remoted/main.c b/src/remoted/main.c new file mode 100755 index 0000000..14708ba --- /dev/null +++ b/src/remoted/main.c @@ -0,0 +1,160 @@ +/* @(#) $Id: main.c,v 1.23 2009/11/18 19:07:41 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "remoted.h" + + +int main(int argc, char **argv) +{ + int i = 0,c = 0; + int uid = 0, gid = 0; + int test_config = 0,run_foreground = 0; + + char *cfg = DEFAULTCPATH; + char *dir = DEFAULTDIR; + char *user = REMUSER; + char *group = GROUPGLOBAL; + + + /* Setting the name -- must be done ASAP */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "Vdthfu:g:c:D:")) != -1){ + switch(c){ + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'u': + if(!optarg) + ErrorExit("%s: -u needs an argument",ARGV0); + user = optarg; + break; + case 'g': + if(!optarg) + ErrorExit("%s: -g needs an argument",ARGV0); + group = optarg; + break; + case 't': + test_config = 1; + break; + case 'c': + if (!optarg) + ErrorExit("%s: -c need an argument", ARGV0); + cfg = optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + dir = optarg; + } + } + + debug1(STARTED_MSG,ARGV0); + + + /* Return 0 if not configured */ + if(RemotedConfig(cfg, &logr) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* Exit if test_config is set */ + if(test_config) + exit(0); + + + /* Check if the user and group given are valid */ + uid = Privsep_GetUser(user); + gid = Privsep_GetGroup(group); + if((uid < 0)||(gid < 0)) + ErrorExit(USER_ERROR, ARGV0, user, group); + + + /* pid before going daemon */ + i = getpid(); + + + if(!run_foreground) + { + nowDaemon(); + goDaemon(); + } + + + /* Setting new group */ + if(Privsep_SetGroup(gid) < 0) + ErrorExit(SETGID_ERROR, ARGV0, group); + + /* Going on chroot */ + if(Privsep_Chroot(dir) < 0) + ErrorExit(CHROOT_ERROR,ARGV0,dir); + + + nowChroot(); + + + /* Starting the signal manipulation */ + StartSIG(ARGV0); + + + /* Creating some randoness */ + #ifdef __OpenBSD__ + srandomdev(); + #else + srandom( time(0) + getpid()+ i); + #endif + + random(); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* Really starting the program. */ + i = 0; + while(logr.conn[i] != 0) + { + /* Forking for each connection handler */ + if(fork() == 0) + { + /* On the child */ + debug1("%s: DEBUG: Forking remoted: '%d'.",ARGV0, i); + HandleRemote(i, uid); + } + else + { + i++; + continue; + } + } + + + /* Done over here */ + return(0); +} + + +/* EOF */ diff --git a/src/remoted/manager.c b/src/remoted/manager.c new file mode 100755 index 0000000..38c92cd --- /dev/null +++ b/src/remoted/manager.c @@ -0,0 +1,662 @@ +/* @(#) $Id: manager.c,v 1.47 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" +#include + +#include "remoted.h" +#include "os_net/os_net.h" +#include "os_crypto/md5/md5_op.h" + + +/* Internal structures */ +typedef struct _file_sum +{ + int mark; + char *name; + os_md5 sum; +}file_sum; + + + +/* Internal functions prototypes */ +void read_controlmsg(int agentid, char *msg); + + + + +/* Global vars, acessible every where */ +file_sum **f_sum; + +time_t _ctime; +time_t _stime; + + + +/* For the last message tracking */ +char *_msg[MAX_AGENTS +1]; +char *_keep_alive[MAX_AGENTS +1]; +int _changed[MAX_AGENTS +1]; +int modified_agentid; + + +/* pthread mutex variables */ +pthread_mutex_t lastmsg_mutex; +pthread_cond_t awake_mutex; + + + +/* save_controlmsg: Save a control message received + * from an agent. read_contromsg (other thread) is going + * to deal with it (only if message changed). + */ +void save_controlmsg(int agentid, char *r_msg) +{ + char msg_ack[OS_FLSIZE +1]; + + + /* Replying to the agent. */ + snprintf(msg_ack, OS_FLSIZE, "%s%s", CONTROL_HEADER, HC_ACK); + send_msg(agentid, msg_ack); + + + /* Checking if there is a keep alive already for this agent. */ + if(_keep_alive[agentid] && _msg[agentid] && + (strcmp(_msg[agentid], r_msg) == 0)) + { + utimes(_keep_alive[agentid], NULL); + } + + else if(strcmp(r_msg, HC_STARTUP) == 0) + { + return; + } + + else + { + FILE *fp; + char *uname = r_msg; + + + /* locking mutex. */ + if(pthread_mutex_lock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return; + } + + + /* Update rmsg. */ + if(_msg[agentid]) + { + free(_msg[agentid]); + } + os_strdup(r_msg, _msg[agentid]); + + + /* Unlocking mutex. */ + if(pthread_mutex_unlock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return; + } + + + r_msg = strchr(r_msg, '\n'); + if(!r_msg) + { + merror("%s: WARN: Invalid message from agent id: '%d'(uname)", + ARGV0, + agentid); + return; + } + + + *r_msg = '\0'; + + + /* Updating the keep alive. */ + if(!_keep_alive[agentid]) + { + char agent_file[OS_SIZE_1024 +1]; + agent_file[OS_SIZE_1024] = '\0'; + + /* Writting to the agent file */ + snprintf(agent_file, OS_SIZE_1024, "%s/%s-%s", + AGENTINFO_DIR, + keys.keyentries[agentid]->name, + keys.keyentries[agentid]->ip->ip); + + os_strdup(agent_file, _keep_alive[agentid]); + } + + + /* Writing to the file. */ + fp = fopen(_keep_alive[agentid], "w"); + if(fp) + { + fprintf(fp, "%s\n", uname); + fclose(fp); + } + } + + + /* Locking now to notify of change. */ + if(pthread_mutex_lock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return; + } + + + /* Assign new values */ + _changed[agentid] = 1; + modified_agentid = agentid; + + + /* Signal that new data is available */ + pthread_cond_signal(&awake_mutex); + + + /* Unlocking mutex */ + if(pthread_mutex_unlock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return; + } + + + return; +} + + + +/* f_files: Free the files memory + */ +void f_files() +{ + int i; + if(!f_sum) + return; + for(i = 0;;i++) + { + if(f_sum[i] == NULL) + break; + + if(f_sum[i]->name) + free(f_sum[i]->name); + + free(f_sum[i]); + f_sum[i] = NULL; + } + + free(f_sum); + f_sum = NULL; +} + + + +/* c_files: Create the structure with the files and checksums + * Returns void + */ +void c_files() +{ + DIR *dp; + + struct dirent *entry; + + os_md5 md5sum; + + int f_size = 0; + + + f_sum = NULL; + + + /* Creating merged file. */ + os_realloc(f_sum, (f_size +2) * sizeof(file_sum *), f_sum); + os_calloc(1, sizeof(file_sum), f_sum[f_size]); + f_sum[f_size]->mark = 0; + f_sum[f_size]->name = NULL; + f_sum[f_size]->sum[0] = '\0'; + MergeAppendFile(SHAREDCFG_FILE, NULL); + f_size++; + + + + /* Opening the directory given */ + dp = opendir(SHAREDCFG_DIR); + if(!dp) + { + merror("%s: Error opening directory: '%s': %s ", + ARGV0, + SHAREDCFG_DIR, + strerror(errno)); + return; + } + + + /* Reading directory */ + while((entry = readdir(dp)) != NULL) + { + char tmp_dir[512]; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + snprintf(tmp_dir, 512, "%s/%s", SHAREDCFG_DIR, entry->d_name); + + + /* Leaving the shared config file for later. */ + if(strcmp(tmp_dir, SHAREDCFG_FILE) == 0) + { + continue; + } + + + if(OS_MD5_File(tmp_dir, md5sum) != 0) + { + merror("%s: Error accessing file '%s'",ARGV0, tmp_dir); + continue; + } + + + f_sum = (file_sum **)realloc(f_sum, (f_size +2) * sizeof(file_sum *)); + if(!f_sum) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + f_sum[f_size] = calloc(1, sizeof(file_sum)); + if(!f_sum[f_size]) + { + ErrorExit(MEM_ERROR,ARGV0); + } + + + strncpy(f_sum[f_size]->sum, md5sum, 32); + os_strdup(entry->d_name, f_sum[f_size]->name); + f_sum[f_size]->mark = 0; + + + MergeAppendFile(SHAREDCFG_FILE, tmp_dir); + f_size++; + } + + if(f_sum != NULL) + f_sum[f_size] = NULL; + + closedir(dp); + + + if(OS_MD5_File(SHAREDCFG_FILE, md5sum) != 0) + { + merror("%s: Error accessing file '%s'",ARGV0, SHAREDCFG_FILE); + f_sum[0]->sum[0] = '\0'; + } + strncpy(f_sum[0]->sum, md5sum, 32); + + + os_strdup(SHAREDCFG_FILENAME, f_sum[0]->name); + + return; +} + + + +/* send_file_toagent: Sends a file to the agent. + * Returns -1 on error + */ +int send_file_toagent(int agentid, char *name, char *sum) +{ + int i = 0, n = 0; + char file[OS_SIZE_1024 +1]; + char buf[OS_SIZE_1024 +1]; + + FILE *fp; + + + snprintf(file, OS_SIZE_1024, "%s/%s",SHAREDCFG_DIR, name); + fp = fopen(file, "r"); + if(!fp) + { + merror(FOPEN_ERROR, ARGV0, file); + return(-1); + } + + + /* Sending the file name first */ + snprintf(buf, OS_SIZE_1024, "%s%s%s %s\n", + CONTROL_HEADER, FILE_UPDATE_HEADER, sum, name); + + if(send_msg(agentid, buf) == -1) + { + merror(SEC_ERROR,ARGV0); + fclose(fp); + return(-1); + } + + + /* Sending the file content */ + while((n = fread(buf, 1, 900, fp)) > 0) + { + buf[n] = '\0'; + + if(send_msg(agentid, buf) == -1) + { + merror(SEC_ERROR,ARGV0); + fclose(fp); + return(-1); + } + + /* Sleep 1 every 30 messages -- no flood */ + if(i > 30) + { + sleep(1); + i = 0; + } + i++; + } + + + /* Sending the message to close the file */ + snprintf(buf, OS_SIZE_1024, "%s%s", CONTROL_HEADER, FILE_CLOSE_HEADER); + if(send_msg(agentid, buf) == -1) + { + merror(SEC_ERROR,ARGV0); + fclose(fp); + return(-1); + } + + + fclose(fp); + + return(0); +} + + + +/** void read_contromsg(int agentid, char *msg) v0.2. + * Reads the available control message from + * the agent. + */ +void read_controlmsg(int agentid, char *msg) +{ + int i; + + + /* Remove uname */ + msg = strchr(msg,'\n'); + if(!msg) + { + merror("%s: Invalid message from '%d' (uname)",ARGV0, agentid); + return; + } + + + *msg = '\0'; + msg++; + + + if(!f_sum) + { + /* Nothing to share with agent */ + return; + } + + + /* Parse message */ + while(*msg != '\0') + { + char *md5; + char *file; + + md5 = msg; + file = msg; + + msg = strchr(msg, '\n'); + if(!msg) + { + merror("%s: Invalid message from '%s' (strchr \\n)", + ARGV0, + keys.keyentries[agentid]->ip->ip); + break; + } + + *msg = '\0'; + msg++; + + file = strchr(file, ' '); + if(!file) + { + merror("%s: Invalid message from '%s' (strchr ' ')", + ARGV0, + keys.keyentries[agentid]->ip->ip); + break; + } + + *file = '\0'; + file++; + + + /* New agents only have merged.mg. */ + if(strcmp(file, SHAREDCFG_FILENAME) == 0) + { + if(strcmp(f_sum[0]->sum, md5) != 0) + { + debug1("%s: DEBUG Sending file '%s' to agent.", ARGV0, + f_sum[0]->name); + if(send_file_toagent(agentid,f_sum[0]->name,f_sum[0]->sum)<0) + { + merror("%s: ERROR: Unable to send file '%s' to agent.", + ARGV0, + f_sum[0]->name); + } + } + + i = 0; + while(f_sum[i]) + { + f_sum[i]->mark = 0; + i++; + } + + return; + } + + + for(i = 1;;i++) + { + if(f_sum[i] == NULL) + break; + + else if(strcmp(f_sum[i]->name, file) != 0) + continue; + + else if(strcmp(f_sum[i]->sum, md5) != 0) + f_sum[i]->mark = 1; /* Marked to update */ + + else + { + f_sum[i]->mark = 2; + } + break; + } + } + + + /* Updating each file marked */ + for(i = 1;;i++) + { + if(f_sum[i] == NULL) + break; + + if((f_sum[i]->mark == 1) || + (f_sum[i]->mark == 0)) + { + + debug1("%s: Sending file '%s' to agent.", ARGV0, f_sum[i]->name); + if(send_file_toagent(agentid,f_sum[i]->name,f_sum[i]->sum) < 0) + { + merror("%s: Error sending file '%s' to agent.", + ARGV0, + f_sum[i]->name); + } + } + + f_sum[i]->mark = 0; + } + + + return; +} + + + +/** void *wait_for_msgs(void *none) v0.1 + * Wait for new messages to read. + * The messages are going to be sent from save_controlmsg. + */ +void *wait_for_msgs(void *none) +{ + int id, i; + char msg[OS_SIZE_1024 +2]; + + + /* Initializing the memory */ + memset(msg, '\0', OS_SIZE_1024 +2); + + + /* should never leave this loop */ + while(1) + { + /* Every NOTIFY * 30 minutes, re read the files. + * If something changed, notify all agents + */ + _ctime = time(0); + if((_ctime - _stime) > (NOTIFY_TIME*30)) + { + f_files(); + c_files(); + + _stime = _ctime; + } + + + /* locking mutex */ + if(pthread_mutex_lock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return(NULL); + } + + /* If no agent changed, wait for signal */ + if(modified_agentid == -1) + { + pthread_cond_wait(&awake_mutex, &lastmsg_mutex); + } + + /* Unlocking mutex */ + if(pthread_mutex_unlock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return(NULL); + } + + + /* Checking if any agent is ready */ + for(i = 0;i= i) + { + modified_agentid = -1; + } + + id = 1; + } + + /* Unlocking mutex */ + if(pthread_mutex_unlock(&lastmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + break; + } + + if(id) + { + read_controlmsg(i, msg); + } + } + } + + return(NULL); +} + + + +/* manager_init: Should be called before anything here */ +void manager_init(int isUpdate) +{ + int i; + _stime = time(0); + + f_files(); + c_files(); + + debug1("%s: DEBUG: Running manager_init", ARGV0); + + for(i=0; iip); + tmp_ips++; + } + } + } + + + /* Bind TCP */ + if(logr.proto[position] == TCP_PROTO) + { + if((logr.sock = + OS_Bindporttcp(logr.port[position],logr.lip[position])) < 0) + { + ErrorExit(BIND_ERROR, ARGV0, logr.port[position]); + } + } + else + { + /* Using UDP. Fast, unreliable.. perfect */ + if((logr.sock = + OS_Bindportudp(logr.port[position], logr.lip[position])) < 0) + { + ErrorExit(BIND_ERROR, ARGV0, logr.port[position]); + } + } + + + + /* Revoking the privileges */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR,ARGV0, REMUSER); + } + + + /* Creating PID */ + if(CreatePID(ARGV0, getpid()) < 0) + { + ErrorExit(PID_ERROR,ARGV0); + } + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + + /* If Secure connection, deal with it */ + if(logr.conn[position] == SECURE_CONN) + { + HandleSecure(); + } + + else if(logr.proto[position] == TCP_PROTO) + { + HandleSyslogTCP(); + } + + /* If not, deal with syslog */ + else + { + HandleSyslog(); + } + + return; +} + + +/* EOF */ diff --git a/src/remoted/remoted.h b/src/remoted/remoted.h new file mode 100755 index 0000000..2ebc56b --- /dev/null +++ b/src/remoted/remoted.h @@ -0,0 +1,74 @@ +/* @(#) $Id: remoted.h,v 1.18 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __LOGREMOTE_H + +#define __LOGREMOTE_H + +#ifndef ARGV0 +#define ARGV0 "ossec-remoted" +#endif + +#include "config/remote-config.h" +#include "sec.h" + + +/*** Function prototypes ***/ + +/* Read remoted config */ +int RemotedConfig(char *cfgfile, remoted *logr); + +/* Handle Remote connections */ +void HandleRemote(int position, int uid); + +/* Handle Syslog */ +void HandleSyslog(); + +/* Handle Syslog TCP */ +void HandleSyslogTCP(); + +/* Handle Secure connections */ +void HandleSecure(); + +/* Forward active response events */ +void *AR_Forward(void *arg); + +/* Initialize the manager */ +void manager_init(int isUpdate); + +/* Wait for messages from the agent to analyze */ +void *wait_for_msgs(void *none); + +/* Save control messages */ +void save_controlmsg(int agentid, char *msg); + +/* Send message to agent */ +int send_msg(int agentid, char *msg); + +/* Initializing send_msg */ +void send_msg_init(); + +int check_keyupdate(); + +void key_lock(); + +void key_unlock(); + +void keyupdate_init(); + + +/*** Global variables ***/ + +keystore keys; +remoted logr; + +#endif diff --git a/src/remoted/secure.c b/src/remoted/secure.c new file mode 100755 index 0000000..f9e9ec7 --- /dev/null +++ b/src/remoted/secure.c @@ -0,0 +1,237 @@ +/* @(#) $Id: secure.c,v 1.29 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "os_net/os_net.h" + + +#include "remoted.h" + + +/** void HandleSecure() v0.3 + * Handle the secure connections + */ +void HandleSecure() +{ + int agentid; + + char buffer[OS_MAXSTR +1]; + char cleartext_msg[OS_MAXSTR +1]; + char srcip[IPSIZE +1]; + char *tmp_msg; + char srcmsg[OS_FLSIZE +1]; + + + int recv_b; + + struct sockaddr_in peer_info; + socklen_t peer_size; + + + /* Send msg init */ + send_msg_init(); + + + /* Initializing key mutex. */ + keyupdate_init(); + + + /* Initializing manager */ + manager_init(0); + + + /* Creating Ar forwarder thread */ + if(CreateThread(AR_Forward, (void *)NULL) != 0) + { + ErrorExit(THREAD_ERROR, ARGV0); + } + + /* Creating wait_for_msgs thread */ + if(CreateThread(wait_for_msgs, (void *)NULL) != 0) + { + ErrorExit(THREAD_ERROR, ARGV0); + } + + + /* Connecting to the message queue + * Exit if it fails. + */ + if((logr.m_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); + } + + + verbose(AG_AX_AGENTS, ARGV0, MAX_AGENTS); + + + /* Reading authentication keys */ + verbose(ENC_READ, ARGV0); + + OS_ReadKeys(&keys); + + debug1("%s: DEBUG: OS_StartCounter.", ARGV0); + OS_StartCounter(&keys); + debug1("%s: DEBUG: OS_StartCounter completed.", ARGV0); + + + /* setting up peer size */ + peer_size = sizeof(peer_info); + logr.peer_size = sizeof(peer_info); + + + /* Initializing some variables */ + memset(buffer, '\0', OS_MAXSTR +1); + memset(cleartext_msg, '\0', OS_MAXSTR +1); + memset(srcmsg, '\0', OS_FLSIZE +1); + tmp_msg = NULL; + + + + /* loop in here */ + while(1) + { + /* Receiving message */ + recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0, + (struct sockaddr *)&peer_info, &peer_size); + + + /* Nothing received */ + if(recv_b <= 0) + { + continue; + } + + + /* Setting the source ip */ + strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE); + srcip[IPSIZE] = '\0'; + + + + /* Getting a valid agentid */ + if(buffer[0] == '!') + { + tmp_msg = buffer; + tmp_msg++; + + + /* We need to make sure that we have a valid id + * and that we reduce the recv buffer size. + */ + while(isdigit((int)*tmp_msg)) + { + tmp_msg++; + recv_b--; + } + + if(*tmp_msg != '!') + { + merror(ENCFORMAT_ERROR, __local_name, srcip); + continue; + } + + *tmp_msg = '\0'; + tmp_msg++; + recv_b-=2; + + agentid = OS_IsAllowedDynamicID(&keys, buffer +1, srcip); + if(agentid == -1) + { + if(check_keyupdate()) + { + agentid = OS_IsAllowedDynamicID(&keys, buffer +1, srcip); + if(agentid == -1) + { + merror(ENC_IP_ERROR, ARGV0, srcip); + continue; + } + } + else + { + merror(ENC_IP_ERROR, ARGV0, srcip); + continue; + } + } + } + else + { + agentid = OS_IsAllowedIP(&keys, srcip); + if(agentid < 0) + { + if(check_keyupdate()) + { + agentid = OS_IsAllowedIP(&keys, srcip); + if(agentid == -1) + { + merror(DENYIP_WARN,ARGV0,srcip); + continue; + } + } + else + { + merror(DENYIP_WARN,ARGV0,srcip); + continue; + } + } + tmp_msg = buffer; + } + + + /* Decrypting the message */ + tmp_msg = ReadSecMSG(&keys, tmp_msg, cleartext_msg, + agentid, recv_b -1); + if(tmp_msg == NULL) + { + /* If duplicated, a warning was already generated */ + continue; + } + + + /* Check if it is a control message */ + if(IsValidHeader(tmp_msg)) + { + /* We need to save the peerinfo if it is a control msg */ + memcpy(&keys.keyentries[agentid]->peer_info, &peer_info, peer_size); + keys.keyentries[agentid]->rcvd = time(0); + + save_controlmsg(agentid, tmp_msg); + + continue; + } + + + /* Generating srcmsg */ + snprintf(srcmsg, OS_FLSIZE,"(%s) %s",keys.keyentries[agentid]->name, + keys.keyentries[agentid]->ip->ip); + + + /* If we can't send the message, try to connect to the + * socket again. If it not exit. + */ + if(SendMSG(logr.m_queue, tmp_msg, srcmsg, + SECURE_MQ) < 0) + { + merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); + + if((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); + } + } + } +} + + + +/* EOF */ diff --git a/src/remoted/sendmsg.c b/src/remoted/sendmsg.c new file mode 100755 index 0000000..16a50b2 --- /dev/null +++ b/src/remoted/sendmsg.c @@ -0,0 +1,163 @@ +/* @(#) $Id: sendmsg.c,v 1.4 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include + +#include "remoted.h" +#include "os_net/os_net.h" + + +/* pthread send_msg mutex */ +pthread_mutex_t sendmsg_mutex; + +/* pthread key update mutex */ +pthread_mutex_t keyupdate_mutex; + + +/* void keyupdate_init() + * Initializes mutex. + */ +void keyupdate_init() +{ + /* Initializing mutex */ + pthread_mutex_init(&keyupdate_mutex, NULL); +} + + +/* void void key_lock() + * void key_unlock() + * Locks/unlocks the update mutex. + */ +void key_lock() +{ + if(pthread_mutex_lock(&keyupdate_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + } +} +void key_unlock() +{ + if(pthread_mutex_unlock(&keyupdate_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + } +} + + +/* check_keyupdate() + * Check for key updates. + */ +int check_keyupdate() +{ + /* Checking key for updates. */ + if(!OS_CheckUpdateKeys(&keys)) + { + return(0); + } + + key_lock(); + + /* Locking before using */ + if(pthread_mutex_lock(&sendmsg_mutex) != 0) + { + key_unlock(); + merror(MUTEX_ERROR, ARGV0); + return(0); + } + + if(OS_UpdateKeys(&keys)) + { + if(pthread_mutex_unlock(&sendmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + } + key_unlock(); + return(1); + } + + if(pthread_mutex_unlock(&sendmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + } + key_unlock(); + + return(0); +} + + +/* send_msg_init(): + * Initializes send_msg. + */ +void send_msg_init() +{ + /* Initializing mutex */ + pthread_mutex_init(&sendmsg_mutex, NULL); +} + + +/* send_msg() + * Send message to an agent. + * Returns -1 on error + */ +int send_msg(int agentid, char *msg) +{ + int msg_size; + char crypt_msg[OS_MAXSTR +1]; + + + /* If we don't have the agent id, ignore it */ + if(keys.keyentries[agentid]->rcvd < (time(0) - (2*NOTIFY_TIME))) + { + return(-1); + } + + + msg_size = CreateSecMSG(&keys, msg, crypt_msg, agentid); + if(msg_size == 0) + { + merror(SEC_ERROR,ARGV0); + return(-1); + } + + + /* Locking before using */ + if(pthread_mutex_lock(&sendmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return(-1); + } + + + /* Sending initial message */ + if(sendto(logr.sock, crypt_msg, msg_size, 0, + (struct sockaddr *)&keys.keyentries[agentid]->peer_info, + logr.peer_size) < 0) + { + merror(SEND_ERROR,ARGV0, keys.keyentries[agentid]->id); + } + + + /* Unlocking mutex */ + if(pthread_mutex_unlock(&sendmsg_mutex) != 0) + { + merror(MUTEX_ERROR, ARGV0); + return(-1); + } + + + return(0); +} + + + +/* EOF */ diff --git a/src/remoted/syslog.c b/src/remoted/syslog.c new file mode 100755 index 0000000..bbd0522 --- /dev/null +++ b/src/remoted/syslog.c @@ -0,0 +1,144 @@ +/* @(#) $Id: syslog.c,v 1.17 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "os_net/os_net.h" + +#include "remoted.h" + + + +/* OS_IPNotAllowed, v0.1, 2005/02/11 + * Checks if an IP is not allowed. + */ +static int OS_IPNotAllowed(char *srcip) +{ + if(logr.denyips != NULL) + { + if(OS_IPFoundList(srcip, logr.denyips)) + { + return(1); + } + } + if(logr.allowips != NULL) + { + if(OS_IPFoundList(srcip, logr.allowips)) + { + return(0); + } + } + + /* If the ip is not allowed, it will be denied */ + return(1); +} + + +/** void HandleSyslog() v0.2 + * Handle syslog connections + */ +void HandleSyslog() +{ + char buffer[OS_SIZE_1024 +2]; + char srcip[IPSIZE +1]; + + char *buffer_pt = NULL; + + int recv_b; + + struct sockaddr_in peer_info; + socklen_t peer_size; + + + /* setting peer size */ + peer_size = sizeof(peer_info); + + + /* Initializing some variables */ + memset(buffer, '\0', OS_SIZE_1024 +2); + + + /* Connecting to the message queue + * Exit if it fails. + */ + if((logr.m_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL,ARGV0, DEFAULTQUEUE); + } + + + /* Infinite loop in here */ + while(1) + { + /* Receiving message */ + recv_b = recvfrom(logr.sock, buffer, OS_SIZE_1024, 0, + (struct sockaddr *)&peer_info, &peer_size); + + /* Nothing received */ + if(recv_b <= 0) + continue; + + + /* null terminating the message */ + buffer[recv_b] = '\0'; + + + /* Removing new line */ + if(buffer[recv_b -1] == '\n') + { + buffer[recv_b -1] = '\0'; + } + + /* Setting the source ip */ + strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE); + srcip[IPSIZE] = '\0'; + + + /* Removing syslog header */ + if(buffer[0] == '<') + { + buffer_pt = strchr(buffer+1, '>'); + if(buffer_pt) + { + buffer_pt++; + } + else + { + buffer_pt = buffer; + } + } + else + { + buffer_pt = buffer; + } + + /* Checking if IP is allowed here */ + if(OS_IPNotAllowed(srcip)) + { + merror(DENYIP_WARN,ARGV0,srcip); + } + + else if(SendMSG(logr.m_queue, buffer_pt, srcip, + SYSLOG_MQ) < 0) + { + merror(QUEUE_ERROR,ARGV0,DEFAULTQUEUE, strerror(errno)); + if((logr.m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0) + { + ErrorExit(QUEUE_FATAL,ARGV0,DEFAULTQUEUE); + } + } + } +} + + + +/* EOF */ diff --git a/src/remoted/syslogtcp.c b/src/remoted/syslogtcp.c new file mode 100755 index 0000000..c0efcd5 --- /dev/null +++ b/src/remoted/syslogtcp.c @@ -0,0 +1,247 @@ +/* @(#) $Id: syslogtcp.c,v 1.8 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + + +#include "shared.h" +#include "os_net/os_net.h" + +#include "remoted.h" + + + +/* OS_IPNotAllowed, v0.1, 2005/02/11 + * Checks if an IP is not allowed. + */ +static int OS_IPNotAllowed(char *srcip) +{ + if(logr.denyips != NULL) + { + if(OS_IPFoundList(srcip, logr.denyips)) + { + return(1); + } + } + if(logr.allowips != NULL) + { + if(OS_IPFoundList(srcip, logr.allowips)) + { + return(0); + } + } + + /* If the ip is not allowed, it will be denied */ + return(1); +} + + +/** void HandleClient() v0,1 + * Handle each client + */ +static void HandleClient(int client_socket, char *srcip) +{ + int sb_size = OS_MAXSTR; + int r_sz = 0; + + char buffer[OS_MAXSTR +2]; + char storage_buffer[OS_MAXSTR +2]; + char tmp_buffer[OS_MAXSTR +2]; + + char *buffer_pt = NULL; + + + /* Initializing some variables */ + memset(buffer, '\0', OS_MAXSTR +2); + memset(storage_buffer, '\0', OS_MAXSTR +2); + memset(tmp_buffer, '\0', OS_MAXSTR +2); + + + while(1) + { + /* If we fail, we need to return and close the socket */ + if((r_sz = OS_RecvTCPBuffer(client_socket, buffer, OS_MAXSTR -2)) < 0) + { + close(client_socket); + return; + } + + /* We must have a new line at the end */ + buffer_pt = strchr(buffer, '\n'); + if(!buffer_pt) + { + /* Buffer is full */ + if((sb_size - r_sz) <= 2) + { + merror("%s: Full buffer receiving from: '%s'", ARGV0, srcip); + sb_size = OS_MAXSTR; + storage_buffer[0] = '\0'; + continue; + } + + strncat(storage_buffer, buffer, sb_size); + sb_size -= r_sz; + continue; + } + + /* Seeing if we received more then just one message */ + if(*(buffer_pt +1) != '\0') + { + *buffer_pt = '\0'; + buffer_pt++; + strncpy(tmp_buffer, buffer_pt, OS_MAXSTR); + } + + /* Storing everything on the storage_buffer */ + /* Checking if buffer will be full */ + if((sb_size - r_sz) <= 2) + { + merror("%s: Full buffer receiving from: '%s'.", ARGV0, srcip); + sb_size = OS_MAXSTR; + storage_buffer[0] = '\0'; + tmp_buffer[0] = '\0'; + continue; + } + + strncat(storage_buffer, buffer, sb_size); + + + /* Removing carriage returns too */ + buffer_pt = strchr(storage_buffer, '\r'); + if(buffer_pt) + *buffer_pt = '\0'; + + + /* Removing syslog header */ + if(storage_buffer[0] == '<') + { + buffer_pt = strchr(storage_buffer+1, '>'); + if(buffer_pt) + { + buffer_pt++; + } + else + { + buffer_pt = storage_buffer; + } + } + else + { + buffer_pt = storage_buffer; + } + + + /* Sending to the queue */ + if(SendMSG(logr.m_queue, buffer_pt, srcip,SYSLOG_MQ) < 0) + { + merror(QUEUE_ERROR,ARGV0,DEFAULTQUEUE, strerror(errno)); + if((logr.m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0) + { + ErrorExit(QUEUE_FATAL,ARGV0,DEFAULTQUEUE); + } + } + + /* Cleaning up the buffers */ + if(tmp_buffer[0] != '\0') + { + strncpy(storage_buffer, tmp_buffer, OS_MAXSTR); + sb_size = OS_MAXSTR - (strlen(storage_buffer) +1); + tmp_buffer[0] = '\0'; + } + else + { + storage_buffer[0] = '\0'; + sb_size = OS_MAXSTR; + } + } +} + + +/** void HandleSyslogTCP() v0.2 + * Handle syslog tcp connections + */ +void HandleSyslogTCP() +{ + int client_socket = 0; + int st_errors = 0; + int childcount = 0; + + char srcip[IPSIZE +1]; + + /* Initializing some variables */ + memset(srcip, '\0', IPSIZE + 1); + + + /* Connecting to the message queue + * Exit if it fails. + */ + if((logr.m_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL,ARGV0, DEFAULTQUEUE); + } + + + /* Infinit loop in here */ + while(1) + { + /* Waiting for the childs .. */ + while (childcount) + { + int wp; + wp = waitpid((pid_t) -1, NULL, WNOHANG); + if (wp < 0) + merror(WAITPID_ERROR, ARGV0); + + /* if = 0, we still need to wait for the child process */ + else if (wp == 0) + break; + else + childcount--; + } + + + /* Accepting new connections */ + client_socket = OS_AcceptTCP(logr.sock, srcip, IPSIZE); + if(client_socket < 0) + { + st_errors++; + } + + /* Checking if IP is allowed here */ + if(OS_IPNotAllowed(srcip)) + { + merror(DENYIP_WARN,ARGV0,srcip); + close(client_socket); + } + + + /* Forking to deal with new client */ + if(fork() == 0) + { + HandleClient(client_socket, srcip); + exit(0); + } + else + { + childcount++; + + /* Closing client socket, since the child is handling it */ + close(client_socket); + continue; + } + + /* The parent process should not reach here */ + return; + } +} + + + +/* EOF */ diff --git a/src/rootcheck/Makefile b/src/rootcheck/Makefile new file mode 100755 index 0000000..e47d7c8 --- /dev/null +++ b/src/rootcheck/Makefile @@ -0,0 +1,24 @@ +# Makefile for OSSEC rootcheck +# Daniel B. Cid || +# http://www.ossec.net/hids/ +# http://www.ossec.net/rootcheck/ + +PT=../ +NAME=ossec-rootcheck + +include ../Config.Make + + +OBJS = check_open_ports.c check_rc_pids.c check_rc_trojans.c run_rk_check.c check_rc_dev.c check_rc_ports.c check_rc_policy.c common.c common_rcl.c win-common.c unix-process.c check_rc_files.c check_rc_readproc.c os_string.c check_rc_if.c check_rc_sys.c rootcheck.c +OBJS2 = ${OS_SHARED} ${OS_XML} ${OS_REGEX} + +rootcheck: + $(CC) $(CFLAGS) -c ${OBJS} config.c -D_GNU_SOURCE + ar cru rootcheck_lib.a *.o + ranlib rootcheck_lib.a + +binary: + $(CC) $(CFLAGS) ${OS_LINK} ${OBJS} rootcheck-config.c ${OBJS2} -UOSSECHIDS -D_GNU_SOURCE -o ${NAME} +clean: + ${CLEAN} rootcheck_lib.a +build: diff --git a/src/rootcheck/check_open_ports.c b/src/rootcheck/check_open_ports.c new file mode 100755 index 0000000..bbe2fc5 --- /dev/null +++ b/src/rootcheck/check_open_ports.c @@ -0,0 +1,134 @@ +/* @(#) $Id: check_open_ports.c,v 1.8 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "headers/defs.h" +#include "headers/debug_op.h" + +#include "rootcheck.h" + + +int _ports_open; +int open_ports_size; +char open_ports_str[OS_SIZE_1024 + 1]; + +/* connect_to_port */ +int connect_to_port(int proto, int port) +{ + int rc = 0; + + int ossock; + struct sockaddr_in server; + + if(proto == IPPROTO_UDP) + { + if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) + return(0); + } + else if(proto == IPPROTO_TCP) + { + if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) + return(0); + } + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons( port ); + server.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if(connect(ossock, (struct sockaddr *)&server, sizeof(server)) == 0) + { + rc = 1; + } + + close(ossock); + + return(rc); +} + +/* try_to_access_ports */ +void try_to_access_ports() +{ + int i; + + for(i = 0; i<= 65535; i++) + { + if(total_ports_tcp[i] && connect_to_port(IPPROTO_TCP, i)) + { + char port_proto[64]; + + if(_ports_open == 0) + { + snprintf(port_proto, 64, "\n %d (tcp),", i); + } + else + { + snprintf(port_proto, 64, "%d (tcp),", i); + } + strncat(open_ports_str, port_proto, open_ports_size); + open_ports_size -= strlen(port_proto) +1; + + _ports_open++; + } + if(total_ports_udp[i] && connect_to_port(IPPROTO_UDP, i)) + { + char port_proto[64]; + + if(_ports_open == 0) + { + snprintf(port_proto, 64, "\n %d (udp),", i); + } + else + { + snprintf(port_proto, 64, "%d (udp),", i); + } + + strncat(open_ports_str, port_proto, open_ports_size); + open_ports_size -= strlen(port_proto) +1; + + _ports_open++; + } + + if(_ports_open >= 4) + { + _ports_open = 0; + } + } + +} + + +/* check_open_ports: v0.1 + * Check all open ports + */ +void check_open_ports() +{ + memset(open_ports_str, '\0', OS_SIZE_1024 +1); + open_ports_size = OS_SIZE_1024 - 1; + _ports_open = 0; + + #ifndef OSSECHIDS + snprintf(open_ports_str, OS_SIZE_1024, "The following ports are open:"); + open_ports_size-=strlen(open_ports_str) +1; + + /* Testing All ports */ + try_to_access_ports(); + + open_ports_str[strlen(open_ports_str) -1] = '\0'; + + notify_rk(ALERT_OK, open_ports_str); + + #endif + return; +} + +/* EOF */ diff --git a/src/rootcheck/check_rc_dev.c b/src/rootcheck/check_rc_dev.c new file mode 100755 index 0000000..5fb8503 --- /dev/null +++ b/src/rootcheck/check_rc_dev.c @@ -0,0 +1,191 @@ +/* @(#) $Id: check_rc_dev.c,v 1.24 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef WIN32 +#include "shared.h" +#include "rootcheck.h" + +int _dev_errors; +int _dev_total; + +/** Prototypes **/ +int read_dev_dir(char *dir_name); + +int read_dev_file(char *file_name) +{ + struct stat statbuf; + + if(lstat(file_name, &statbuf) < 0) + { + return(-1); + } + + if(S_ISDIR(statbuf.st_mode)) + { + #ifdef DEBUG + verbose("%s: Reading dir: %s\n",ARGV0, file_name); + #endif + + return(read_dev_dir(file_name)); + } + + else if(S_ISREG(statbuf.st_mode)) + { + char op_msg[OS_SIZE_1024 +1]; + + snprintf(op_msg, OS_SIZE_1024, "File '%s' present on /dev." + " Possible hidden file.", file_name); + notify_rk(ALERT_SYSTEM_CRIT, op_msg); + + _dev_errors++; + } + + return(0); +} + +/* read_dir v0.1 + * + */ +int read_dev_dir(char *dir_name) +{ + int i; + + DIR *dp; + + struct dirent *entry; + + /* when will these people learn that dev is not + * meant to store log files or other kind of texts.. + */ + char *(ignore_dev[]) = {"MAKEDEV","README.MAKEDEV", + "MAKEDEV.README", ".udevdb", + ".udev.tdb", ".initramfs-tools", + "MAKEDEV.local", ".udev", ".initramfs", + "oprofile","fd", + #ifdef SOLARIS + ".devfsadm_dev.lock", + ".devlink_db_lock", + ".devlink_db", + ".devfsadm_daemon.lock", + ".devfsadm_deamon.lock", + ".devfsadm_synch_door", + ".zone_reg_door", + #endif + NULL}; + + + /* Full path ignore */ + char *(ignore_dev_full_path[]) = {"/dev/shm/sysconfig", + "/dev/bus/usb/.usbfs", + "/dev/shm", + "/dev/gpmctl", + NULL}; + + if((dir_name == NULL)||(strlen(dir_name) > PATH_MAX)) + { + merror("%s: Invalid directory given.",ARGV0); + return(-1); + } + + /* Opening the directory given */ + dp = opendir(dir_name); + if(!dp) + { + return(-1); + } + + while((entry = readdir(dp)) != NULL) + { + char f_name[PATH_MAX +2]; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + continue; + + _dev_total++; + + /* Do not look for the ignored files */ + for(i = 0;ignore_dev[i] != NULL;i++) + { + if(strcmp(ignore_dev[i], entry->d_name) == 0) + break; + } + + if(ignore_dev[i] != NULL) + continue; + + f_name[PATH_MAX +1] = '\0'; + snprintf(f_name, PATH_MAX +1, "%s/%s",dir_name, entry->d_name); + + + /* Do not look for the full ignored files */ + for(i = 0;ignore_dev_full_path[i] != NULL;i++) + { + if(strcmp(ignore_dev_full_path[i], f_name) == 0) + break; + } + + + /* Checking against the full path. */ + if(ignore_dev_full_path[i] != NULL) + { + continue; + } + + + read_dev_file(f_name); + + } + + closedir(dp); + + return(0); +} + + +/* check_rc_dev: v0.1 + * + */ +void check_rc_dev(char *basedir) +{ + char file_path[OS_SIZE_1024 +1]; + + _dev_total = 0, _dev_errors = 0; + + debug1("%s: DEBUG: Starting on check_rc_dev", ARGV0); + + snprintf(file_path, OS_SIZE_1024, "%s/dev", basedir); + + read_dev_dir(file_path); + + if(_dev_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "No problem detected on the /dev " + "directory. Analyzed %d files", + _dev_total); + notify_rk(ALERT_OK, op_msg); + } + + return; +} + +/* EOF */ + +#else +/* Windows */ +void check_rc_dev(char *basedir) +{ + return; +} +#endif diff --git a/src/rootcheck/check_rc_files.c b/src/rootcheck/check_rc_files.c new file mode 100755 index 0000000..a83f89c --- /dev/null +++ b/src/rootcheck/check_rc_files.c @@ -0,0 +1,219 @@ +/* @(#) $Id: check_rc_files.c,v 1.12 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck.h" + + + +/* check_rc_files: + * Read the file pointer specified (rootkit_files) + * and check if the configured file is there + */ +void check_rc_files(char *basedir, FILE *fp) +{ + char buf[OS_SIZE_1024 +1]; + char file_path[OS_SIZE_1024 +1]; + + char *file; + char *name; + char *link; + + int _errors = 0; + int _total = 0; + + + debug1("%s: DEBUG: Starting on check_rc_files", ARGV0); + + while(fgets(buf, OS_SIZE_1024, fp) != NULL) + { + char *nbuf; + + /* Removing end of line */ + nbuf = strchr(buf, '\n'); + if(nbuf) + { + *nbuf = '\0'; + } + + /* Assigning buf to be used */ + nbuf = buf; + + /* Excluding commented lines or blanked ones */ + while(*nbuf != '\0') + { + if(*nbuf == ' ' || *nbuf == '\t') + { + nbuf++; + continue; + } + else if(*nbuf == '#') + goto newline; + else + break; + } + + if(*nbuf == '\0') + goto newline; + + /* File now may be valid */ + file = nbuf; + name = nbuf; + + + /* Getting the file and the rootkit name */ + while(*nbuf != '\0') + { + if(*nbuf == ' ' || *nbuf == '\t') + { + /* Setting the limit for the file */ + *nbuf = '\0'; + nbuf++; + break; + } + else + { + nbuf++; + } + } + + if(*nbuf == '\0') + goto newline; + + + /* Some ugly code to remove spaces and \t */ + while(*nbuf != '\0') + { + if(*nbuf == '!') + { + nbuf++; + if(*nbuf == ' ' || *nbuf == '\t') + { + nbuf++; + name = nbuf; + + break; + } + } + else if(*nbuf == ' ' || *nbuf == '\t') + { + nbuf++; + continue; + } + else + { + goto newline; + } + } + + + /* Getting the link (if present) */ + link = strchr(nbuf, ':'); + if(link) + { + *link = '\0'; + + link++; + if(*link == ':') + { + link++; + } + } + + + /* Cleaning any space of \t at the end */ + nbuf = strchr(nbuf, ' '); + if(nbuf) + { + *nbuf = '\0'; + } + + nbuf = strchr(nbuf, '\t'); + if(nbuf) + { + *nbuf = '\0'; + } + + _total++; + + + /* Checking if it is a file to search everywhere */ + if(*file == '*') + { + if(rk_sys_count >= MAX_RK_SYS) + { + merror(MAX_RK_MSG, ARGV0, MAX_RK_SYS); + } + + else + { + /* Removing * / from the file */ + file++; + if(*file == '/') + file++; + + /* Memory assignment */ + rk_sys_file[rk_sys_count] = strdup(file); + rk_sys_name[rk_sys_count] = strdup(name); + + if(!rk_sys_name[rk_sys_count] || + !rk_sys_file[rk_sys_count] ) + { + merror(MEM_ERROR, ARGV0); + + if(rk_sys_file[rk_sys_count]) + free(rk_sys_file[rk_sys_count]); + if(rk_sys_name[rk_sys_count]) + free(rk_sys_name[rk_sys_count]); + + rk_sys_file[rk_sys_count] = NULL; + rk_sys_name[rk_sys_count] = NULL; + } + + rk_sys_count++; + + /* Always assigning the last as NULL */ + rk_sys_file[rk_sys_count] = NULL; + rk_sys_name[rk_sys_count] = NULL; + } + continue; + } + + snprintf(file_path, OS_SIZE_1024, "%s/%s",basedir, file); + + /* Checking if file exists */ + if(is_file(file_path)) + { + char op_msg[OS_SIZE_1024 +1]; + + _errors = 1; + snprintf(op_msg, OS_SIZE_1024, "Rootkit '%s' detected " + "by the presence of file '%s'.",name, file_path); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + } + + newline: + continue; + } + + if(_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg,OS_SIZE_1024,"No presence of public rootkits detected." + " Analyzed %d files.", _total); + notify_rk(ALERT_OK, op_msg); + } +} + + +/* EOF */ diff --git a/src/rootcheck/check_rc_if.c b/src/rootcheck/check_rc_if.c new file mode 100755 index 0000000..3415861 --- /dev/null +++ b/src/rootcheck/check_rc_if.c @@ -0,0 +1,144 @@ +/* @(#) $Id: check_rc_if.c,v 1.10 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#ifndef WIN32 +#include +#include + +#include +#include + +#include +#include +#include +#include + +/* Solaris happy again */ +#ifdef SOLARIS +#include +#include +#endif + +#include "headers/defs.h" +#include "headers/debug_op.h" + +#include "rootcheck.h" + +#ifndef IFCONFIG +#define IFCONFIG "ifconfig %s | grep PROMISC > /dev/null 2>&1" +#endif + + +/* run_ifconfig: Execute the ifconfig command. + * Returns 1 if interface in promisc mode. + */ +int run_ifconfig(char *ifconfig) +{ + char nt[OS_SIZE_1024 +1]; + + snprintf(nt, OS_SIZE_1024, IFCONFIG, ifconfig); + + if(system(nt) == 0) + return(1); + + return(0); +} + + +/* check_rc_if: v0.1 + * Check all interfaces for promiscuous mode + */ +void check_rc_if() +{ + int _fd, _errors = 0, _total = 0; + struct ifreq tmp_str[16]; + + struct ifconf _if; + struct ifreq *_ir; + struct ifreq *_ifend; + struct ifreq _ifr; + + _fd = socket(AF_INET, SOCK_DGRAM, 0); + if(_fd < 0) + { + merror("%s: Error checking interfaces (socket)", ARGV0); + return; + } + + + memset(tmp_str, 0, sizeof(struct ifreq)*16); + _if.ifc_len = sizeof(tmp_str); + _if.ifc_buf = (caddr_t)(tmp_str); + + if (ioctl(_fd, SIOCGIFCONF, &_if) < 0) + { + close(_fd); + merror("%s: Error checking interfaces (ioctl)", ARGV0); + return; + } + + _ifend = (struct ifreq*) ((char*)tmp_str + _if.ifc_len); + _ir = tmp_str; + + /* Looping on all interfaces */ + for (; _ir < _ifend; _ir++) + { + strncpy(_ifr.ifr_name, _ir->ifr_name, sizeof(_ifr.ifr_name)); + + /* Getting information from each interface */ + if (ioctl(_fd, SIOCGIFFLAGS, (char*)&_ifr) == -1) + { + continue; + } + + _total++; + + + if ((_ifr.ifr_flags & IFF_PROMISC) ) + { + char op_msg[OS_SIZE_1024 +1]; + if(run_ifconfig(_ifr.ifr_name)) + { + snprintf(op_msg, OS_SIZE_1024,"Interface '%s' in promiscuous" + " mode.", _ifr.ifr_name); + notify_rk(ALERT_SYSTEM_CRIT, op_msg); + } + else + { + snprintf(op_msg, OS_SIZE_1024,"Interface '%s' in promiscuous" + " mode, but ifconfig is not showing it" + "(probably trojaned).", _ifr.ifr_name); + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + } + _errors++; + } + } + close(_fd); + + if(_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "No problem detected on ifconfig/ifs." + " Analyzed %d interfaces.", _total); + notify_rk(ALERT_OK, op_msg); + } + + return; +} + +/* EOF */ + +#else +void check_rc_if() +{ + return; +} +#endif diff --git a/src/rootcheck/check_rc_pids.c b/src/rootcheck/check_rc_pids.c new file mode 100755 index 0000000..982cc6c --- /dev/null +++ b/src/rootcheck/check_rc_pids.c @@ -0,0 +1,391 @@ +/* @(#) $Id: check_rc_pids.c,v 1.29 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#ifndef WIN32 +#include "shared.h" +#include "rootcheck.h" + + +int noproc; + + +/** int proc_read(int pid) + * If /proc is mounted, check to see if the pid is present + */ +int proc_read(int pid) +{ + char dir[OS_SIZE_1024 +1]; + + if(noproc) + return(0); + + snprintf(dir, OS_SIZE_1024, "%d", pid); + if(isfile_ondir(dir, "/proc")) + { + return(1); + } + return(0); +} + + +/** int proc_chdir(int pid) + * If /proc is mounted, check to see if the pid is present + */ +int proc_chdir(int pid) +{ + int ret = 0; + char curr_dir[OS_SIZE_1024 + 1]; + char dir[OS_SIZE_1024 + 1]; + + if(noproc) + return(0); + + if(!getcwd(curr_dir, OS_SIZE_1024)) + { + return(0); + } + + if(chdir("/proc") == -1) + return(0); + + snprintf(dir, OS_SIZE_1024, "/proc/%d", pid); + if(chdir(dir) == 0) + { + ret = 1; + } + + /* Returning to the previous directory */ + chdir(curr_dir); + + return(ret); +} + + +/** int proc_stat(int pid) + * If /proc is mounted, check to see if the pid is present there. + */ +int proc_stat(int pid) +{ + char proc_dir[OS_SIZE_1024 + 1]; + + if(noproc) + return(0); + + snprintf(proc_dir, OS_SIZE_1024, "%s/%d", "/proc", pid); + + if(is_file(proc_dir)) + { + return(1); + } + + return(0); +} + + +/** void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total) + * Check all the available PIDs for hidden stuff. + */ +void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total) +{ + int _kill0 = 0; + int _kill1 = 0; + int _gsid0 = 0; + int _gsid1 = 0; + int _gpid0 = 0; + int _gpid1 = 0; + int _ps0 = -1; + int _proc_stat = 0; + int _proc_read = 0; + int _proc_chdir = 0; + + pid_t i = 1; + pid_t my_pid; + + char command[OS_SIZE_1024 +1]; + + my_pid = getpid(); + + for(;;i++) + { + if((i <= 0)||(i > max_pid)) + break; + + (*_total)++; + + _kill0 = 0; + _kill1 = 0; + _gsid0 = 0; + _gsid1 = 0; + _gpid0 = 0; + _gpid1 = 0; + _ps0 = -1; + _proc_stat = 0; + _proc_read = 0; + _proc_chdir = 0; + + + /* kill test */ + if(!((kill(i, 0) == -1)&&(errno == ESRCH))) + { + _kill0 = 1; + } + + /* getsid to test */ + if(!((getsid(i) == -1)&&(errno == ESRCH))) + { + _gsid0 = 1; + } + + /* getpgid test */ + if(!((getpgid(i) == -1)&&(errno == ESRCH))) + { + _gpid0 = 1; + } + + + /* proc stat */ + _proc_stat = proc_stat(i); + + /* proc readdir */ + _proc_read = proc_read(i); + + /* proc chdir */ + _proc_chdir = proc_chdir(i); + + + /* IF PID does not exist, keep going */ + if(!_kill0 && !_gsid0 && !_gpid0 && + !_proc_stat && !_proc_read && !_proc_chdir) + { + continue; + } + + /* We do not need to look at our own pid */ + else if(i == my_pid) + { + continue; + } + + /* Checking the number of errors */ + if((*_errors) > 15) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg,OS_SIZE_1024,"Excessive number of hidden processes" + ". It maybe a false-positive or " + "something really bad is going on."); + notify_rk(ALERT_SYSTEM_CRIT, op_msg); + return; + } + + + /* checking if process appears on ps */ + if(*ps) + { + snprintf(command, OS_SIZE_1024, "%s -p %d > /dev/null 2>&1", + ps, + (int)i); + + /* Found PID on ps */ + _ps0 = 0; + if(system(command) == 0) + _ps0 = 1; + } + + /* If we are being run by the ossec hids, sleep here (no rush) */ + #ifdef OSSECHIDS + sleep(2); + #endif + + /* Everyone returned ok */ + if(_ps0 && _kill0 && _gsid0 && _gpid0 && _proc_stat && _proc_read) + { + continue; + } + + + + /* If our kill or getsid system call, got the + * PID , but ps didn't, we need to find if it was a problem + * with a PID being deleted (not used anymore) + */ + { + if(!((getsid(i) == -1)&&(errno == ESRCH))) + { + _gsid1 = 1; + } + + if(!((kill(i, 0) == -1)&&(errno == ESRCH))) + { + _kill1 = 1; + } + + if(!((getpgid(i) == -1)&&(errno == ESRCH))) + { + _gpid1 = 1; + } + + + _proc_stat = proc_stat(i); + + _proc_read = proc_read(i); + + _proc_chdir = proc_chdir(i); + + /* If it matches, process was terminated */ + if(!_gsid1 &&!_kill1 &&!_gpid1 &&!_proc_stat && + !_proc_read &&!_proc_chdir) + { + continue; + } + } + + #ifdef AIX + /* Ignoring AIX wait and sched programs. */ + if((_gsid0 == _gsid1) && + (_kill0 == _kill1) && + (_gpid0 == _gpid1) && + (_ps0 == 1) && + (_gsid0 == 1) && + (_kill0 == 0)) + { + /* The wait and sched programs do not respond to kill 0. + * So, if everything else finds it, including ps, getpid, getsid, + * but not + * kill, we can safely ignore on AIX. + * A malicious program would specially try to hide from ps.. + */ + continue; + } + #endif + + + if((_gsid0 == _gsid1)&& + (_kill0 == _kill1)&& + (_gsid0 != _kill0)) + { + /* If kill found, but getsid and getpgid didnt', it may + * be a defunct process -- ignore. + */ + if(!((_kill0 == 1)&&(_gsid0 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0))) + { + char op_msg[OS_SIZE_1024 +1]; + + snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from " + "kill (%d) or getsid (%d). Possible kernel-level" + " rootkit.", (int)i, _kill0, _gsid0); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + (*_errors)++; + } + } + else if((_kill1 != _gsid1)|| + (_gpid1 != _kill1)|| + (_gpid1 != _gsid1)) + { + /* See defunct process comment above. */ + if(!((_kill1 == 1)&&(_gsid1 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0))) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from " + "kill (%d), getsid (%d) or getpgid. Possible " + "kernel-level rootkit.", (int)i, _kill1, _gsid1); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + (*_errors)++; + } + } + else if((_proc_read != _proc_stat)|| + (_proc_read != _proc_chdir)|| + (_proc_stat != _kill1)) + { + /* checking if the pid is a thread (not showing on proc */ + if(!noproc && !check_rc_readproc((int)i)) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from " + "/proc. Possible kernel level rootkit.", (int)i); + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + (*_errors)++; + } + } + else if(_gsid1 && _kill1 && !_ps0) + { + /* checking if the pid is a thread (not showing on ps */ + if(!check_rc_readproc((int)i)) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from " + "ps. Possible trojaned version installed.", + (int)i); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + (*_errors)++; + } + } + } +} + + +/* check_rc_sys: v0.1 + * Scan the whole filesystem looking for possible issues + */ +void check_rc_pids() +{ + int _total = 0; + int _errors = 0; + + char ps[OS_SIZE_1024 +1]; + + char proc_0[] = "/proc"; + char proc_1[] = "/proc/1"; + + pid_t max_pid = MAX_PID; + + noproc = 1; + + /* Checking where ps is */ + memset(ps, '\0', OS_SIZE_1024 +1); + strncpy(ps, "/bin/ps", OS_SIZE_1024); + if(!is_file(ps)) + { + strncpy(ps, "/usr/bin/ps", OS_SIZE_1024); + if(!is_file(ps)) + ps[0] = '\0'; + } + + + /* Proc is mounted */ + if(is_file(proc_0) && is_file(proc_1)) + { + noproc = 0; + } + + loop_all_pids(ps, max_pid, &_errors, &_total); + + if(_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "No hidden process by Kernel-level " + "rootkits.\n %s is not trojaned. " + "Analyzed %d processes.", ps, _total); + notify_rk(ALERT_OK, op_msg); + } + + return; +} + +/* EOF */ +#else +void check_rc_pids() +{ + return; +} +#endif diff --git a/src/rootcheck/check_rc_policy.c b/src/rootcheck/check_rc_policy.c new file mode 100755 index 0000000..c7b96e5 --- /dev/null +++ b/src/rootcheck/check_rc_policy.c @@ -0,0 +1,69 @@ +/* @(#) $Id: check_rc_policy.c,v 1.3 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck.h" + + + +/* check_rc_unixaudit: + * Read the file pointer specified + * and check if the configured file is there + */ +void check_rc_unixaudit(FILE *fp, void *p_list) +{ + debug1("%s: DEBUG: Starting on check_rc_unixaudit", ARGV0); + + rkcl_get_entry(fp, "System Audit:", p_list); + +} + + + +/* check_rc_winaudit: + * Read the file pointer specified (winpolicy) + * and check if the configured file is there + */ +void check_rc_winaudit(FILE *fp, void *p_list) +{ + debug1("%s: DEBUG: Starting on check_rc_winaudit", ARGV0); + + rkcl_get_entry(fp, "Windows Audit:", p_list); + +} + +/* check_rc_winmalware: + * Read the file pointer specified (winpolicy) + * and check if the configured file is there + */ +void check_rc_winmalware(FILE *fp, void *p_list) +{ + debug1("%s: DEBUG: Starting on check_rc_winmalware", ARGV0); + + rkcl_get_entry(fp, "Windows Malware:", p_list); + +} + +/* check_rc_winapps: + * Read the file pointer specified (winpolicy) + * and check if the configured file is there + */ +void check_rc_winapps(FILE *fp, void *p_list) +{ + debug1("%s: DEBUG: Starting on check_rc_winapps", ARGV0); + + rkcl_get_entry(fp, "Application Found:", p_list); +} + + + +/* EOF */ diff --git a/src/rootcheck/check_rc_ports.c b/src/rootcheck/check_rc_ports.c new file mode 100755 index 0000000..57cc3d5 --- /dev/null +++ b/src/rootcheck/check_rc_ports.c @@ -0,0 +1,209 @@ +/* @(#) $Id: check_rc_ports.c,v 1.21 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef WIN32 + +#include "shared.h" +#include "rootcheck.h" + +/* SunOS netstat */ +#if defined(sun) || defined(__sun__) +#define NETSTAT "netstat -an -P %s | "\ + "grep \"[^0-9]%d \" > /dev/null 2>&1" + +/* +#elif WIN32 +#define NETSTAT "netstat -an -p %s | "\ + "find \":%d\"" +*/ + +#elif defined(Linux) +#define NETSTAT_LIST "netstat -an | grep \"^%s\" | "\ + "cut -d ':' -f 2 | cut -d ' ' -f 1" +#define NETSTAT "netstat -an | grep \"^%s\" | " \ + "grep \"[^0-9]%d \" > /dev/null 2>&1" +#endif + +#ifndef NETSTAT +#define NETSTAT "netstat -an | grep \"^%s\" | " \ + "grep \"[^0-9]%d \" > /dev/null 2>&1" +#endif + + +int run_netstat(int proto, int port) +{ + char nt[OS_SIZE_1024 +1]; + + if(proto == IPPROTO_TCP) + snprintf(nt, OS_SIZE_1024, NETSTAT, "tcp", port); + else if(proto == IPPROTO_UDP) + snprintf(nt, OS_SIZE_1024, NETSTAT, "udp", port); + else + { + merror("%s: Netstat error (wrong protocol)", ARGV0); + return(0); + } + + if(system(nt) == 0) + return(1); + + return(0); +} + + +int conn_port(int proto, int port) +{ + int rc = 0; + int ossock; + struct sockaddr_in server; + + if(proto == IPPROTO_UDP) + { + if((ossock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) + return(0); + } + else if(proto == IPPROTO_TCP) + { + if((ossock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) + return(0); + } + + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons( port ); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + + /* If we can't bind, it means the port is open */ + if(bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0) + { + rc = 1; + } + + /* Setting if port is open or closed */ + if(proto == IPPROTO_TCP) + { + total_ports_tcp[port] = rc; + } + else + { + total_ports_udp[port] = rc; + } + + close(ossock); + + return(rc); +} + + +void test_ports(int proto, int *_errors, int *_total) +{ + int i; + + for(i = 0; i<= 65535; i++) + { + (*_total)++; + if(conn_port(proto, i)) + { + /* Checking if we can find it using netstat, if not, + * check again to see if the port is still being used. + */ + if(run_netstat(proto, i)) + { + continue; + + #ifdef OSSECHIDS + sleep(2); + #endif + } + + /* If we are being run by the ossec hids, sleep here (no rush) */ + #ifdef OSSECHIDS + sleep(2); + #endif + + if(!run_netstat(proto, i) && conn_port(proto, i)) + { + char op_msg[OS_SIZE_1024 +1]; + + (*_errors)++; + + snprintf(op_msg, OS_SIZE_1024, "Port '%d'(%s) hidden. " + "Kernel-level rootkit or trojaned " + "version of netstat.", i, + (proto == IPPROTO_UDP)? "udp" : "tcp"); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + } + } + + if((*_errors) > 20) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Excessive number of '%s' ports " + "hidden. It maybe a false-positive or " + "something really bad is going on.", + (proto == IPPROTO_UDP)? "udp" : "tcp" ); + notify_rk(ALERT_SYSTEM_CRIT, op_msg); + return; + } + } + +} + + +/* check_rc_ports: v0.1 + * Check all ports + */ +void check_rc_ports() +{ + int _errors = 0; + int _total = 0; + + int i = 0; + + while(i<=65535) + { + total_ports_tcp[i] = 0; + total_ports_udp[i] = 0; + i++; + } + + /* Trsting TCP ports */ + test_ports(IPPROTO_TCP, &_errors, &_total); + + /* Testing UDP ports */ + test_ports(IPPROTO_UDP, &_errors, &_total); + + if(_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg,OS_SIZE_1024,"No kernel-level rootkit hiding any port." + "\n Netstat is acting correctly." + " Analyzed %d ports.", _total); + notify_rk(ALERT_OK, op_msg); + } + + return; +} + + +#else +void check_rc_ports() +{ + return; +} +#endif + + +/* EOF */ diff --git a/src/rootcheck/check_rc_readproc.c b/src/rootcheck/check_rc_readproc.c new file mode 100755 index 0000000..d086b38 --- /dev/null +++ b/src/rootcheck/check_rc_readproc.c @@ -0,0 +1,154 @@ +/* @(#) $Id: check_rc_readproc.c,v 1.8 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef WIN32 +#include "shared.h" +#include "rootcheck.h" + +#define PROC 0 +#define PID 1 +#define TASK 2 + +int proc_pid_found; + + +/** Prototypes **/ +int read_proc_dir(char *dir_name, char *pid, int position); + + +int read_proc_file(char *file_name, char *pid, int position) +{ + struct stat statbuf; + + if(lstat(file_name, &statbuf) < 0) + { + return(-1); + } + + /* If directory, read the directory */ + else if(S_ISDIR(statbuf.st_mode)) + { + return(read_proc_dir(file_name, pid, position)); + } + + return(0); +} + +/* read_dir v0.1 + * + */ +int read_proc_dir(char *dir_name, char *pid, int position) +{ + DIR *dp; + + struct dirent *entry; + + + if((dir_name == NULL)||(strlen(dir_name) > PATH_MAX)) + { + merror("%s: Invalid directory given",ARGV0); + return(-1); + } + + /* Opening the directory given */ + dp = opendir(dir_name); + if(!dp) + { + return(0); + } + + while((entry = readdir(dp)) != NULL) + { + char f_name[PATH_MAX +2]; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + continue; + + if(position == PROC) + { + char *tmp_str; + + tmp_str = entry->d_name; + + while(*tmp_str != '\0') + { + if(!isdigit((int)*tmp_str)) + break; + tmp_str++; + } + + if(*tmp_str != '\0') + continue; + + + snprintf(f_name, PATH_MAX +1, "%s/%s",dir_name, entry->d_name); + + read_proc_file(f_name, pid, position+1); + } + + else if(position == PID) + { + if(strcmp(entry->d_name, "task") == 0) + { + snprintf(f_name, PATH_MAX +1, "%s/%s",dir_name, entry->d_name); + read_proc_file(f_name, pid, position+1); + } + } + + else if(position == TASK) + { + /* checking under proc/pid/task/lwp */ + if(strcmp(entry->d_name, pid) == 0) + { + proc_pid_found = 1; + break; + } + } + else + { + break; + } + } + + closedir(dp); + + return(0); +} + + +/* int check_rc_readproc(int pid): v0.1 + * Reads the /proc directory (if present) and checks + * if the given pid is there (or as a PID or as a thread). + */ +int check_rc_readproc(int pid) +{ + char char_pid[32]; + + proc_pid_found = 0; + + /* NL threads */ + snprintf(char_pid, 31, "/proc/.%d", pid); + if(is_file(char_pid)) + return(1); + + + snprintf(char_pid, 31, "%d", pid); + + read_proc_dir("/proc", char_pid, PROC); + + return(proc_pid_found); +} + +/* EOF */ +#endif diff --git a/src/rootcheck/check_rc_sys.c b/src/rootcheck/check_rc_sys.c new file mode 100755 index 0000000..68e56fb --- /dev/null +++ b/src/rootcheck/check_rc_sys.c @@ -0,0 +1,507 @@ +/* @(#) $Id: check_rc_sys.c,v 1.42 2009/09/29 19:52:25 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck.h" + +int _sys_errors; +int _sys_total; +dev_t did; + +FILE *_wx; +FILE *_ww; +FILE *_suid; + +/** Prototypes **/ +int read_sys_dir(char *dir_name, int do_read); + +int read_sys_file(char *file_name, int do_read) +{ + struct stat statbuf; + + _sys_total++; + + + #ifdef WIN32 + /* Check for NTFS ADS on Windows */ + os_check_ads(file_name); + #endif + + + if(lstat(file_name, &statbuf) < 0) + { + #ifndef WIN32 + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Anomaly detected in file '%s'. " + "Hidden from stats, but showing up on readdir. " + "Possible kernel level rootkit.", + file_name); + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + _sys_errors++; + + #endif + return(-1); + } + + /* If directory, read the directory */ + else if(S_ISDIR(statbuf.st_mode)) + { + /* Making Darwin happy. for some reason, + * when I read /dev/fd, it goes forever on + * /dev/fd5, /dev/fd6, etc.. weird + */ + if(strstr(file_name, "/dev/fd") != NULL) + return(0); + + /* Ignoring /proc directory (it has the size 0). */ + if(statbuf.st_size == 0) + return(0); + + return(read_sys_dir(file_name, do_read)); + } + + /* Check if the size from stats is the same as when we + * read the file + */ + if(S_ISREG(statbuf.st_mode) && do_read) + { + char buf[OS_SIZE_1024]; + int fd; + int nr; + unsigned long int total = 0; + + fd = open(file_name, O_RDONLY, 0); + + /* It may not necessarily open */ + if(fd >= 0) + { + while ((nr = read(fd, buf, sizeof(buf))) > 0) + { + total += nr; + } + close(fd); + + if(strcmp(file_name, "/dev/bus/usb/.usbfs/devices") == 0) + { + /* Ignore .usbfs/devices. */ + } + + else if(total != statbuf.st_size) + { + struct stat statbuf2; + + if((lstat(file_name, &statbuf2) == 0) && + (total != statbuf2.st_size) && + (statbuf.st_size == statbuf2.st_size)) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Anomaly detected in file " + "'%s'. File size doesn't match what we found. " + "Possible kernel level rootkit.", + file_name); + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + _sys_errors++; + } + } + } + } + + + /* If has OTHER write and exec permission, alert */ + #ifndef WIN32 + if(((statbuf.st_mode & S_IWOTH) == S_IWOTH) && + (S_ISREG(statbuf.st_mode))) + { + if((statbuf.st_mode & S_IXUSR) == S_IXUSR) + { + if(_wx) + fprintf(_wx, "%s\n",file_name); + + _sys_errors++; + } + else + { + if(_ww) + fprintf(_ww, "%s\n", file_name); + } + + if(statbuf.st_uid == 0) + { + char op_msg[OS_SIZE_1024 +1]; + #ifdef OSSECHIDS + snprintf(op_msg, OS_SIZE_1024, "File '%s' is owned by root " + "and has written permissions to anyone.", + file_name); + #else + snprintf(op_msg, OS_SIZE_1024, "File '%s' is: \n" + " - owned by root,\n" + " - has written permissions to anyone.", + file_name); + #endif + notify_rk(ALERT_SYSTEM_CRIT, op_msg); + + } + _sys_errors++; + } + + else if((statbuf.st_mode & S_ISUID) == S_ISUID) + { + if(_suid) + fprintf(_suid,"%s\n", file_name); + } + #endif + + return(0); +} + +/* read_dir v0.1 + * + */ +int read_sys_dir(char *dir_name, int do_read) +{ + int i = 0; + unsigned int entry_count = 0; + int did_changed = 0; + DIR *dp; + + struct dirent *entry; + struct stat statbuf; + + #ifndef WIN32 + char *(dirs_to_doread[]) = { "/bin", "/sbin", "/usr/bin", + "/usr/sbin", "/dev", "/etc", + "/boot", NULL }; + #endif + + if((dir_name == NULL)||(strlen(dir_name) > PATH_MAX)) + { + merror("%s: Invalid directory given.",ARGV0); + return(-1); + } + + + /* Ignoring user-supplied list. */ + if(rootcheck.ignore) + { + while(rootcheck.ignore[i]) + { + if(strcmp(dir_name, rootcheck.ignore[i]) == 0) + { + return(1); + } + i++; + } + i = 0; + } + + + + /* Getting the number of nodes. The total number on opendir + * must be the same + */ + if(lstat(dir_name, &statbuf) < 0) + { + return(-1); + } + + + /* Currently device id */ + if(did != statbuf.st_dev) + { + if(did != 0) + did_changed = 1; + did = statbuf.st_dev; + } + + + if(!S_ISDIR(statbuf.st_mode)) + { + return(-1); + } + + + #ifndef WIN32 + /* Check if the do_read is valid for this directory */ + while(dirs_to_doread[i]) + { + if(strcmp(dir_name, dirs_to_doread[i]) == 0) + { + do_read = 1; + break; + } + i++; + } + #else + do_read = 0; + #endif + + + /* Opening the directory given */ + dp = opendir(dir_name); + if(!dp) + { + if((strcmp(dir_name, "") == 0)&& + (dp = opendir("/"))) + { + /* ok */ + } + else + { + return(-1); + } + } + + + /* Reading every entry in the directory */ + while((entry = readdir(dp)) != NULL) + { + char f_name[PATH_MAX +2]; + struct stat statbuf_local; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + { + entry_count++; + continue; + } + + /* Creating new file + path string */ + if(strcmp(dir_name, "/") == 0) + { + snprintf(f_name, PATH_MAX +1, "/%s", entry->d_name); + } + else + { + snprintf(f_name, PATH_MAX +1, "%s/%s",dir_name, entry->d_name); + } + + /* Checking if file is a directory */ + if(lstat(f_name, &statbuf_local) == 0) + { + /* On all the systems, except darwin, the + * link count is only increased on directories. + */ + #ifndef Darwin + if(S_ISDIR(statbuf_local.st_mode)) + #else + if(S_ISDIR(statbuf_local.st_mode) || + S_ISREG(statbuf_local.st_mode) || + S_ISLNK(statbuf_local.st_mode)) + #endif + { + entry_count++; + } + } + + + /* Checking every file against the rootkit database */ + for(i = 0; i<= rk_sys_count; i++) + { + if(!rk_sys_file[i]) + break; + + if(strcmp(rk_sys_file[i], entry->d_name) == 0) + { + char op_msg[OS_SIZE_1024 +1]; + + _sys_errors++; + snprintf(op_msg, OS_SIZE_1024, "Rootkit '%s' detected " + "by the presence of file '%s/%s'.", + rk_sys_name[i], dir_name, rk_sys_file[i]); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + } + } + + /* Ignoring /proc */ + if((strcmp(f_name, "/proc") == 0) || (strcmp(f_name, "/sys") == 0)) + continue; + + read_sys_file(f_name, do_read); + } + + /* Entry count for directory different than the actual + * link count from stats. + */ + if((entry_count != statbuf.st_nlink) && + ((did_changed == 0) || ((entry_count + 1) != statbuf.st_nlink))) + { + #ifndef WIN32 + struct stat statbuf2; + char op_msg[OS_SIZE_1024 +1]; + + + if((lstat(dir_name, &statbuf2) == 0) && + (statbuf2.st_nlink != entry_count)) + { + snprintf(op_msg, OS_SIZE_1024, "Files hidden inside directory " + "'%s'. Link count does not match number of files " + "(%d,%d).", + dir_name, entry_count, (int)statbuf.st_nlink); + + /* Solaris /boot is terrible :) */ + #ifdef SOLARIS + if(strncmp(dir_name, "/boot", strlen("/boot")) != 0) + { + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + _sys_errors++; + } + #elif Darwin + if(strncmp(dir_name, "/dev", strlen("/dev")) != 0) + { + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + _sys_errors++; + } + #else + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + + _sys_errors++; + #endif + } + + #endif + } + + closedir(dp); + + return(0); +} + + +/* check_rc_sys: v0.1 + * Scan the whole filesystem looking for possible issues + */ +void check_rc_sys(char *basedir) +{ + char file_path[OS_SIZE_1024 +1]; + + debug1("%s: DEBUG: Starting on check_rc_sys", ARGV0); + + _sys_errors = 0; + _sys_total = 0; + did = 0; /* device id */ + + snprintf(file_path, OS_SIZE_1024, "%s", basedir); + + + /* Opening output files */ + if(rootcheck.notify != QUEUE) + { + _wx = fopen("rootcheck-rw-rw-rw-.txt", "w"); + _ww = fopen("rootcheck-rwxrwxrwx.txt", "w"); + _suid=fopen("rootcheck-suid-files.txt", "w"); + } + else + { + _wx = NULL; + _ww = NULL; + _suid = NULL; + } + + + + /* Scan the whole file system -- may be slow */ + if(rootcheck.scanall) + { + #ifndef WIN32 + snprintf(file_path, 3, "%s", "/"); + #endif + + read_sys_dir(file_path, rootcheck.readall); + } + + + /* Scan only specific directories */ + else + { + int _i = 0; + + #ifndef WIN32 + char *(dirs_to_scan[]) = {"/bin", "/sbin", "/usr/bin", + "/usr/sbin", "/dev", "/lib", + "/etc", "/root", "/var/log", + "/var/mail", "/var/lib", "/var/www", + "/usr/lib", "/usr/include", + "/tmp", "/boot", "/usr/local", + "/var/tmp", "/sys", NULL}; + + #else + char *(dirs_to_scan[]) = {"C:\\WINDOWS", "C:\\Program Files", NULL}; + #endif + + for(_i = 0; _i <= 24; _i++) + { + if(dirs_to_scan[_i] == NULL) + break; + + #ifndef WIN32 + snprintf(file_path, OS_SIZE_1024, "%s%s", + basedir, + dirs_to_scan[_i]); + read_sys_dir(file_path, rootcheck.readall); + + #else + read_sys_dir(dirs_to_scan[_i], rootcheck.readall); + #endif + + } + } + + if(_sys_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "No problem found on the system." + " Analyzed %d files.", _sys_total); + notify_rk(ALERT_OK, op_msg); + } + + else if(_wx && _ww && _suid) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg, OS_SIZE_1024, "Check the following files for more " + "information:\n%s%s%s", + (ftell(_wx) == 0)?"": + " rootcheck-rw-rw-rw-.txt (list of world writable files)\n", + (ftell(_ww) == 0)?"": + " rootcheck-rwxrwxrwx.txt (list of world writtable/executable files)\n", + (ftell(_suid) == 0)?"": + " rootcheck-suid-files.txt (list of suid files)"); + + notify_rk(ALERT_SYSTEM_ERROR, op_msg); + } + + if(_wx) + { + if(ftell(_wx) == 0) + unlink("rootcheck-rw-rw-rw-.txt"); + fclose(_wx); + } + + if(_ww) + { + if(ftell(_ww) == 0) + unlink("rootcheck-rwxrwxrwx.txt"); + fclose(_ww); + } + + if(_suid) + { + if(ftell(_suid) == 0) + unlink("rootcheck-suid-files.txt"); + fclose(_suid); + } + + return; +} + +/* EOF */ diff --git a/src/rootcheck/check_rc_trojans.c b/src/rootcheck/check_rc_trojans.c new file mode 100755 index 0000000..e30cd80 --- /dev/null +++ b/src/rootcheck/check_rc_trojans.c @@ -0,0 +1,148 @@ +/* @(#) $Id: check_rc_trojans.c,v 1.12 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck.h" + + +/* check_rc_trojans: + * Read the file pointer specified (rootkit_trojans) + * and check if the any trojan entry is on the configured files + */ +void check_rc_trojans(char *basedir, FILE *fp) +{ + int i = 0, _errors = 0, _total = 0; + char buf[OS_SIZE_1024 +1]; + char file_path[OS_SIZE_1024 +1]; + + char *file; + char *string_to_look; + + #ifndef WIN32 + char *(all_paths[]) = {"bin","sbin","usr/bin","usr/sbin", NULL}; + #else + char *(all_paths[]) = {"C:\\Windows\\", "D:\\Windows\\", NULL}; + #endif + + debug1("%s: DEBUG: Starting on check_rc_trojans", ARGV0); + + + while(fgets(buf, OS_SIZE_1024, fp) != NULL) + { + char *nbuf; + char *message = NULL; + + i = 0; + + /* Removing end of line */ + nbuf = strchr(buf, '\n'); + if(nbuf) + { + *nbuf = '\0'; + } + + + /* Normalizing line */ + nbuf = normalize_string(buf); + + + if(*nbuf == '\0' || *nbuf == '#') + { + continue; + } + + + /* File now may be valid */ + file = nbuf; + + string_to_look = strchr(file, '!'); + if(!string_to_look) + { + continue; + } + + *string_to_look = '\0'; + string_to_look++; + + message = strchr(string_to_look, '!'); + if(!message) + { + continue; + } + *message = '\0'; + message++; + + string_to_look = normalize_string(string_to_look); + file = normalize_string(file); + message = normalize_string(message); + + + if(*file == '\0' || *string_to_look == '\0') + { + continue; + } + + _total++; + + + /* Trying with all possible paths */ + while(all_paths[i] != NULL) + { + if(*file != '/') + { + snprintf(file_path, OS_SIZE_1024, "%s/%s/%s",basedir, + all_paths[i], + file); + } + else + { + strncpy(file_path, file, OS_SIZE_1024); + file_path[OS_SIZE_1024 -1] = '\0'; + } + + /* Checking if entry is found */ + if(is_file(file_path) && os_string(file_path, string_to_look)) + { + char op_msg[OS_SIZE_1024 +1]; + _errors = 1; + + snprintf(op_msg, OS_SIZE_1024, "Trojaned version of file " + "'%s' detected. Signature used: '%s' (%s).", + file_path, + string_to_look, + *message == '\0'? + "Generic":message); + + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + } + + if(*file == '/') + { + break; + } + i++; + } + continue; + } + + + if(_errors == 0) + { + char op_msg[OS_SIZE_1024 +1]; + snprintf(op_msg,OS_SIZE_1024, "No binaries with any trojan detected. " + "Analyzed %d files.", _total); + notify_rk(ALERT_OK, op_msg); + } +} + + +/* EOF */ diff --git a/src/rootcheck/common.c b/src/rootcheck/common.c new file mode 100755 index 0000000..67ae180 --- /dev/null +++ b/src/rootcheck/common.c @@ -0,0 +1,712 @@ +/* @(#) $Id: common.c,v 1.25 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/main/license/ . + */ + + +#include "shared.h" +#include "rootcheck.h" +#include "os_regex/os_regex.h" + + + +/** Checks if the specified string is already in the array. + */ +int _is_str_in_array(char **ar, char *str) +{ + while(*ar) + { + if(strcmp(*ar, str) == 0) + { + return(1); + } + ar++; + } + return(0); +} + + + +/** int rk_check_dir(char *dir, char *file, char *pattern) + */ +int rk_check_dir(char *dir, char *file, char *pattern) +{ + int ret_code = 0; + char f_name[PATH_MAX +2]; + struct dirent *entry; + struct stat statbuf_local; + DIR *dp = NULL; + + + f_name[PATH_MAX +1] = '\0'; + + + dp = opendir(dir); + if(!dp) + return(0); + + + while((entry = readdir(dp)) != NULL) + { + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + + /* Creating new file + path string */ + snprintf(f_name, PATH_MAX +1, "%s/%s",dir, entry->d_name); + + + /* Checking if the read entry, matches the provided file name. */ + if(strncasecmp(file, "r:", 2) == 0) + { + if(OS_Regex(file +2, entry->d_name)) + { + if(rk_check_file(f_name, pattern)) + { + ret_code = 1; + } + } + } + + /* Trying without regex. */ + else + { + if(OS_Match2(file, entry->d_name)) + { + if(rk_check_file(f_name, pattern)) + { + ret_code = 1; + } + } + } + + + /* Checking if file is a directory */ + if(lstat(f_name, &statbuf_local) == 0) + { + if(S_ISDIR(statbuf_local.st_mode)) + { + if(rk_check_dir(f_name, file, pattern)) + { + ret_code = 1; + } + } + } + } + + closedir(dp); + return(ret_code); + +} + + + +/** int rk_check_file(char *value, char *pattern) + */ +int rk_check_file(char *file, char *pattern) +{ + char *split_file; + + FILE *fp; + char buf[OS_SIZE_2048 +1]; + + + /* If string is null, we don't match */ + if(file == NULL) + { + return(0); + } + + + /* Checking if the file is divided */ + split_file = strchr(file, ','); + if(split_file) + { + *split_file = '\0'; + split_file++; + } + + + /* Getting each file */ + do + { + + + /* If we don't have a pattern, just check if the file/dir is there */ + if(pattern == NULL) + { + if(is_file(file)) + { + int i = 0; + char _b_msg[OS_SIZE_1024 +1]; + + _b_msg[OS_SIZE_1024] = '\0'; + snprintf(_b_msg, OS_SIZE_1024, " File: %s.", + file); + + /* Already present. */ + if(_is_str_in_array(rootcheck.alert_msg, _b_msg)) + { + return(1); + } + + while(rootcheck.alert_msg[i] && (i < 255)) + i++; + + if(!rootcheck.alert_msg[i]) + os_strdup(_b_msg, rootcheck.alert_msg[i]); + + return(1); + } + } + + else + { + /* Checking for a content in the file */ + fp = fopen(file, "r"); + if(fp) + { + + buf[OS_SIZE_2048] = '\0'; + while(fgets(buf, OS_SIZE_2048, fp) != NULL) + { + char *nbuf; + + /* Removing end of line */ + nbuf = strchr(buf, '\n'); + if(nbuf) + { + *nbuf = '\0'; + } + + + #ifdef WIN32 + /* Removing end of line */ + nbuf = strchr(buf, '\r'); + if(nbuf) + { + *nbuf = '\0'; + } + #endif + + + /* Matched */ + if(pt_matches(buf, pattern)) + { + int i = 0; + char _b_msg[OS_SIZE_1024 +1]; + + + /* Closing the file before dealing with the alert. */ + fclose(fp); + + /* Generating the alert itself. */ + _b_msg[OS_SIZE_1024] = '\0'; + snprintf(_b_msg, OS_SIZE_1024, " File: %s.", + file); + + /* Already present. */ + if(_is_str_in_array(rootcheck.alert_msg, _b_msg)) + { + return(1); + } + + while(rootcheck.alert_msg[i] && (i < 255)) + i++; + + if(!rootcheck.alert_msg[i]) + os_strdup(_b_msg, rootcheck.alert_msg[i]); + + return(1); + } + } + + fclose(fp); + } + } + + if(split_file) + { + file = split_file; + split_file = strchr(split_file, ','); + if(split_file) + { + split_file++; + } + } + + + }while(split_file); + + + return(0); +} + + + +/** int pt_matches(char *str, char *pattern) + * Checks if the specific pattern is present on str. + * A pattern can be preceeded by: + * =: (for equal) - default - strcasecmp + * r: (for ossec regexes) + * >: (for strcmp greater) + * <: (for strcmp lower) + * + * Multiple patterns can be specified by using " && " between them. + * All of them must match for it to return true. + */ +int pt_matches(char *str, char *pattern) +{ + int neg = 0; + int ret_code = 0; + char *tmp_pt = pattern; + char *tmp_ret = NULL; + + + /* If string we null, we don't match */ + if(str == NULL) + { + return(0); + } + + while(tmp_pt != NULL) + { + /* We first look for " && " */ + tmp_pt = strchr(pattern, ' '); + if(tmp_pt && tmp_pt[1] == '&' && tmp_pt[2] == '&' && tmp_pt[3] == ' ') + { + /* Marking pointer to clean it up */ + tmp_ret = tmp_pt; + + *tmp_pt = '\0'; + tmp_pt += 4; + } + else + { + tmp_pt = NULL; + } + + + /* Checking for negate values */ + neg = 0; + ret_code = 0; + if(*pattern == '!') + { + pattern++; + neg = 1; + } + + + /* Doing strcasecmp */ + if(strncasecmp(pattern, "=:", 2) == 0) + { + pattern += 2; + if(strcasecmp(pattern, str) == 0) + { + ret_code = 1; + } + } + else if(strncasecmp(pattern, "r:", 2) == 0) + { + pattern += 2; + if(OS_Regex(pattern, str)) + { + ret_code = 1; + } + } + else if(strncasecmp(pattern, "<:", 2) == 0) + { + pattern += 2; + if(strcmp(pattern, str) < 0) + { + ret_code = 1; + } + } + else if(strncasecmp(pattern, ">:", 2) == 0) + { + pattern += 2; + if(strcmp(pattern, str) > 0) + { + ret_code = 1; + } + } + else + { + #ifdef WIN32 + char final_file[2048 +1]; + + /* Try to get Windows variable */ + if(*pattern == '%') + { + final_file[0] = '\0'; + final_file[2048] = '\0'; + + ExpandEnvironmentStrings(pattern, final_file, 2047); + } + else + { + strncpy(final_file, pattern, 2047); + } + + /* Comparing against the expanded variable */ + if(strcasecmp(final_file, str) == 0) + { + ret_code = 1; + } + + #else + if(strcasecmp(pattern, str) == 0) + { + ret_code = 1; + } + + #endif + } + + /* Fixing tmp_ret entry */ + if(tmp_ret != NULL) + { + *tmp_ret = ' '; + tmp_ret = NULL; + } + + + /* If we have "!", return true if we don't match */ + if(neg == 1) + { + if(ret_code) + { + ret_code = 0; + break; + } + } + else + { + if(!ret_code) + { + ret_code = 0; + break; + } + } + + ret_code = 1; + pattern = tmp_pt; + } + + return(ret_code); +} + + + +/** char *normalize_string + * Normalizes a string, removing white spaces and tabs + * from the begining and the end of it. + */ +char *normalize_string(char *str) +{ + int str_sz = strlen(str) -1; + + while(*str != '\0') + { + if(*str == ' ' || *str == '\t') + { + str++; + } + else + { + break; + } + } + + while(str[str_sz] == ' ' || str[str_sz] == '\t') + { + str[str_sz] = '\0'; + str_sz--; + } + + return(str); +} + + + +/** int isfile_ondir(char *file, char *dir) + * Checks is 'file' is present on 'dir' using readdir + */ +int isfile_ondir(char *file, char *dir) +{ + DIR *dp = NULL; + struct dirent *entry; + dp = opendir(dir); + + if(!dp) + return(0); + + while((entry = readdir(dp)) != NULL) + { + if(strcmp(entry->d_name, file) == 0) + { + closedir(dp); + return(1); + } + } + + closedir(dp); + return(0); +} + + + +/* is_file: Check if the file is present + * by different attempts (to try to avoid syscall hidding). + */ +int is_file(char *file_name) +{ + int ret = 0; + + struct stat statbuf; + FILE *fp = NULL; + DIR *dp = NULL; + + + #ifndef WIN32 + + char curr_dir[1024]; + + char *file_dirname; + char *file_basename; + + + curr_dir[1023] = '\0'; + + if(!getcwd(curr_dir, 1022)) + { + return(0); + } + + /* Getting dir name */ + file_basename = strrchr(file_name, '/'); + if(!file_basename) + { + merror("%s: RK: Invalid file name: %s!", ARGV0, file_name); + return(0); + } + + + /* If file_basename == file_name, then the file + * only has one slash at the beginning. + */ + if(file_basename != file_name) + { + /* Dir name and base name are now set */ + *file_basename = '\0'; + file_basename++; + file_dirname = file_name; + + /** chdir test **/ + if(chdir(file_dirname) == 0) + { + if(chdir(file_basename) == 0) + { + ret = 1; + } + /* Checking errno (if file exists, but it is not + * a directory. + */ + else if(errno == ENOTDIR) + { + ret = 1; + } + + /** Trying open dir **/ + dp = opendir(file_basename); + if(dp) + { + closedir(dp); + ret = 1; + } + else if(errno == ENOTDIR) + { + ret = 1; + } + + /* Returning to the previous directory */ + chdir(curr_dir); + } + + + file_basename--; + *file_basename = '/'; + + } + else + { + if(chdir(file_name) == 0) + { + ret = 1; + + /* Returning to the previous directory */ + chdir(curr_dir); + } + else if(errno == ENOTDIR) + { + ret = 1; + } + } + + #else + dp = opendir(file_name); + if(dp) + { + closedir(dp); + ret = 1; + } + + #endif /* WIN32 */ + + + /* Trying other calls */ + if( (stat(file_name, &statbuf) < 0) && + #ifndef WIN32 + (access(file_name, F_OK) < 0) && + #endif + ((fp = fopen(file_name, "r")) == NULL)) + { + return(ret); + } + + /* must close it over here */ + if(fp) + fclose(fp); + + return(1); +} + + + +/* del_plist:. Deletes the process list + */ +int del_plist(void *p_list_p) +{ + OSList *p_list = (OSList *)p_list_p; + OSListNode *l_node; + OSListNode *p_node = NULL; + + if(p_list == NULL) + { + return(0); + } + + l_node = OSList_GetFirstNode(p_list); + while(l_node) + { + Proc_Info *pinfo; + + pinfo = (Proc_Info *)l_node->data; + + if(pinfo->p_name) + { + free(pinfo->p_name); + } + + if(pinfo->p_path) + { + free(pinfo->p_path); + } + + free(l_node->data); + + if(p_node) + { + free(p_node); + p_node = NULL; + } + p_node = l_node; + + l_node = OSList_GetNextNode(p_list); + } + + if(p_node) + { + free(p_node); + p_node = NULL; + } + + free(p_list); + + return(1); +} + + + +/* is_process: Check is a process is running. + */ +int is_process(char *value, void *p_list_p) +{ + OSList *p_list = (OSList *)p_list_p; + OSListNode *l_node; + if(p_list == NULL) + { + return(0); + } + if(!value) + { + return(0); + } + + + l_node = OSList_GetFirstNode(p_list); + while(l_node) + { + Proc_Info *pinfo; + + pinfo = (Proc_Info *)l_node->data; + + /* Checking if value matches */ + if(pt_matches(pinfo->p_path, value)) + { + int i = 0; + char _b_msg[OS_SIZE_1024 +1]; + + _b_msg[OS_SIZE_1024] = '\0'; + + snprintf(_b_msg, OS_SIZE_1024, " Process: %s.", + pinfo->p_path); + + /* Already present. */ + if(_is_str_in_array(rootcheck.alert_msg, _b_msg)) + { + return(1); + } + + while(rootcheck.alert_msg[i] && (i< 255)) + i++; + + if(!rootcheck.alert_msg[i]) + os_strdup(_b_msg, rootcheck.alert_msg[i]); + + return(1); + } + + l_node = OSList_GetNextNode(p_list); + } + + return(0); + +} + + + +/* EOF */ diff --git a/src/rootcheck/common_rcl.c b/src/rootcheck/common_rcl.c new file mode 100755 index 0000000..ede727a --- /dev/null +++ b/src/rootcheck/common_rcl.c @@ -0,0 +1,787 @@ +/* @(#) $Id: common_rcl.c,v 1.17 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/main/license/ + */ + + +#include "shared.h" +#include "rootcheck.h" + + +/* Types of values */ +#define RKCL_TYPE_FILE 1 +#define RKCL_TYPE_REGISTRY 2 +#define RKCL_TYPE_PROCESS 3 +#define RKCL_TYPE_DIR 4 + +#define RKCL_COND_ALL 0x001 +#define RKCL_COND_ANY 0x002 +#define RKCL_COND_REQ 0x004 +#define RKCL_COND_INV 0x010 + + + +/** char *_rkcl_getrootdir() + */ +char *_rkcl_getrootdir(char *root_dir, int dir_size) +{ + #ifdef WIN32 + char final_file[2048 +1]; + char *tmp; + + final_file[0] = '\0'; + final_file[2048] = '\0'; + + ExpandEnvironmentStrings("%WINDIR%", final_file, 2047); + + tmp = strchr(final_file, '\\'); + if(tmp) + { + *tmp = '\0'; + strncpy(root_dir, final_file, dir_size); + return(root_dir); + } + + return(NULL); + + #endif + + return(NULL); +} + + + +/** char *_rkcl_getfp: Get next available buffer in file. + */ +char *_rkcl_getfp(FILE *fp, char *buf) +{ + while(fgets(buf, OS_SIZE_1024, fp) != NULL) + { + char *nbuf; + + /* Removing end of line */ + nbuf = strchr(buf, '\n'); + if(nbuf) + { + *nbuf = '\0'; + } + + /* Assigning buf to be used */ + nbuf = buf; + + + /* Excluding commented lines or blanked ones */ + while(*nbuf != '\0') + { + if(*nbuf == ' ' || *nbuf == '\t') + { + nbuf++; + continue; + } + else if(*nbuf == '#') + { + *nbuf = '\0'; + continue; + } + else + { + break; + } + } + + /* Going to next line if empty */ + if(*nbuf == '\0') + { + continue; + } + + return(nbuf); + } + + return(NULL); +} + + + +/** int _rkcl_is_name + */ +int _rkcl_is_name(char *buf) +{ + if(*buf == '[' && buf[strlen(buf) -1] == ']') + { + return(1); + } + return(0); +} + + + +/** int _rkcl_get_vars(vars, nbuf) + */ +int _rkcl_get_vars(OSStore *vars, char *nbuf) +{ + char *var_name; + char *var_value; + char *tmp; + + /* If not a variable, return 0 */ + if(*nbuf != '$') + { + return(0); + } + + + /* Removing ; from the end. */ + tmp = strchr(nbuf, ';'); + if(tmp) + { + *tmp = '\0'; + } + else + { + return(-1); + } + + + /* Getting value. */ + tmp = strchr(nbuf, '='); + if(tmp) + { + *tmp = '\0'; + tmp++; + } + else + { + return(-1); + } + + + /* Dumping the variable options. */ + os_strdup(nbuf, var_name); + os_strdup(tmp, var_value); + + + /* Adding entry to the storage */ + OSStore_Put(vars, var_name, var_value); + return(1); +} + + + +/** int _rkcl_get_name + */ +char *_rkcl_get_name(char *buf, char *ref, int *condition) +{ + char *tmp_location; + char *tmp_location2; + + *condition = 0; + + /* Checking if name is valid */ + if(!_rkcl_is_name(buf)) + { + return(NULL); + } + + /* Setting name */ + buf++; + tmp_location = strchr(buf, ']'); + if(!tmp_location) + { + return(NULL); + } + *tmp_location = '\0'; + + + /* Getting condition */ + tmp_location++; + if(*tmp_location != ' ' && tmp_location[1] != '[') + { + return(NULL); + } + tmp_location+=2; + + tmp_location2 = strchr(tmp_location, ']'); + if(!tmp_location2) + { + return(NULL); + } + *tmp_location2 = '\0'; + tmp_location2++; + + + /* Getting condition */ + if(strcmp(tmp_location, "all") == 0) + { + *condition |= RKCL_COND_ALL; + } + else if(strcmp(tmp_location,"any") == 0) + { + *condition |= RKCL_COND_ANY; + } + else if(strcmp(tmp_location,"any required") == 0) + { + *condition |= RKCL_COND_ANY; + *condition |= RKCL_COND_REQ; + } + else if(strcmp(tmp_location, "all required") == 0) + { + *condition |= RKCL_COND_ALL; + *condition |= RKCL_COND_REQ; + } + else + { + *condition = RKCL_COND_INV; + return(NULL); + } + + + /* Getting reference */ + if(*tmp_location2 != ' ' && tmp_location2[1] != '[') + { + return(NULL); + } + + tmp_location2+=2; + tmp_location = strchr(tmp_location2, ']'); + if(!tmp_location) + { + return(NULL); + } + *tmp_location = '\0'; + + /* Copying reference */ + strncpy(ref, tmp_location2, 255); + + return(strdup(buf)); +} + + + +/** char *_rkcl_get_pattern(char *value) + */ +char *_rkcl_get_pattern(char *value) +{ + while(*value != '\0') + { + if((*value == ' ') && (value[1] == '-') && + (value[2] == '>') && (value[3] == ' ')) + { + *value = '\0'; + value += 4; + + return(value); + } + value++; + } + + return(NULL); +} + + + +/** char *_rkcl_get_value + */ +char *_rkcl_get_value(char *buf, int *type) +{ + char *tmp_str; + char *value; + + /* Zeroing type before using it --make sure return is valid + * in case of error. + */ + *type = 0; + + value = strchr(buf, ':'); + if(value == NULL) + { + return(NULL); + } + + *value = '\0'; + value++; + + tmp_str = strchr(value, ';'); + if(tmp_str == NULL) + { + return(NULL); + } + *tmp_str = '\0'; + + + /* Getting types - removing negate flag (using later) */ + if(*buf == '!') + { + buf++; + } + + if(strcmp(buf, "f") == 0) + { + *type = RKCL_TYPE_FILE; + } + else if(strcmp(buf, "r") == 0) + { + *type = RKCL_TYPE_REGISTRY; + } + else if(strcmp(buf, "p") == 0) + { + *type = RKCL_TYPE_PROCESS; + } + else if(strcmp(buf, "d") == 0) + { + *type = RKCL_TYPE_DIR; + } + else + { + return(NULL); + } + + return(value); +} + + + +/** int rkcl_get_entry: + */ +int rkcl_get_entry(FILE *fp, char *msg, void *p_list_p) +{ + int type = 0, condition = 0, root_dir_len = 0; + char *nbuf; + char buf[OS_SIZE_1024 +2]; + char root_dir[OS_SIZE_1024 +2]; + char final_file[2048 +1]; + char ref[255 +1]; + + char *value; + char *name = NULL; + + OSStore *vars; + OSList *p_list = (OSList *)p_list_p; + + + /* Cleaning up vars */ + memset(buf, '\0', sizeof(buf)); + memset(root_dir, '\0', sizeof(root_dir)); + memset(final_file, '\0', sizeof(final_file)); + memset(ref, '\0', sizeof(ref)); + + + root_dir_len = sizeof(root_dir) -1; + + + #ifdef WIN32 + /* Getting Windows rootdir */ + _rkcl_getrootdir(root_dir, root_dir_len); + if(root_dir[0] == '\0') + { + merror(INVALID_ROOTDIR, ARGV0); + } + #endif + + + /* Getting variables */ + vars = OSStore_Create(); + + + /* We first read all variables -- they must be defined at the top. */ + while(1) + { + int rc_code = 0; + nbuf = _rkcl_getfp(fp, buf); + if(nbuf == NULL) + { + goto clean_return; + } + + rc_code = _rkcl_get_vars(vars, nbuf); + if(rc_code == 0) + { + break; + } + else if(rc_code == -1) + { + merror(INVALID_RKCL_VAR, ARGV0, nbuf); + goto clean_return; + } + } + + + /* Getting first name */ + name = _rkcl_get_name(nbuf, ref, &condition); + if(name == NULL || condition == RKCL_COND_INV) + { + merror(INVALID_RKCL_NAME, ARGV0, nbuf); + goto clean_return; + } + + + + /* Getting the real entries. */ + do + { + int g_found = 0; + + + /* Getting entry name */ + if(name == NULL) + { + merror(INVALID_RKCL_NAME, ARGV0, "NULL"); + goto clean_return; + } + + debug2("%s: DEBUG: Checking entry: '%s'.", ARGV0, name); + + + /* Getting each value */ + do + { + int negate = 0; + int found = 0; + value = NULL; + + nbuf = _rkcl_getfp(fp, buf); + if(nbuf == NULL) + { + break; + } + + + /* We first try to get the name, looking for new entries */ + if(_rkcl_is_name(nbuf)) + { + break; + } + + + /* Getting value to look for */ + value = _rkcl_get_value(nbuf, &type); + if(value == NULL) + { + merror(INVALID_RKCL_VALUE, ARGV0, nbuf); + goto clean_return; + } + + + /* Getting negate value */ + if(*value == '!') + { + negate = 1; + value++; + } + + + /* Checking for a file. */ + if(type == RKCL_TYPE_FILE) + { + char *pattern = NULL; + char *f_value = NULL; + + + pattern = _rkcl_get_pattern(value); + f_value = value; + + + /* Getting any variable. */ + if(value[0] == '$') + { + f_value = OSStore_Get(vars, value); + if(!f_value) + { + merror(INVALID_RKCL_VAR, ARGV0, value); + continue; + } + } + + + #ifdef WIN32 + else if(value[0] == '\\') + { + final_file[0] = '\0'; + final_file[sizeof(final_file) -1] = '\0'; + + snprintf(final_file, sizeof(final_file) -2, "%s%s", + root_dir, value); + f_value = final_file; + } + else + { + final_file[0] = '\0'; + final_file[sizeof(final_file) -1] = '\0'; + + ExpandEnvironmentStrings(value, final_file, + sizeof(final_file) -2); + f_value = final_file; + } + #endif + + + debug2("%s: DEBUG: Checking file: '%s'.", ARGV0, f_value); + if(rk_check_file(f_value, pattern)) + { + debug1("%s: DEBUG: found file.", ARGV0); + found = 1; + } + } + + + /* Checking for a registry entry */ + else if(type == RKCL_TYPE_REGISTRY) + { + char *entry = NULL; + char *pattern = NULL; + + + /* Looking for additional entries in the registry + * and a pattern to match. + */ + entry = _rkcl_get_pattern(value); + if(entry) + { + pattern = _rkcl_get_pattern(entry); + } + + + #ifdef WIN32 + debug2("%s: DEBUG: Checking registry: '%s'.", ARGV0, value); + if(is_registry(value, entry, pattern)) + { + debug2("%s: DEBUG: found registry.", ARGV0); + found = 1; + } + #endif + } + + + /* Checking for a directory. */ + else if(type == RKCL_TYPE_DIR) + { + char *file = NULL; + char *pattern = NULL; + char *f_value = NULL; + char *dir = NULL; + + + file = _rkcl_get_pattern(value); + if(file) + { + pattern = _rkcl_get_pattern(file); + } + + + /* Getting any variable. */ + if(value[0] == '$') + { + f_value = OSStore_Get(vars, value); + if(!f_value) + { + merror(INVALID_RKCL_VAR, ARGV0, value); + continue; + } + } + else + { + f_value = value; + } + + + /* Checking for multiple, comma separated directories. */ + dir = f_value; + f_value = strchr(dir, ','); + if(f_value) + { + *f_value = '\0'; + } + + + while(dir) + { + debug2("%s: Checking dir: %s", ARGV0, dir); + if(rk_check_dir(dir, file, pattern)) + { + debug2("%s: DEBUG: Found dir.", ARGV0); + found = 1; + } + + if(f_value) + { + *f_value = ','; + f_value++; + + dir = f_value; + + f_value = strchr(dir, ','); + if(f_value) + { + *f_value = '\0'; + } + } + else + { + dir = NULL; + } + } + } + + + /* Checking for a process. */ + else if(type == RKCL_TYPE_PROCESS) + { + debug2("%s: DEBUG: Checking process: '%s'.", ARGV0, value); + if(is_process(value, p_list)) + { + debug2("%s: DEBUG: found process.", ARGV0); + found = 1; + } + } + + + /* Switching the values if ! is present */ + if(negate) + { + if(found) + { + found = 0; + } + else + { + found = 1; + } + } + + + /** Checking the conditions **/ + if(condition & RKCL_COND_ANY) + { + debug2("%s: DEBUG: Condition ANY.", ARGV0); + if(found) + { + g_found = 1; + } + } + /* Condition for ALL */ + else + { + debug2("%s: DEBUG: Condition ALL.", ARGV0); + if(found && (g_found != -1)) + { + g_found = 1; + } + else + { + g_found = -1; + } + } + }while(value != NULL); + + + /* Alerting if necessary */ + if(g_found == 1) + { + int j = 0; + char op_msg[OS_SIZE_1024 +1]; + char **p_alert_msg = rootcheck.alert_msg; + + while(1) + { + if(ref[0] != '\0') + { + snprintf(op_msg, OS_SIZE_1024, "%s %s.%s" + " Reference: %s .",msg, name, + p_alert_msg[j]?p_alert_msg[j]:"\0", + ref); + } + else + { + snprintf(op_msg, OS_SIZE_1024, "%s %s.%s",msg, + name, p_alert_msg[j]?p_alert_msg[j]:"\0"); + } + + if((type == RKCL_TYPE_DIR) || (j == 0)) + { + notify_rk(ALERT_POLICY_VIOLATION, op_msg); + } + + if(p_alert_msg[j]) + { + free(p_alert_msg[j]); + p_alert_msg[j] = NULL; + j++; + + if(!p_alert_msg[j]) + break; + } + else + { + break; + } + } + } + else + { + int j = 0; + while(rootcheck.alert_msg[j]) + { + free(rootcheck.alert_msg[j]); + rootcheck.alert_msg[j] = NULL; + j++; + } + + + /* Checking if this entry is required for the rest of the file. */ + if(condition & RKCL_COND_REQ) + { + goto clean_return; + } + } + + + /* Ending if we don't have anything else. */ + if(!nbuf) + { + goto clean_return; + } + + + /* Cleaning up name. */ + if(name) + { + free(name); + name = NULL; + } + + + /* Getting name already read */ + name = _rkcl_get_name(nbuf, ref, &condition); + if(!name) + { + merror(INVALID_RKCL_NAME, ARGV0, nbuf); + goto clean_return; + } + }while(nbuf != NULL); + + + + /* Cleaning up the memory */ + clean_return: + if(name) + { + free(name); + name = NULL; + } + vars = OSStore_Free(vars); + + + return(1); +} + + +/* EOF */ diff --git a/src/rootcheck/config.c b/src/rootcheck/config.c new file mode 100755 index 0000000..cf085dc --- /dev/null +++ b/src/rootcheck/config.c @@ -0,0 +1,41 @@ +/* @(#) $Id: config.c,v 1.18 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#ifdef OSSECHIDS +#include "shared.h" +#include "rootcheck.h" +#include "config/config.h" + + + +/* Read_Rootcheck_Config: Reads the rootcheck config + */ +int Read_Rootcheck_Config(char * cfgfile) +{ + int modules = 0; + + modules|= CROOTCHECK; + + if(ReadConfig(modules, cfgfile, &rootcheck, NULL) < 0) + return(OS_INVALID); + + + #ifdef CLIENT + /* Reading shared config */ + modules|= CAGENT_CONFIG; + ReadConfig(modules, AGENTCONFIG, &rootcheck, NULL); + #endif + + return(0); +} + +/* EOF */ +#endif diff --git a/src/rootcheck/db/cis_debian_linux_rcl.txt b/src/rootcheck/db/cis_debian_linux_rcl.txt new file mode 100644 index 0000000..6d6d524 --- /dev/null +++ b/src/rootcheck/db/cis_debian_linux_rcl.txt @@ -0,0 +1,212 @@ +# @(#) $Id: cis_debian_linux_rcl.txt,v 1.2 2008/07/10 18:03:00 dcid Exp $ +# +# OSSEC Linux Audit - (C) 2008 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Application name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - p (process running) +# - d (any file inside the directory) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + +# CIS Checks for Debian/Ubuntu +# Based on Center for Internet Security Benchmark for Debian Linux v1.0 + + +# Main one. Only valid for Debian/Ubuntu. +[CIS - Testing against the CIS Debian Linux Benchmark v1.0] [all required] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/debian_version; +f:/proc/sys/kernel/ostype -> Linux; + + + +# Section 1.4 - Partition scheme. +[CIS - Debian Linux 1.4 - Robust partition scheme - /tmp is not on its own partition] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:/tmp; + +[CIS - Debian Linux 1.4 - Robust partition scheme - /opt is not on its own partition] [all] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/opt; +f:/etc/fstab -> !r:/opt; + +[CIS - Debian Linux 1.4 - Robust partition scheme - /var is not on its own partition] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:/var; + + + +# Section 2.3 - SSH configuration +[CIS - Debian Linux 2.3 - SSH Configuration - Protocol version 1 enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/ssh/sshd_config -> !r:^# && r:Protocol\.+1; + +[CIS - Debian Linux 2.3 - SSH Configuration - IgnoreRHosts disabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/ssh/sshd_config -> !r:^# && r:IgnoreRhosts\.+no; + +[CIS - Debian Linux 2.3 - SSH Configuration - Empty passwords permitted] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/ssh/sshd_config -> !r:^# && r:^PermitEmptyPasswords\.+yes; + +[CIS - Debian Linux 2.3 - SSH Configuration - Host based authentication enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/ssh/sshd_config -> !r:^# && r:HostbasedAuthentication\.+yes; + +[CIS - Debian Linux 2.3 - SSH Configuration - Root login allowed] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/ssh/sshd_config -> !r:^# && r:PermitRootLogin\.+yes; + + + +# Section 2.4 Enable system accounting +[CIS - Debian Linux 2.4 - System Accounting - Sysstat not installed] [all] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:!/etc/default/sysstat; +f:!/var/log/sysstat; + +[CIS - Debian Linux 2.4 - System Accounting - Sysstat not enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:!/etc/default/sysstat; +f:/etc/default/sysstat -> !r:^# && r:ENABLED="false"; + + + +# Section 2.5 Install and run Bastille +[CIS - Debian Linux 2.5 - System harderning - Bastille is not installed] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:!/etc/Bastille; + + + +# Section 2.6 Ensure sources.list Sanity +[CIS - Debian Linux 2.6 - Sources list sanity - Security updates not enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:!/etc/apt/sources.list; +f:!/etc/apt/sources.list -> !r:^# && r:http://security.debian|http://security.ubuntu; + + + +# Section 3 - Minimize inetd services +[CIS - Debian Linux 3.3 - Telnet enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:telnet; + +[CIS - Debian Linux 3.4 - FTP enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:/ftp; + +[CIS - Debian Linux 3.5 - rsh/rlogin/rcp enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:shell|login; + +[CIS - Debian Linux 3.6 - tftpd enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:tftp; + +[CIS - Debian Linux 3.7 - imap enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:imap; + +[CIS - Debian Linux 3.8 - pop3 enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:pop; + +[CIS - Debian Linux 3.9 - Ident enabled on inetd] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inetd.conf -> !r:^# && r:ident; + + + +# Section 4 - Minimize boot services +[CIS - Debian Linux 4.1 - Disable inetd - Inetd enabled but no services running] [all] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +p:inetd; +f:!/etc/inetd.conf -> !r:^# && r:wait; + +[CIS - Debian Linux 4.3 - GUI login enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/inittab -> !r:^# && r:id:5; + +[CIS - Debian Linux 4.6 - Disable standard boot services - Samba Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/samba; + +[CIS - Debian Linux 4.7 - Disable standard boot services - NFS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/nfs-common; +f:/etc/init.d/nfs-user-server; +f:/etc/init.d/nfs-kernel-server; + +[CIS - Debian Linux 4.9 - Disable standard boot services - NIS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/nis; + +[CIS - Debian Linux 4.13 - Disable standard boot services - Web server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/apache; +f:/etc/init.d/apache2; + +[CIS - Debian Linux 4.15 - Disable standard boot services - DNS server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/bind; + +[CIS - Debian Linux 4.16 - Disable standard boot services - MySQL server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/mysql; + +[CIS - Debian Linux 4.16 - Disable standard boot services - PostgreSQL server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/postgresql; + +[CIS - Debian Linux 4.17 - Disable standard boot services - Webmin Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/webmin; + +[CIS - Debian Linux 4.18 - Disable standard boot services - Squid Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/init.d/squid; + + + +# Section 5 - Kernel tuning +[CIS - Debian Linux 5.1 - Network parameters - Source routing accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/proc/sys/net/ipv4/conf/all/accept_source_route -> 1; + +[CIS - Debian Linux 5.1 - Network parameters - ICMP broadcasts accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts -> 0; + +[CIS - Debian Linux 5.2 - Network parameters - IP Forwarding enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/proc/sys/net/ipv4/ip_forward -> 1; +f:/proc/sys/net/ipv6/ip_forward -> 1; + + + +# Section 7 - Permissions +[CIS - Debian Linux 7.1 - Partition /var without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/var && !r:nodev; + +[CIS - Debian Linux 7.1 - Partition /tmp without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/tmp && !r:nodev; + +[CIS - Debian Linux 7.1 - Partition /opt without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/opt && !r:nodev; + +[CIS - Debian Linux 7.1 - Partition /home without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/home && !r:nodev ; + +[CIS - Debian Linux 7.2 - Removable partition /media without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:/media && !r:nodev; + +[CIS - Debian Linux 7.2 - Removable partition /media without 'nosuid' set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:/media && !r:nosuid; + +[CIS - Debian Linux 7.3 - User-mounted removable partition /media] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/fstab -> !r:^# && r:/media && r:user; + + + +# Section 8 - Access and authentication +[CIS - Debian Linux 8.8 - LILO Password not set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/lilo.conf -> !r:^# && !r:restricted; +f:/etc/lilo.conf -> !r:^# && !r:password=; + +[CIS - Debian Linux 8.8 - GRUB Password not set] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/boot/grub/menu.lst -> !r:^# && !r:password; + +[CIS - Debian Linux 9.2 - Account with empty password present] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/shadow -> r:^\w+::; + +[CIS - Debian Linux 13.11 - Non-root account with uid 0] [any] [http://www.ossec.net/wiki/index.php/CIS_DebianLinux] +f:/etc/passwd -> !r:^# && !r:^root: && r:^\w+:\w+:0:; + + +# EOF diff --git a/src/rootcheck/db/cis_rhel5_linux_rcl.txt b/src/rootcheck/db/cis_rhel5_linux_rcl.txt new file mode 100644 index 0000000..a252d98 --- /dev/null +++ b/src/rootcheck/db/cis_rhel5_linux_rcl.txt @@ -0,0 +1,188 @@ +# @(#) $Id: cis_rhel5_linux_rcl.txt,v 1.5 2009/02/20 15:33:25 dcid Exp $ +# +# OSSEC Linux Audit - (C) 2008 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Application name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - p (process running) +# - d (any file inside the directory) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + +# CIS Checks for Red Hat (RHEL 2.1, 3.0, 4.0 and Fedora Core 1,2,3,4 and 5). +# Based on CIS Benchmark for Red Hat Enterprise Linux 5 v1.1 + + + +# RC scripts location +$rc_dirs=/etc/rc.d/rc2.d,/etc/rc.d/rc3.d,/etc/rc.d/rc4.d,/etc/rc.d/rc5.d; + + + +# Main one. Only valid for Red Hat 5. +[CIS - Testing against the CIS Red Hat Enterprise Linux 5 Benchmark v1.1] [any required] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/redhat-release -> r:^Red Hat Enterprise Linux \S+ release 5; +f:/etc/redhat-release -> r:^CentOS && r:release 5.2; + + + +# Build considerations - Partition scheme. +[CIS - RHEL5 - Build considerations - Robust partition scheme - /var is not on its own partition] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/fstab -> !r:/var; + + + +# Section 2.3 - SSH configuration +[CIS - RHEL5 2.3 - SSH Configuration - Protocol version 1 enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/ssh/sshd_config -> !r:^# && r:Protocol\.+1; + +[CIS - RHEL5 2.3 - SSH Configuration - IgnoreRHosts disabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/ssh/sshd_config -> !r:^# && r:IgnoreRhosts\.+no; + +[CIS - RHEL5 2.3 - SSH Configuration - Empty passwords permitted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/ssh/sshd_config -> !r:^# && r:^PermitEmptyPasswords\.+yes; + +[CIS - RHEL5 2.3 - SSH Configuration - Host based authentication enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/ssh/sshd_config -> !r:^# && r:HostbasedAuthentication\.+yes; + +[CIS - RHEL5 2.3 - SSH Configuration - Root login allowed] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/ssh/sshd_config -> !r:^# && r:PermitRootLogin\.+yes; + + + +# Section 2.4 Enable system accounting +[CIS - RHEL5 2.4 - System Accounting - Sysstat not installed] [all] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:!/var/log/sa; + + + +# Section 3 - Minimize xinetd services +[CIS - RHEL5 3.3 - Telnet enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/xinetd.c/telnet -> !r:^# && r:disable && r:no; + +[CIS - RHEL5 3.4 - VSFTP enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/xinetd.c/vsftpd -> !r:^# && r:disable && r:no; + +[CIS - RHEL5 3.5 - rsh/rlogin/rcp enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/xinetd.c/rlogin -> !r:^# && r:disable && r:no; +f:/etc/xinetd.c/rsh -> !r:^# && r:disable && r:no; +f:/etc/xinetd.c/shell -> !r:^# && r:disable && r:no; + +[CIS - RHEL5 3.6 - tftpd enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/xinetd.c/tftpd -> !r:^# && r:disable && r:no; + +[CIS - RHEL5 3.7 - imap enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/xinetd.c/cyrus-imapd -> !r:^# && r:disable && r:no; + +[CIS - RHEL5 3.8 - pop3 enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/xinetd.c/dovecot -> !r:^# && r:disable && r:no; + + + +# Section 4 - Minimize boot services +[CIS - RHEL5 4.1 - Set daemon umask - Default umask is higher than 027] [all] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/init.d/functions -> !r:^# && r:^umask && <:umask 027; + +[CIS - RHEL5 4.4 - GUI login enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/inittab -> !r:^# && r:id:5; + +[CIS - RHEL5 4.7 - Disable standard boot services - Samba Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dsamba$; +d:$rc_dirs -> ^S\d\dsmb$; + +[CIS - RHEL5 4.8 - Disable standard boot services - NFS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dnfs$; +d:$rc_dirs -> ^S\d\dnfslock$; + +[CIS - RHEL5 4.10 - Disable standard boot services - NIS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dypbind$; +d:$rc_dirs -> ^S\d\dypserv$; + +[CIS - RHEL5 4.13 - Disable standard boot services - NetFS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dnetfs$; + +[CIS - RHEL5 4.15 - Disable standard boot services - Apache web server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dapache$; + +[CIS - RHEL5 4.16 - Disable standard boot services - SNMPD process Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dsnmpd$; + +[CIS - RHEL5 4.17 - Disable standard boot services - DNS server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dnamed$; + +[CIS - RHEL5 4.18 - Disable standard boot services - MySQL server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dmysqld$; + +[CIS - RHEL5 4.18 - Disable standard boot services - PostgreSQL server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dpostgresql$; + +[CIS - RHEL5 4.19 - Disable standard boot services - Squid Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dsquid$; + +[CIS - RHEL5 4.20 - Disable standard boot services - Kudzu hardware detection Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +d:$rc_dirs -> ^S\d\dkudzu$; + + + +# Section 5 - Kernel tuning +[CIS - RHEL5 5.1 - Network parameters - Source routing accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/proc/sys/net/ipv4/conf/all/accept_source_route -> 1; + +[CIS - RHEL5 5.1 - Network parameters - ICMP redirects accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/proc/sys/net/ipv4/conf/all/accept_redirects -> 1; + +[CIS - RHEL5 5.1 - Network parameters - ICMP secure redirects accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/proc/sys/net/ipv4/conf/all/secure_redirects -> 1; + +[CIS - RHEL5 5.1 - Network parameters - ICMP broadcasts accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts -> 0; + +[CIS - RHEL5 5.2 - Network parameters - IP Forwarding enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/proc/sys/net/ipv4/ip_forward -> 1; +f:/proc/sys/net/ipv6/ip_forward -> 1; + + + +# Section 7 - Permissions +[CIS - RHEL5 7.2 - Removable partition /media without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/fstab -> !r:^# && r:/media && !r:nodev; + +[CIS - RHEL5 7.2 - Removable partition /media without 'nosuid' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/fstab -> !r:^# && r:/media && !r:nosuid; + +[CIS - RHEL5 7.3 - User-mounted removable partition allowed on the console] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/security/console.perms -> r:^ \d+ ; +f:/etc/security/console.perms -> r:^ \d+ ; + + + +# Section 8 - Access and authentication +[CIS - RHEL5 8.7 - GRUB Password not set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/boot/grub/menu.lst -> !r:^# && !r:password; + +[CIS - RHEL5 9.2 - Account with empty password present] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/shadow -> r:^\w+::; + +[CIS - RHEL5 SN.11 - Non-root account with uid 0] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL5] +f:/etc/passwd -> !r:^# && !r:^root: && r:^\w+:\w+:0:; + + +# EOF diff --git a/src/rootcheck/db/cis_rhel_linux_rcl.txt b/src/rootcheck/db/cis_rhel_linux_rcl.txt new file mode 100644 index 0000000..a4cb1f5 --- /dev/null +++ b/src/rootcheck/db/cis_rhel_linux_rcl.txt @@ -0,0 +1,296 @@ +# @(#) $Id: cis_rhel_linux_rcl.txt,v 1.5 2008/08/28 12:07:35 dcid Exp $ +# +# OSSEC Linux Audit - (C) 2008 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Application name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - p (process running) +# - d (any file inside the directory) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + +# CIS Checks for Red Hat (RHEL 2.1, 3.0, 4.0 and Fedora Core 1,2,3,4 and 5). +# Based on CIS Benchmark for Red Hat Enterprise Linux v1.0.5 + + + +# RC scripts location +$rc_dirs=/etc/rc.d/rc2.d,/etc/rc.d/rc3.d,/etc/rc.d/rc4.d,/etc/rc.d/rc5.d; + + + +# Main one. Only valid for Red Hat/Fedora. +[CIS - Testing against the CIS Red Hat Enterprise Linux Benchmark v1.0.5] [any required] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/redhat-release -> r:^Red Hat Enterprise Linux \S+ release 4; +f:/etc/redhat-release -> r:^Red Hat Enterprise Linux \S+ release 3; +f:/etc/redhat-release -> r:^Red Hat Enterprise Linux \S+ release 2.1; +f:/etc/fedora-release -> r:^Fedora && r:release 1; +f:/etc/fedora-release -> r:^Fedora && r:release 2; +f:/etc/fedora-release -> r:^Fedora && r:release 3; +f:/etc/fedora-release -> r:^Fedora && r:release 4; +f:/etc/fedora-release -> r:^Fedora && r:release 5; + + + +# Build considerations - Partition scheme. +[CIS - Red Hat Linux - Build considerations - Robust partition scheme - /var is not on its own partition] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:/var; + +[CIS - Red Hat Linux - Build considerations - Robust partition scheme - /home is not on its own partition] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:/home; + + + + +# Section 1.3 - SSH configuration +[CIS - Red Hat Linux 1.3 - SSH Configuration - Protocol version 1 enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/ssh/sshd_config -> !r:^# && r:Protocol\.+1; + +[CIS - Red Hat Linux 1.3 - SSH Configuration - IgnoreRHosts disabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/ssh/sshd_config -> !r:^# && r:IgnoreRhosts\.+no; + +[CIS - Red Hat Linux 1.3 - SSH Configuration - Empty passwords permitted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/ssh/sshd_config -> !r:^# && r:^PermitEmptyPasswords\.+yes; + +[CIS - Red Hat Linux 1.3 - SSH Configuration - Host based authentication enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/ssh/sshd_config -> !r:^# && r:HostbasedAuthentication\.+yes; + +[CIS - Red Hat Linux 1.3 - SSH Configuration - Root login allowed] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/ssh/sshd_config -> !r:^# && r:PermitRootLogin\.+yes; + + + +# Section 1.4 Enable system accounting +[CIS - Red Hat Linux 1.4 - System Accounting - Sysstat not installed] [all] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:!/var/log/sa; + + + +# Section 2.5 Install and run Bastille +[CIS - Red Hat Linux 1.5 - System harderning - Bastille is not installed] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:!/etc/Bastille; + + + +# Section 2 - Minimize xinetd services +[CIS - Red Hat Linux 2.3 - Telnet enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/telnet -> !r:^# && r:disable && r:no; + +[CIS - Red Hat Linux 2.4 - VSFTP enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/vsftpd -> !r:^# && r:disable && r:no; + +[CIS - Red Hat Linux 2.4 - WU-FTP enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/wu-ftpd -> !r:^# && r:disable && r:no; + +[CIS - Red Hat Linux 2.5 - rsh/rlogin/rcp enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/rlogin -> !r:^# && r:disable && r:no; +f:/etc/xinetd.c/rsh -> !r:^# && r:disable && r:no; +f:/etc/xinetd.c/shell -> !r:^# && r:disable && r:no; + +[CIS - Red Hat Linux 2.6 - tftpd enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/tftpd -> !r:^# && r:disable && r:no; + +[CIS - Red Hat Linux 2.7 - imap enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/imap -> !r:^# && r:disable && r:no; +f:/etc/xinetd.c/imaps -> !r:^# && r:disable && r:no; + +[CIS - Red Hat Linux 2.8 - pop3 enabled on xinetd] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/xinetd.c/ipop3 -> !r:^# && r:disable && r:no; +f:/etc/xinetd.c/pop3s -> !r:^# && r:disable && r:no; + + + +# Section 3 - Minimize boot services +[CIS - Red Hat Linux 3.1 - Set daemon umask - Default umask is higher than 027] [all] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/init.d/functions -> !r:^# && r:^umask && >:umask 027; + +[CIS - Red Hat Linux 3.4 - GUI login enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/inittab -> !r:^# && r:id:5; + +[CIS - Red Hat Linux 3.7 - Disable standard boot services - Samba Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dsamba$; +d:$rc_dirs -> ^S\d\dsmb$; + +[CIS - Red Hat Linux 3.8 - Disable standard boot services - NFS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dnfs$; +d:$rc_dirs -> ^S\d\dnfslock$; + +[CIS - Red Hat Linux 3.10 - Disable standard boot services - NIS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dypbind$; +d:$rc_dirs -> ^S\d\dypserv$; + +[CIS - Red Hat Linux 3.13 - Disable standard boot services - NetFS Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dnetfs$; + +[CIS - Red Hat Linux 3.15 - Disable standard boot services - Apache web server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dapache$; +d:$rc_dirs -> ^S\d\dhttpd$; + +[CIS - Red Hat Linux 3.15 - Disable standard boot services - TUX web server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dtux$; + +[CIS - Red Hat Linux 3.16 - Disable standard boot services - SNMPD process Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dsnmpd$; + +[CIS - Red Hat Linux 3.17 - Disable standard boot services - DNS server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dnamed$; + +[CIS - Red Hat Linux 3.18 - Disable standard boot services - MySQL server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dmysqld$; + +[CIS - Red Hat Linux 3.18 - Disable standard boot services - PostgreSQL server Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dpostgresql$; + +[CIS - Red Hat Linux 3.19 - Disable standard boot services - Webmin Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dwebmin$; + +[CIS - Red Hat Linux 3.20 - Disable standard boot services - Squid Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dsquid$; + +[CIS - Red Hat Linux 3.21 - Disable standard boot services - Kudzu hardware detection Enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +d:$rc_dirs -> ^S\d\dkudzu$; + + + +# Section 4 - Kernel tuning +[CIS - Red Hat Linux 4.1 - Network parameters - Source routing accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/proc/sys/net/ipv4/conf/all/accept_source_route -> 1; + +[CIS - Red Hat Linux 4.1 - Network parameters - ICMP broadcasts accepted] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts -> 0; + +[CIS - Red Hat Linux 4.2 - Network parameters - IP Forwarding enabled] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/proc/sys/net/ipv4/ip_forward -> 1; +f:/proc/sys/net/ipv6/ip_forward -> 1; + + + +# Section 6 - Permissions +[CIS - Red Hat Linux 6.1 - Partition /var without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/var && !r:nodev; + +[CIS - Red Hat Linux 6.1 - Partition /tmp without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/tmp && !r:nodev; + +[CIS - Red Hat Linux 6.1 - Partition /opt without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/opt && !r:nodev; + +[CIS - Red Hat Linux 6.1 - Partition /home without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:^# && r:ext2|ext3 && r:/home && !r:nodev ; + +[CIS - Red Hat Linux 6.2 - Removable partition /media without 'nodev' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:^# && r:/media && !r:nodev; + +[CIS - Red Hat Linux 6.2 - Removable partition /media without 'nosuid' set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/fstab -> !r:^# && r:/media && !r:nosuid; + +[CIS - Red Hat Linux 6.3 - User-mounted removable partition allowed on the console] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/security/console.perms -> r:^ \d+ ; +f:/etc/security/console.perms -> r:^ \d+ ; + + + +# Section 7 - Access and authentication +[CIS - Red Hat Linux 7.8 - LILO Password not set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/lilo.conf -> !r:^# && !r:restricted; +f:/etc/lilo.conf -> !r:^# && !r:password=; + +[CIS - Red Hat Linux 7.8 - GRUB Password not set] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/boot/grub/menu.lst -> !r:^# && !r:password; + +[CIS - Red Hat Linux 8.2 - Account with empty password present] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/shadow -> r:^\w+::; + +[CIS - Red Hat Linux SN.11 - Non-root account with uid 0] [any] [http://www.ossec.net/wiki/index.php/CIS_RHEL] +f:/etc/passwd -> !r:^# && !r:^root: && r:^\w+:\w+:0:; + + + +# Tests specific for VMware ESX - Runs on Red Hat Linux +# Will not be tested anywhere else. +[VMware ESX - Testing against the Security Harderning benchmark VI3 for ESX 3.5] [any required] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +f:/etc/vmware-release -> r:^VMware ESX; + + +# Virtual Machine Files and Settings - 1 +# 1.1 +[VMware ESX - VM settings - Copy operation between guest and console enabled] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^isolation.tools.copy.disable; +d:/vmfs/volumes -> .vmx$ -> r:^isolation.tools.copy.disable && r:false; + +# 1.2 +[VMware ESX - VM settings - Paste operation between guest and console enabled] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^isolation.tools.paste.disable; +d:/vmfs/volumes -> .vmx$ -> r:^isolation.tools.paste.disable && r:false; + +# 1.3 +[VMware ESX - VM settings - GUI Options enabled] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> r:^isolation.tools.setGUIOptions.enable && r:true; + +# 1.4 +[VMware ESX - VM settings - Data Flow from the Virtual Machine to the Datastore not limited - Rotate size not 100KB] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^log.rotateSize; +d:/vmfs/volumes -> .vmx$ -> r:^log.rotateSize && !r:"100000"; + +# 1.5 +[VMware ESX - VM settings - Data Flow from the Virtual Machine to the Datastore not limited - Maximum number of logs not 10] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^log.keepOld; +d:/vmfs/volumes -> .vmx$ -> r:^log.keepOld && r:"10"; + +# 1.6 +[VMware ESX - VM settings - Data Flow from the Virtual Machine to the Datastore not limited - Guests allowed to write SetInfo data to config] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^isolation.tools.setinfo.disable; +d:/vmfs/volumes -> .vmx$ -> r:^isolation.tools.setinfo.disable && r:false; + +# 1.7 +[VMware ESX - VM settings - Nonpersistent Disks being used] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> r:^scsi\d:\d.mode && r:!independent-nonpersistent; + +# 1.8 +[VMware ESX - VM settings - Floppy drive present] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> r:^floppy\d+.present && r:!false; + +[VMware ESX - VM settings - Serial port present] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> r:^serial\d+.present && r:!false; + +[VMware ESX - VM settings - Parallel port present] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> r:^parallel\d+.present && r:!false; + +# 1.9 +[VMware ESX - VM settings - Unauthorized Removal or Connection of Devices allowed] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^Isolation.tools.connectable.disable; +d:/vmfs/volumes -> .vmx$ -> r:^Isolation.tools.connectable.disable && r:false; + +# 1.10 +[VMware ESX - VM settings - Avoid Denial of Service Caused by Virtual Disk Modification Operations - diskWiper enabled] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^isolation.tools.diskWiper.disable; +d:/vmfs/volumes -> .vmx$ -> r:^isolation.tools.diskWiper.disable && r:false; + +[VMware ESX - VM settings - Avoid Denial of Service Caused by Virtual Disk Modification Operations - diskShrink enabled] [any] [http://www.ossec.net/wiki/index.php/SecurityHardening_VMwareESX] +d:/vmfs/volumes -> .vmx$ -> !r:^isolation.tools.diskShrink.disable; +d:/vmfs/volumes -> .vmx$ -> r:^isolation.tools.diskShrink.disable && r:false; + + +# Configuring the Service Console in ESX 3.5 - 2 +# 2.1 + + +# EOF diff --git a/src/rootcheck/db/rootkit_files.txt b/src/rootcheck/db/rootkit_files.txt new file mode 100755 index 0000000..624c4fe --- /dev/null +++ b/src/rootcheck/db/rootkit_files.txt @@ -0,0 +1,468 @@ +# @(#) $Id: rootkit_files.txt,v 1.21 2009/01/29 16:53:37 dcid Exp $ +# +# rootkit_files.txt, (C) Daniel B. Cid +# Imported from the rootcheck project. +# +# Lines starting with '#' are not going to be read. +# Blank lines are not going to be read too. +# +# Each line must be in the following format: +# file_name ! Name ::Link to it + +# Files that start with an '*' are going to be searched +# in the whole system. + + +# Bash door +tmp/mcliZokhb ! Bash door ::/rootkits/bashdoor.php +tmp/mclzaKmfa ! Bash door ::/rootkits/bashdoor.php + + +#adore Worm +dev/.shit/red.tgz ! Adore Worm ::/rootkits/adorew.php +usr/lib/libt ! Adore Worm ::/rootkits/adorew.php +usr/bin/adore ! Adore Worm ::/rootkits/adorew.php +*/klogd.o ! Adore Worm ::/rootkits/adorew.php +*/red.tar ! Adore Worm ::/rootkits/adorew.php + + +#T.R.K rootkit +usr/bin/soucemask ! TRK rootkit ::/rootkits/trk.php +usr/bin/sourcemask ! TRK rootkit ::/rootkits/trk.php + + +# 55.808.A Worm +tmp/.../a ! 55808.A Worm :: +tmp/.../r ! 55808.A Worm :: + + +# Volc Rootkit +usr/lib/volc ! Volc Rootkit :: +usr/bin/volc ! Volc Rootkit :: + + +# Illogic +lib/security/.config ! Illogic Rootkit ::rootkits/illogic.php +usr/bin/sia ! Illogic Rootkit ::rootkits/illogic.php +etc/ld.so.hash ! Illogic Rootkit ::rootkits/illogic.php +*/uconf.inv ! Illogic Rootkit ::rootkits/illogic.php + + +#T0rnkit installed +usr/src/.puta ! t0rn Rootkit ::rootkits/torn.php +usr/info/.t0rn ! t0rn Rootkit ::rootkits/torn.php +lib/ldlib.tk ! t0rn Rootkit ::rootkits/torn.php +etc/ttyhash ! t0rn Rootkit ::rootkits/torn.php +sbin/xlogin ! t0rn Rootkit ::rootkits/torn.php +*/ldlib.tk ! t0rn Rootkit ::rootkits/torn.php +*/.t0rn ! t0rn Rootkit ::rootkits/torn.php +*/.puta ! t0rn Rootkit ::rootkits/torn.php + + +#RK17 +bin/rtty ! RK17 :: +bin/squit ! RK17 :: +sbin/pback ! RK17 :: +proc/kset ! RK17 :: +usr/src/linux/modules/autod.o ! RK17 :: +usr/src/linux/modules/soundx.o ! RK17 :: + + +# Ramen Worm +usr/lib/ldlibps.so ! Ramen Worm ::rootkits/ramen.php +usr/lib/ldlibns.so ! Ramen Worm ::rootkits/ramen.php +usr/lib/ldliblogin.so ! Ramen Worm ::rootkits/ramen.php +usr/src/.poop ! Ramen Worm ::rootkits/ramen.php +tmp/ramen.tgz ! Ramen Worm ::rootkits/ramen.php +etc/xinetd.d/asp ! Ramen Worm ::rootkits/ramen.php + + +# Sadmind/IIS Worm +dev/cuc ! Sadmind/IIS Worm :: + + +#Monkit +lib/defs ! Monkit :: +usr/lib/libpikapp.a ! Monkit found :: + + +#RSHA +usr/bin/kr4p ! RSHA :: +usr/bin/n3tstat ! RSHA :: +usr/bin/chsh2 ! RSHA :: +usr/bin/slice2 ! RSHA :: +etc/rc.d/rsha ! RSHA :: + + +#ShitC worm +bin/home ! ShitC :: +sbin/home ! ShitC :: +usr/sbin/in.slogind ! ShitC :: + + +#Omega Worm +dev/chr ! Omega Worm :: + + +#rh-sharpe +bin/.ps ! Rh-Sharpe :: +usr/bin/cleaner ! Rh-Sharpe :: +usr/bin/slice ! Rh-Sharpe :: +usr/bin/vadim ! Rh-Sharpe :: +usr/bin/.ps ! Rh-Sharpe :: +bin/.lpstree ! Rh-Sharpe :: +usr/bin/.lpstree ! Rh-Sharpe :: +usr/bin/lnetstat ! Rh-Sharpe :: +bin/lnetstat ! Rh-Sharpe :: +usr/bin/ldu ! Rh-Sharpe :: +bin/ldu ! Rh-Sharpe :: +usr/bin/lkillall ! Rh-Sharpe :: +bin/lkillall ! Rh-Sharpe :: +usr/include/rpcsvc/du ! Rh-Sharpe :: + + +#Maniac RK +usr/bin/mailrc ! Maniac RK :: + + +#Showtee / romaniam +usr/lib/.egcs ! Showtee :: +usr/lib/.wormie ! Showtee :: +usr/lib/.kinetic ! Showtee :: +usr/lib/liblog.o ! Showtee :: +usr/include/addr.h ! Showtee / Romanian rootkit :: +usr/include/cron.h ! Showtee :: +usr/include/file.h ! Showtee / Romaniam rootkit :: +usr/include/syslogs.h ! Showtee / Romaniam rootkit :: +usr/include/proc.h ! Showtee / Romaniam rootkit :: +usr/include/chk.h ! Showtee :: +usr/sbin/initdl ! Romanian rootkit :: +usr/sbin/xntps ! Romanian rootkit :: + + +#Optickit +usr/bin/xchk ! Optickit :: +usr/bin/xsf ! Optickit :: + + +# LDP worm +dev/.kork ! LDP Worm :: +bin/.login ! LDP Worm :: +bin/.ps ! LDP Worm :: + + +# Telekit +dev/hda06 ! TeLeKit trojan :: +usr/info/libc1.so ! TeleKit trojan :: + + +# Tribe bot +dev/wd4 ! Tribe bot :: + + +# LRK +dev/ida/.inet ! LRK rootkit ::rootkits/lrk.php +*/bindshell ! LRK rootkit ::rootkits/lrk.php + + +# Adore Rootkit +etc/bin/ava ! Adore Rootkit :: +etc/sbin/ava ! Adore Rootkit :: + + +# Slapper +tmp/.bugtraq ! Slapper installed :: +tmp/.bugtraq.c ! Slapper installed :: +tmp/.cinik ! Slapper installed :: +tmp/.b ! Slapper installed :: +tmp/httpd ! Slapper installed :: +tmp./update ! Slapper installed :: +tmp/.unlock ! Slapper installed :: +tmp/.font-unix/.cinik ! Slapper installed :: +tmp/.cinik ! Slapper installed :: + + + +# Scalper +tmp/.uua ! Scalper installed :: +tmp/.a ! Scalper installed :: + + +# Knark +proc/knark ! Knark Installed ::rootkits/knark.php +dev/.pizda ! Knark Installed ::rootkits/knark.php +dev/.pula ! Knark Installed ::rootkits/knark.php +dev/.pula ! Knark Installed ::rootkits/knark.php +*/taskhack ! Knark Installed ::rootkits/knark.php +*/rootme ! Knark Installed ::rootkits/knark.php +*/nethide ! Knark Installed ::rootkits/knark.php +*/hidef ! Knark Installed ::rootkits/knark.php +*/ered ! Knark Installed ::rootkits/knark.php + + +# Lion worm +dev/.lib ! Lion Worm ::rootkits/lion.php +dev/.lib/1iOn.sh ! Lion Worm ::rootkits/lion.php +bin/mjy ! Lion Worm ::rootkits/lion.php +bin/in.telnetd ! Lion Worm ::rootkits/lion.php +usr/info/torn ! Lion Worm ::rootkits/lion.php +*/1iOn\.sh ! Lion Worm ::rootkits/lion.php + + +# Bobkit +usr/include/.../ ! Bobkit Rootkit ::rootkits/bobkit.php +usr/lib/.../ ! Bobkit Rootkit ::rootkits/bobkit.php +usr/sbin/.../ ! Bobkit Rootkit ::rootkits/bobkit.php +usr/bin/ntpsx ! Bobkit Rootkit ::rootkits/bobkit.php +tmp/.bkp ! Bobkit Rootkit ::rootkits/bobkit.php +usr/lib/.bkit- ! Bobkit Rootkit ::rootkits/bobkit.php +*/bkit- ! Bobkit Rootkit ::rootkits/bobkit.php + +# Hidrootkit +var/lib/games/.k ! Hidr00tkit :: + + +# Ark +dev/ptyxx ! Ark rootkit :: + + +#Mithra Rootkit +usr/lib/locale/uboot ! Mithra`s rootkit :: + + +# Optickit +usr/bin/xsf ! OpticKit :: +usr/bin/xchk ! OpticKit :: + + +# LOC rookit +tmp/xp ! LOC rookit :: +tmp/kidd0.c ! LOC rookit :: +tmp/kidd0 ! LOC rookit :: + + +# TC2 worm +usr/info/.tc2k ! TC2 Worm :: +usr/bin/util ! TC2 Worm :: +usr/sbin/initcheck ! TC2 Worm :: +usr/sbin/ldb ! TC2 Worm :: + + +# Anonoiyng rootkit +usr/sbin/mech ! Anonoiyng rootkit :: +usr/sbin/kswapd ! Anonoiyng rootkit :: + + +# SuckIt +lib/.x ! SuckIt rootkit :: +*/hide.log ! Suckit rootkit :: +lib/sk ! SuckIT rootkit :: + + +# Beastkit +usr/local/bin/bin ! Beastkit rootkit ::rootkits/beastkit.php +usr/man/.man10 ! Beastkit rootkit ::rootkits/beastkit.php +usr/sbin/arobia ! Beastkit rootkit ::rootkits/beastkit.php +usr/lib/elm/arobia ! Beastkit rootkit ::rootkits/beastkit.php +usr/local/bin/.../bktd ! Beastkit rootkit ::rootkits/beastkit.php + + +# Tuxkit +dev/tux ! Tuxkit rootkit ::rootkits/Tuxkit.php +usr/bin/xsf ! Tuxkit rootkit ::rootkits/Tuxkit.php +usr/bin/xchk ! Tuxkit rootkit ::rootkits/Tuxkit.php +*/.file ! Tuxkit rootkit ::rootkits/Tuxkit.php +*/.addr ! Tuxkit rootkit ::rootkits/Tuxkit.php + + +# Old rootkits +usr/include/rpc/ ../kit ! Old rootkits ::rootkits/Old.php +usr/include/rpc/ ../kit2 ! Old rootkits ::rootkits/Old.php +usr/doc/.sl ! Old rootkits ::rootkits/Old.php +usr/doc/.sp ! Old rootkits ::rootkits/Old.php +usr/doc/.statnet ! Old rootkits ::rootkits/Old.php +usr/doc/.logdsys ! Old rootkits ::rootkits/Old.php +usr/doc/.dpct ! Old rootkits ::rootkits/Old.php +usr/doc/.gifnocfi ! Old rootkits ::rootkits/Old.php +usr/doc/.dnif ! Old rootkits ::rootkits/Old.php +usr/doc/.nigol ! Old rootkits ::rootkits/Old.php + + +# Kenga3 rootkit +usr/include/. . ! Kenga3 rootkit + + +# ESRK rootkit +usr/lib/tcl5.3 ! ESRK rootkit + + +# Fu rootkit +sbin/xc ! Fu rootkit +usr/include/ivtype.h ! Fu rootkit +bin/.lib ! Fu rootkit + + +# ShKit rootkit +lib/security/.config ! ShKit rootkit +etc/ld.so.hash ! ShKit rootkit + + +# AjaKit rootkit +lib/.ligh.gh ! AjaKit rootkit +lib/.libgh.gh ! AjaKit rootkit +lib/.libgh-gh ! AjaKit rootkit +dev/tux ! AjaKit rootkit +dev/tux/.proc ! AjaKit rootkit +dev/tux/.file ! AjaKit rootkit + + +# zaRwT rootkit +bin/imin ! zaRwT rootkit +bin/imout ! zaRwT rootkit + + +# Madalin rootkit +usr/include/icekey.h ! Madalin rootkit +usr/include/iceconf.h ! Madalin rootkit +usr/include/iceseed.h ! Madalin rootkit + + +# shv5 rootkit XXX http://www.askaboutskating.com/forum/.../shv5/setup +lib/libsh.so ! shv5 rootkit +usr/lib/libsh ! shv5 rootkit + + +# BMBL rootkit (http://www.giac.com/practical/GSEC/Steve_Terrell_GSEC.pdf) +etc/.bmbl ! BMBL rootkit +etc/.bmbl/sk ! BMBL rootkit + + +# rootedoor rootkit +*/rootedoor ! Rootedoor rootkit + + +# 0vason rootkit +*/ovas0n ! ovas0n rootkit ::/rootkits/ovason.php +*/ovason ! ovas0n rootkit ::/rootkits/ovason.php + + +# Rpimp reverse telnet +*/rpimp ! rpv21 (Reverse Pimpage)::/rootkits/rpimp.php + + +# Cback Linux worm +tmp/cback ! cback worm ::/rootkits/cback.php +tmp/derfiq ! cback worm ::/rootkits/cback.php +*/cback ! cback worm ::/rootkits/cback.php + + +# aPa Kit (from rkhunter) +usr/share/.aPa ! Apa Kit + + +# enye-sec Rootkit +etc/.enyelkmHIDE^IT.ko ! enye-sec Rootkit ::/rootkits/enye-sec.php + + +# Override Rootkit +dev/grid-hide-pid- ! Override rootkit ::/rootkits/override.php +dev/grid-unhide-pid- ! Override rootkit ::/rootkits/override.php +dev/grid-show-pids ! Override rootkit ::/rootkits/override.php +dev/grid-hide-port- ! Override rootkit ::/rootkits/override.php +dev/grid-unhide-port- ! Override rootkit ::/rootkits/override.php + + +# PHALANX rootkit +usr/share/.home.ph1 ! PHALANX rootkit :: +usr/share/.home.ph1/tty ! PHALANX rootkit :: +etc/host.ph1 ! PHALANX rootkit :: +bin/host.ph1 ! PHALANX rootkit :: + + +# ZK rootkit (http://honeyblog.org/junkyard/reports/redhat-compromise2.pdf) +# and from chkrootkit +usr/share/.zk ! ZK rootkit :: +usr/share/.zk/zk ! ZK rootkit :: +etc/1ssue.net ! ZK rootkit :: +usr/X11R6/.zk ! ZK rootkit :: +usr/X11R6/.zk/xfs ! ZK rootkit :: +usr/X11R6/.zk/echo ! ZK rootkit :: +etc/sysconfig/console/load.zk ! ZK rootkit :: + + +# Public sniffers +*/.linux-sniff ! Sniffer log :: +*/sniff-l0g ! Sniffer log :: +*/core_$ ! Sniffer log :: +*/tcp.log ! Sniffer log :: +*/chipsul ! Sniffer log :: +*/beshina ! Sniffer log :: +*/.owned$ | Sniffer log :: + + +# Solaris worm - +# http://blogs.sun.com/security/entry/solaris_in_telnetd_worm_seen +var/adm/.profile ! Solaris Worm :: +var/spool/lp/.profile ! Solaris Worm :: +var/adm/sa/.adm ! Solaris Worm :: +var/spool/lp/admins/.lp ! Solaris Worm :: + + +#Suspicious files +etc/rc.d/init.d/rc.modules ! Suspicious file ::rootkits/Suspicious.php +lib/ldd.so ! Suspicious file ::rootkits/Suspicious.php +usr/man/muie ! Suspicious file ::rootkits/Suspicious.php +usr/X11R6/include/pain ! Suspicious file ::rootkits/Suspicious.php +usr/bin/sourcemask ! Suspicious file ::rootkits/Suspicious.php +usr/bin/ras2xm ! Suspicious file ::rootkits/Suspicious.php +usr/bin/ddc ! Suspicious file ::rootkits/Suspicious.php +usr/bin/jdc ! Suspicious file ::rootkits/Suspicious.php +usr/sbin/in.telnet ! Suspicious file ::rootkits/Suspicious.php +sbin/vobiscum ! Suspicious file ::rootkits/Suspicious.php +usr/sbin/jcd ! Suspicious file ::rootkits/Suspicious.php +usr/sbin/atd2 ! Suspicious file ::rootkits/Suspicious.php +usr/bin/ishit ! Suspicious file ::rootkits/Suspicious.php +usr/bin/.etc ! Suspicious file ::rootkits/Suspicious.php +usr/bin/xstat ! Suspicious file ::rootkits/Suspicious.php +var/run/.tmp ! Suspicious file ::rootkits/Suspicious.php +usr/man/man1/lib/.lib ! Suspicious file ::rootkits/Suspicious.php +usr/man/man2/.man8 ! Suspicious file ::rootkits/Suspicious.php +var/run/.pid ! Suspicious file ::rootkits/Suspicious.php +lib/.so ! Suspicious file ::rootkits/Suspicious.php +lib/.fx ! Suspicious file ::rootkits/Suspicious.php +lib/lblip.tk ! Suspicious file ::rootkits/Suspicious.php +usr/lib/.fx ! Suspicious file ::rootkits/Suspicious.php +var/local/.lpd ! Suspicious file ::rootkits/Suspicious.php +dev/rd/cdb ! Suspicious file ::rootkits/Suspicious.php +dev/.rd/ ! Suspicious file ::rootkits/Suspicious.php +usr/lib/pt07 ! Suspicious file ::rootkits/Suspicious.php +usr/bin/atm ! Suspicious file ::rootkits/Suspicious.php +tmp/.cheese ! Suspicious file ::rootkits/Suspicious.php +dev/.arctic ! Suspicious file ::rootkits/Suspicious.php +dev/.xman ! Suspicious file ::rootkits/Suspicious.php +dev/.golf ! Suspicious file ::rootkits/Suspicious.php +dev/srd0 ! Suspicious file ::rootkits/Suspicious.php +dev/ptyzx ! Suspicious file ::rootkits/Suspicious.php +dev/ptyzg ! Suspicious file ::rootkits/Suspicious.php +dev/xdf1 ! Suspicious file ::rootkits/Suspicious.php +dev/ttyop ! Suspicious file ::rootkits/Suspicious.php +dev/ttyof ! Suspicious file ::rootkits/Suspicious.php +dev/hd7 ! Suspicious file ::rootkits/Suspicious.php +dev/hdx1 ! Suspicious file ::rootkits/Suspicious.php +dev/hdx2 ! Suspicious file ::rootkits/Suspicious.php +dev/xdf2 ! Suspicious file ::rootkits/Suspicious.php +dev/ptyp ! Suspicious file ::rootkits/Suspicious.php +dev/ptyr ! Suspicious file ::rootkits/Suspicious.php +sbin/pback ! Suspicious file ::rootkits/Suspicious.php +usr/man/man3/psid ! Suspicious file ::rootkits/Suspicious.php +proc/kset ! Suspicious file ::rootkits/Suspicious.php +usr/bin/gib ! Suspicious file ::rootkits/Suspicious.php +usr/bin/snick ! Suspicious file ::rootkits/Suspicious.php +usr/bin/kfl ! Suspicious file ::rootkits/Suspicious.php +tmp/.dump ! Suspicious file ::rootkits/Suspicious.php +var/.x ! Suspicious file ::rootkits/Suspicious.php +var/.x/psotnic ! Suspicious file ::rootkits/Suspicious.php +*/.log ! Suspicious file ::rootkits/Suspicious.php +*/ecmf ! Suspicious file ::rootkits/Suspicious.php +*/mirkforce ! Suspicious file ::rootkits/Suspicious.php +*/mfclean ! Suspicious file ::rootkits/Suspicious.php diff --git a/src/rootcheck/db/rootkit_trojans.txt b/src/rootcheck/db/rootkit_trojans.txt new file mode 100755 index 0000000..d133e16 --- /dev/null +++ b/src/rootcheck/db/rootkit_trojans.txt @@ -0,0 +1,119 @@ +# @(#) $Id: rootkit_trojans.txt,v 1.20 2009/06/03 19:18:32 dcid Exp $ +# +# rootkit_trojans.txt, (C) Daniel B. Cid +# Imported from the rootcheck project. +# Some entries taken from the chkrootkit project. +# +# Lines starting with '#' are not going to be read (comments). +# Blank lines are not going to be read too. +# +# Each line must be in the following format: +# file_name !string_to_search!Description + +# Commom binaries and public trojan entries +ls !bash|^/bin/sh|dev/[^clu]|\.tmp/lsfile|duarawkz|/prof|/security|file\.h! +env !bash|^/bin/sh|file\.h|proc\.h|/dev/|^/bin/.*sh! +echo !bash|^/bin/sh|file\.h|proc\.h|/dev/[^cl]|^/bin/.*sh! +chown !bash|^/bin/sh|file\.h|proc\.h|/dev/[^cl]|^/bin/.*sh! +chmod !bash|^/bin/sh|file\.h|proc\.h|/dev/[^cl]|^/bin/.*sh! +chgrp !bash|^/bin/sh|file\.h|proc\.h|/dev/[^cl]|^/bin/.*sh! +cat !bash|^/bin/sh|file\.h|proc\.h|/dev/[^cl]|^/bin/.*sh! +bash !proc\.h|/dev/[0-9]|/dev/[hijkz]! +sh !proc\.h|/dev/[0-9]|/dev/[hijkz]! +uname !bash|^/bin/sh|file\.h|proc\.h|^/bin/.*sh! +date !bash|^/bin/sh|file\.h|proc\.h|/dev/[^cln]|^/bin/.*sh! +du !/dev|w0rm|/prof|file\.h! +df !bash|^/bin/sh|file\.h|proc\.h|/dev/[^clurdv]|^/bin/.*sh! +login !bash|elite|SucKIT|xlogin|vejeta|porcao|lets_log|sukasuk! +passwd !bash|file\.h|proc\.h|/dev/ttyo|/dev/[A-Z]|/dev/[b-s,uvxz]! +mingetty !bash|Dimensioni|pacchetto! +chfn !bash|file\.h|proc\.h|/dev/ttyo|/dev/[A-Z]|/dev/[a-s,uvxz]! +chsh !bash|file\.h|proc\.h|/dev/ttyo|/dev/[A-Z]|/dev/[a-s,uvxz]! +mail !bash|file\.h|proc\.h|/dev/[^nu]! +su !bash|/dev/[d-s,abuvxz]|/dev/[A-D]|/dev/[F-Z]|/dev/[0-9]|satori|vejeta|conf\.inv! +sudo !bash|satori|vejeta|conf\.inv! +crond !/dev/[^nt]|bash! +gpm !bash|mingetty! +ifconfig !bash|^/bin/sh|/dev/tux|session.null|/dev/[^cludisopt]! +diff !bash|^/bin/sh|file\.h|proc\.h|/dev/[^n]|^/bin/.*sh! +md5sum !bash|^/bin/sh|file\.h|proc\.h|/dev/|^/bin/.*sh! +hdparm !bash|/dev/ida! +ldd !/dev/[^n]|proc\.h|libshow.so|libproc.a! + + +# Trojan entries for troubleshooting binaries + +grep !bash|givemer|/dev/! +egrep !bash|^/bin/sh|file\.h|proc\.h|/dev/|^/bin/.*sh! +find !bash|/dev/[^tnlcs]|/prof|/home/virus|file\.h! +lsof !/prof|/dev/[^apcmnfk]|proc\.h|bash|^/bin/sh|/dev/ttyo|/dev/ttyp! +netstat !bash|^/bin/sh|/dev/[^aik]|/prof|grep|addr\.h! +top !/dev/[^npi3st%]|proc\.h|/prof/! +ps !/dev/ttyo|\.1proc|proc\.h|bash|^/bin/sh! +tcpdump !bash|^/bin/sh|file\.h|proc\.h|/dev/[^bu]|^/bin/.*sh! +pidof !bash|^/bin/sh|file\.h|proc\.h|/dev/[^f]|^/bin/.*sh! +fuser !bash|^/bin/sh|file\.h|proc\.h|/dev/[a-dtz]|^/bin/.*sh! +w !uname -a|proc\.h|bash! + + +# Trojan entries for common daemons + +sendmail !bash|fuck! +named !bash|blah|/dev/[0-9]|^/bin/sh! +inetd !bash|^/bin/sh|file\.h|proc\.h|/dev/[^un%]|^/bin/.*sh! +apachectl !bash|^/bin/sh|file\.h|proc\.h|/dev/[^n]|^/bin/.*sh! +sshd !check_global_passwd|panasonic|satori|vejeta|\.ark|/hash\.zk|bash|/dev[a-s]|/dev[A-Z]/! +syslogd !bash|/usr/lib/pt07|/dev/[^cln]]|syslogs\.h|proc\.h! +xinetd !bash|file\.h|proc\.h! +in.telnetd !cterm100|vt350|VT100|ansi-term|bash|^/bin/sh|/dev[A-R]|/dev/[a-z]/! +in.fingerd !bash|^/bin/sh|cterm100|/dev/! +identd !bash|^/bin/sh|file\.h|proc\.h|/dev/[^n]|^/bin/.*sh! +init !bash|/dev/h|HOME! +tcpd !bash|proc\.h|p1r0c4|hack|/dev/[^n]! +rlogin !p1r0c4|r00t|bash|/dev/[^nt]! + + +# Kill trojan + +killall !/dev/[^t%]|proc\.h|bash|tmp! +kill !/dev/[ab,d-k,m-z]|/dev/[F-Z]|/dev/[A-D]|/dev/[0-9]|proc\.h|bash|tmp! + + +# Rootkit entries +/sbin/init !HOME! Suckit rootkit +/proc/1/maps !init.! Suckit rootkit +/etc/rc.d/rc.sysinit !enyelkmHIDE! enye-sec Rootkit + + +# ZK rootkit (http://honeyblog.org/junkyard/reports/redhat-compromise2.pdf) +/etc/sysconfig/console/load.zk !/bin/sh! ZK rootkit +/etc/sysconfig/console/load.zk !usr/bin/run! ZK rootkit + + +# Modified /etc/hosts entries +# Idea taken from: +# http://blog.tenablesecurity.com/2006/12/detecting_compr.html +# http://www.sophos.com/security/analyses/trojbagledll.html +# http://www.f-secure.com/v-descs/fantibag_b.shtml +/etc/hosts !^[^#]*avp.ch!Anti-virus site on the hosts file +/etc/hosts !^[^#]*avp.ru!Anti-virus site on the hosts file +/etc/hosts !^[^#]*awaps.net! Anti-virus site on the hosts file +/etc/hosts !^[^#]*ca.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*mcafee.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*microsoft.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*f-secure.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*sophos.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*symantec.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*my-etrust.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*nai.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*networkassociates.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*viruslist.ru! Anti-virus site on the hosts file +/etc/hosts !^[^#]*kaspersky! Anti-virus site on the hosts file +/etc/hosts !^[^#]*symantecliveupdate.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*grisoft.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*clamav.net! Anti-virus site on the hosts file +/etc/hosts !^[^#]*bitdefender.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*antivirus.com! Anti-virus site on the hosts file +/etc/hosts !^[^#]*sans.org! Security site on the hosts file + +# EOF # diff --git a/src/rootcheck/db/system_audit_rcl.txt b/src/rootcheck/db/system_audit_rcl.txt new file mode 100644 index 0000000..82efb69 --- /dev/null +++ b/src/rootcheck/db/system_audit_rcl.txt @@ -0,0 +1,194 @@ +# @(#) $Id: system_audit_rcl.txt,v 1.3 2008/04/14 18:30:07 dcid Exp $ +# +# OSSEC Linux Audit - (C) 2007 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Application name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - p (process running) +# - d (any file inside the directory) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + +$php.ini=/var/www/conf/php.ini,/etc/php5/apache2/php.ini; +$web_dirs=/var/www,/var/htdocs,/home/httpd,/usr/local/apache,/usr/local/apache2,/usr/local/www; + + +# PHP checks +[PHP - Register globals are enabled] [any] [http://www.ossec.net/wiki] +f:$php.ini -> r:^register_globals = On; + + +# PHP checks +[PHP - Expose PHP is enabled] [any] [] +f:$php.ini -> r:^expose_php = On; + + +# PHP checks +[PHP - Allow URL fopen is enabled] [any] [] +f:$php.ini -> r:^allow_url_fopen = On; + + +# PHP checks +[PHP - Safe mode disabled] [any] [] +f:$php.ini -> r:^safe_mode = Off; + + +# PHP checks +[PHP - Displaying of errors is enabled] [any] [] +f:$php.ini -> r:^display_errors = On; + + +# PHP checks - consider open_basedir && disable_functions + + +## Looking for common web exploits (might indicate that you are owned). +## Using http://www.ossec.net/wiki/index.php/WebAttacks_links as a reference. +[Web exploits - Possible compromise] [any] [http://www.ossec.net/wiki/index.php/WebAttacks_links] +d:$web_dirs -> ^echo$ -> r: ^id.txt$ -> r: ^irc.txt$ -> r: ^stringa.txt -> r: ^cmd1.gif$ -> r: ^mambo1.txt$|^hai.txt$|^iyes.txt$ -> r: ^57.txt$ -> r: ^r57.txt -> r: ^evilx$ -> r: ^cmd$ -> r: ^root.gif -> r: ^bn.txt -> r: ^kk.txt -> r: ^graba.txt -> r: ^no.txt -> r: ^ddos.pl -> r: ^rox.txt -> r: ^lila.jpg -> r: ^safe.txt -> r: ^rootlab.jpg -> r: ^tool25.dat -> r: ^sela.txt -> r: ^zero.txt -> r: ^paged.gif -> r: ^hh.txt -> r: ^metodi.txt -> r: ^idpitbull.txt -> r: ^echo.txt -> r: ^ban.gif -> r: ^c.txt -> r: ^gay.txt -> r: ^genlog.txt$ -> r: ^safe$ -> r: ^safe3$ -> r: ^tool25.txt$ -> r: ^test.txt$ -> r: ^safeon.txt$ -> r: ^.yop$; + +[Web exploits (uncommon file name inside htdocs) - Possible compromise] [any] [http://www.ossec.net/wiki/index.php/WebAttacks_links] +d:$web_dirs -> ^id$; + +[Web exploits (uncommon file name inside htdocs) - Possible compromise] [any] [http://www.ossec.net/wiki/index.php/WebAttacks_links] +d:$web_dirs -> ^.ssh$; + +[Web exploits (uncommon file name inside htdocs) - Possible compromise] [any] [http://www.ossec.net/wiki/index.php/WebAttacks_links] +d:$web_dirs -> ^...$; + +[Web exploits (uncommon file name inside htdocs) - Possible compromise] [any] [http://www.ossec.net/wiki/index.php/WebAttacks_links] +d:$web_dirs -> ^.shell$; + +# EOF # diff --git a/src/rootcheck/db/win_applications_rcl.txt b/src/rootcheck/db/win_applications_rcl.txt new file mode 100644 index 0000000..5b06d69 --- /dev/null +++ b/src/rootcheck/db/win_applications_rcl.txt @@ -0,0 +1,146 @@ +# @(#) $Id: win_applications_rcl.txt,v 1.3 2007/08/18 01:07:50 dcid Exp $ +# +# OSSEC Application detection - (C) 2007 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Application name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - r (registry entry) +# - p (process running) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + + +[Chat/IM/VoIP - Skype] [any] [] +f:\Program Files\Skype\Phone; +f:\Documents and Settings\All Users\Documents\My Skype Pictures; +f:\Documents and Settings\Skype; +f:\Documents and Settings\All Users\Start Menu\Programs\Skype; +r:HKLM\SOFTWARE\Skype; +r:HKEY_LOCAL_MACHINE\Software\Policies\Skype; +p:r:Skype.exe; + + +[Chat/IM - Yahoo] [any] [] +f:\Documents and Settings\All Users\Start Menu\Programs\Yahoo! Messenger; +r:HKLM\SOFTWARE\Yahoo; + + +[Chat/IM - ICQ] [any] [] +r:HKEY_CURRENT_USER\Software\Mirabilis\ICQ; + + +[Chat/IM - AOL] [any] [http://www.aol.com] +r:HKEY_LOCAL_MACHINE\SOFTWARE\America Online\AOL Instant Messenger; +r:HKEY_CLASSES_ROOT\aim\shell\open\command; +r:HKEY_CLASSES_ROOT\AIM.Protocol; +r:HKEY_CLASSES_ROOT\MIME\Database\Content Type\application/x-aim; +f:\Program Files\AIM95; +p:r:aim.exe; + + +[Chat/IM - MSN] [any] [http://www.msn.com] +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSNMessenger; +r:HKEY_CURRENT_USER\SOFTWARE\Microsoft\MSNMessenger; +f:\Program Files\MSN Messenger; +f:\Program Files\Messenger; +p:r:msnmsgr.exe; + + +[Chat/IM - ICQ] [any] [http://www.icq.com] +r:HKLM\SOFTWARE\Mirabilis\ICQ; + + +[P2P - UTorrent] [any] [] +p:r:utorrent.exe; + + +[P2P - LimeWire] [any] [] +r:HKEY_LOCAL_MACHINE\SOFTWARE\Limewire; +r:HKLM\software\microsoft\windows\currentversion\run -> limeshop; +f:\Program Files\limewire; +f:\Program Files\limeshop; + + +[P2P/Adware - Kazaa] [any] [] +f:\Program Files\kazaa; +f:\Documents and Settings\All Users\Start Menu\Programs\kazaa; +f:\Documents and Settings\All Users\DESKTOP\Kazaa Media Desktop.lnk; +f:\Documents and Settings\All Users\DESKTOP\Kazaa Promotions.lnk; +f:%WINDIR%\System32\Cd_clint.dll; +r:HKEY_LOCAL_MACHINE\SOFTWARE\KAZAA; +r:HKEY_CURRENT_USER\SOFTWARE\KAZAA; +r:HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\RUN\KAZAA; + + +# http://vil.nai.com/vil/content/v_135023.htm +[Adware - RxToolBar] [any] [http://vil.nai.com/vil/content/v_135023.htm] +r:HKEY_CURRENT_USER\Software\Infotechnics; +r:HKEY_CURRENT_USER\Software\Infotechnics\RX Toolbar; +r:HKEY_CURRENT_USER\Software\RX Toolbar; +r:HKEY_CLASSES_ROOT\BarInfoUrl.TBInfo; +r:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\RX Toolbar; +f:\Program Files\RXToolBar; + + +# http://btfaq.com/serve/cache/18.html +[P2P - BitTorrent] [any] [http://btfaq.com/serve/cache/18.html] +f:\Program Files\BitTorrent; +r:HKEY_CLASSES_ROOT\.torrent; +r:HKEY_CLASSES_ROOT\MIME\Database\Content Type\application/x-bittorrent; +r:HKEY_CLASSES_ROOT\bittorrent; +r:HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\BitTorrent; + + +# http://www.gotomypc.com +[Remote Access - GoToMyPC] [any] [] +f:\Program Files\Citrix\GoToMyPC; +f:\Program Files\Citrix\GoToMyPC\g2svc.exe; +f:\Program Files\Citrix\GoToMyPC\g2comm.exe; +f:\Program Files\expertcity\GoToMyPC; +r:HKLM\software\microsoft\windows\currentversion\run -> gotomypc; +r:HKEY_LOCAL_MACHINE\software\citrix\gotomypc; +r:HKEY_LOCAL_MACHINE\system\currentcontrolset\services\gotomypc; +p:r:g2svc.exe; +p:r:g2pre.exe; + + +[Spyware - Twain Tec Spyware] [any] [] +r:HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TwaintecDll.TwaintecDllObj.1; +r:HKEY_LOCAL_MACHINE\SOFTWARE\twaintech; +f:%WINDIR%\twaintec.dll; + + +# http://www.symantec.com/security_response/writeup.jsp?docid=2004-062611-4548-99&tabid=2 +[Spyware - SpyBuddy] [any] [] +f:\Program Files\ExploreAnywhere\SpyBuddy\sb32mon.exe; +f:\Program Files\ExploreAnywhere\SpyBuddy; +f:\Program Files\ExploreAnywhere; +f:%WINDIR%\System32\sysicept.dll; +r:HKEY_LOCAL_MACHINE\Software\ExploreAnywhere Software\SpyBuddy; + + +[Spyware - InternetOptimizer] [any] [] +r:HKLM\SOFTWARE\Avenue Media; +r:HKEY_CLASSES_ROOT\\safesurfinghelper.iebho.1; +r:HKEY_CLASSES_ROOT\\safesurfinghelper.iebho; + + +# EOF # diff --git a/src/rootcheck/db/win_audit_rcl.txt b/src/rootcheck/db/win_audit_rcl.txt new file mode 100644 index 0000000..17b0b86 --- /dev/null +++ b/src/rootcheck/db/win_audit_rcl.txt @@ -0,0 +1,96 @@ +# @(#) $Id: win_audit_rcl.txt,v 1.2 2009/03/26 15:01:32 dcid Exp $ +# +# OSSEC Windows Audit - (C) 2007 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Application name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - r (registry entry) +# - p (process running) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + + + +# http://technet2.microsoft.com/windowsserver/en/library/486896ba-dfa1-4850-9875-13764f749bba1033.mspx?mfr=true +[Disabled Registry tools set] [any] [] +r:HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System -> DisableRegistryTools -> 1; +r:HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System -> DisableRegistryTools -> 1; + + + +# http://support.microsoft.com/kb/825750 +[DCOM disabled] [any] [] +r:HKEY_LOCAL_MACHINE\Software\Microsoft\OLE -> EnableDCOM -> N; + + + +# http://web.mit.edu/is/topics/windows/server/winmitedu/security.html +[LM authentication allowed (weak passwords)] [any] [] +r:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA -> LMCompatibilityLevel -> 0; +r:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA -> LMCompatibilityLevel -> 1; + + + +# http://research.eeye.com/html/alerts/AL20060813.html +# Disabled by some Malwares (sometimes by McAfee and Symantec +# security center too). +[Firewall/Anti Virus notification disabled] [any] [] +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Security Center -> FirewallDisableNotify -> !0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Security Center -> antivirusoverride -> !0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Security Center -> firewalldisablenotify -> !0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Security Center -> firewalldisableoverride -> !0; + + + +# Checking for the microsoft firewall. +[Microsoft Firewall disabled] [all] [] +r:HKEY_LOCAL_MACHINE\software\policies\microsoft\windowsfirewall\domainprofile -> enablefirewall -> 0; +r:HKEY_LOCAL_MACHINE\software\policies\microsoft\windowsfirewall\standardprofile -> enablefirewall -> 0; + + + +#http://web.mit.edu/is/topics/windows/server/winmitedu/security.html +[Null sessions allowed] [any] [] +r:HKLM\System\CurrentControlSet\Control\Lsa -> RestrictAnonymous -> 0; + + + +[Error reporting disabled] [any] [http://windowsir.blogspot.com/2007/04/something-new-to-look-for.html] +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PCHealth\ErrorReporting -> DoReport -> 0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PCHealth\ErrorReporting -> IncludeKernelFaults -> 0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PCHealth\ErrorReporting -> IncludeMicrosoftApps -> 0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PCHealth\ErrorReporting -> IncludeWindowsApps -> 0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PCHealth\ErrorReporting -> IncludeShutdownErrs -> 0; +r:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PCHealth\ErrorReporting -> ShowUI -> 0; + + + +# http://support.microsoft.com/default.aspx?scid=315231 +[Automatic Logon enabled] [any] [http://support.microsoft.com/default.aspx?scid=315231] +r:HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon -> DefaultPassword; +r:HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon -> AutoAdminLogon -> 1; + + +[Winpcap packet filter driver found] [any] [] +f:%WINDIR%\System32\drivers\npf.sys; + + +# EOF # diff --git a/src/rootcheck/db/win_malware_rcl.txt b/src/rootcheck/db/win_malware_rcl.txt new file mode 100644 index 0000000..8a6cb13 --- /dev/null +++ b/src/rootcheck/db/win_malware_rcl.txt @@ -0,0 +1,138 @@ +# @(#) $Id: win_malware_rcl.txt,v 1.5 2008/07/21 18:33:20 dcid Exp $ +# +# OSSEC Windows Malware list - (C) 2007 Daniel B. Cid - dcid@ossec.net +# +# Released under the same license as OSSEC. +# More details at the LICENSE file included with OSSEC or online +# at: http://www.ossec.net/en/licensing.html +# +# [Malware name] [any or all] [reference] +# type:; +# +# Type can be: +# - f (for file or directory) +# - r (registry entry) +# - p (process running) +# +# Additional values: +# For the registry , use "->" to look for a specific entry and another +# "->" to look for the value. +# For files, use "->" to look for a specific value in the file. +# +# # Values can be preceeded by: =: (for equal) - default +# r: (for ossec regexes) +# >: (for strcmp greater) +# <: (for strcmp lower) +# Multiple patterns can be specified by using " && " between them. +# (All of them must match for it to return true). + + +# http://www.iss.net/threats/ginwui.html +[Ginwui Backdoor] [any] [http://www.iss.net/threats/ginwui.html] +f:%WINDIR%\System32\zsyhide.dll; +f:%WINDIR%\System32\zsydll.dll; +r:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\zsydll; +r:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows -> AppInit_DLLs -> r:zsyhide.dll; + + +# http://www.symantec.com/security_response/writeup.jsp?docid=2006-081312-3302-99&tabid=2 +[Wargbot Backdoor] [any] [] +f:%WINDIR%\System32\wgareg.exe; +r:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\wgareg; + + +# http://www.f-prot.com/virusinfo/descriptions/sober_j.html +[Sober Worm] [any] [] +f:%WINDIR%\System32\nonzipsr.noz; +f:%WINDIR%\System32\clonzips.ssc; +f:%WINDIR%\System32\clsobern.isc; +f:%WINDIR%\System32\sb2run.dii; +f:%WINDIR%\System32\winsend32.dal; +f:%WINDIR%\System32\winroot64.dal; +f:%WINDIR%\System32\zippedsr.piz; +f:%WINDIR%\System32\winexerun.dal; +f:%WINDIR%\System32\winmprot.dal; +f:%WINDIR%\System32\dgssxy.yoi; +f:%WINDIR%\System32\cvqaikxt.apk; +f:%WINDIR%\System32\sysmms32.lla; +f:%WINDIR%\System32\Odin-Anon.Ger; + + +# http://www.symantec.com/security_response/writeup.jsp?docid=2005-042611-0148-99&tabid=2 +[Hotword Trojan] [any] [] +f:%WINDIR%\System32\_; +f:%WINDIR%\System32\explore.exe; +f:%WINDIR%\System32\ svchost.exe; +f:%WINDIR%\System32\mmsystem.dlx; +f:%WINDIR%\System32\WINDLL-ObjectsWin*.DLX; +f:%WINDIR%\System32\CFXP.DRV; +f:%WINDIR%\System32\CHJO.DRV; +f:%WINDIR%\System32\MMSYSTEM.DLX; +f:%WINDIR%\System32\OLECLI.DL; + + +[Beagle worm] [any] [] +f:%WINDIR%\System32\winxp.exe; +f:%WINDIR%\System32\winxp.exeopen; +f:%WINDIR%\System32\winxp.exeopenopen; +f:%WINDIR%\System32\winxp.exeopenopenopen; +f:%WINDIR%\System32\winxp.exeopenopenopenopen; + + +# http://symantec.com/security_response/writeup.jsp?docid=2007-071711-3132-99 +[Gpcoder Trojan] [any] [http://symantec.com/security_response/writeup.jsp?docid=2007-071711-3132-99] +f:%WINDIR%\System32\ntos.exe; +f:%WINDIR%\System32\wsnpoem; +f:%WINDIR%\System32\wsnpoem\audio.dll; +f:%WINDIR%\System32\wsnpoem\video.dll; +r:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run -> userinit -> r:ntos.exe; + + +# [http://www.symantec.com/security_response/writeup.jsp?docid=2006-112813-0222-99&tabid=2 +[Looked.BK Worm] [any] [] +f:%WINDIR%\uninstall\rundl132.exe; +f:%WINDIR%\Logo1_.exe; +f:%Windir%\RichDll.dll; +r:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -> load -> r:rundl132.exe; + + +[Possible Malware - Svchost running outside system32] [all] [] +p:r:svchost.exe && !%WINDIR%\System32\svchost.exe; +f:!%WINDIR%\SysWOW64; + + +[Possible Malware - Inetinfo running outside system32\inetsrv] [all] [] +p:r:inetinfo.exe && !%WINDIR%\System32\inetsrv\inetinfo.exe; +f:!%WINDIR%\SysWOW64; + + +[Possible Malware - Rbot/Sdbot detected] [any] [] +f:%Windir%\System32\rdriv.sys; +f:%Windir%\lsass.exe; + + +[Possible Malware File] [any] [] +f:%WINDIR%\utorrent.exe; +f:%WINDIR%\System32\utorrent.exe; +f:%WINDIR%\System32\Files32.vxd; + + +# Modified /etc/hosts entries +# Idea taken from: +# http://blog.tenablesecurity.com/2006/12/detecting_compr.html +# http://www.sophos.com/security/analyses/trojbagledll.html +# http://www.f-secure.com/v-descs/fantibag_b.shtml +[Anti-virus site on the hosts file] [any] [] +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:avp.ch|avp.ru|nai.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:awaps.net|ca.com|mcafee.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:microsoft.com|f-secure.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:sophos.com|symantec.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:my-etrust.com|viruslist.ru; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:networkassociates.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:kaspersky|grisoft.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:symantecliveupdate.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:clamav.net|bitdefender.com; +f:%WINDIR%\System32\Drivers\etc\HOSTS -> r:antivirus.com|sans.org; + + +# EOF # diff --git a/src/rootcheck/os_string.c b/src/rootcheck/os_string.c new file mode 100755 index 0000000..64cf643 --- /dev/null +++ b/src/rootcheck/os_string.c @@ -0,0 +1,315 @@ +/* @(#) $Id: os_string.c,v 1.12 2007/04/18 02:04:58 dcid Exp $ */ + +/* Included and modified strings.c from the OpenBSD project. + * Copyright bellow. + */ + +/* + * Copyright (c) 1980, 1987, 1993 + * The Regents of the University of California. 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 University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef WIN32 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* Again, making solaris happy... */ +#ifdef SOLARIS +#include + +#elif defined Darwin || defined HPUX + +/* For some reason darwin does not have that */ +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned char a_machtype; /* machine type */ + unsigned short a_magic; /* magic number */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; +#define OMAGIC 0407 /* Object file or impure executable. */ +#define NMAGIC 0410 /* Code indicating pure executable. */ +#define ZMAGIC 0413 /* Code indicating demand-paged executable. */ +#define BMAGIC 0415 /* Used by a b.out object. */ +#define M_OLDSUN2 0 + +#else + +#include +#endif + + +#ifndef PAGSIZ +#define PAGSIZ 0x02000 +#endif + +#ifndef OLD_PAGSIZ +#define OLD_PAGSIZ 0x00800 +#endif + +#ifndef N_BADMAG + +#ifdef AIX +#define N_BADMAG(x) \ + (((x).magic)!=U802TOCMAGIC && ((x).magic)!=U803TOCMAGIC && ((x).magic)!=U803XTOCMAGIC && ((x).magic)!=U64_TOCMAGIC) +#else /* non AIX */ +#define N_BADMAG(x) \ + (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC) +#endif + +#endif /* N_BADMAG */ + +#ifndef N_PAGSIZ +#define N_PAGSIZ(x) \ + ((x).a_machtype == M_OLDSUN2? OLD_PAGSIZ : PAGSIZ) +#endif + +#ifndef N_TXTOFF + +#ifdef AIX +#define N_TXTOFF(x) \ + /* text segment */ \ + ((x).magic==U64_TOCMAGIC ? 0 : sizeof (struct aouthdr)) +#else /* non AIX */ +#define N_TXTOFF(x) \ + /* text segment */ \ + ((x).a_machtype == M_OLDSUN2 \ + ? ((x).a_magic==ZMAGIC ? N_PAGSIZ(x) : sizeof (struct exec)) \ + : ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec)) ) +#endif + +#endif /* N_TXTOFF */ + + +#include "headers/defs.h" +#include "headers/debug_op.h" +#include "headers/regex_op.h" + +#include "error_messages/error_messages.h" + +#define STR_MINLEN 4 /* Minumum length for a string */ + +#define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t')) + + +#ifdef AIX +typedef struct aouthdr EXEC; +#else +typedef struct exec EXEC; +#endif + +typedef struct _os_strings +{ + int head_len; + int read_len; + int hcnt; + long foff; + unsigned char hbfr[sizeof(EXEC)]; + FILE *fp; +}os_strings; + + +/* os_getch: Read each character from a binary file */ +int os_getch(os_strings *oss); + + +/* os_strings: List the strings of a binary and + * check if the regex given is there. + */ +int os_string(char *file, char *regex) +{ + int ch, cnt; + + unsigned char *C; + unsigned char *bfr; + + char line[OS_SIZE_1024 +1]; + char *buf; + + EXEC *head; + + os_strings oss; + + /* Return didn't match */ + if(!file || !regex) + { + return(0); + } + + + /* Allocating for the buffer */ + bfr = calloc(STR_MINLEN + 2, sizeof(char *)); + if (!bfr) + { + merror(MEM_ERROR, ARGV0); + return(0); + } + + /* Opening the file */ + oss.fp = fopen(file, "r"); + if(!oss.fp) + { + free(bfr); + return(0); + } + + /* cleaning the line */ + memset(line, '\0', OS_SIZE_1024 +1); + + /* starting .. (from old strings.c) */ + oss.foff = 0; + oss.head_len = 0; + + oss.read_len = -1; + head = (EXEC *)oss.hbfr; + + + if ((oss.head_len = read(fileno(oss.fp), head, sizeof(EXEC))) == -1) + { + oss.head_len = 0; + oss.read_len = -1; + } + else if (oss.head_len == sizeof(EXEC) && !N_BADMAG(*head)) + { + oss.foff = N_TXTOFF(*head); + if (fseek(stdin, oss.foff, SEEK_SET) == -1) + { + oss.read_len = -1; + } + else + { + #ifdef AIX + oss.read_len = head->tsize + head->dsize; + #else + oss.read_len = head->a_text + head->a_data; + #endif + } + + oss.head_len = 0; + } + else + { + oss.hcnt = 0; + } + + /* Read the file and perform the regex comparison */ + for (cnt = 0; (ch = os_getch(&oss)) != EOF;) + { + if (ISSTR(ch)) + { + if (!cnt) + C = bfr; + *C++ = ch; + if (++cnt < STR_MINLEN) + continue; + + strncpy(line, (char *)bfr, STR_MINLEN +1); + buf = line; + buf+=strlen(line); + + + while ((ch = os_getch(&oss)) != EOF && ISSTR(ch)) + { + if(cnt < OS_SIZE_1024) + { + *buf = (char)ch; + buf++; + } + else + { + *buf = '\0'; + break; + } + cnt++; + } + + *buf = '\0'; + + if(OS_PRegex(line, regex)) + { + if(oss.fp) + fclose(oss.fp); + free(bfr); + return(1); + } + } + + cnt = 0; + } + + if(oss.fp) + fclose(oss.fp); + free(bfr); + return(0); +} + + +/* + * getch (os_getch, modified)-- + * get next character from wherever + */ +int os_getch(os_strings *oss) +{ + ++oss->foff; + if (oss->head_len) + { + if (oss->hcnt < oss->head_len) + return((int)oss->hbfr[oss->hcnt++]); + oss->head_len = 0; + } + if (oss->read_len == -1 || oss->read_len-- > 0) + { + return(fgetc(oss->fp)); + } + return(EOF); +} + +/* EOF */ +#else +int os_string(char *file, char *regex) +{ + return(0); +} +#endif diff --git a/src/rootcheck/rootcheck-config.c b/src/rootcheck/rootcheck-config.c new file mode 100755 index 0000000..9b7bc5f --- /dev/null +++ b/src/rootcheck/rootcheck-config.c @@ -0,0 +1,183 @@ +/* @(#) $Id: rootcheck-config.c,v 1.11 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef OSSECHIDS +#include +#include +#include +#include + +#include "shared.h" + +#include "os_xml/os_xml.h" + +#include "rootcheck.h" + + +/* Read_Rootcheck_Config: Reads the rootcheck config + */ +int Read_Rootcheck_Config(char * cfgfile) +{ + OS_XML xml; + + char *str = NULL; + + + /* XML Definitions */ + char *(xml_daemon[])={xml_rootcheck,"daemon", NULL}; + char *(xml_notify[])={xml_rootcheck, "notify", NULL}; + char *(xml_base_dir[])={xml_rootcheck, "base_directory", NULL}; + char *(xml_workdir[])={xml_rootcheck, "work_directory", NULL}; + char *(xml_rootkit_files[])={xml_rootcheck, "rootkit_files", NULL}; + char *(xml_rootkit_trojans[])={xml_rootcheck, "rootkit_trojans", NULL}; + char *(xml_rootkit_unixaudit[])={xml_rootcheck, "system_audit", NULL}; + char *(xml_rootkit_winaudit[])={xml_rootcheck, "windows_audit", NULL}; + char *(xml_rootkit_winapps[])={xml_rootcheck, "windows_apps", NULL}; + char *(xml_rootkit_winmalware[])={xml_rootcheck, "windows_malware", NULL}; + char *(xml_scanall[])={xml_rootcheck, "scanall", NULL}; + char *(xml_readall[])={xml_rootcheck, "readall", NULL}; + char *(xml_time[])={xml_rootcheck, "frequency", NULL}; + + /* :) */ + xml_time[2] = NULL; + + if(OS_ReadXML(cfgfile,&xml) < 0) + { + merror("config_op: XML error: %s",xml.err); + return(OS_INVALID); + } + + if(!OS_RootElementExist(&xml,xml_rootcheck)) + { + OS_ClearXML(&xml); + merror("%s: Rootcheck configuration not found. ",ARGV0); + return(-1); + } + + + /* run as a daemon */ + str = OS_GetOneContentforElement(&xml,xml_daemon); + if(str) + { + if(str[0] == 'n') + rootcheck.daemon = 0; + free(str); + str = NULL; + } + + /* time */ + #ifdef OSSECHIDS + str = OS_GetOneContentforElement(&xml,xml_time); + if(str) + { + if(!OS_StrIsNum(str)) + { + merror("Invalid frequency time '%s' for the rootkit " + "detection (must be int).", str); + return(OS_INVALID); + } + + rootcheck.time = atoi(str); + + free(str); + str = NULL; + } + #endif + + + /* Scan all flag */ + if(!rootcheck.scanall) + { + str = OS_GetOneContentforElement(&xml,xml_scanall); + if(str) + { + if(str[0] == 'y') + rootcheck.scanall = 1; + free(str); + str = NULL; + } + } + + + /* read all flag */ + if(!rootcheck.readall) + { + str = OS_GetOneContentforElement(&xml,xml_readall); + if(str) + { + if(str[0] == 'y') + rootcheck.readall = 1; + free(str); + str = NULL; + } + } + + + /* Notifications type */ + str = OS_GetOneContentforElement(&xml,xml_notify); + if(str) + { + if(strcasecmp(str,"queue") == 0) + rootcheck.notify = QUEUE; + else if(strcasecmp(str,"syslog") == 0) + rootcheck.notify = SYSLOG; + else + { + merror("%s: Invalid notification option. Only " + "'syslog' or 'queue' are allowed.",ARGV0); + return(-1); + } + + free(str); + str = NULL; + } + else + { + /* Default to SYSLOG */ + rootcheck.notify = SYSLOG; + } + + /* Getting work directory */ + if(!rootcheck.workdir) + rootcheck.workdir = OS_GetOneContentforElement(&xml,xml_workdir); + + + rootcheck.rootkit_files = OS_GetOneContentforElement + (&xml,xml_rootkit_files); + rootcheck.rootkit_trojans = OS_GetOneContentforElement + (&xml,xml_rootkit_trojans); + + rootcheck.unixaudit = OS_GetContents + (&xml,xml_rootkit_unixaudit); + + rootcheck.winaudit = OS_GetOneContentforElement + (&xml,xml_rootkit_winaudit); + + rootcheck.winapps = OS_GetOneContentforElement + (&xml,xml_rootkit_winapps); + + rootcheck.winmalware = OS_GetOneContentforElement + (&xml,xml_rootkit_winmalware); + + rootcheck.basedir = OS_GetOneContentforElement(&xml, xml_base_dir); + + + OS_ClearXML(&xml); + + debug1("%s: DEBUG: Daemon set to '%d'",ARGV0, rootcheck.daemon); + debug1("%s: DEBUG: alert set to '%d'",ARGV0, rootcheck.notify); + + return(0); +} + +/* EOF */ +#endif diff --git a/src/rootcheck/rootcheck.c b/src/rootcheck/rootcheck.c new file mode 100755 index 0000000..38b52f2 --- /dev/null +++ b/src/rootcheck/rootcheck.c @@ -0,0 +1,280 @@ +/* @(#) $Id: rootcheck.c,v 1.33 2009/07/23 19:31:35 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* + * Rootcheck v 0.3 + * Copyright (C) 2003 Daniel B. Cid + * http://www.ossec.net/rootcheck/ + * + */ + +/* Included from the Rootcheck project */ + + +#include "headers/shared.h" + +#include "rootcheck.h" + +#ifndef ARGV0 +#define ARGV0 "rootcheck" +#endif + + + +/** Prototypes **/ +/* Read the new XML config */ +int Read_Rootcheck_Config(char * cfgfile, rkconfig *cfg); + + +#ifndef OSSECHIDS + +void rootcheck_help() +{ + printf("\n"); + printf("Rootcheck v0.8 (Mar/12/2008):\n"); + printf("http://www.ossec.net/rootcheck/\n"); + printf("Available options:\n"); + printf("\t\t-h\t This Help message\n"); + printf("\t\t-c Configuration file\n"); + printf("\t\t-d\t Enable debug\n"); + printf("\t\t-D Set the working directory\n"); + printf("\t\t-s\t Scans the whole system\n"); + printf("\t\t-r\t Read all the files for kernel-based detection\n"); + printf("\n"); + exit(0); +} + +/* main v0.1 + * + */ +int main(int argc, char **argv) +{ + int c; + int test_config = 0; + +#else + +int rootcheck_init(int test_config) +{ + int c; + +#endif + + #ifdef OSSECHIDS + char *cfg = DEFAULTCPATH; + #else + char *cfg = "./rootcheck.conf"; + #endif + + /* Zeroing the structure */ + rootcheck.workdir = NULL; + rootcheck.basedir = NULL; + rootcheck.unixaudit = NULL; + rootcheck.ignore = NULL; + rootcheck.rootkit_files = NULL; + rootcheck.rootkit_trojans = NULL; + rootcheck.winaudit = NULL; + rootcheck.winmalware = NULL; + rootcheck.winapps = NULL; + rootcheck.daemon = 1; + rootcheck.notify = QUEUE; + rootcheck.scanall = 0; + rootcheck.readall = 0; + rootcheck.disabled = 0; + rootcheck.alert_msg = NULL; + rootcheck.time = ROOTCHECK_WAIT; + + + /* We store up to 255 alerts in there. */ + os_calloc(256, sizeof(char *), rootcheck.alert_msg); + c = 0; + while(c <= 255) + { + rootcheck.alert_msg[c] = NULL; + c++; + } + + + #ifndef OSSECHIDS + rootcheck.notify = SYSLOG; + rootcheck.daemon = 0; + while((c = getopt(argc, argv, "VstrdhD:c:")) != -1) + { + switch(c) + { + case 'V': + print_version(); + break; + case 'h': + rootcheck_help(); + break; + case 'd': + nowDebug(); + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + rootcheck.workdir = optarg; + break; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 's': + rootcheck.scanall = 1; + break; + case 't': + test_config = 1; + break; + case 'r': + rootcheck.readall = 1; + break; + default: + rootcheck_help(); + break; + } + + } + + + #ifdef WIN32 + /* Starting Winsock */ + { + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) + { + ErrorExit("%s: WSAStartup() failed", ARGV0); + } + } + #endif + + + #endif /* OSSECHIDS */ + + + /* Staring message */ + debug1(STARTED_MSG,ARGV0); + + + /* Checking if the configuration is present */ + if(File_DateofChange(cfg) < 0) + { + merror("%s: Configuration file '%s' not found",ARGV0,cfg); + return(-1); + } + + + /* Reading configuration --function specified twice (check makefile) */ + if(Read_Rootcheck_Config(cfg, &rootcheck) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* If testing config, exit here */ + if(test_config) + return(0); + + + /* Return 1 disables rootcheck */ + if(rootcheck.disabled == 1) + { + verbose("%s: Rootcheck disabled. Exiting.", ARGV0); + return(1); + } + + + /* Checking if Unix audit file is configured. */ + if(!rootcheck.unixaudit) + { + #ifndef WIN32 + log2file("%s: System audit file not configured.", ARGV0); + #endif + } + + + /* Setting default values */ + if(rootcheck.workdir == NULL) + rootcheck.workdir = DEFAULTDIR; + + + #ifdef OSSECHIDS + + + /* Start up message */ + #ifdef WIN32 + verbose(STARTUP_MSG, "ossec-rootcheck", getpid()); + #else + + + /* Connect to the queue if configured to do so */ + if(rootcheck.notify == QUEUE) + { + debug1("%s: Starting queue ...",ARGV0); + + /* Starting the queue. */ + if((rootcheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + merror(QUEUE_ERROR,ARGV0,DEFAULTQPATH, strerror(errno)); + + /* 5 seconds to see if the agent starts */ + sleep(5); + if((rootcheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + /* more 10 seconds wait.. */ + merror(QUEUE_ERROR,ARGV0,DEFAULTQPATH, strerror(errno)); + sleep(10); + if((rootcheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + ErrorExit(QUEUE_FATAL,ARGV0,DEFAULTQPATH); + } + } + } + + #endif /* Not win32 */ + + #endif /* ossec hids */ + + + /* Initializing rk list */ + rk_sys_name = calloc(MAX_RK_SYS +2, sizeof(char *)); + rk_sys_file = calloc(MAX_RK_SYS +2, sizeof(char *)); + if(!rk_sys_name || !rk_sys_file) + { + ErrorExit(MEM_ERROR, ARGV0); + } + rk_sys_name[0] = NULL; + rk_sys_file[0] = NULL; + + + #ifndef OSSECHIDS + + #ifndef WIN32 + /* Start the signal handling */ + StartSIG(ARGV0); + #endif + + #else + return(0); + + #endif + + + debug1("%s: DEBUG: Running run_rk_check",ARGV0); + run_rk_check(); + + + debug1("%s: DEBUG: Leaving...",ARGV0); + + return(0); +} + +/* EOF */ diff --git a/src/rootcheck/rootcheck.conf b/src/rootcheck/rootcheck.conf new file mode 100755 index 0000000..eda1905 --- /dev/null +++ b/src/rootcheck/rootcheck.conf @@ -0,0 +1,14 @@ + + no + syslog + ./db/rootkit_files.txt + ./db/rootkit_trojans.txt + + ./db/system_audit_rcl.txt + ./db/cis_debian_linux_rcl.txt + ./db/cis_rhel_linux_rcl.txt + ./db/cis_rhel5_linux_rcl.txt + ./shared/win_audit_rcl.txt + ./shared/win_applications_rcl.txt + ./shared/win_malware_rcl.txt + diff --git a/src/rootcheck/rootcheck.h b/src/rootcheck/rootcheck.h new file mode 100755 index 0000000..5aa42fa --- /dev/null +++ b/src/rootcheck/rootcheck.h @@ -0,0 +1,168 @@ +/* @(#) $Id: rootcheck.h,v 1.34 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __ROOTCHECK_H +#define __ROOTCHECK_H + +#include "config/rootcheck-config.h" +rkconfig rootcheck; + + +/* output types */ +#define QUEUE 101 +#define SYSLOG 102 + + +/* Maximum files to search on the whole system */ +#define MAX_RK_SYS 512 + + +/* rk_types */ +#define ALERT_OK 0 +#define ALERT_SYSTEM_ERROR 1 +#define ALERT_SYSTEM_CRIT 2 +#define ALERT_ROOTKIT_FOUND 3 +#define ALERT_POLICY_VIOLATION 4 + +#define ROOTCHECK "rootcheck" + +/* Default to 10 hours */ +#define ROOTCHECK_WAIT 72000 + + + + +/** Prototypes **/ + +/* common isfile_ondir: Check if file is present on dir */ +int isfile_ondir(char *file, char *dir); + +/* int rk_check_file(char *value, char *pattern) */ +int rk_check_file(char *file, char *pattern); + +/* int rk_check_dir(char *dir, char *file, char *pattern) */ +int rk_check_dir(char *dir, char *file, char *pattern); + +/* pt_matches: Checks if pattern is present on string */ +int pt_matches(char *str, char *pattern); + + +/* common is_file: Check if a file exist (using stat, fopen and opendir) */ +int is_file(char *file_name); + +/* win_common is_registry: Check if a entry is in the registry */ +int is_registry(char *entry_name, char *reg_option, char *reg_value); + +/* int rkcl_get_entry: Reads cl configuration file. */ +int rkcl_get_entry(FILE *fp, char *msg, void *p_list); + + +/** char *normalize_string + * Normalizes a string, removing white spaces and tabs + * from the begining and the end of it. + */ +char *normalize_string(char *str); + + +/* Check if regex is present on the file. + * Similar to `strings file | grep -r regex` + */ +int os_string(char *file, char *regex); + +/* check for NTFS ADS (Windows only) + */ +int os_check_ads(char *full_path); + +/* os_get_process_list: Get list of processes + */ +void *os_get_process_list(); + +/* is_process: Check is a process is running. + */ +int is_process(char *value, void *p_list); + + +/* del_plist:. Deletes the process list + */ +int del_plist(void *p_list); + + +/* Used to report messages */ +int notify_rk(int rk_type, char *msg); + + + +/* rootcheck_init: Starts the rootcheck externally + */ +int rootcheck_init(int test_config); + +/* run_rk_check: checks the integrity of the files against the + * saved database + */ +void run_rk_check(); + +/* start_rk_daemon: Runs run_rk_check periodically. + */ +void start_rk_daemon(); + + +/*** Plugins prototypes ***/ +void check_rc_files(char *basedir, FILE *fp); + +void check_rc_trojans(char *basedir, FILE *fp); + +void check_rc_unixaudit(FILE *fp, void *p_list); + +void check_rc_winaudit(FILE *fp, void *p_list); + +void check_rc_winmalware(FILE *fp, void *p_list); + +void check_rc_winapps(FILE *fp, void *p_list); + +void check_rc_dev(char *basedir); + +void check_rc_sys(char *basedir); + +void check_rc_pids(); + +/* Verifies if "pid" is in the proc directory */ +int check_rc_readproc(int pid); + +void check_rc_ports(); + +void check_open_ports(); + +void check_rc_if(); + + +/* Global vars */ +char **rk_sys_file; +char **rk_sys_name; +int rk_sys_count; + + +/* All the ports */ +char total_ports_udp[65535 +1]; +char total_ports_tcp[65535 +1]; + + +/* Process struct */ +typedef struct _Proc_Info +{ + char *p_name; + char *p_path; +}Proc_Info; + + +#endif + +/* EOF */ diff --git a/src/rootcheck/run_rk_check.c b/src/rootcheck/run_rk_check.c new file mode 100755 index 0000000..8ce7b7a --- /dev/null +++ b/src/rootcheck/run_rk_check.c @@ -0,0 +1,387 @@ +/* @(#) $Id: run_rk_check.c,v 1.41 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck.h" + + +/* notify_rk + * Report a problem. + */ +int notify_rk(int rk_type, char *msg) +{ + /* Non-queue notification */ + if(rootcheck.notify != QUEUE) + { + if(rk_type == ALERT_OK) + printf("[OK]: %s\n", msg); + else if(rk_type == ALERT_SYSTEM_ERROR) + printf("[ERR]: %s\n", msg); + else if(rk_type == ALERT_POLICY_VIOLATION) + printf("[INFO]: %s\n", msg); + else + { + printf("[FAILED]: %s\n", msg); + } + + printf("\n"); + return(0); + } + + /* No need to alert on that to the server */ + if(rk_type <= ALERT_SYSTEM_ERROR) + return(0); + + #ifdef OSSECHIDS + if(SendMSG(rootcheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + + if((rootcheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + + if(SendMSG(rootcheck.queue,msg,ROOTCHECK,ROOTCHECK_MQ) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + } + #endif + + return(0); +} + + +/* start_rk_daemon + * Start the rootkit daemon variables + */ +void start_rk_daemon() +{ + return; + + if(rootcheck.notify == QUEUE) + { + } +} + + +/* run_rk_check: v0.1 + * Execute the rootkit checks + */ +void run_rk_check() +{ + time_t time1; + time_t time2; + + FILE *fp; + OSList *plist; + + #ifndef WIN32 + /* Hard coding basedir */ + int i; + char basedir[] = "/"; + + /* Removing the last / from basedir */ + i = strlen(basedir); + if(i > 0) + { + if(basedir[i-1] == '/') + { + basedir[i-1] = '\0'; + } + } + #else + + /* Basedir for Windows */ + char basedir[] = "C:\\"; + + #endif + + + /* Setting basedir */ + if(rootcheck.basedir == NULL) + { + rootcheck.basedir = basedir; + } + + + time1 = time(0); + + /*** Initial message ***/ + if(rootcheck.notify != QUEUE) + { + printf("\n"); + printf("** Starting Rootcheck v0.9 by Daniel B. Cid **\n"); + printf("** http://www.ossec.net/en/about.html#dev-team **\n"); + printf("** http://www.ossec.net/rootcheck/ **\n\n"); + printf("Be patient, it may take a few minutes to complete...\n"); + printf("\n"); + } + + + /* Cleaning the global variables */ + rk_sys_count = 0; + rk_sys_file[rk_sys_count] = NULL; + rk_sys_name[rk_sys_count] = NULL; + + + + /* Sending scan start message */ + notify_rk(ALERT_POLICY_VIOLATION, "Starting rootcheck scan."); + if(rootcheck.notify == QUEUE) + { + merror("%s: INFO: Starting rootcheck scan.", ARGV0); + } + + + + /*** First check, look for rootkits ***/ + /* Open rootkit_files and pass the pointer to check_rc_files */ + if(!rootcheck.rootkit_files) + { + #ifndef WIN32 + merror("%s: No rootcheck_files file configured.", ARGV0); + #endif + } + + else + { + fp = fopen(rootcheck.rootkit_files, "r"); + if(!fp) + { + merror("%s: No rootcheck_files file: '%s'",ARGV0, + rootcheck.rootkit_files); + } + + else + { + check_rc_files(rootcheck.basedir, fp); + + fclose(fp); + } + } + + + + /*** Second check. look for trojan entries in common binaries ***/ + if(!rootcheck.rootkit_trojans) + { + #ifndef WIN32 + merror("%s: No rootcheck_trojans file configured.", ARGV0); + #endif + } + + else + { + fp = fopen(rootcheck.rootkit_trojans, "r"); + if(!fp) + { + merror("%s: No rootcheck_trojans file: '%s'",ARGV0, + rootcheck.rootkit_trojans); + } + + else + { + #ifndef HPUX + check_rc_trojans(rootcheck.basedir, fp); + #endif + + fclose(fp); + } + } + + + + #ifdef WIN32 + + /*** Getting process list ***/ + plist = os_get_process_list(); + + + /*** Windows audit check ***/ + if(!rootcheck.winaudit) + { + merror("%s: No winaudit file configured.", ARGV0); + } + else + { + fp = fopen(rootcheck.winaudit, "r"); + if(!fp) + { + merror("%s: No winaudit file: '%s'",ARGV0, + rootcheck.winaudit); + } + else + { + check_rc_winaudit(fp, plist); + fclose(fp); + } + } + + /* Windows malware */ + if(!rootcheck.winmalware) + { + merror("%s: No winmalware file configured.", ARGV0); + } + else + { + fp = fopen(rootcheck.winmalware, "r"); + if(!fp) + { + merror("%s: No winmalware file: '%s'",ARGV0, + rootcheck.winmalware); + } + else + { + check_rc_winmalware(fp, plist); + fclose(fp); + } + } + + /* Windows Apps */ + if(!rootcheck.winapps) + { + merror("%s: No winapps file configured.", ARGV0); + } + else + { + fp = fopen(rootcheck.winapps, "r"); + if(!fp) + { + merror("%s: No winapps file: '%s'",ARGV0, + rootcheck.winapps); + } + else + { + check_rc_winapps(fp, plist); + fclose(fp); + } + } + + + /* Freeing process list */ + del_plist((void *)plist); + + + + /** Checks for other non Windows. **/ + #else + + + + /*** Unix audit check ***/ + if(rootcheck.unixaudit) + { + /* Getting process list. */ + plist = os_get_process_list(); + + + i = 0; + while(rootcheck.unixaudit[i]) + { + fp = fopen(rootcheck.unixaudit[i], "r"); + if(!fp) + { + merror("%s: No unixaudit file: '%s'",ARGV0, + rootcheck.unixaudit[i]); + } + else + { + /* Running unix audit. */ + check_rc_unixaudit(fp, plist); + + fclose(fp); + } + + i++; + } + + + /* Freeing list */ + del_plist((void *)plist); + } + + + #endif + + + /*** Third check, looking for files on the /dev ***/ + debug1("%s: DEBUG: Going into check_rc_dev", ARGV0); + check_rc_dev(rootcheck.basedir); + + /*** Fourth check, scan the whole system looking for additional issues */ + debug1("%s: DEBUG: Going into check_rc_sys", ARGV0); + check_rc_sys(rootcheck.basedir); + + /*** Process checking ***/ + debug1("%s: DEBUG: Going into check_rc_pids", ARGV0); + check_rc_pids(); + + /*** Check all the ports ***/ + debug1("%s: DEBUG: Going into check_rc_ports", ARGV0); + check_rc_ports(); + + /*** Check open ports ***/ + debug1("%s: DEBUG: Going into check_open_ports", ARGV0); + check_open_ports(); + + /*** Check interfaces ***/ + debug1("%s: DEBUG: Going into check_rc_if", ARGV0); + check_rc_if(); + + + debug1("%s: DEBUG: Completed with all checks.", ARGV0); + + + /* Cleaning the global memory */ + { + int li; + for(li = 0;li <= rk_sys_count; li++) + { + if(!rk_sys_file[li] || + !rk_sys_name[li]) + break; + + free(rk_sys_file[li]); + free(rk_sys_name[li]); + } + } + + /*** Final message ***/ + time2 = time(0); + + if(rootcheck.notify != QUEUE) + { + printf("\n"); + printf("- Scan completed in %d seconds.\n\n", (int)(time2 - time1)); + } + else + { + sleep(5); + } + + + /* Sending scan ending message */ + notify_rk(ALERT_POLICY_VIOLATION, "Ending rootcheck scan."); + if(rootcheck.notify == QUEUE) + { + merror("%s: INFO: Ending rootcheck scan.", ARGV0); + } + + + debug1("%s: DEBUG: Leaving run_rk_check",ARGV0); + return; +} + + +/* EOF */ diff --git a/src/rootcheck/unix-process.c b/src/rootcheck/unix-process.c new file mode 100755 index 0000000..43a3e71 --- /dev/null +++ b/src/rootcheck/unix-process.c @@ -0,0 +1,145 @@ +/* @(#) $Id: unix-process.c,v 1.5 2009/06/24 18:53:07 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/main/license/ . + */ + + +#include "shared.h" +#include "rootcheck.h" + +#ifndef WIN32 + +char *_os_get_runps(char *ps, int mpid) +{ + char *tmp_str, *nbuf; + char buf[OS_SIZE_2048 +1]; + char command[OS_SIZE_1024 +1]; + FILE *fp; + + + buf[0] = '\0'; + command[0] = '\0'; + command[OS_SIZE_1024] = '\0'; + + + snprintf(command, OS_SIZE_1024, "%s -p %d 2> /dev/null", ps, mpid); + + fp = popen(command, "r"); + if(fp) + { + while(fgets(buf, OS_SIZE_2048, fp) != NULL) + { + tmp_str = strchr(buf, ':'); + if(!tmp_str) + { + continue; + } + + nbuf = tmp_str++; + + tmp_str = strchr(nbuf, ' '); + if(!tmp_str) + { + continue; + } + tmp_str++; + + + /* Removing white spaces. */ + while(*tmp_str == ' ') + tmp_str++; + + + nbuf = tmp_str; + + + tmp_str = strchr(nbuf, '\n'); + if(tmp_str) + { + *tmp_str = '\0'; + } + + pclose(fp); + return(strdup(nbuf)); + } + + pclose(fp); + } + + return(NULL); +} + + + +/* os_get_unix_process_list: Get list of Unix processes */ +void *os_get_process_list() +{ + int i = 1; + pid_t max_pid = MAX_PID; + OSList *p_list = NULL; + + char ps[OS_SIZE_1024 +1]; + + + /* Checking where ps is */ + memset(ps, '\0', OS_SIZE_1024 +1); + strncpy(ps, "/bin/ps", OS_SIZE_1024); + if(!is_file(ps)) + { + strncpy(ps, "/usr/bin/ps", OS_SIZE_1024); + if(!is_file(ps)) + { + merror("%s: ERROR: 'ps' not found.", ARGV0); + return(NULL); + } + } + + + /* Creating process list */ + p_list = OSList_Create(); + if(!p_list) + { + merror(LIST_ERROR, ARGV0); + return(NULL); + } + + + + for(i = 1; i<= max_pid; i++) + { + /* Checking if the pid is present. */ + if((!((getsid(i) == -1)&&(errno == ESRCH))) && + (!((getpgid(i) == -1)&&(errno == ESRCH)))) + { + Proc_Info *p_info; + char *p_name; + + p_name = _os_get_runps(ps, (int)i); + if(!p_name) + { + continue; + } + + os_calloc(1, sizeof(Proc_Info), p_info); + p_info->p_path = p_name; + p_info->p_name = NULL; + OSList_AddData(p_list, p_info); + } + } + + return((void *)p_list); +} + + +#endif + +/* EOF */ diff --git a/src/rootcheck/util/ads_dump.c b/src/rootcheck/util/ads_dump.c new file mode 100644 index 0000000..43ecd58 --- /dev/null +++ b/src/rootcheck/util/ads_dump.c @@ -0,0 +1,215 @@ +/* @(#) $Id: ads_dump.c,v 1.4 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include +#include +#include +#include +#include + + +/* ads_dump. + * Dumps every NTFS ADS found in a directory (recursive) + */ + +/* Prototypes */ +int read_sys_dir(char *dir_name); +int ads_found = 0; + + +/* Print out streams of a file */ +int os_get_streams(char *full_path) +{ + HANDLE file_h; + WIN32_STREAM_ID sid; + void *context = NULL; + + char stream_name[MAX_PATH +1]; + char final_name[MAX_PATH +1]; + + DWORD dwRead, shs, dw1, dw2; + + + /* Opening file */ + file_h = CreateFile(full_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, + NULL); + + if (file_h == INVALID_HANDLE_VALUE) + { + return 0; + } + + + /* Zeroing memory */ + ZeroMemory(&sid, sizeof(WIN32_STREAM_ID)); + + /* Getting stream header size -- should be 20 bytes */ + shs = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid+ sid.dwStreamNameSize; + + + while(1) + { + if(BackupRead(file_h, (LPBYTE) &sid, shs, &dwRead, + FALSE, FALSE, &context) == 0) + { + break; + } + if(dwRead == 0) + { + break; + } + + stream_name[0] = '\0'; + stream_name[MAX_PATH] = '\0'; + if(BackupRead(file_h, (LPBYTE)stream_name, + sid.dwStreamNameSize, + &dwRead, FALSE, FALSE, &context)) + { + if(dwRead != 0) + { + char *tmp_pt; + snprintf(final_name, MAX_PATH, "%s%S", full_path, + (WCHAR *)stream_name); + tmp_pt = strrchr(final_name, ':'); + if(tmp_pt) + { + *tmp_pt = '\0'; + } + printf("Found NTFS ADS: '%s' \n", final_name); + ads_found = 1; + } + } + + /* Getting next */ + if(!BackupSeek(file_h, sid.Size.LowPart, sid.Size.HighPart, + &dw1, &dw2, &context)) + { + break; + } + } + + CloseHandle(file_h); + return(0); +} + + +int read_sys_file(char *file_name) +{ + struct stat statbuf; + + + /* Getting streams */ + os_get_streams(file_name); + + + if(stat(file_name, &statbuf) < 0) + { + return(0); + } + + /* If directory, read the directory */ + else if(S_ISDIR(statbuf.st_mode)) + { + return(read_sys_dir(file_name)); + } + + + + return(0); +} + + +int read_sys_dir(char *dir_name) +{ + DIR *dp; + + struct dirent *entry; + struct stat statbuf; + + + /* Getting the number of nodes. The total number on opendir + * must be the same + */ + if(stat(dir_name, &statbuf) < 0) + { + return(-1); + } + + + /* Must be a directory */ + if(!S_ISDIR(statbuf.st_mode)) + { + return(-1); + } + + + /* Opening the directory given */ + dp = opendir(dir_name); + if(!dp) + { + return(-1); + } + + /* Reading every entry in the directory */ + while((entry = readdir(dp)) != NULL) + { + char f_name[MAX_PATH +2]; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + /* Creating new file + path string */ + snprintf(f_name, MAX_PATH +1, "%s\\%s",dir_name, entry->d_name); + + read_sys_file(f_name); + } + + closedir(dp); + + return(0); +} + + + +int main(int argc, char **argv) +{ + printf("%s: NTFS ADS dumper (GPL v2)\n", argv[0]); + printf("by Daniel B. Cid - dcid at ossec.net\n\n"); + + + /* Going to print every NTFS ADS found */ + if(argc < 2) + { + printf("%s dir\n", argv[0]); + exit(1); + } + + + /* Getting streams */ + read_sys_file(argv[1]); + + + if(ads_found == 0) + { + printf("No NTFS ADS found.\n"); + } + return(0); +} +/* EOF */ diff --git a/src/rootcheck/win-common.c b/src/rootcheck/win-common.c new file mode 100644 index 0000000..1d6b602 --- /dev/null +++ b/src/rootcheck/win-common.c @@ -0,0 +1,448 @@ +/* @(#) $Id: win-common.c,v 1.15 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "rootcheck.h" + +#ifdef WIN32 + + +/** Registry checking values **/ + +/* Global variables */ +HKEY rk_sub_tree; + +/* Default values */ +#define MAX_KEY_LENGTH 255 +#define MAX_KEY 2048 +#define MAX_VALUE_NAME 16383 + + + +/* os_check_ads. + * Check if file has NTFS ADS. + */ +int os_check_ads(char *full_path) +{ + HANDLE file_h; + WIN32_STREAM_ID sid; + void *context = NULL; + + char stream_name[MAX_PATH +1]; + char final_name[MAX_PATH +1]; + + DWORD dwRead, shs, dw1, dw2; + + + /* Opening file */ + file_h = CreateFile(full_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, + NULL); + + if (file_h == INVALID_HANDLE_VALUE) + { + return 0; + } + + + /* Zeroing memory */ + ZeroMemory(&sid, sizeof(WIN32_STREAM_ID)); + + /* Getting stream header size -- should be 20 bytes */ + shs = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid+ sid.dwStreamNameSize; + + + while(1) + { + if(BackupRead(file_h, (LPBYTE) &sid, shs, &dwRead, + FALSE, FALSE, &context) == 0) + { + break; + } + if(dwRead == 0) + { + break; + } + + stream_name[0] = '\0'; + stream_name[MAX_PATH] = '\0'; + if(BackupRead(file_h, (LPBYTE)stream_name, + sid.dwStreamNameSize, + &dwRead, FALSE, FALSE, &context)) + { + if(dwRead != 0) + { + int i = 0, max_path_size = 0; + char *tmp_pt; + char op_msg[OS_SIZE_1024 +1]; + + snprintf(final_name, MAX_PATH, "%s", full_path); + + max_path_size = strlen(final_name); + + + /* Copying from wide char to char. */ + while((i < dwRead) && (max_path_size < MAX_PATH)) + { + if(stream_name[i] != 0) + { + final_name[max_path_size] = stream_name[i]; + max_path_size++; + final_name[max_path_size] = '\0'; + } + i++; + } + + + tmp_pt = strrchr(final_name, ':'); + if(tmp_pt) + { + *tmp_pt = '\0'; + } + + snprintf(op_msg, OS_SIZE_1024, "NTFS Alternate data stream " + "found: '%s'. Possible hidden" + " content.", + final_name); + notify_rk(ALERT_ROOTKIT_FOUND, op_msg); + } + } + + /* Getting next */ + if(!BackupSeek(file_h, sid.Size.LowPart, sid.Size.HighPart, + &dw1, &dw2, &context)) + { + break; + } + } + + CloseHandle(file_h); + return(0); +} + + + +/** char *__os_winreg_getkey(char *reg_entry) + * Gets registry high level key. + */ +char *__os_winreg_getkey(char *reg_entry) +{ + char *ret = NULL; + char *tmp_str; + + /* Getting only the sub tree first */ + tmp_str = strchr(reg_entry, '\\'); + if(tmp_str) + { + *tmp_str = '\0'; + ret = tmp_str+1; + } + + /* Setting sub tree */ + if((strcmp(reg_entry, "HKEY_LOCAL_MACHINE") == 0) || + (strcmp(reg_entry, "HKLM") == 0)) + { + rk_sub_tree = HKEY_LOCAL_MACHINE; + } + else if(strcmp(reg_entry, "HKEY_CLASSES_ROOT") == 0) + { + rk_sub_tree = HKEY_CLASSES_ROOT; + } + else if(strcmp(reg_entry, "HKEY_CURRENT_CONFIG") == 0) + { + rk_sub_tree = HKEY_CURRENT_CONFIG; + } + else if(strcmp(reg_entry, "HKEY_USERS") == 0) + { + rk_sub_tree = HKEY_USERS; + } + else if((strcmp(reg_entry, "HKCU") == 0) || + (strcmp(reg_entry, "HKEY_CURRENT_USER") == 0)) + { + rk_sub_tree = HKEY_CURRENT_USER; + } + else + { + /* Setting sub tree to null */ + rk_sub_tree = NULL; + + /* Returning tmp_str to the previous value */ + if(tmp_str && (*tmp_str == '\0')) + *tmp_str = '\\'; + return(NULL); + } + + /* Checking if ret has nothing else. */ + if(ret && (*ret == '\0')) + ret = NULL; + + /* fixing tmp_str and the real name of the registry */ + if(tmp_str && (*tmp_str == '\0')) + *tmp_str = '\\'; + + return(ret); +} + + + +/* int __os_winreg_querykey + * Query the key and get the value of a specific entry. + */ +int __os_winreg_querykey(HKEY hKey, char *p_key, char *full_key_name, + char *reg_option, char *reg_value) +{ + int i, rc; + DWORD j; + + /* QueryInfo and EnumKey variables */ + TCHAR sub_key_name_b[MAX_KEY_LENGTH +1]; + TCHAR class_name_b[MAX_PATH +1]; + DWORD class_name_s = MAX_PATH; + + /* Number of sub keys */ + DWORD subkey_count = 0; + + /* Number of values */ + DWORD value_count; + + /* Variables for RegEnumValue */ + TCHAR value_buffer[MAX_VALUE_NAME +1]; + TCHAR data_buffer[MAX_VALUE_NAME +1]; + DWORD value_size; + DWORD data_size; + + /* Data type for RegEnumValue */ + DWORD data_type = 0; + + + /* Storage var */ + char var_storage[MAX_VALUE_NAME +1]; + + + /* Initializing the memory for some variables */ + class_name_b[0] = '\0'; + class_name_b[MAX_PATH] = '\0'; + sub_key_name_b[0] = '\0'; + sub_key_name_b[MAX_KEY_LENGTH] = '\0'; + + + /* We use the class_name, subkey_count and the value count. */ + rc = RegQueryInfoKey(hKey, class_name_b, &class_name_s, NULL, + &subkey_count, NULL, NULL, &value_count, + NULL, NULL, NULL, NULL); + + + /* Check return code of QueryInfo */ + if(rc != ERROR_SUCCESS) + { + return(0); + } + + + + /* Getting Values (if available) */ + if (value_count) + { + char *mt_data; + + + /* Clearing the values for value_size and data_size */ + value_buffer[MAX_VALUE_NAME] = '\0'; + data_buffer[MAX_VALUE_NAME] = '\0'; + var_storage[MAX_VALUE_NAME] = '\0'; + + + /* Getting each value */ + for(i=0;i 2) + { + strncat(var_storage, mt_data, size_available); + strncat(var_storage, " ", 2); + size_available = MAX_VALUE_NAME - + (strlen(var_storage) +2); + } + mt_data += strlen(mt_data) +1; + } + + break; + case REG_DWORD: + snprintf(var_storage, MAX_VALUE_NAME, + "%x",(unsigned int)*data_buffer); + break; + default: + + size_available = MAX_VALUE_NAME -2; + for(j = 0;j 2) + { + strncat(var_storage, tmp_c, size_available); + size_available = MAX_VALUE_NAME - + (strlen(var_storage) +2); + } + } + break; + } + + /* Checking if value matches */ + if(pt_matches(var_storage, reg_value)) + { + return(1); + } + + return(0); + } + } + + return(0); +} + + + +/* int __os_winreg_open_key(char *subkey) + * Open the registry key + */ +int __os_winreg_open_key(char *subkey, char *full_key_name, + char *reg_option, char *reg_value) +{ + int ret = 1; + HKEY oshkey; + + + if(RegOpenKeyEx(rk_sub_tree, subkey, 0, KEY_READ,&oshkey) != ERROR_SUCCESS) + { + return(0); + } + + + /* If option is set, return the value of query key */ + if(reg_option) + { + ret = __os_winreg_querykey(oshkey, subkey, full_key_name, + reg_option, reg_value); + } + + + RegCloseKey(oshkey); + return(ret); +} + + + +/* is_registry: Check if the entry is present in the registry + */ +int is_registry(char *entry_name, char *reg_option, char *reg_value) +{ + + char *rk; + + rk = __os_winreg_getkey(entry_name); + if(rk_sub_tree == NULL || rk == NULL) + { + merror(SK_INV_REG, ARGV0, entry_name); + return(0); + } + + if(__os_winreg_open_key(rk, entry_name, reg_option, reg_value) == 0) + { + return(0); + } + + return(1); +} + + +#else /* WIN32 */ + + +/* Non windows defs for them. */ +int os_check_ads(char *full_path) +{ + return(0); +} +int is_registry(char *entry_name, char *reg_option, char *reg_value) +{ + return(0); +} + + +#endif +/* EOF */ diff --git a/src/rootcheck/win-process.c b/src/rootcheck/win-process.c new file mode 100644 index 0000000..f71f9bd --- /dev/null +++ b/src/rootcheck/win-process.c @@ -0,0 +1,205 @@ +/* @(#) $Id: win-process.c,v 1.5 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#ifdef WIN32 +#include "shared.h" +#include "rootcheck.h" + +#include +#include + + +/* Using: http://support.microsoft.com/kb/q131065/ as ref for debug priv */ + + +/* Set Debug privilege */ +int os_win32_setdebugpriv(HANDLE h, int en) +{ + TOKEN_PRIVILEGES tp; + TOKEN_PRIVILEGES tpPrevious; + LUID luid; + DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); + + if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) + { + return(0); + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = 0; + + AdjustTokenPrivileges(h, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), + &tpPrevious,&cbPrevious); + + if(GetLastError() != ERROR_SUCCESS) + { + return(0); + } + + tpPrevious.PrivilegeCount = 1; + tpPrevious.Privileges[0].Luid = luid; + + + /* If en is set to true, we enable the privilege */ + if(en) + { + tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); + } + else + { + tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & + tpPrevious.Privileges[0].Attributes); + } + + AdjustTokenPrivileges(h, FALSE, &tpPrevious, cbPrevious, NULL, NULL); + if(GetLastError() != ERROR_SUCCESS) + { + return(0); + } + + return(1); +} + + + +/* os_get_process_list: Get list of win32 processes */ +void *os_get_process_list() +{ + OSList *p_list = NULL; + + HANDLE hsnap; + HANDLE hpriv; + PROCESSENTRY32 p_entry; + p_entry.dwSize = sizeof(PROCESSENTRY32); + + + /* Getting token for enable debug priv */ + if(!OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, FALSE, &hpriv)) + { + if(GetLastError() == ERROR_NO_TOKEN) + { + if(!ImpersonateSelf(SecurityImpersonation)) + { + merror("%s: ERROR: os_get_win32_process_list -> " + "ImpersonateSelf",ARGV0); + return(NULL); + } + + if(!OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, + FALSE, &hpriv)) + { + merror("%s: ERROR: os_get_win32_process_list -> " + "OpenThread",ARGV0); + return(NULL) ; + } + } + else + { + merror("%s: ERROR: os_get_win32_process_list -> OpenThread",ARGV0); + return(NULL); + } + } + + + /* Enabling debug privilege */ + if(!os_win32_setdebugpriv(hpriv, 1)) + { + merror("%s: ERROR: os_win32_setdebugpriv",ARGV0); + CloseHandle(hpriv); + + return(NULL); + } + + + /* Snapshot of every process */ + hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if(hsnap == INVALID_HANDLE_VALUE) + { + merror("%s: ERROR: CreateToolhelp32Snapshot",ARGV0); + return(NULL); + } + + + /* Getting first and second processes -- system entries */ + if(!Process32First(hsnap, &p_entry) && !Process32Next(hsnap, &p_entry )) + { + merror("%s: ERROR: Process32First", ARGV0); + CloseHandle(hsnap); + return(NULL); + } + + + /* Creating process list */ + p_list = OSList_Create(); + if(!p_list) + { + CloseHandle(hsnap); + merror(LIST_ERROR, ARGV0); + return(0); + } + + + /* Getting each process name and path */ + while(Process32Next( hsnap, &p_entry)) + { + char *p_name; + char *p_path; + Proc_Info *p_info; + + /* Setting process name */ + os_strdup(p_entry.szExeFile, p_name); + + + /* Getting additional information from modules */ + HANDLE hmod = INVALID_HANDLE_VALUE; + MODULEENTRY32 m_entry; + m_entry.dwSize = sizeof(MODULEENTRY32); + + /* Snapshot of the process */ + hmod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, + p_entry.th32ProcessID); + if(hmod == INVALID_HANDLE_VALUE) + { + os_strdup(p_name, p_path); + } + + /* Getting executable path (first entry in the module list */ + else if(!Module32First(hmod, &m_entry)) + { + CloseHandle(hmod); + os_strdup(p_name, p_path); + } + + else + { + os_strdup(m_entry.szExePath, p_path); + CloseHandle(hmod); + } + + os_calloc(1, sizeof(Proc_Info), p_info); + p_info->p_name = p_name; + p_info->p_path = p_path; + OSList_AddData(p_list, p_info); + } + + /* Removing debug privileges */ + os_win32_setdebugpriv(hpriv, 0); + + CloseHandle(hsnap); + return((void *)p_list); +} + +#endif /* WIN32 */ + +/* EOF */ diff --git a/src/shared/Makefile b/src/shared/Makefile new file mode 100755 index 0000000..9aa6c47 --- /dev/null +++ b/src/shared/Makefile @@ -0,0 +1,15 @@ +# Makefile -- shared functions +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +NAME=shared-libs +PT=../ + +include ../Config.Make + +shared: + ${CC} -c ${CFLAGS} ${SOURCES} + ar cru lib_shared.a ${OBJECTS} + ranlib lib_shared.a +clean: + ${CLEAN} diff --git a/src/shared/agent_op.c b/src/shared/agent_op.c new file mode 100755 index 0000000..beeb361 --- /dev/null +++ b/src/shared/agent_op.c @@ -0,0 +1,220 @@ +/* @(#) $Id: agent_op.c,v 1.8 2009/12/01 20:27:01 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + + + +/** Checks if syscheck is to be executed/restarted. + * Returns 1 on success or 0 on failure (shouldn't be executed now). + */ +int os_check_restart_syscheck() +{ + struct stat restart_status; + + /* If the restart is not present, return 0. + */ + + if(isChroot()) + { + if(stat(SYSCHECK_RESTART, &restart_status) == -1) + return(0); + + unlink(SYSCHECK_RESTART); + } + else + { + if(stat(SYSCHECK_RESTART_PATH, &restart_status) == -1) + return(0); + + unlink(SYSCHECK_RESTART_PATH); + } + + + return(1); +} + + + +/** Sets syscheck to be restarted. + * Returns 1 on success or 0 on failure. + */ +int os_set_restart_syscheck() +{ + FILE *fp; + + fp = fopen(SYSCHECK_RESTART, "w"); + if(!fp) + { + merror(FOPEN_ERROR, __local_name, SYSCHECK_RESTART); + return(0); + } + + fprintf(fp, "%s\n", SYSCHECK_RESTART); + fclose(fp); + + + return(1); +} + + + +/** char *os_read_agent_name() + * Reads the agent name for the current agent. + * Returns NULL on error. + */ +char* os_read_agent_name() +{ + int i = 0; + char buf[1024 + 1]; + FILE *fp = NULL; + + if(isChroot()) + fp = fopen(AGENT_INFO_FILE, "r"); + else + fp = fopen(AGENT_INFO_FILEP, "r"); + + /* We give 1 second for the file to be created... */ + if(!fp) + { + sleep(1); + + if(isChroot()) + fp = fopen(AGENT_INFO_FILE, "r"); + else + fp = fopen(AGENT_INFO_FILEP, "r"); + } + + if(!fp) + { + debug1(FOPEN_ERROR, __local_name, AGENT_INFO_FILE); + return(NULL); + } + + buf[1024] = '\0'; + + + /* Getting name */ + if(fgets(buf, 1024, fp)) + { + char *ret = NULL; + os_strdup(buf, ret); + fclose(fp); + + return(ret); + } + + fclose(fp); + return(NULL); +} + + + +/** char *os_read_agent_ip() + * Reads the agent ip for the current agent. + * Returns NULL on error. + */ +char *os_read_agent_ip() +{ + char buf[1024 + 1]; + FILE *fp; + + fp = fopen(AGENT_INFO_FILE, "r"); + if(!fp) + { + merror(FOPEN_ERROR, __local_name, AGENT_INFO_FILE); + return(NULL); + } + + buf[1024] = '\0'; + + + /* Getting IP */ + if(fgets(buf, 1024, fp) && fgets(buf, 1024, fp)) + { + char *ret = NULL; + os_strdup(buf, ret); + fclose(fp); + + return(ret); + } + + fclose(fp); + return(NULL); +} + + + +/** char *os_read_agent_id() + * Reads the agent id for the current agent. + * Returns NULL on error. + */ +char *os_read_agent_id() +{ + char buf[1024 + 1]; + FILE *fp; + + fp = fopen(AGENT_INFO_FILE, "r"); + if(!fp) + { + merror(FOPEN_ERROR, __local_name, AGENT_INFO_FILE); + return(NULL); + } + + buf[1024] = '\0'; + + + /* Getting id */ + if(fgets(buf, 1024, fp) && fgets(buf, 1024, fp) && fgets(buf, 1024, fp)) + { + char *ret = NULL; + os_strdup(buf, ret); + fclose(fp); + + return(ret); + } + + fclose(fp); + return(NULL); +} + + + +/** int os_write_agent_info(char *agent_name, char *agent_ip, char *agent_id) + * Writes the agent info inside the queue, for the other processes to read. + * Returns 1 on success or <= 0 on failure. + */ +int os_write_agent_info(char *agent_name, char *agent_ip, char *agent_id) +{ + FILE *fp; + + fp = fopen(AGENT_INFO_FILE, "w"); + if(!fp) + { + merror(FOPEN_ERROR, __local_name, AGENT_INFO_FILE); + return(0); + } + + fprintf(fp, "%s\n-\n%s\n", agent_name, agent_id); + fclose(fp); + return(1); +} + + + +int os_agent_config_changed() +{ + return(0); +} + + +/* EOF */ diff --git a/src/shared/debug_op.c b/src/shared/debug_op.c new file mode 100755 index 0000000..9c2ac06 --- /dev/null +++ b/src/shared/debug_op.c @@ -0,0 +1,221 @@ +/* @(#) $Id: debug_op.c,v 1.15 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "headers/shared.h" + + +int dbg_flag = 0; +int chroot_flag = 0; +int daemon_flag = 0; + +#ifdef WIN32 +void WinSetError(); +#endif + +/* For internal logs */ +#ifndef LOGFILE + #ifndef WIN32 + #define LOGFILE "/logs/ossec.log" + #else + #define LOGFILE "ossec.log" + #endif +#endif + + +/* _log function */ +void _log(const char * msg,va_list args) +{ + time_t tm; + struct tm *p; + + /* For the stderr print */ + va_list args2; + + FILE *fp; + + tm = time(NULL); + p = localtime(&tm); + + /* Duplicating args */ + va_copy(args2, args); + + + /* If under chroot, log directly to /logs/ossec.log */ + if(chroot_flag == 1) + { + fp = fopen(LOGFILE, "a"); + } + else + { + char _logfile[256]; + #ifndef WIN32 + snprintf(_logfile, 256, "%s%s", DEFAULTDIR, LOGFILE); + #else + snprintf(_logfile, 256, "%s", LOGFILE); + #endif + fp = fopen(_logfile, "a"); + } + + /* Maybe log to syslog if the log file is not available. */ + if(fp) + { + (void)fprintf(fp,"%d/%02d/%02d %02d:%02d:%02d ", + p->tm_year+1900,p->tm_mon+1, + p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec); + (void)vfprintf(fp, msg, args); + #ifdef WIN32 + (void)fprintf(fp, "\r\n"); + #else + (void)fprintf(fp, "\n"); + #endif + fflush(fp); + fclose(fp); + } + + + /* Only if not in daemon mode */ + if(daemon_flag == 0) + { + /* Print to stderr */ + (void)fprintf(stderr,"%d/%02d/%02d %02d:%02d:%02d ", + p->tm_year+1900,p->tm_mon+1 ,p->tm_mday, + p->tm_hour,p->tm_min,p->tm_sec); + (void)vfprintf(stderr, msg, args2); + #ifdef WIN32 + (void)fprintf(stderr, "\r\n"); + #else + (void)fprintf(stderr, "\n"); + #endif + } + + + /* args2 must be ended here */ + va_end(args2); +} + + +void debug1(const char * msg,...) +{ + if(dbg_flag >= 1) + { + va_list args; + va_start(args, msg); + + _log(msg, args); + + va_end(args); + } +} + +void debug2(const char * msg,...) +{ + if(dbg_flag >= 2) + { + va_list args; + va_start(args, msg); + _log(msg, args); + va_end(args); + } +} + +void merror(const char * msg,... ) +{ + va_list args; + va_start(args, msg); + _log(msg, args); + va_end(args); +} + +void verbose(const char * msg,... ) +{ + va_list args; + va_start(args, msg); + _log(msg, args); + va_end(args); +} + +/* Only logs to a file */ +void log2file(const char * msg,... ) +{ + int dbg_tmp; + va_list args; + va_start(args, msg); + + /* We set daemon flag to 1, so nothing is printed to the terminal */ + dbg_tmp = daemon_flag; + daemon_flag = 1; + _log(msg, args); + + daemon_flag = dbg_tmp; + + va_end(args); +} + +void ErrorExit(const char *msg, ...) +{ + va_list args; + + #ifdef WIN32 + /* If not MA */ + #ifndef MA + WinSetError(); + #endif + #endif + + va_start(args, msg); + _log(msg, args); + va_end(args); + + exit(1); +} + + +void nowChroot() +{ + chroot_flag = 1; +} + + +void nowDaemon() +{ + daemon_flag = 1; +} + +void print_out(const char *msg, ...) +{ + va_list args; + va_start(args, msg); + + /* Print to stderr */ + (void)vfprintf(stderr, msg, args); + + #ifdef WIN32 + (void)fprintf(stderr, "\r\n"); + #else + (void)fprintf(stderr, "\n"); + #endif + + va_end(args); +} + + +void nowDebug() +{ + dbg_flag++; +} + +int isChroot() +{ + return(chroot_flag); +} + +/* EOF */ diff --git a/src/shared/dirtree_op.c b/src/shared/dirtree_op.c new file mode 100755 index 0000000..5d469b5 --- /dev/null +++ b/src/shared/dirtree_op.c @@ -0,0 +1,298 @@ +/* @(#) $Id: dirtree_op.c,v 1.4 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Common API for dealing with directory trees */ + + +#include "shared.h" + + +/* Create the tree + * Return NULL on error + */ +OSDirTree *OSDirTree_Create() +{ + OSDirTree *my_tree; + + my_tree = calloc(1, sizeof(OSDirTree)); + if(!my_tree) + { + return(NULL); + } + + my_tree->first_node = NULL; + my_tree->last_node = NULL; + + return(my_tree); +} + + + +/* Get first node from tree (starting from parent) + * Returns null on invalid tree (not initialized) + */ +OSTreeNode *OSDirTree_GetFirstNode(OSDirTree *tree) +{ + return(tree->first_node); +} + + + +/** OSDirTree *_OSTreeNode_Add + * Internal call, looks up for an entry in the middle of the tree. + * Should not be called directly. + */ +OSDirTree *_OSTreeNode_Add(OSDirTree *tree, char *str, + void *data, char sep) +{ + char *tmp_str; + OSTreeNode *newnode; + OSTreeNode *curnode; + + + /* Looking for a next entry */ + tmp_str = strchr(str, sep); + if(tmp_str) + { + *tmp_str = '\0'; + } + + + /* Creating new tree */ + if(!tree) + { + tree = calloc(1, sizeof(OSDirTree)); + if(!tree) + { + return(NULL); + } + + tree->first_node = NULL; + tree->last_node = NULL; + } + + + curnode = tree->first_node; + + /* Looping on all nodes */ + while(curnode) + { + if(strcmp(curnode->value, str) == 0) + { + /* If we have other elements, keep going */ + if(tmp_str) + { + curnode->child = _OSTreeNode_Add(curnode->child, + tmp_str +1, data, sep); + } + break; + } + curnode = curnode->next; + } + + + /* Add a new entry, if not found. */ + if(!curnode) + { + os_calloc(1, sizeof(OSTreeNode), newnode); + //printf("XXXX Adding node: %s\n", str); + + + if(!tree->first_node && !tree->last_node) + { + tree->last_node = newnode; + tree->first_node = newnode; + } + else + { + tree->last_node->next = newnode; + } + + newnode->next = NULL; + tree->last_node = newnode; + os_strdup(str, newnode->value); + + + /* If we have other elements, keep going */ + if(tmp_str) + { + newnode->child = _OSTreeNode_Add(newnode->child, + tmp_str +1, data, sep); + newnode->data = NULL; + } + /* Otherwise, set the data in here */ + else + { + newnode->data = data; + newnode->child = NULL; + } + } + + + /* Fixing the string back */ + if(tmp_str) + { + *tmp_str = sep; + } + + + return(tree); +} + + + +/** void OSDirTree_AddToTree + * Adds a new string to the tree, setting the data at the final leaf. + * The tree will be divided by the "separator", where each token + * will delimiter the child. + * For example, /etc/my/name.conf will become: + * /etc/ + * -> /my + * -> /name.conf + * Str must not be NULL. + */ +void OSDirTree_AddToTree(OSDirTree *tree, char *str, void *data, char sep) +{ + char *tmp_str; + OSTreeNode *newnode; + OSTreeNode *curnode; + + + /* First character doesn't count as a separator */ + tmp_str = strchr(str +1, sep); + if(tmp_str) + { + *tmp_str = '\0'; + } + + + curnode = tree->first_node; + while(curnode) + { + if(strcmp(str, curnode->value) == 0) + { + /* If we have other elements, keep going */ + if(tmp_str) + { + curnode->child = _OSTreeNode_Add(curnode->child, + tmp_str +1, data, sep); + } + break; + } + + curnode = curnode->next; + } + + + /* If we didn't find an entry, create one. */ + if(!curnode) + { + os_calloc(1, sizeof(OSTreeNode), newnode); + printf("XX Adding MAIN node: %s\n", str); + + if(!tree->first_node && !tree->last_node) + { + tree->last_node = newnode; + tree->first_node = newnode; + } + else + { + printf("XXX last new node: %s\n", tree->last_node->value); + tree->last_node->next = newnode; + tree->last_node = newnode; + } + + newnode->next = NULL; + os_strdup(str, newnode->value); + + + /* If we have other elements, keep going */ + if(tmp_str) + { + newnode->child = _OSTreeNode_Add(newnode->child, + tmp_str +1, data, sep); + newnode->data = NULL; + } + /* Otherwise, set the data in here */ + else + { + newnode->data = data; + newnode->child = NULL; + } + } + + /* Fixing the string back */ + if(tmp_str) + { + *tmp_str = sep; + } + + return; +} + + + +void *OSDirTree_SearchTree(OSDirTree *tree, char *str, char sep) +{ + void *ret = NULL; + char *tmp_str; + OSTreeNode *curnode; + + + /* First character doesn't count as a separator */ + tmp_str = strchr(str +1, sep); + if(tmp_str) + { + *tmp_str = '\0'; + } + + printf("looking for: %s\n", str); + + /* If our tree is not empty, look for the main entry */ + curnode = tree->first_node; + while(curnode) + { + printf("comparing: '%s' and '%s'\n", str, curnode->value); + if(strcmp(str, curnode->value) == 0) + { + printf("found node: %s\n", str); + + /* If we have other elements, keep going */ + if(tmp_str) + { + ret = OSDirTree_SearchTree(curnode->child, tmp_str +1, sep); + } + else + { + ret = curnode->data; + } + break; + } + + curnode = curnode->next; + } + + + /* Fixing the string back */ + if(tmp_str) + { + *tmp_str = sep; + } + + + return(ret); +} + +/* EOF */ diff --git a/src/shared/file-queue.c b/src/shared/file-queue.c new file mode 100755 index 0000000..4245817 --- /dev/null +++ b/src/shared/file-queue.c @@ -0,0 +1,240 @@ +/* @(#) $Id: file-queue.c,v 1.11 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* File monitoring functions */ + +#include "shared.h" +#include "file-queue.h" + + +/* To translante between month (int) to month (char) */ +char *(s_month[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", + "Sep","Oct","Nov","Dec"}; + + + +/** void file_sleep(); + * file_sleep + */ +void file_sleep() +{ + #ifndef WIN32 + struct timeval fp_timeout; + + fp_timeout.tv_sec = FQ_TIMEOUT; + fp_timeout.tv_usec = 0; + + /* Waiting for the select timeout */ + select(0, NULL, NULL, NULL, &fp_timeout); + + #else + /* Windows don't like select that way */ + Sleep((FQ_TIMEOUT + 2) * 1000); + #endif + + return; +} + + + +/** void GetFile_Queue(file_queue *fileq) + * Get the file queue for that specific hour + */ +void GetFile_Queue(file_queue *fileq) +{ + /* Creating the logfile name */ + fileq->file_name[0] = '\0'; + fileq->file_name[MAX_FQUEUE] = '\0'; + + if(fileq->flags & CRALERT_FP_SET) + { + snprintf(fileq->file_name, MAX_FQUEUE, + ""); + } + else + { + snprintf(fileq->file_name, MAX_FQUEUE, + "%s/%d/%s/ossec-alerts-%02d.log", + ALERTS, + fileq->year, + fileq->mon, + fileq->day); + } +} + + + +/** int Handle_Queue(file_queue *fileq) + * Re Handle the file queue. + */ +int Handle_Queue(file_queue *fileq, int flags) +{ + /* Closing if it is open */ + if(!(flags & CRALERT_FP_SET)) + { + if(fileq->fp) + { + fclose(fileq->fp); + fileq->fp = NULL; + } + + + /* We must be able to open the file, fseek and get the + * time of change from it. + */ + fileq->fp = fopen(fileq->file_name, "r"); + if(!fileq->fp) + { + /* Queue not available */ + return(0); + } + } + + + /* Seeking the end of file */ + if(!(flags & CRALERT_READ_ALL)) + { + if(fseek(fileq->fp, 0, SEEK_END) < 0) + { + merror(FSEEK_ERROR, __local_name, fileq->file_name); + fclose(fileq->fp); + fileq->fp = NULL; + return(-1); + } + } + + + /* File change time */ + if(fstat(fileno(fileq->fp), &fileq->f_status) < 0) + { + merror(FILE_ERROR, __local_name, fileq->file_name); + fclose(fileq->fp); + fileq->fp = NULL; + return(-1); + } + + fileq->last_change = fileq->f_status.st_mtime; + + return(1); +} + + + +/** int Init_FileQueue(file_queue *fileq, struct tm *p, int flags) + * Initiates the file monitoring. + */ +int Init_FileQueue(file_queue *fileq, struct tm *p, int flags) +{ + /* Initializing file_queue fields. */ + if(!(flags & CRALERT_FP_SET)) + { + fileq->fp = NULL; + } + fileq->last_change = 0; + fileq->flags = 0; + + fileq->day = p->tm_mday; + fileq->year = p->tm_year+1900; + + strncpy(fileq->mon, s_month[p->tm_mon], 4); + memset(fileq->file_name, '\0',MAX_FQUEUE + 1); + + + /* Setting the supplied flags */ + fileq->flags = flags; + + + /* Getting latest file */ + GetFile_Queue(fileq); + + + /* Always seek end when starting the queue */ + if(Handle_Queue(fileq, fileq->flags) < 0) + { + return(-1); + } + + return(0); +} + + + +/** int Read_FileMon(file_queue *fileq, struct tm *p, int timeout) + * Reads from the monitored file. + */ +alert_data *Read_FileMon(file_queue *fileq, struct tm *p, int timeout) +{ + int i = 0; + alert_data *al_data; + + + /* If the file queue is not available, try to access it */ + if(!fileq->fp) + { + if(Handle_Queue(fileq, 0) != 1) + { + file_sleep(); + return(NULL); + } + } + + + /* Getting currently file */ + if(p->tm_mday != fileq->day) + { + /* If the day changes, we need to get all remaining alerts. */ + al_data = GetAlertData(fileq->flags, fileq->fp); + if(!al_data) + { + fileq->day = p->tm_mday; + fileq->year = p->tm_year+1900; + strncpy(fileq->mon, s_month[p->tm_mon], 4); + + /* Getting latest file */ + GetFile_Queue(fileq); + + if(Handle_Queue(fileq, 0) != 1) + { + file_sleep(); + return(NULL); + } + } + else + { + return(al_data); + } + } + + + /* Try up to timeout times to get an event */ + while(i < timeout) + { + al_data = GetAlertData(fileq->flags, fileq->fp); + if(al_data) + { + return(al_data); + } + + i++; + file_sleep(); + } + + + /* Returning NULL if timeout expires. */ + return(NULL); +} + + +/* EOF */ diff --git a/src/shared/file_op.c b/src/shared/file_op.c new file mode 100755 index 0000000..be8754f --- /dev/null +++ b/src/shared/file_op.c @@ -0,0 +1,1208 @@ +/* @(#) $Id: file_op.c,v 1.32 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Functions to handle operation with files + */ + + +#include "shared.h" + + +/* Vista product information. */ +#ifdef WIN32 +#ifndef PRODUCT_UNLICENSED +#define PRODUCT_UNLICENSED 0xABCDABCD +#define PRODUCT_UNLICENSED_C "Product Unlicensed " +#endif + +#ifndef PRODUCT_BUSINESS +#define PRODUCT_BUSINESS 0x00000006 +#define PRODUCT_BUSINESS_C "Business Edition " +#endif + +#ifndef PRODUCT_BUSINESS_N +#define PRODUCT_BUSINESS_N 0x00000010 +#define PRODUCT_BUSINESS_N_C "Business Edition " +#endif + +#ifndef PRODUCT_CLUSTER_SERVER +#define PRODUCT_CLUSTER_SERVER 0x00000012 +#define PRODUCT_CLUSTER_SERVER_C "Cluster Server Edition " +#endif + +#ifndef PRODUCT_DATACENTER_SERVER +#define PRODUCT_DATACENTER_SERVER 0x00000008 +#define PRODUCT_DATACENTER_SERVER_C "Datacenter Edition (full) " +#endif + +#ifndef PRODUCT_DATACENTER_SERVER_CORE +#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C +#define PRODUCT_DATACENTER_SERVER_CORE_C "Datacenter Edition (core) " +#endif + +#ifndef PRODUCT_DATACENTER_SERVER_CORE_V +#define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027 +#define PRODUCT_DATACENTER_SERVER_CORE_V_C "Datacenter Edition (core) " +#endif + +#ifndef PRODUCT_DATACENTER_SERVER_V +#define PRODUCT_DATACENTER_SERVER_V 0x00000025 +#define PRODUCT_DATACENTER_SERVER_V_C "Datacenter Edition (full) " +#endif + +#ifndef PRODUCT_ENTERPRISE +#define PRODUCT_ENTERPRISE 0x00000004 +#define PRODUCT_ENTERPRISE_C "Enterprise Edition " +#endif + +#ifndef PRODUCT_ENTERPRISE_N +#define PRODUCT_ENTERPRISE_N 0x0000001B +#define PRODUCT_ENTERPRISE_N_C "Enterprise Edition " +#endif + +#ifndef PRODUCT_ENTERPRISE_SERVER +#define PRODUCT_ENTERPRISE_SERVER 0x0000000A +#define PRODUCT_ENTERPRISE_SERVER_C "Enterprise Edition (full) " +#endif + +#ifndef PRODUCT_ENTERPRISE_SERVER_CORE +#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E +#define PRODUCT_ENTERPRISE_SERVER_CORE_C "Enterprise Edition (core) " +#endif + +#ifndef PRODUCT_ENTERPRISE_SERVER_CORE_V +#define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029 +#define PRODUCT_ENTERPRISE_SERVER_CORE_V_C "Enterprise Edition (core) " +#endif + +#ifndef PRODUCT_ENTERPRISE_SERVER_IA64 +#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F +#define PRODUCT_ENTERPRISE_SERVER_IA64_C "Enterprise Edition for Itanium-based Systems " +#endif + +#ifndef PRODUCT_ENTERPRISE_SERVER_V +#define PRODUCT_ENTERPRISE_SERVER_V 0x00000026 +#define PRODUCT_ENTERPRISE_SERVER_V_C "Enterprise Edition (full) " +#endif + +#ifndef PRODUCT_HOME_BASIC +#define PRODUCT_HOME_BASIC 0x00000002 +#define PRODUCT_HOME_BASIC_C "Home Basic Edition " +#endif + +#ifndef PRODUCT_HOME_BASIC_N +#define PRODUCT_HOME_BASIC_N 0x00000005 +#define PRODUCT_HOME_BASIC_N_C "Home Basic Edition " +#endif + +#ifndef PRODUCT_HOME_PREMIUM +#define PRODUCT_HOME_PREMIUM 0x00000003 +#define PRODUCT_HOME_PREMIUM_C "Home Premium Edition " +#endif + +#ifndef PRODUCT_HOME_PREMIUM_N +#define PRODUCT_HOME_PREMIUM_N 0x0000001A +#define PRODUCT_HOME_PREMIUM_N_C "Home Premium Edition " +#endif + +#ifndef PRODUCT_HOME_SERVER +#define PRODUCT_HOME_SERVER 0x00000013 +#define PRODUCT_HOME_SERVER_C "Home Server Edition " +#endif + +#ifndef PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT +#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E +#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT_C "Essential Business Server Management Server " +#endif + +#ifndef PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING +#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020 +#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING_C "Essential Business Server Messaging Server " +#endif + +#ifndef PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY +#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F +#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY_C "Essential Business Server Security Server " +#endif + +#ifndef PRODUCT_SERVER_FOR_SMALLBUSINESS +#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 +#define PRODUCT_SERVER_FOR_SMALLBUSINESS_C "Small Business Edition " +#endif + +#ifndef PRODUCT_SMALLBUSINESS_SERVER +#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 +#define PRODUCT_SMALLBUSINESS_SERVER_C "Small Business Server " +#endif + +#ifndef PRODUCT_SMALLBUSINESS_SERVER_PREMIUM +#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 +#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_C "Small Business Server Premium Edition " +#endif + +#ifndef PRODUCT_STANDARD_SERVER +#define PRODUCT_STANDARD_SERVER 0x00000007 +#define PRODUCT_STANDARD_SERVER_C "Standard Edition " +#endif + +#ifndef PRODUCT_STANDARD_SERVER_CORE +#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D +#define PRODUCT_STANDARD_SERVER_CORE_C "Standard Edition (core) " +#endif + +#ifndef PRODUCT_STANDARD_SERVER_CORE_V +#define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028 +#define PRODUCT_STANDARD_SERVER_CORE_V_C "Standard Edition " +#endif + +#ifndef PRODUCT_STANDARD_SERVER_V +#define PRODUCT_STANDARD_SERVER_V 0x00000024 +#define PRODUCT_STANDARD_SERVER_V_C "Standard Edition " +#endif + +#ifndef PRODUCT_STARTER +#define PRODUCT_STARTER 0x0000000B +#define PRODUCT_STARTER_C "Starter Edition " +#endif + +#ifndef PRODUCT_STORAGE_ENTERPRISE_SERVER +#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 +#define PRODUCT_STORAGE_ENTERPRISE_SERVER_C "Storage Server Enterprise Edition " +#endif + +#ifndef PRODUCT_STORAGE_EXPRESS_SERVER +#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 +#define PRODUCT_STORAGE_EXPRESS_SERVER_C "Storage Server Express Edition " +#endif + +#ifndef PRODUCT_STORAGE_STANDARD_SERVER +#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 +#define PRODUCT_STORAGE_STANDARD_SERVER_C "Storage Server Standard Edition " +#endif + +#ifndef PRODUCT_STORAGE_WORKGROUP_SERVER +#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 +#define PRODUCT_STORAGE_WORKGROUP_SERVER_C "Storage Server Workgroup Edition " +#endif + +#ifndef PRODUCT_ULTIMATE +#define PRODUCT_ULTIMATE 0x00000001 +#define PRODUCT_ULTIMATE_C "Ultimate Edition " +#endif + +#ifndef PRODUCT_ULTIMATE_N +#define PRODUCT_ULTIMATE_N 0x0000001C +#define PRODUCT_ULTIMATE_N_C "Ultimate Edition " +#endif + +#ifndef PRODUCT_WEB_SERVER +#define PRODUCT_WEB_SERVER 0x00000011 +#define PRODUCT_WEB_SERVER_C "Web Server Edition " +#endif + +#ifndef PRODUCT_WEB_SERVER_CORE +#define PRODUCT_WEB_SERVER_CORE 0x0000001D +#define PRODUCT_WEB_SERVER_CORE_C "Web Server Edition " +#endif +#endif /* WIN32 */ + + + +/* Sets the name of the starting program */ +void OS_SetName(char *name) +{ + __local_name = name; + return; +} + + +int File_DateofChange(char *file) +{ + struct stat file_status; + + if(stat(file, &file_status) < 0) + return(-1); + + return (file_status.st_mtime); +} + +int IsDir(char *file) +{ + struct stat file_status; + if(stat(file,&file_status) < 0) + return(-1); + if(S_ISDIR(file_status.st_mode)) + return(0); + return(-1); +} + + +int CreatePID(char *name, int pid) +{ + char file[256]; + FILE *fp; + + if(isChroot()) + { + snprintf(file,255,"%s/%s-%d.pid",OS_PIDFILE,name,pid); + } + else + { + snprintf(file,255,"%s%s/%s-%d.pid",DEFAULTDIR, + OS_PIDFILE,name,pid); + } + + fp = fopen(file,"a"); + if(!fp) + return(-1); + + fprintf(fp,"%d\n",pid); + + fclose(fp); + + return(0); +} + +int DeletePID(char *name) +{ + char file[256]; + + if(isChroot()) + { + snprintf(file,255,"%s/%s-%d.pid",OS_PIDFILE,name,(int)getpid()); + } + else + { + snprintf(file,255,"%s%s/%s-%d.pid",DEFAULTDIR, + OS_PIDFILE,name,(int)getpid()); + } + + if(File_DateofChange(file) < 0) + return(-1); + + unlink(file); + + return(0); +} + + +int UnmergeFiles(char *finalpath, char *optdir) +{ + int i = 0, n = 0, ret = 1; + long files_size = 0; + + char *files; + char final_name[2048 +1]; + char buf[2048 + 1]; + FILE *fp; + FILE *finalfp; + + finalfp = fopen(finalpath, "r"); + if(!finalfp) + { + merror("%s: ERROR: Unable to read merged file: '%s'.", + __local_name, finalpath); + return(0); + } + + while(1) + { + /* Reading header portion. */ + if(fgets(buf, sizeof(buf) -1, finalfp) == NULL) + { + break; + } + + + /* Initiator. */ + if(buf[0] != '!') + continue; + + + /* Getting file size and name. */ + files_size = atol(buf +1); + + files = strchr(buf, '\n'); + if(files) + *files = '\0'; + + files = strchr(buf, ' '); + if(!files) + { + ret = 0; + continue; + } + files++; + + + if(optdir) + { + snprintf(final_name, 2048, "%s/%s", optdir, files); + } + else + { + strncpy(final_name, files, 2048); + final_name[2048] = '\0'; + } + + + /* Opening file name. */ + fp = fopen(final_name,"w"); + if(!fp) + { + ret = 0; + merror("%s: ERROR: Unable to unmerge file '%s'.", + __local_name, final_name); + } + + + if(files_size < sizeof(buf) -1) + { + i = files_size; + files_size = 0; + } + else + { + i = sizeof(buf) -1; + files_size -= sizeof(buf) -1; + } + + while((n = fread(buf, 1, i, finalfp)) > 0) + { + buf[n] = '\0'; + + if(fp) + { + fwrite(buf, n, 1, fp); + } + + if(files_size == 0) + { + break; + } + else + { + if(files_size < sizeof(buf) -1) + { + i = files_size; + files_size = 0; + } + else + { + i = sizeof(buf) -1; + files_size -= sizeof(buf) -1; + } + } + } + + if(fp) + fclose(fp); + } + + fclose(finalfp); + return(ret); +} + + +int MergeAppendFile(char *finalpath, char *files) +{ + int n = 0; + long files_size = 0; + + char buf[2048 + 1]; + char *tmpfile; + FILE *fp; + FILE *finalfp; + + + /* Creating a new entry. */ + if(files == NULL) + { + finalfp = fopen(finalpath, "w"); + if(!finalfp) + { + merror("%s: ERROR: Unable to create merged file: '%s'.", + __local_name, finalpath); + return(0); + } + fclose(finalfp); + + return(1); + } + + + finalfp = fopen(finalpath, "a"); + if(!finalfp) + { + merror("%s: ERROR: Unable to create merged file: '%s'.", + __local_name, finalpath); + return(0); + } + + + fp = fopen(files,"r"); + if(!fp) + { + merror("%s: ERROR: Unable to merge file '%s'.", __local_name, files); + fclose(finalfp); + return(0); + } + + + fseek(fp, 0, SEEK_END); + files_size = ftell(fp); + + tmpfile = strrchr(files, '/'); + if(tmpfile) + { + tmpfile++; + } + else + { + tmpfile = files; + } + fprintf(finalfp, "!%ld %s\n", files_size, tmpfile); + + fseek(fp, 0, SEEK_SET); + + while((n = fread(buf, 1, sizeof(buf) -1, fp)) > 0) + { + buf[n] = '\0'; + fwrite(buf, n, 1, finalfp); + } + + fclose(fp); + + fclose(finalfp); + return(1); +} + + + +int MergeFiles(char *finalpath, char **files) +{ + int i = 0, n = 0, ret = 1; + long files_size = 0; + + char *tmpfile; + char buf[2048 + 1]; + FILE *fp; + FILE *finalfp; + + finalfp = fopen(finalpath, "w"); + if(!finalfp) + { + merror("%s: ERROR: Unable to create merged file: '%s'.", + __local_name, finalpath); + return(0); + } + + while(files[i]) + { + fp = fopen(files[i],"r"); + if(!fp) + { + merror("%s: ERROR: Unable to merge file '%s'.", __local_name, files[i]); + i++; + ret = 0; + continue; + } + + fseek(fp, 0, SEEK_END); + files_size = ftell(fp); + + /* Removing last entry. */ + tmpfile = strrchr(files[i], '/'); + if(tmpfile) + { + tmpfile++; + } + else + { + tmpfile = files[i]; + } + + fprintf(finalfp, "!%ld %s\n", files_size, tmpfile); + + fseek(fp, 0, SEEK_SET); + + while((n = fread(buf, 1, sizeof(buf) -1, fp)) > 0) + { + buf[n] = '\0'; + fwrite(buf, n, 1, finalfp); + } + + fclose(fp); + i++; + } + + fclose(finalfp); + return(ret); +} + + +#ifndef WIN32 +/* getuname; Get uname and returns a string with it. + * Memory must be freed after use + */ +char *getuname() +{ + struct utsname uts_buf; + + if(uname(&uts_buf) >= 0) + { + char *ret; + + ret = calloc(256, sizeof(char)); + if(ret == NULL) + return(NULL); + + snprintf(ret, 255, "%s %s %s %s %s - %s %s", + uts_buf.sysname, + uts_buf.nodename, + uts_buf.release, + uts_buf.version, + uts_buf.machine, + __name, __version); + + return(ret); + } + else + { + char *ret; + ret = calloc(256, sizeof(char)); + if(ret == NULL) + return(NULL); + + snprintf(ret, 255, "No system info available - %s %s", + __name, __version); + + return(ret); + } + + return(NULL); +} + + + +/* goDaemon: Daemonize a process without closing stdin/stdout/stderr.. + * + */ +void goDaemonLight() +{ + pid_t pid; + + pid = fork(); + + if(pid < 0) + { + merror(FORK_ERROR, __local_name); + return; + } + else if(pid) + { + exit(0); + } + + + /* becoming session leader */ + if(setsid() < 0) + { + merror(SETSID_ERROR, __local_name); + return; + } + + + /* forking again */ + pid = fork(); + if(pid < 0) + { + merror(FORK_ERROR, __local_name); + return; + } + else if(pid) + { + exit(0); + } + + + dup2(1, 2); + + + /* Going to / */ + chdir("/"); + + + return; +} + + + +/* goDaemon: Daemonize a process.. + * + */ +void goDaemon() +{ + int fd; + pid_t pid; + + pid = fork(); + + if(pid < 0) + { + merror(FORK_ERROR, __local_name); + return; + } + else if(pid) + { + exit(0); + } + + /* becoming session leader */ + if(setsid() < 0) + { + merror(SETSID_ERROR, __local_name); + return; + } + + /* forking again */ + pid = fork(); + if(pid < 0) + { + merror(FORK_ERROR, __local_name); + return; + } + else if(pid) + { + exit(0); + } + + + /* Dup stdin, stdout and stderr to /dev/null */ + if((fd = open("/dev/null", O_RDWR)) >= 0) + { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + } + + + /* Going to / */ + chdir("/"); + + + /* Closing stdin, stdout and stderr */ + /* + fclose(stdin); + fclose(stdout); + fclose(stderr); + */ + + /* Openining stdin, stdout and stderr to /dev/null */ + /* + open("/dev/null", O_RDONLY); + open("/dev/null", O_RDWR); + open("/dev/null", O_RDWR); + */ + + return; +} + + +#else +int checkVista() +{ + char *m_uname; + isVista = 0; + + m_uname = getuname(); + if(!m_uname) + { + merror(MEM_ERROR, __local_name); + return(0); + } + + + /* We check if the system is vista (most be called during the startup. */ + if(strstr(m_uname, "Windows Server 2008") || + strstr(m_uname, "Vista")) + { + isVista = 1; + verbose("%s: INFO: System is Vista or Windows Server 2008.", + __local_name); + } + + free(m_uname); + + return(isVista); +} + + + +/** get uname for windows **/ +char *getuname() +{ + int ret_size = OS_SIZE_1024 -2; + char *ret = NULL; + char os_v[128 +1]; + + typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); + typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); + + + /* Extracted from ms web site + * http://msdn.microsoft.com/library/en-us/sysinfo/base/getting_the_system_version.asp + */ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + PGNSI pGNSI; + PGPI pGPI; + BOOL bOsVersionInfoEx; + DWORD dwType; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if(!(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO *)&osvi)) + return(NULL); + } + + /* Allocating the memory */ + os_calloc(OS_SIZE_1024 +1, sizeof(char), ret); + ret[OS_SIZE_1024] = '\0'; + + switch(osvi.dwPlatformId) + { + /* Test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 ) + { + if(osvi.wProductType == VER_NT_WORKSTATION ) + strncat(ret, "Microsoft Windows Vista ", ret_size -1); + else + { + strncat(ret, "Microsoft Windows Server 2008 ", ret_size -1); + } + + ret_size-=strlen(ret) +1; + + + /* Getting product version. */ + pGPI = (PGPI) GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), + "GetProductInfo"); + + pGPI( 6, 0, 0, 0, &dwType); + + switch(dwType) + { + case PRODUCT_UNLICENSED: + strncat(ret, PRODUCT_UNLICENSED_C, ret_size -1); + break; + case PRODUCT_BUSINESS: + strncat(ret, PRODUCT_BUSINESS_C, ret_size -1); + break; + case PRODUCT_BUSINESS_N: + strncat(ret, PRODUCT_BUSINESS_N_C, ret_size -1); + break; + case PRODUCT_CLUSTER_SERVER: + strncat(ret, PRODUCT_CLUSTER_SERVER_C, ret_size -1); + break; + case PRODUCT_DATACENTER_SERVER: + strncat(ret, PRODUCT_DATACENTER_SERVER_C, ret_size -1); + break; + case PRODUCT_DATACENTER_SERVER_CORE: + strncat(ret, PRODUCT_DATACENTER_SERVER_CORE_C, ret_size -1); + break; + case PRODUCT_DATACENTER_SERVER_CORE_V: + strncat(ret, PRODUCT_DATACENTER_SERVER_CORE_V_C, ret_size -1); + break; + case PRODUCT_DATACENTER_SERVER_V: + strncat(ret, PRODUCT_DATACENTER_SERVER_V_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE: + strncat(ret, PRODUCT_ENTERPRISE_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE_N: + strncat(ret, PRODUCT_ENTERPRISE_N_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE_SERVER: + strncat(ret, PRODUCT_ENTERPRISE_SERVER_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + strncat(ret, PRODUCT_ENTERPRISE_SERVER_CORE_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE_SERVER_CORE_V: + strncat(ret, PRODUCT_ENTERPRISE_SERVER_CORE_V_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + strncat(ret, PRODUCT_ENTERPRISE_SERVER_IA64_C, ret_size -1); + break; + case PRODUCT_ENTERPRISE_SERVER_V: + strncat(ret, PRODUCT_ENTERPRISE_SERVER_V_C, ret_size -1); + break; + case PRODUCT_HOME_BASIC: + strncat(ret, PRODUCT_HOME_BASIC_C, ret_size -1); + break; + case PRODUCT_HOME_BASIC_N: + strncat(ret, PRODUCT_HOME_BASIC_N_C, ret_size -1); + break; + case PRODUCT_HOME_PREMIUM: + strncat(ret, PRODUCT_HOME_PREMIUM_C, ret_size -1); + break; + case PRODUCT_HOME_PREMIUM_N: + strncat(ret, PRODUCT_HOME_PREMIUM_N_C, ret_size -1); + break; + case PRODUCT_HOME_SERVER: + strncat(ret, PRODUCT_HOME_SERVER_C, ret_size -1); + break; + case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT: + strncat(ret, PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT_C, ret_size -1); + break; + case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING: + strncat(ret, PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING_C, ret_size -1); + break; + case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY: + strncat(ret, PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY_C, ret_size -1); + break; + case PRODUCT_SERVER_FOR_SMALLBUSINESS: + strncat(ret, PRODUCT_SERVER_FOR_SMALLBUSINESS_C, ret_size -1); + break; + case PRODUCT_SMALLBUSINESS_SERVER: + strncat(ret, PRODUCT_SMALLBUSINESS_SERVER_C, ret_size -1); + break; + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + strncat(ret, PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_C, ret_size -1); + break; + case PRODUCT_STANDARD_SERVER: + strncat(ret, PRODUCT_STANDARD_SERVER_C, ret_size -1); + break; + case PRODUCT_STANDARD_SERVER_CORE: + strncat(ret, PRODUCT_STANDARD_SERVER_CORE_C, ret_size -1); + break; + case PRODUCT_STANDARD_SERVER_CORE_V: + strncat(ret, PRODUCT_STANDARD_SERVER_CORE_V_C, ret_size -1); + break; + case PRODUCT_STANDARD_SERVER_V: + strncat(ret, PRODUCT_STANDARD_SERVER_V_C, ret_size -1); + break; + case PRODUCT_STARTER: + strncat(ret, PRODUCT_STARTER_C, ret_size -1); + break; + case PRODUCT_STORAGE_ENTERPRISE_SERVER: + strncat(ret, PRODUCT_STORAGE_ENTERPRISE_SERVER_C, ret_size -1); + break; + case PRODUCT_STORAGE_EXPRESS_SERVER: + strncat(ret, PRODUCT_STORAGE_EXPRESS_SERVER_C, ret_size -1); + break; + case PRODUCT_STORAGE_STANDARD_SERVER: + strncat(ret, PRODUCT_STORAGE_STANDARD_SERVER_C, ret_size -1); + break; + case PRODUCT_STORAGE_WORKGROUP_SERVER: + strncat(ret, PRODUCT_STORAGE_WORKGROUP_SERVER_C, ret_size -1); + break; + case PRODUCT_ULTIMATE: + strncat(ret, PRODUCT_ULTIMATE_C, ret_size -1); + break; + case PRODUCT_ULTIMATE_N: + strncat(ret, PRODUCT_ULTIMATE_N_C, ret_size -1); + break; + case PRODUCT_WEB_SERVER: + strncat(ret, PRODUCT_WEB_SERVER_C, ret_size -1); + break; + case PRODUCT_WEB_SERVER_CORE: + strncat(ret, PRODUCT_WEB_SERVER_CORE_C, ret_size -1); + break; + } + + + ret_size-=strlen(ret) +1; + } + + else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + pGNSI = (PGNSI) GetProcAddress( + GetModuleHandle("kernel32.dll"), + "GetNativeSystemInfo"); + if(NULL != pGNSI) + pGNSI(&si); + + if( GetSystemMetrics(89) ) + strncat(ret, "Microsoft Windows Server 2003 R2 ", + ret_size -1); + else if(osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + { + strncat(ret, + "Microsoft Windows XP Professional x64 Edition ", + ret_size -1 ); + } + else + { + strncat(ret, "Microsoft Windows Server 2003, ",ret_size-1); + } + + ret_size-=strlen(ret) +1; + } + + else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + { + strncat(ret, "Microsoft Windows XP ", ret_size -1); + + ret_size-=strlen(ret) +1; + } + + else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + strncat(ret, "Microsoft Windows 2000 ", ret_size -1); + + ret_size-=strlen(ret) +1; + } + + else if (osvi.dwMajorVersion <= 4) + { + strncat(ret, "Microsoft Windows NT ", ret_size -1); + + ret_size-=strlen(ret) +1; + } + else + { + strncat(ret, "Microsoft Windows Unknown ", ret_size -1); + + ret_size-=strlen(ret) +1; + } + + /* Test for specific product on Windows NT 4.0 SP6 and later. */ + if(bOsVersionInfoEx) + { + /* Test for the workstation type. */ + if (osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64) + { + if( osvi.dwMajorVersion == 4 ) + strncat(ret, "Workstation 4.0 ", ret_size -1); + else if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) + strncat(ret, "Home Edition ", ret_size -1); + else + strncat(ret, "Professional ",ret_size -1); + + /* Fixing size */ + ret_size-=strlen(ret) +1; + } + + /* Test for the server type. */ + else if( osvi.wProductType == VER_NT_SERVER || + osvi.wProductType == VER_NT_DOMAIN_CONTROLLER ) + { + if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2) + { + if (si.wProcessorArchitecture== + PROCESSOR_ARCHITECTURE_IA64 ) + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + strncat(ret, + "Datacenter Edition for Itanium-based Systems ", + ret_size -1); + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strncat(ret, + "Enterprise Edition for Itanium-based Systems ", + ret_size -1); + + ret_size-=strlen(ret) +1; + } + + else if ( si.wProcessorArchitecture== + PROCESSOR_ARCHITECTURE_AMD64 ) + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + strncat(ret, "Datacenter x64 Edition ", + ret_size -1 ); + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strncat(ret, "Enterprise x64 Edition ", + ret_size -1 ); + else + strncat(ret, "Standard x64 Edition ", + ret_size -1 ); + + ret_size-=strlen(ret) +1; + } + + else + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + strncat(ret, "Datacenter Edition ", + ret_size -1 ); + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strncat(ret,"Enterprise Edition ",ret_size -1); + else if ( osvi.wSuiteMask == VER_SUITE_BLADE ) + strncat(ret,"Web Edition ",ret_size -1 ); + else + strncat(ret, "Standard Edition ",ret_size -1); + + ret_size-=strlen(ret) +1; + } + } + else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0) + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + strncat(ret, "Datacenter Server ",ret_size -1); + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strncat(ret, "Advanced Server ",ret_size -1 ); + else + strncat(ret, "Server ",ret_size -1); + + ret_size-=strlen(ret) +1; + } + else if(osvi.dwMajorVersion <= 4) /* Windows NT 4.0 */ + { + if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strncat(ret, "Server 4.0, Enterprise Edition ", + ret_size -1 ); + else + strncat(ret, "Server 4.0 ",ret_size -1); + + ret_size-=strlen(ret) +1; + } + } + } + /* Test for specific product on Windows NT 4.0 SP5 and earlier */ + else + { + HKEY hKey; + char szProductType[81]; + DWORD dwBufLen=80; + LONG lRet; + + lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_QUERY_VALUE, &hKey ); + if(lRet == ERROR_SUCCESS) + { + char __wv[32]; + + lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL, + (LPBYTE) szProductType, &dwBufLen); + RegCloseKey( hKey ); + + if((lRet == ERROR_SUCCESS) && (dwBufLen < 80) ) + { + if (lstrcmpi( "WINNT", szProductType) == 0 ) + strncat(ret, "Workstation ",ret_size -1); + else if(lstrcmpi( "LANMANNT", szProductType) == 0 ) + strncat(ret, "Server ",ret_size -1); + else if(lstrcmpi( "SERVERNT", szProductType) == 0 ) + strncat(ret, "Advanced Server " ,ret_size -1); + + ret_size-=strlen(ret) +1; + + memset(__wv, '\0', 32); + snprintf(__wv, 31, + "%d.%d ", + (int)osvi.dwMajorVersion, + (int)osvi.dwMinorVersion); + + strncat(ret, __wv, ret_size -1); + ret_size-=strlen(__wv) +1; + } + } + } + + /* Display service pack (if any) and build number. */ + + if( osvi.dwMajorVersion == 4 && + lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 ) + { + HKEY hKey; + LONG lRet; + char __wp[64]; + + memset(__wp, '\0', 64); + /* Test for SP6 versus SP6a. */ + lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", + 0, KEY_QUERY_VALUE, &hKey ); + if( lRet == ERROR_SUCCESS ) + snprintf(__wp, 63, "Service Pack 6a (Build %d)", + (int)osvi.dwBuildNumber & 0xFFFF ); + else /* Windows NT 4.0 prior to SP6a */ + { + snprintf(__wp, 63, "%s (Build %d)", + osvi.szCSDVersion, + (int)osvi.dwBuildNumber & 0xFFFF); + } + + strncat(ret, __wp, ret_size -1); + ret_size-=strlen(__wp) +1; + RegCloseKey( hKey ); + } + else + { + char __wp[64]; + + memset(__wp, '\0', 64); + + snprintf(__wp, 63, "%s (Build %d)", + osvi.szCSDVersion, + (int)osvi.dwBuildNumber & 0xFFFF); + + strncat(ret, __wp, ret_size -1); + ret_size-=strlen(__wp) +1; + } + break; + + /* Test for the Windows Me/98/95. */ + case VER_PLATFORM_WIN32_WINDOWS: + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + { + strncat(ret, "Microsoft Windows 95 ", ret_size -1); + ret_size-=strlen(ret) +1; + } + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + strncat(ret, "Microsoft Windows 98 ", ret_size -1); + ret_size-=strlen(ret) +1; + } + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + { + strncat(ret, "Microsoft Windows Millennium Edition", + ret_size -1); + + ret_size-=strlen(ret) +1; + } + break; + + case VER_PLATFORM_WIN32s: + + strncat(ret, "Microsoft Win32s", ret_size -1); + ret_size-=strlen(ret) +1; + break; + } + + + /* Adding ossec version */ + snprintf(os_v, 128, " - %s %s", __name, __version); + strncat(ret, os_v, ret_size -1); + + + /* Returning system information */ + return(ret); + +} +#endif + +/* EOF */ diff --git a/src/shared/hash_op.c b/src/shared/hash_op.c new file mode 100755 index 0000000..1ef278d --- /dev/null +++ b/src/shared/hash_op.c @@ -0,0 +1,283 @@ +/* @(#) $Id: hash_op.c,v 1.5 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Common API for dealing with hashes/maps */ + + +#include "shared.h" + + + +/** OSHash *OSHash_Create() + * Creates the Hash. + * Returns NULL on error. + */ +OSHash *OSHash_Create() +{ + int i = 0; + OSHash *self; + + /* Allocating memory for the hash */ + self = calloc(1, sizeof(OSHash)); + if(!self) + { + return(NULL); + } + + + /* Setting default row size */ + self->rows = os_getprime(1024); + if(self->rows == 0) + { + free(self); + return(NULL); + } + + + /* Creating hashing table */ + self->table = (OSHashNode **)calloc(self->rows +1, sizeof(OSHashNode *)); + if(!self->table) + { + free(self); + return(NULL); + } + + + /* Zeroing our tables */ + for(i = 0; i <= self->rows; i++) + { + self->table[i] = NULL; + } + + + /* Getting seed */ + srandom(time(0)); + self->initial_seed = os_getprime(random() % self->rows); + self->constant = os_getprime(random() % self->rows); + + + return(self); +} + + + +/** void *OSHash_Free(OSHash *self) + * Frees the memory used by the hash. + */ +void *OSHash_Free(OSHash *self) +{ + int i = 0; + OSHashNode *curr_node; + OSHashNode *next_node; + + + /* Freeing each entry */ + while(i <= self->rows) + { + curr_node = self->table[i]; + next_node = curr_node; + while(next_node) + { + next_node = next_node->next; + free(curr_node); + curr_node = next_node; + } + i++; + } + + + /* Freeing the hash table */ + free(self->table); + + free(self); + return(NULL); +} + + + +/** int _os_genhash(OSHash *self, char *key) + * Generates hash for key + */ +int _os_genhash(OSHash *self, char *key) +{ + unsigned int hash_key = self->initial_seed; + + /* What we have here is a simple polynomial hash. + * x0 * a^k-1 .. xk * a^k-k +1 + */ + while(*key) + { + hash_key *= self->constant; + hash_key += *key; + key++; + } + + return(hash_key); +} + + + +/** int OSHash_setSize(OSHash *self, int size) + * Sets new size for hash. + * Returns 0 on error (out of memory). + */ +int OSHash_setSize(OSHash *self, int new_size) +{ + int i = 0; + + /* We can't decrease the size */ + if(new_size <= self->rows) + { + return(1); + } + + + /* Getting next prime */ + self->rows = os_getprime(new_size); + if(self->rows == 0) + { + return(0); + } + + + /* If we fail, the hash should not be used anymore */ + self->table = realloc(self->table, (self->rows +1) * sizeof(OSHashNode *)); + if(!self->table) + { + return(0); + } + + + /* Zeroing our tables */ + for(i = 0; i <= self->rows; i++) + { + self->table[i] = NULL; + } + + + /* New seed */ + self->initial_seed = os_getprime(random() % self->rows); + self->constant = os_getprime(random() % self->rows); + + return(1); +} + + + +/** int OSHash_Add(OSHash *self, char *key, void *data) + * Returns 0 on error. + * Returns 1 on duplicated key (not added) + * Returns 2 on success + * Key must not be NULL. + */ +int OSHash_Add(OSHash *self, char *key, void *data) +{ + unsigned int hash_key; + unsigned int index; + + OSHashNode *curr_node; + OSHashNode *new_node; + + + /* Generating hash of the message */ + hash_key = _os_genhash(self, key); + + + /* Getting array index */ + index = hash_key % self->rows; + + + /* Checking for duplicated entries in the index */ + curr_node = self->table[index]; + while(curr_node) + { + /* Checking for duplicated key -- not adding */ + if(strcmp(curr_node->key, key) == 0) + { + /* Not adding */ + return(1); + } + curr_node = curr_node->next; + } + + + /* Creating new node */ + new_node = calloc(1, sizeof(OSHashNode)); + if(!new_node) + { + return(0); + } + new_node->next = NULL; + new_node->data = data; + new_node->key = key; + + + /* Adding to table */ + if(!self->table[index]) + { + self->table[index] = new_node; + } + /* If there is duplicated, add to the beginning */ + else + { + new_node->next = self->table[index]; + self->table[index] = new_node; + } + + return(2); +} + + + +/** void *OSHash_Get(OSHash *self, char *key) + * Returns NULL on error (key not found). + * Returns the key otherwise. + * Key must not be NULL. + */ +void *OSHash_Get(OSHash *self, char *key) +{ + unsigned int hash_key; + unsigned int index; + + OSHashNode *curr_node; + + + /* Generating hash of the message */ + hash_key = _os_genhash(self, key); + + + /* Getting array index */ + index = hash_key % self->rows; + + + /* Getting entry */ + curr_node = self->table[index]; + while(curr_node) + { + /* We may have colisions, so double check with strcmp */ + if(strcmp(curr_node->key, key) == 0) + { + return(curr_node->data); + } + + curr_node = curr_node->next; + } + + return(NULL); +} + + + +/* EOF */ diff --git a/src/shared/help.c b/src/shared/help.c new file mode 100755 index 0000000..6e141b8 --- /dev/null +++ b/src/shared/help.c @@ -0,0 +1,51 @@ +/* @(#) $Id: help.c,v 1.10 2009/11/18 19:07:42 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net/hids/ + */ + +/* Help Function + */ + + +#include "shared.h" + +void help(const char *prog) +{ + print_out(" "); + print_out("%s %s - %s (%s)", __name, __version, __author, __contact); + print_out("%s", __site); + print_out(" "); + print_out(" %s: -[Vhdt] [-u user] [-g group] [-c config] [-D dir]", prog); + print_out(" -V Version and license message"); + print_out(" -h This help message"); + print_out(" -d Execute in debug mode"); + print_out(" -t Test configuration"); + print_out(" -f Run in foreground"); + print_out(" -u Run as 'user'"); + print_out(" -g Run as 'group'"); + print_out(" -c Read the 'config' file"); + print_out(" -D Chroot to 'dir'"); + print_out(" "); + exit(1); +} + +void print_version() +{ + print_out(" "); + print_out("%s %s - %s", __name, __version, __author); + print_out(" "); + print_out("%s",__license); + exit(1); +} + +/* EOF */ diff --git a/src/shared/list_op.c b/src/shared/list_op.c new file mode 100755 index 0000000..e98b712 --- /dev/null +++ b/src/shared/list_op.c @@ -0,0 +1,332 @@ +/* @(#) $Id: list_op.c,v 1.17 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Common API for dealing with lists */ + + +#include "shared.h" + + +/* Create the list + * Return NULL on error + */ +OSList *OSList_Create() +{ + OSList *my_list; + + my_list = calloc(1, sizeof(OSList)); + if(!my_list) + return(NULL); + + my_list->first_node = NULL; + my_list->last_node = NULL; + my_list->cur_node = NULL; + my_list->currently_size = 0; + my_list->max_size = 0; + my_list->free_data_function = NULL; + + return(my_list); +} + + +/* Set the maximum number of elements + * in the list. Returns 0 on error or + * 1 on success. + */ +int OSList_SetMaxSize(OSList *list, int max_size) +{ + if(!list) + { + return(0); + } + + /* Minimum size is 1 */ + if(max_size <= 1) + { + return(0); + } + + list->max_size = max_size; + + return(1); +} + + +/* Set the pointer to the function to free the memory + * data. + */ +int OSList_SetFreeDataPointer(OSList *list, void *free_data_function) +{ + if(!list) + { + return(0); + } + + list->free_data_function = free_data_function; + return(1); +} + + +/* Get first node from list + * Returns null on invalid list + */ +OSListNode *OSList_GetFirstNode(OSList *list) +{ + list->cur_node = list->first_node; + return(list->first_node); +} + + +/* Get last node from list + * Returns null on invalid list + */ +OSListNode *OSList_GetLastNode(OSList *list) +{ + list->cur_node = list->last_node; + return(list->last_node); +} + + +/* Get next node from list + * Returns null on invalid list or at + * the end of the list + */ +OSListNode *OSList_GetNextNode(OSList *list) +{ + if(list->cur_node == NULL) + return(NULL); + + list->cur_node = list->cur_node->next; + + return(list->cur_node); +} + + +/* Get the prev node from the list + * Returns NULL at the beginning + */ +OSListNode *OSList_GetPrevNode(OSList *list) +{ + if(list->cur_node == NULL) + return(NULL); + + list->cur_node = list->cur_node->prev; + + return(list->cur_node); +} + + +/* Get the currently node. + * Returns null when no currently node is available + */ +OSListNode *OSList_GetCurrentlyNode(OSList *list) +{ + return(list->cur_node); +} + + +/* Delete first node from list */ +void OSList_DeleteOldestNode(OSList *list) +{ + OSListNode *next; + + if(list->first_node) + { + next = list->first_node->next; + if(next) + next->prev = NULL; + else + list->last_node = next; + + free(list->first_node); + list->first_node = next; + } + else + { + merror("%s: No Oldest node to delete", __local_name); + } + + return; +} + + +/* Delete this node from list + * Pointer goes to the next node available. + */ +void OSList_DeleteThisNode(OSList *list, OSListNode *thisnode) +{ + OSListNode *prev; + OSListNode *next; + + if(thisnode == NULL) + return; + + prev = thisnode->prev; + next = thisnode->next; + + /* Setting the previous node of the next one + * and the next node of the previous one.. :) + */ + if(prev && next) + { + prev->next = next; + next->prev = prev; + } + else if(prev) + { + prev->next = NULL; + list->last_node = prev; + } + else if(next) + { + next->prev = NULL; + list->first_node = next; + } + else + { + list->last_node = NULL; + list->first_node = NULL; + } + + + /* Freeing the node memory */ + free(thisnode); + + /* Setting the currently node to the next one */ + list->cur_node = next; + + list->currently_size--; +} + + +/* Delete currently node from list + * Pointer goes to the next node available. + * Returns void + */ +void OSList_DeleteCurrentlyNode(OSList *list) +{ + OSListNode *prev; + OSListNode *next; + + if(list->cur_node == NULL) + return; + + prev = list->cur_node->prev; + next = list->cur_node->next; + + + /* Setting the previous node of the next one + * and the next node of the previous one.. :) + */ + if(prev && next) + { + prev->next = next; + next->prev = prev; + } + else if(prev) + { + prev->next = NULL; + list->last_node = prev; + } + else if(next) + { + next->prev = NULL; + list->first_node = next; + } + else + { + list->last_node = NULL; + list->first_node = NULL; + } + + /* Freeing the node memory */ + free(list->cur_node); + + /* Setting the currently node to the next one */ + list->cur_node = next; + + list->currently_size--; +} + + +/* Add data to the list + * Returns 1 on success and 0 on failure + */ +int OSList_AddData(OSList *list, void *data) +{ + OSListNode *newnode; + + + /* Allocating memory for new node */ + newnode = calloc(1, sizeof(OSListNode)); + if(!newnode) + { + merror(MEM_ERROR, __local_name); + return(0); + } + + newnode->prev = list->last_node; + newnode->next = NULL; + newnode->data = data; + + + /* If we don't havea first node, assign it */ + if(!list->first_node) + { + list->first_node = newnode; + } + + /* If we have a last node, set the next to new node */ + if(list->last_node) + { + list->last_node->next = newnode; + } + + + /* newnode become last node */ + list->last_node = newnode; + + /* Increment list size */ + list->currently_size++; + + /* if currently_size higher than the maximum size, remove the + * oldest node (first one) + */ + if(list->max_size) + { + if(list->currently_size > list->max_size) + { + /* Remove first node */ + newnode = list->first_node->next; + + newnode->prev = NULL; + + /* Clearing any internal memory using the pointer */ + if(list->free_data_function) + { + list->free_data_function(list->first_node->data); + } + + /* Clearing the memory */ + free(list->first_node); + + /* First node become the ex first->next */ + list->first_node = newnode; + + /* Reduce list size */ + list->currently_size--; + } + } + + return(1); +} + +/* EOF */ diff --git a/src/shared/math_op.c b/src/shared/math_op.c new file mode 100755 index 0000000..3130013 --- /dev/null +++ b/src/shared/math_op.c @@ -0,0 +1,63 @@ +/* @(#) $Id: math_op.c,v 1.3 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" + + +/** int os_getprime + * Get the first available prime after the provided value. + * Returns 0 on error. + */ +int os_getprime(int val) +{ + int i; + int max_i; + + /* Value can't be even */ + if((val % 2) == 0) + { + val++; + } + + + do + { + /* We just need to check odd numbers up until half + * the size of the provided value. + */ + i = 3; + max_i = val/2; + while(i <= max_i) + { + /* Not prime */ + if((val % i) == 0) + { + break; + } + i += 2; + } + + /* Prime */ + if(i >= max_i) + { + return(val); + } + }while(val += 2); + + return(0); +} + + +/* EOF */ diff --git a/src/shared/mem_op.c b/src/shared/mem_op.c new file mode 100755 index 0000000..b58385d --- /dev/null +++ b/src/shared/mem_op.c @@ -0,0 +1,123 @@ +/* @(#) $Id: mem_op.c,v 1.7 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "mem_op.h" + + +/* Check if String is on array (Must be NULL terminated) */ +int os_IsStrOnArray(char *str, char **array) +{ + if(!str || !array) + { + return(0); + } + + while(*array) + { + if(strcmp(*array, str) == 0) + { + return(1); + } + array++; + } + return(0); +} + + +/* Clear the memory of one char and one char** */ +void os_FreeArray(char *ch1, char **ch2) +{ + /* Cleaning char * */ + if(ch1) + { + free(ch1); + ch1 = NULL; + } + + /* Cleaning chat ** */ + if(ch2) + { + char **nch2 = ch2; + + while(*ch2 != NULL) + { + free(*ch2); + ch2++; + } + + free(nch2); + nch2 = NULL; + } + + return; +} + + +/* os_LoadString: v0.1 + * Allocate memory at "*at" and copy *str to it. + * If *at already exist, realloc the memory and strcat str + * on it. + * It will return the new string on success or NULL on memory error. + */ +char *os_LoadString(char *at, char *str) +{ + if(at == NULL) + { + int strsize = 0; + if((strsize = strlen(str)) < OS_SIZE_2048) + { + at = calloc(strsize+1,sizeof(char)); + if(at == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + strncpy(at, str, strsize); + return(at); + } + else + { + merror(SIZE_ERROR,ARGV0,str); + return(NULL); + } + } + else /*at is not null. Need to reallocat its memory and copy str to it*/ + { + int strsize = strlen(str); + int atsize = strlen(at); + int finalsize = atsize+strsize+1; + + if((atsize > OS_SIZE_2048) || (strsize > OS_SIZE_2048)) + { + merror(SIZE_ERROR,ARGV0,str); + return(NULL); + } + + at = realloc(at, (finalsize)*sizeof(char)); + + if(at == NULL) + { + merror(MEM_ERROR,ARGV0); + return(NULL); + } + + strncat(at,str,strsize); + + at[finalsize-1] = '\0'; + + return(at); + } + return(NULL); +} + + +/* EOF */ diff --git a/src/shared/mq_op.c b/src/shared/mq_op.c new file mode 100755 index 0000000..c7f124b --- /dev/null +++ b/src/shared/mq_op.c @@ -0,0 +1,176 @@ +/* @(#) $Id: mq_op.c,v 1.25 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "os_net/os_net.h" + + +#ifndef WIN32 + +/* StartMQ v0.2, 2004/07/30 + * Start the Message Queue. type: WRITE||READ + */ +int StartMQ(char * path, short int type) +{ + + if(type == READ) + { + return(OS_BindUnixDomain(path, 0660, OS_MAXSTR + 512)); + } + + /* We give up to 21 seconds for the other end to + * start + */ + else + { + int rc = 0; + if(File_DateofChange(path) < 0) + { + sleep(1); + if(File_DateofChange(path) < 0) + { + sleep(5); + if(File_DateofChange(path) < 0) + { + merror(QUEUE_ERROR, __local_name, path, "Queue not found"); + sleep(15); + if(File_DateofChange(path) < 0) + { + return(-1); + } + } + } + } + + /* Wait up to 3 seconds to connect to the unix domain. + * After three errors, exit. + */ + if((rc = OS_ConnectUnixDomain(path, OS_MAXSTR + 256)) < 0) + { + sleep(1); + if((rc = OS_ConnectUnixDomain(path, OS_MAXSTR + 256)) < 0) + { + sleep(2); + if((rc = OS_ConnectUnixDomain(path, OS_MAXSTR + 256)) < 0) + { + merror(QUEUE_ERROR, __local_name, path, + strerror(errno)); + return(-1); + } + } + } + + debug1(MSG_SOCKET_SIZE, __local_name, OS_getsocketsize(rc)); + return(rc); + } +} + + +/* SendMSG v0.1, 2005/02/15 + * Send a message to the queue. + */ +int SendMSG(int queue, char *message, char *locmsg, char loc) +{ + int __mq_rcode; + char tmpstr[OS_MAXSTR+1]; + + tmpstr[OS_MAXSTR] = '\0'; + + + /* Checking for global locks */ + os_wait(); + + + if(loc == SECURE_MQ) + { + loc = message[0]; + message++; + + if(message[0] != ':') + { + merror(FORMAT_ERROR, __local_name); + return(0); + } + + message++; /* Pointing now to the location */ + + snprintf(tmpstr,OS_MAXSTR,"%c:%s->%s",loc, locmsg, message); + } + else + snprintf(tmpstr,OS_MAXSTR,"%c:%s:%s",loc,locmsg,message); + + + /* queue not available */ + if(queue < 0) + return(-1); + + + /* We attempt 5 times to send the message if + * the receiver socket is busy. + * After the first error, we wait 1 second. + * After the second error, we wait more 3 seconds. + * After the third error, we wait 5 seconds. + * After the fourth error, we wait 10 seconds. + * If we failed again, the message is not going + * to be delivered and an error is sent back. + */ + if((__mq_rcode = OS_SendUnix(queue, tmpstr,0)) < 0) + { + /* Error on the socket */ + if(__mq_rcode == OS_SOCKTERR) + { + merror("%s: socketerr (not available).", __local_name); + close(queue); + queue = -1; + return(-1); + } + + + /* Unable to send. Socket busy */ + sleep(1); + if(OS_SendUnix(queue, tmpstr, 0) < 0) + { + /* When the socket is to busy, we may get some + * error here. Just sleep 2 second and try + * again. + */ + sleep(3); + /* merror("%s: socket busy", __local_name); */ + if(OS_SendUnix(queue, tmpstr,0) < 0) + { + sleep(5); + merror("%s: socket busy ..", __local_name); + if(OS_SendUnix(queue, tmpstr,0) < 0) + { + sleep(10); + merror("%s: socket busy ..", __local_name); + if(OS_SendUnix(queue, tmpstr,0) < 0) + { + /* Message is going to be lost + * if the application does not care + * about checking the error + */ + close(queue); + queue = -1; + return(-1); + } + } + } + } + } + + return(0); +} + +#endif + +/* EOF */ diff --git a/src/shared/privsep_op.c b/src/shared/privsep_op.c new file mode 100755 index 0000000..58fe566 --- /dev/null +++ b/src/shared/privsep_op.c @@ -0,0 +1,102 @@ +/* $OSSEC, privsep_op.h, v0.2, 2004/08/05, Daniel B. Cid$ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC HIDS + * Available at http://www.ossec.net + */ + +/* Functions for privilege separation. + */ + +#ifndef WIN32 + +#include +#include +#include +#include +#include + +#include "headers/os_err.h" + +int Privsep_GetUser(char * name) +{ + int os_uid = -1; + + struct passwd *pw; + pw = getpwnam(name); + if(pw == NULL) + return(OS_INVALID); + + os_uid = (int)pw->pw_uid; + endpwent(); + + return(os_uid); +} + +int Privsep_GetGroup(char * name) +{ + int os_gid = -1; + + struct group *grp; + grp = getgrnam(name); + if(grp == NULL) + return(OS_INVALID); + + os_gid = (int)grp->gr_gid; + endgrent(); + + return(os_gid); +} + +int Privsep_SetUser(uid_t uid) +{ + if(setuid(uid) < 0) + return(OS_INVALID); + + #ifndef HPUX + if(seteuid(uid) < 0) + return(OS_INVALID); + #endif + + return(OS_SUCCESS); +} + +int Privsep_SetGroup(gid_t gid) +{ + if (setgroups(1, &gid) == -1) + return(OS_INVALID); + + #ifndef HPUX + if(setegid(gid) < 0) + return(OS_INVALID); + #endif + + if(setgid(gid) < 0) + return(OS_INVALID); + + return(OS_SUCCESS); +} + +int Privsep_Chroot(char * path) +{ + if(chdir(path) < 0) + return(OS_INVALID); + + if(chroot(path) < 0) + return(OS_INVALID); + + chdir("/"); + + return(OS_SUCCESS); +} + +#endif +/* EOF */ diff --git a/src/shared/pthreads_op.c b/src/shared/pthreads_op.c new file mode 100755 index 0000000..0262110 --- /dev/null +++ b/src/shared/pthreads_op.c @@ -0,0 +1,45 @@ +/* @(#) $Id: pthreads_op.c,v 1.8 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef WIN32 +#include "shared.h" +#include + + + +/* CreateThread(void v0.1 + * Creates a new thread and gives the argument passed to the function + * Return 0 on success or -1 on error + */ +int CreateThread(void *function_pointer(void *data), void *data) +{ + pthread_t lthread; + int ret = 0; + + ret = pthread_create(<hread, NULL, function_pointer, (void*)data); + if(ret != 0) + { + merror(THREAD_ERROR, __local_name); + return (-1); + } + + if(pthread_detach(lthread) != 0) + { + merror(THREAD_ERROR, __local_name); + return(-1); + } + + return(0); +} + +#endif +/* EOF */ diff --git a/src/shared/read-agents.c b/src/shared/read-agents.c new file mode 100755 index 0000000..c3323a2 --- /dev/null +++ b/src/shared/read-agents.c @@ -0,0 +1,1473 @@ +/* @(#) $Id: read-agents.c,v 1.19 2009/08/19 18:35:57 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#include "shared.h" +#include "read-agents.h" +#include "os_net/os_net.h" + + +/* Free the agent list in memory + */ +void free_agents(char **agent_list) +{ + int i; + if(!agent_list) + return; + + for(i = 0;;i++) + { + if(agent_list[i] == NULL) + break; + + free(agent_list[i]); + agent_list[i] = NULL; + } + + free(agent_list); + agent_list = NULL; +} + + +#ifndef WIN32 + +/* Print syscheck attributes. */ +#define sk_strchr(x,y,z) z = strchr(x, y); if(z == NULL) return(0); else { *z = '\0'; z++; } +int _do_print_attrs_syscheck(char *prev_attrs, char *attrs, int csv_output, + int is_win, int number_of_changes) +{ + char *p_size, *p_perm, *p_uid, *p_gid, *p_md5, *p_sha1; + char *size, *perm, *uid, *gid, *md5, *sha1; + int perm_int; + char perm_str[36]; + + + /* Setting each value. */ + size = attrs; + sk_strchr(size, ':', perm); + sk_strchr(perm, ':', uid); + sk_strchr(uid, ':', gid); + sk_strchr(gid, ':', md5); + sk_strchr(md5, ':', sha1); + + if(strcmp(attrs, "-1") == 0) + { + printf("File deleted. "); + return(0); + } + else if(prev_attrs && (strcmp(prev_attrs, "-1") == 0)) + { + printf("File restored. "); + } + else if(prev_attrs) + { + printf("File changed. "); + p_size = prev_attrs; + sk_strchr(p_size, ':', p_perm); + sk_strchr(p_perm, ':', p_uid); + sk_strchr(p_uid, ':', p_gid); + sk_strchr(p_gid, ':', p_md5); + sk_strchr(p_md5, ':', p_sha1); + } + else + { + p_size = size; + p_perm = perm; + p_uid = uid; + p_gid = gid; + p_md5 = md5; + p_sha1 = sha1; + printf("File added to the database. "); + } + + + /* Fixing number of changes. */ + if(prev_attrs && !number_of_changes) + { + number_of_changes = 1; + } + + + if(number_of_changes) + { + switch(number_of_changes) + { + case 1: + printf("- 1st time modified.\n"); + break; + case 2: + printf("- 2nd time modified.\n"); + break; + case 3: + printf("- 3rd time modified.\n"); + break; + default: + printf("- Being ignored (3 or more changes).\n"); + } + } + else + { + printf("\n"); + } + + + perm_str[35] = '\0'; + perm_int = atoi(perm); + snprintf(perm_str, 35, + "%c%c%c%c%c%c%c%c%c", + (perm_int & S_IRUSR)? 'r' : '-', + (perm_int & S_IWUSR)? 'w' : '-', + + (perm_int & S_ISUID)? 's' : + (perm_int & S_IXUSR)? 'x' : '-', + + + (perm_int & S_IRGRP)? 'r' : '-', + (perm_int & S_IWGRP)? 'w' : '-', + + (perm_int & S_ISGID)? 's' : + (perm_int & S_IXGRP)? 'x' : '-', + + + (perm_int & S_IROTH)? 'r' : '-', + (perm_int & S_IWOTH)? 'w' : '-', + (perm_int & S_ISVTX)? 't' : + (perm_int & S_IXOTH)? 'x' : '-'); + + + printf("Integrity checking values:\n"); + printf(" Size:%s%s\n", (strcmp(size,p_size) == 0)? " ": " >", size); + if(!is_win) + { + printf(" Perm:%s%s\n", (strcmp(perm,p_perm) == 0)? " ": " >", perm_str); + printf(" Uid: %s%s\n", (strcmp(uid,p_uid) == 0)? " ": " >", uid); + printf(" Gid: %s%s\n", (strcmp(gid,p_gid) == 0)? " ": " >", gid); + } + printf(" Md5: %s%s\n", (strcmp(md5,p_md5) == 0)? " ": " >", md5); + printf(" Sha1:%s%s\n", (strcmp(sha1,p_sha1) == 0)? " ": " >", sha1); + + + /* Fixing entries. */ + perm[-1] = ':'; + uid[-1] = ':'; + gid[-1] = ':'; + md5[-1] = ':'; + sha1[-1] = ':'; + + return(0); +} + + + +/* Print information about a specific file. */ +int _do_print_file_syscheck(FILE *fp, char *fname, + int update_counter, int csv_output) +{ + int f_found = 0; + struct tm *tm_time; + + char read_day[24 +1]; + char buf[OS_MAXSTR + 1]; + + OSMatch reg; + OSStore *files_list; + + fpos_t init_pos; + + buf[OS_MAXSTR] = '\0'; + read_day[24] = '\0'; + + + /* If the compilation failed, we don't need to free anything */ + if(!OSMatch_Compile(fname, ®, 0)) + { + printf("\n** ERROR: Invalid file name: '%s'\n", fname); + return(0); + } + + + /* Creating list with files. */ + files_list = OSStore_Create(); + if(!files_list) + { + OSMatch_FreePattern(®); + return(0); + } + + + /* Getting initial position. */ + if(fgetpos(fp, &init_pos) != 0) + { + printf("\n** ERROR: fgetpos failed.\n"); + return(0); + } + + + while(fgets(buf, OS_MAXSTR, fp) != NULL) + { + if(buf[0] == '!' || buf[0] == '#') + { + int number_changes = 0; + time_t change_time = 0; + char *changed_file_name; + char *changed_attrs; + char *prev_attrs; + + + if(strlen(buf) < 16) + { + fgetpos(fp, &init_pos); + continue; + } + + /* Removing new line. */ + buf[strlen(buf) -1] = '\0'; + + + /* with update counter, we only modify the last entry. */ + if(update_counter && buf[0] == '#') + { + fgetpos(fp, &init_pos); + continue; + } + + + /* Checking number of changes. */ + if(buf[1] == '!') + { + number_changes = 2; + if(buf[2] == '!') + { + number_changes = 3; + } + else if(buf[2] == '?') + { + number_changes = 4; + } + } + + changed_attrs = buf + 3; + + + changed_file_name = strchr(changed_attrs, '!'); + if(!changed_file_name) + { + fgetpos(fp, &init_pos); + continue; + } + + + /* Getting time of change. */ + changed_file_name[-1] = '\0'; + changed_file_name++; + change_time = (time_t)atoi(changed_file_name); + + changed_file_name = strchr(changed_file_name, ' '); + changed_file_name++; + + + /* Checking if the name should be printed. */ + if(!OSMatch_Execute(changed_file_name, strlen(changed_file_name), + ®)) + { + fgetpos(fp, &init_pos); + continue; + } + + + f_found = 1; + + + /* Reset the values. */ + if(update_counter) + { + if(fsetpos(fp, &init_pos) != 0) + { + printf("\n** ERROR: fsetpos failed (unable to update " + "counter).\n"); + return(0); + } + + if(update_counter == 2) + { + if(fprintf(fp, "!!?") <= 0) + { + printf("\n** ERROR: fputs failed (unable to update " + "counter).\n"); + return(0); + } + } + + else + { + if(fprintf(fp, "!++") <= 0) + { + printf("\n** ERROR: fputs failed (unable to update " + "counter).\n"); + return(0); + } + } + + printf("\n**Counter updated for file '%s'\n\n", + changed_file_name); + return(0); + } + + + tm_time = localtime(&change_time); + strftime(read_day, 23, "%Y %h %d %T", tm_time); + + if(!csv_output) + printf("\n%s,%d - %s\n", read_day, number_changes, + changed_file_name); + else + printf("%s,%s,%d\n", read_day, changed_file_name, + number_changes); + + + prev_attrs = OSStore_Get(files_list, changed_file_name); + if(prev_attrs) + { + char *new_attrs; + os_strdup(changed_attrs, new_attrs); + _do_print_attrs_syscheck(prev_attrs, changed_attrs, + csv_output, + changed_file_name[0] == '/'?0:1, + number_changes); + + free(files_list->cur_node->data); + files_list->cur_node->data = new_attrs; + } + else + { + char *new_name; + char *new_attrs; + + os_strdup(changed_attrs, new_attrs); + os_strdup(changed_file_name, new_name); + OSStore_Put(files_list, new_name, new_attrs); + _do_print_attrs_syscheck(NULL, + changed_attrs, csv_output, + changed_file_name[0] == '/'?0:1, + number_changes); + } + + fgetpos(fp, &init_pos); + } + } + + if(!f_found) + { + printf("\n** No entries found.\n"); + } + OSMatch_FreePattern(®); + + return(0); +} + + + +/* Print syscheck db (of modified files. */ +int _do_print_syscheck(FILE *fp, int all_files, int csv_output) +{ + int f_found = 0; + struct tm *tm_time; + + char read_day[24 +1]; + char saved_read_day[24 +1]; + char buf[OS_MAXSTR + 1]; + + buf[OS_MAXSTR] = '\0'; + read_day[24] = '\0'; + saved_read_day[0] = '\0'; + saved_read_day[24] = '\0'; + + while(fgets(buf, OS_MAXSTR, fp) != NULL) + { + if(buf[0] == '!' || buf[0] == '#') + { + int number_changes = 0; + time_t change_time = 0; + char *changed_file_name; + + + if(strlen(buf) < 16) + continue; + + /* Removing new line. */ + buf[strlen(buf) -1] = '\0'; + + + /* Checking number of changes. */ + if(buf[1] == '!') + { + number_changes = 2; + if(buf[2] == '!') + { + number_changes = 3; + } + else if(buf[2] == '?') + { + number_changes = 4; + } + } + + + changed_file_name = strchr(buf +3, '!'); + if(!changed_file_name) + continue; + + + f_found = 1; + + + /* Getting time of change. */ + changed_file_name++; + change_time = atoi(changed_file_name); + + changed_file_name = strchr(changed_file_name, ' '); + changed_file_name++; + + tm_time = localtime(&change_time); + strftime(read_day, 23, "%Y %h %d", tm_time); + if(strcmp(read_day, saved_read_day) != 0) + { + if(!csv_output) + printf("\nChanges for %s:\n", read_day); + strncpy(saved_read_day, read_day, 23); + } + strftime(read_day, 23, "%Y %h %d %T", tm_time); + + if(!csv_output) + printf("%s,%d - %s\n", read_day, number_changes, + changed_file_name); + else + printf("%s,%s,%d\n", read_day, changed_file_name, + number_changes); + } + } + + if(!f_found && !csv_output) + { + printf("\n** No entries found.\n"); + } + + return(0); +} + + +/* Print syscheck db (of modified files. */ +int print_syscheck(char *sk_name, char *sk_ip, char *fname, int print_registry, + int all_files, int csv_output, int update_counter) +{ + FILE *fp; + char tmp_file[513]; + + tmp_file[512] = '\0'; + + + if(sk_name == NULL) + { + /* Printing database */ + snprintf(tmp_file, 512, "%s/syscheck", + SYSCHECK_DIR); + + fp = fopen(tmp_file, "r+"); + } + + else if(sk_ip == NULL) + { + /* Printing database */ + snprintf(tmp_file, 512, "%s/%s->syscheck",SYSCHECK_DIR, sk_name); + + fp = fopen(tmp_file, "r+"); + } + + else if(!print_registry) + { + /* Printing database */ + snprintf(tmp_file, 512, "%s/(%s) %s->syscheck", + SYSCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "r+"); + } + + else + { + /* Printing database for the windows registry. */ + snprintf(tmp_file, 512, "%s/(%s) %s->syscheck-registry", + SYSCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "r+"); + } + + + if(fp) + { + if(!fname) + { + _do_print_syscheck(fp, all_files, csv_output); + } + else + { + _do_print_file_syscheck(fp, fname, update_counter, csv_output); + } + fclose(fp); + } + + return(0); +} + + + +int _do_get_rootcheckscan(FILE *fp) +{ + char *tmp_str; + char buf[OS_MAXSTR + 1]; + + while(fgets(buf, OS_MAXSTR, fp) != NULL) + { + tmp_str = strstr(buf, "Starting rootcheck scan"); + if(tmp_str) + { + time_t s_time = 0; + tmp_str = buf + 1; + + s_time = (time_t)atoi(tmp_str); + + return((int)s_time); + } + } + + return((int)time(NULL)); +} + + + +/* Print syscheck db (of modified files. */ +int _do_print_rootcheck(FILE *fp, int resolved, int time_last_scan, + int csv_output, int show_last) +{ + int i = 0; + int f_found = 0; + + /* Current time. */ + time_t c_time; + + /* Time from the message. */ + time_t s_time = 0; + time_t i_time = 0; + struct tm *tm_time; + + char old_day[24 +1]; + char read_day[24 +1]; + char buf[OS_MAXSTR + 1]; + char *tmp_str; + + + char *(ig_events[]) = {"Starting rootcheck scan", + "Ending rootcheck scan", + "Starting syscheck scan", + "Ending syscheck scan", + NULL}; + + char *(ns_events[]) = {"Application Found:", + "Windows Audit:", + "Windows Malware:", + NULL}; + + + buf[OS_MAXSTR] = '\0'; + old_day[24] = '\0'; + read_day[24] = '\0'; + + + c_time = time(0); + fseek(fp, 0, SEEK_SET); + + + if(!csv_output) + { + if(show_last) + { + tm_time = localtime((time_t *)&time_last_scan); + strftime(read_day, 23, "%Y %h %d %T", tm_time); + + printf("\nLast scan: %s\n\n", read_day); + } + else if(resolved) + printf("\nResolved events: \n\n"); + else + printf("\nOutstanding events: \n\n"); + } + + + while(fgets(buf, OS_MAXSTR, fp) != NULL) + { + /* Removing first ! */ + tmp_str = buf + 1; + s_time = (time_t)atoi(tmp_str); + + + /* Removing new line. */ + tmp_str = strchr(buf, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + + /* Getting initial time. */ + tmp_str = strchr(buf + 1, '!'); + if(!tmp_str) + continue; + tmp_str++; + + i_time = (time_t)atoi(tmp_str); + + + /* Getting the actual message. */ + tmp_str = strchr(tmp_str, ' '); + if(!tmp_str) + continue; + tmp_str++; + + + + /* Checking for resolved. */ + if(time_last_scan > (s_time + 86400)) + { + if(!resolved) + { + continue; + } + } + else + { + if(resolved) + { + continue; + } + } + + + /* Checking events to ignore. */ + i = 0; + while(ig_events[i]) + { + if(strncmp(tmp_str, ig_events[i], strlen(ig_events[i]) -1) == 0) + break; + i++; + } + if(ig_events[i]) + continue; + + + /* Checking events that are not system audit. */ + i = 0; + while(ns_events[i]) + { + if(strncmp(tmp_str, ns_events[i], strlen(ns_events[i]) -1) == 0) + break; + i++; + } + + + tm_time = localtime((time_t *)&s_time); + strftime(read_day, 23, "%Y %h %d %T", tm_time); + tm_time = localtime((time_t *)&i_time); + strftime(old_day, 23, "%Y %h %d %T", tm_time); + + + if(!csv_output) + { + if(!show_last) + printf("%s (first time detected: %s)\n", read_day, old_day); + + if(ns_events[i]) + { + printf("%s\n\n", tmp_str); + } + else + { + printf("System Audit: %s\n\n", tmp_str); + } + } + else + { + printf("%s,%s,%s,%s%s\n", resolved == 0?"outstanding":"resolved", + read_day, old_day, + ns_events[i] != NULL?"":"System Audit: ", + tmp_str); + } + + + + f_found++; + } + + if(!f_found && !csv_output) + { + printf("** No entries found.\n"); + } + + return(0); +} + + + +/* Print rootcheck db */ +int print_rootcheck(char *sk_name, char *sk_ip, char *fname, int resolved, + int csv_output, int show_last) +{ + int ltime = 0; + FILE *fp; + char tmp_file[513]; + + tmp_file[512] = '\0'; + + + if(sk_name == NULL) + { + /* Printing database */ + snprintf(tmp_file, 512, "%s/rootcheck", + ROOTCHECK_DIR); + + fp = fopen(tmp_file, "r+"); + } + + else + { + /* Printing database */ + snprintf(tmp_file, 512, "%s/(%s) %s->rootcheck", + ROOTCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "r+"); + } + + + if(fp) + { + /* Getting last time of scan. */ + ltime = _do_get_rootcheckscan(fp); + if(!fname) + { + if(resolved == 1) + { + _do_print_rootcheck(fp, 1, ltime, csv_output, 0); + } + else if(resolved == 2) + { + _do_print_rootcheck(fp, 0, ltime, csv_output, show_last); + } + else + { + _do_print_rootcheck(fp, 1, ltime, csv_output, 0); + _do_print_rootcheck(fp, 0, ltime, csv_output, show_last); + } + } + else + { + } + fclose(fp); + } + + return(0); +} + +#endif + + +/* Delete syscheck db */ +int delete_syscheck(char *sk_name, char *sk_ip, int full_delete) +{ + FILE *fp; + char tmp_file[513]; + + tmp_file[512] = '\0'; + + /* Deleting related files */ + snprintf(tmp_file, 512, "%s/(%s) %s->syscheck", + SYSCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "w"); + if(fp) + fclose(fp); + + if(full_delete) + unlink(tmp_file); + + + /* Deleting cpt files */ + snprintf(tmp_file, 512, "%s/.(%s) %s->syscheck.cpt", + SYSCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "w"); + if(fp) + fclose(fp); + unlink(tmp_file); + + + /* Deleting registry entries */ + snprintf(tmp_file, 512, "%s/(%s) %s->syscheck-registry", + SYSCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "w"); + if(fp) + fclose(fp); + if(full_delete) + unlink(tmp_file); + + + /* Deleting cpt files */ + snprintf(tmp_file, 512, "%s/.(%s) %s->syscheck-registry.cpt", + SYSCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "w"); + if(fp) + fclose(fp); + unlink(tmp_file); + + return(1); +} + + + +/* Delete rootcheck db */ +int delete_rootcheck(char *sk_name, char *sk_ip, int full_delete) +{ + FILE *fp; + char tmp_file[513]; + + tmp_file[512] = '\0'; + + /* Deleting related files */ + snprintf(tmp_file, 512, "%s/(%s) %s->rootcheck", + ROOTCHECK_DIR, + sk_name, + sk_ip); + + fp = fopen(tmp_file, "w"); + if(fp) + fclose(fp); + + if(full_delete) + unlink(tmp_file); + + + return(1); +} + + + +/* Delete agent. + */ +int delete_agentinfo(char *name) +{ + char *sk_name; + char *sk_ip; + char tmp_file[513]; + + tmp_file[512] = '\0'; + + + /* Deleting agent info */ + snprintf(tmp_file, 512, "%s/%s", AGENTINFO_DIR, name); + unlink(tmp_file); + + + /* Deleting syscheck */ + sk_name = name; + sk_ip = strrchr(name, '-'); + if(!sk_ip) + return(0); + + *sk_ip = '\0'; + sk_ip++; + + + /* Deleting syscheck */ + delete_syscheck(sk_name, sk_ip, 1); + + return(1); +} + + + +/** char *print_agent_status(int status) + * Prints the text representation of the agent status. + */ +char *print_agent_status(int status) +{ + char *status_str = "Never connected"; + + if(status == GA_STATUS_ACTIVE) + { + status_str = "Active"; + } + else if(status == GA_STATUS_NACTIVE) + { + status_str = "Disconnected"; + } + + return(status_str); +} + + +/* non-windows functions from now on. */ +#ifndef WIN32 + + +/** int send_msg_to_agent(int socket, char *msg) + * Sends a message to an agent. + * returns -1 on error. + */ +int send_msg_to_agent(int msocket, char *msg, char *agt_id, char *exec) +{ + int rc; + char agt_msg[OS_SIZE_1024 +1]; + + agt_msg[OS_SIZE_1024] = '\0'; + + + if(!exec) + { + snprintf(agt_msg, OS_SIZE_1024, + "%s %c%c%c %s %s", + "(msg_to_agent) []", + (agt_id == NULL)?ALL_AGENTS_C:NONE_C, + NO_AR_C, + (agt_id != NULL)?SPECIFIC_AGENT_C:NONE_C, + agt_id != NULL? agt_id: "(null)", + msg); + } + else + { + snprintf(agt_msg, OS_SIZE_1024, + "%s %c%c%c %s %s - %s (from_the_server) (no_rule_id)", + "(msg_to_agent) []", + (agt_id == NULL)?ALL_AGENTS_C:NONE_C, + NONE_C, + (agt_id != NULL)?SPECIFIC_AGENT_C:NONE_C, + agt_id != NULL? agt_id: "(null)", + msg, exec); + + } + + + if((rc = OS_SendUnix(msocket, agt_msg, 0)) < 0) + { + if(rc == OS_SOCKBUSY) + { + merror("%s: ERROR: Remoted socket busy.", __local_name); + } + else + { + merror("%s: ERROR: Remoted socket error.", __local_name); + } + merror("%s: Error communicating with remoted queue (%d).", + __local_name, rc); + + return(-1); + } + + return(0); +} + + + +/** int connect_to_remoted() + * Connects to remoted to be able to send messages to the agents. + * Returns the socket on success or -1 on failure. + */ +int connect_to_remoted() +{ + int arq = -1; + + if((arq = StartMQ(ARQUEUE, WRITE)) < 0) + { + merror(ARQ_ERROR, __local_name); + return(-1); + } + + return(arq); +} + + +#endif + + +/* Internal funtion. Extract last time of scan from rootcheck/syscheck. */ +int _get_time_rkscan(char *agent_name, char *agent_ip, agent_info *agt_info) +{ + FILE *fp; + char buf[1024 +1]; + + + /* Agent name of null, means it is the server info. */ + if(agent_name == NULL) + { + snprintf(buf, 1024, "%s/rootcheck", + ROOTCHECK_DIR); + } + else + { + snprintf(buf, 1024, "%s/(%s) %s->rootcheck", + ROOTCHECK_DIR, agent_name, agent_ip); + } + + + /* If file is not there, set to unknown. */ + fp = fopen(buf, "r"); + if(!fp) + { + os_strdup("Unknown", agt_info->rootcheck_time); + os_strdup("Unknown", agt_info->rootcheck_endtime); + os_strdup("Unknown", agt_info->syscheck_time); + os_strdup("Unknown", agt_info->syscheck_endtime); + return(0); + } + + + while(fgets(buf, 1024, fp) != NULL) + { + char *tmp_str = NULL; + + /* Removing new line. */ + tmp_str = strchr(buf, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + + tmp_str = strstr(buf, "Starting syscheck scan"); + if(tmp_str) + { + time_t s_time = 0; + tmp_str = buf + 1; + + s_time = (time_t)atoi(tmp_str); + + os_strdup(ctime(&s_time), agt_info->syscheck_time); + + /* Removing new line. */ + tmp_str = strchr(agt_info->syscheck_time, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + continue; + } + + tmp_str = strstr(buf, "Ending syscheck scan"); + if(tmp_str) + { + time_t s_time = 0; + tmp_str = buf + 1; + + s_time = (time_t)atoi(tmp_str); + + os_strdup(ctime(&s_time), agt_info->syscheck_endtime); + + /* Removing new line. */ + tmp_str = strchr(agt_info->syscheck_endtime, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + continue; + } + + + tmp_str = strstr(buf, "Starting rootcheck scan"); + if(tmp_str) + { + time_t s_time = 0; + tmp_str = buf + 1; + + s_time = (time_t)atoi(tmp_str); + + os_strdup(ctime(&s_time), agt_info->rootcheck_time); + + /* Removing new line. */ + tmp_str = strchr(agt_info->rootcheck_time, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + continue; + } + + tmp_str = strstr(buf, "Ending rootcheck scan"); + if(tmp_str) + { + time_t s_time = 0; + tmp_str = buf + 1; + + s_time = (time_t)atoi(tmp_str); + + os_strdup(ctime(&s_time), agt_info->rootcheck_endtime); + + /* Removing new line. */ + tmp_str = strchr(agt_info->rootcheck_endtime, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + continue; + } + } + + + /* Setting unknown values. */ + if(!agt_info->rootcheck_time) + os_strdup("Unknown", agt_info->rootcheck_time); + if(!agt_info->rootcheck_endtime) + os_strdup("Unknown", agt_info->rootcheck_endtime); + if(!agt_info->syscheck_time) + os_strdup("Unknown", agt_info->syscheck_time); + if(!agt_info->syscheck_endtime) + os_strdup("Unknown", agt_info->syscheck_endtime); + + fclose(fp); + return(0); +} + + + +/* Internal funtion. Extract last time of scan from rootcheck/syscheck. */ +char *_get_agent_keepalive(char *agent_name, char *agent_ip) +{ + char buf[1024 +1]; + struct stat file_status; + + + /* No keep alive for the server. */ + if(!agent_name) + { + return(strdup("Not available")); + } + + snprintf(buf, 1024, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip); + if(stat(buf, &file_status) < 0) + { + return(strdup("Unknown")); + } + + + return(strdup(ctime(&file_status.st_mtime))); +} + + + +/* Internal funtion. Extracts operating system. */ +int _get_agent_os(char *agent_name, char *agent_ip, agent_info *agt_info) +{ + FILE *fp; + char buf[1024 +1]; + + + /* Getting server info. */ + if(!agent_name) + { + char *ossec_version = NULL; + agt_info->os = getuname(); + os_strdup(__name " " __version, agt_info->version); + + + /* Removing new line. */ + ossec_version = strchr(agt_info->os, '\n'); + if(ossec_version) + *ossec_version = '\0'; + + + ossec_version = strstr(agt_info->os, " - "); + if(ossec_version) + { + *ossec_version = '\0'; + } + + + if(strlen(agt_info->os) > 55) + { + agt_info->os[52] = '.'; + agt_info->os[53] = '.'; + agt_info->os[54] = '\0'; + } + + + return(0); + } + + + snprintf(buf, 1024, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip); + fp = fopen(buf, "r"); + if(!fp) + { + os_strdup("Unknown", agt_info->os); + os_strdup("Unknown", agt_info->version); + return(0); + } + + + if(fgets(buf, 1024, fp)) + { + char *ossec_version = NULL; + + /* Removing new line. */ + ossec_version = strchr(buf, '\n'); + if(ossec_version) + *ossec_version = '\0'; + + + ossec_version = strstr(buf, " - "); + if(ossec_version) + { + *ossec_version = '\0'; + ossec_version += 3; + + os_calloc(1024 +1, sizeof(char), agt_info->version); + strncpy(agt_info->version, ossec_version, 1024); + } + + + if(strlen(buf) > 55) + { + buf[52] = '.'; + buf[53] = '.'; + buf[54] = '\0'; + } + + os_strdup(buf, agt_info->os); + fclose(fp); + + return(1); + } + + fclose(fp); + + os_strdup("Unknown", agt_info->os); + os_strdup("Unknown", agt_info->version); + + return(0); +} + + + +/** agent_info *get_agent_info(char *agent_name, char *agent_ip) + * Get information from an agent. + */ +agent_info *get_agent_info(char *agent_name, char *agent_ip) +{ + char tmp_file[513]; + char *agent_ip_pt = NULL; + char *tmp_str = NULL; + + agent_info *agt_info = NULL; + + tmp_file[512] = '\0'; + + + /* Removing the "/", since it is not present on the file. */ + if((agent_ip_pt = strchr(agent_ip, '/'))) + { + *agent_ip_pt = '\0'; + } + + + /* Allocating memory for the info structure. */ + agt_info = calloc(1, sizeof(agent_info)); + + + /* Zeroing the values. */ + agt_info->rootcheck_time = NULL; + agt_info->rootcheck_endtime = NULL; + agt_info->syscheck_time = NULL; + agt_info->syscheck_endtime = NULL; + agt_info->os = NULL; + agt_info->version = NULL; + agt_info->last_keepalive = NULL; + + + /* Getting information about the OS. */ + _get_agent_os(agent_name, agent_ip, agt_info); + _get_time_rkscan(agent_name, agent_ip, agt_info); + agt_info->last_keepalive = _get_agent_keepalive(agent_name, agent_ip); + + + /* Removing new line from keep alive. */ + tmp_str = strchr(agt_info->last_keepalive, '\n'); + if(tmp_str) + *tmp_str = '\0'; + + + + /* Setting back the ip address. */ + if(agent_ip_pt) + { + *agent_ip_pt = '/'; + } + + + return(agt_info); +} + + + +/** int get_agent_status(char *agent_name, char *agent_ip) + * Gets the status of an agent, based on the name/ip. + */ +int get_agent_status(char *agent_name, char *agent_ip) +{ + char tmp_file[513]; + char *agent_ip_pt = NULL; + + struct stat file_status; + + tmp_file[512] = '\0'; + + + /* Server info. */ + if(agent_name == NULL) + { + return(GA_STATUS_ACTIVE); + } + + + /* Removing the "/", since it is not present on the file. */ + if((agent_ip_pt = strchr(agent_ip, '/'))) + { + *agent_ip_pt = '\0'; + } + + snprintf(tmp_file, 512, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip); + + + /* Setting back the ip address. */ + if(agent_ip_pt) + { + *agent_ip_pt = '/'; + } + + + if(stat(tmp_file, &file_status) < 0) + { + return(GA_STATUS_INV); + } + + + if(file_status.st_mtime > (time(0) - (3*NOTIFY_TIME + 30))) + { + return(GA_STATUS_ACTIVE); + } + + return(GA_STATUS_NACTIVE); +} + + + +/* List available agents. + */ +char **get_agents(int flag) +{ + int f_size = 0; + + char **f_files = NULL; + DIR *dp; + + struct dirent *entry; + + /* Opening the directory given */ + dp = opendir(AGENTINFO_DIR); + if(!dp) + { + merror("%s: Error opening directory: '%s': %s ", + __local_name, + AGENTINFO_DIR, + strerror(errno)); + return(NULL); + } + + + /* Reading directory */ + while((entry = readdir(dp)) != NULL) + { + int status = 0; + char tmp_file[513]; + tmp_file[512] = '\0'; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + continue; + + snprintf(tmp_file, 512, "%s/%s", AGENTINFO_DIR, entry->d_name); + + + if(flag != GA_ALL) + { + struct stat file_status; + + if(stat(tmp_file, &file_status) < 0) + continue; + + if(file_status.st_mtime > (time(0) - (3*NOTIFY_TIME + 30))) + { + status = 1; + if(flag == GA_NOTACTIVE) + continue; + } + else + { + if(flag == GA_ACTIVE) + continue; + } + } + + f_files = (char **)realloc(f_files, (f_size +2) * sizeof(char *)); + if(!f_files) + { + ErrorExit(MEM_ERROR, __local_name); + } + + + /* Adding agent entry */ + if(flag == GA_ALL_WSTATUS) + { + char agt_stat[512]; + + snprintf(agt_stat, sizeof(agt_stat) -1, "%s %s", + entry->d_name, status == 1?"active":"disconnected"); + + os_strdup(agt_stat, f_files[f_size]); + } + else + { + os_strdup(entry->d_name, f_files[f_size]); + } + + f_files[f_size +1] = NULL; + + f_size++; + } + + closedir(dp); + return(f_files); +} + + +/* EOF */ diff --git a/src/shared/read-alert.c b/src/shared/read-alert.c new file mode 100755 index 0000000..ff18f85 --- /dev/null +++ b/src/shared/read-alert.c @@ -0,0 +1,332 @@ +/* @(#) $Id: read-alert.c,v 1.10 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* File monitoring functions */ + +#include "shared.h" +#include "read-alert.h" + + +/* ** Alert xyz: email active-response ** */ + +#define ALERT_BEGIN "** Alert" +#define ALERT_BEGIN_SZ 8 +#define RULE_BEGIN "Rule: " +#define RULE_BEGIN_SZ 6 +#define SRCIP_BEGIN "Src IP: " +#define SRCIP_BEGIN_SZ 8 +#define USER_BEGIN "User: " +#define USER_BEGIN_SZ 6 +#define ALERT_MAIL "mail" +#define ALERT_MAIL_SZ 4 +#define ALERT_AR "active-response" + + +/** void FreeAlertData(alert_data *al_data) + * Free alert data. + */ +void FreeAlertData(alert_data *al_data) +{ + if(al_data->date) + { + free(al_data->date); + } + if(al_data->location) + { + free(al_data->location); + } + if(al_data->comment) + { + free(al_data->comment); + } + if(al_data->group) + { + free(al_data->group); + } + if(al_data->srcip) + { + free(al_data->srcip); + } + if(al_data->user) + { + free(al_data->user); + } + if(al_data->log) + { + while(*(al_data->log)) + { + free(*(al_data->log)); + al_data->log++; + } + } + free(al_data); + al_data = NULL; +} + + +/** alert_data *GetAlertData(FILE *fp) + * Returns alert data for the file specified + */ +alert_data *GetAlertData(int flag, FILE *fp) +{ + int _r = 0, log_size; + char *p; + + char *date = NULL; + char *comment = NULL; + char *location = NULL; + char *srcip = NULL; + char *user = NULL; + char *group = NULL; + char **log = NULL; + int level, rule; + + char str[OS_BUFFER_SIZE+1]; + str[OS_BUFFER_SIZE]='\0'; + + + while(fgets(str, OS_BUFFER_SIZE, fp) != NULL) + { + + /* Enf of alert */ + if(strcmp(str, "\n") == 0) + { + /* Found in here */ + if(_r == 2) + { + alert_data *al_data; + os_calloc(1, sizeof(alert_data), al_data); + al_data->level = level; + al_data->rule = rule; + al_data->location = location; + al_data->comment = comment; + al_data->group = group; + al_data->log = log; + al_data->srcip = srcip; + al_data->user = user; + al_data->date = date; + + return(al_data); + } + _r = 0; + } + + + /* Checking for the header */ + if(strncmp(ALERT_BEGIN, str, ALERT_BEGIN_SZ) == 0) + { + p = str + ALERT_BEGIN_SZ + 1; + + /* Searching for email flag */ + p = strchr(p, ' '); + if(!p) + { + continue; + } + + p++; + + + /* Checking for the flags */ + if((flag & CRALERT_MAIL_SET) && + (strncmp(ALERT_MAIL, p, ALERT_MAIL_SZ) != 0)) + { + continue; + } + + p = strchr(p, '-'); + if(p) + { + p++; + os_strdup(p, group); + + /* Cleaning new line from group */ + os_clearnl(group, p); + } + + + /* Searching for active-response flag */ + _r = 1; + continue; + } + + if(_r < 1) + continue; + + + /*** Extract information from the event ***/ + + /* r1 means: 2006 Apr 13 16:15:17 /var/log/auth.log */ + if(_r == 1) + { + /* Clear new line */ + os_clearnl(str, p); + + p = strchr(str, ':'); + if(p) + { + p = strchr(p, ' '); + if(p) + { + *p = '\0'; + p++; + } + else + { + /* If p is null it is because strchr failed */ + merror("ZZZ: 1() Merror date or location not NULL"); + _r = 0; + goto l_error; + } + } + + + /* If not, str is date and p is the location */ + if(date || location) + merror("ZZZ Merror date or location not NULL"); + + os_strdup(str, date); + os_strdup(p, location); + _r = 2; + log_size = 0; + continue; + } + + + else if(_r == 2) + { + /* Rule begin */ + if(strncmp(RULE_BEGIN, str, RULE_BEGIN_SZ) == 0) + { + os_clearnl(str,p); + + p = str + RULE_BEGIN_SZ; + rule = atoi(p); + + p = strchr(p, ' '); + if(p) + { + p++; + p = strchr(p, ' '); + if(p) + p++; + } + + if(!p) + goto l_error; + + level = atoi(p); + + /* Getting the comment */ + p = strchr(p, '\''); + if(!p) + goto l_error; + + p++; + os_strdup(p, comment); + + /* Must have the closing \' */ + p = strrchr(comment, '\''); + if(p) + { + *p = '\0'; + } + else + { + goto l_error; + } + } + + /* srcip */ + else if(strncmp(SRCIP_BEGIN, str, SRCIP_BEGIN_SZ) == 0) + { + os_clearnl(str,p); + + p = str + SRCIP_BEGIN_SZ; + os_strdup(p, srcip); + } + /* username */ + else if(strncmp(USER_BEGIN, str, USER_BEGIN_SZ) == 0) + { + os_clearnl(str,p); + + p = str + USER_BEGIN_SZ; + os_strdup(p, user); + } + /* It is a log message */ + else if(log_size < 10) + { + os_clearnl(str,p); + + os_realloc(log, (log_size +2)*sizeof(char *), log); + os_strdup(str, log[log_size]); + log_size++; + log[log_size] = NULL; + } + } + + continue; + l_error: + + /* Freeing the memory */ + _r = 0; + if(date) + { + free(date); + date = NULL; + } + if(location) + { + free(location); + location = NULL; + } + if(comment) + { + free(comment); + comment = NULL; + } + if(srcip) + { + free(srcip); + srcip = NULL; + } + if(user) + { + free(user); + user = NULL; + } + if(group) + { + free(group); + group = NULL; + } + while(log_size > 0) + { + log_size--; + if(log[log_size]) + { + free(log[log_size]); + log[log_size] = NULL; + } + } + } + + /* We need to clean end of file before returning */ + clearerr(fp); + return(NULL); +} + + +/* EOF */ diff --git a/src/shared/regex_op.c b/src/shared/regex_op.c new file mode 100755 index 0000000..cf4db77 --- /dev/null +++ b/src/shared/regex_op.c @@ -0,0 +1,51 @@ +/* @(#) $Id: regex_op.c,v 1.12 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef WIN32 +#include "shared.h" +#include + + + +/* OS_PRegex: + * Compile a posix regex, returning NULL on error + * Returns 1 if matches, 0 if not. + */ +int OS_PRegex(char *str, char *regex) +{ + regex_t preg; + + if(!str || !regex) + return(0); + + + if(regcomp(&preg, regex, REG_EXTENDED|REG_NOSUB) != 0) + { + merror("%s: Posix Regex compile error (%s).", __local_name, regex); + return(0); + } + + if(regexec(&preg, str, strlen(str), NULL, 0) != 0) + { + /* Didn't match */ + regfree(&preg); + return(0); + } + + regfree(&preg); + return(1); + +} + +#endif + +/* EOF */ diff --git a/src/shared/report_op.c b/src/shared/report_op.c new file mode 100755 index 0000000..cc51737 --- /dev/null +++ b/src/shared/report_op.c @@ -0,0 +1,672 @@ +/* @(#) $Id: report_op.c,v 1.2 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" + + +/** Helper functions. */ + +/* Sort function used by OSStore sort. + * Returns if d1 > d2. + */ +void *_os_report_sort_compare(void *d1, void *d2) +{ + OSList *d1l = (OSList *)d1; + OSList *d2l = (OSList *)d2; + + if(d1l->currently_size > d2l->currently_size) + { + return(d1l); + } + + return(NULL); +} + + +/* Compares if the id is present in the string. */ +int _os_report_str_int_compare(char *str, int id) +{ + int pt_check = 0; + + do + { + if((*str == ',')||(*str == ' ')) + { + pt_check = 0; + continue; + } + else if(*str == '\0') + { + break; + } + else if(isdigit((int)*str)) + { + if(pt_check == 0) + { + if(id == atoi(str)) + { + return(1); + } + } + pt_check = 1; + } + else + { + return(-1); + } + }while(*str++ != '\0'); + + return(0); +} + + + +/* Check if the al_data should be filtered. */ +int _os_report_check_filters(alert_data *al_data, report_filter *r_filter) +{ + /* Checking for the filters. */ + if(r_filter->group) + { + if(!strstr(al_data->group, r_filter->group)) + { + return(0); + } + } + if(r_filter->rule) + { + if(_os_report_str_int_compare(r_filter->rule, al_data->rule) != 1) + { + return(0); + } + } + if(r_filter->location) + { + if(!OS_Match2(r_filter->location, al_data->location)) + { + return(0); + } + } + if(r_filter->level) + { + if(al_data->level < atoi(r_filter->level)) + { + return(0); + } + } + + return(1); +} + + + +/* Sets the proper value for the related entries. */ +int _report_filter_value(char *filter_by, int prev_filter) +{ + if(strcmp(filter_by, "group") == 0) + { + if(!(prev_filter & REPORT_REL_GROUP)) + { + prev_filter|=REPORT_REL_GROUP; + } + return(prev_filter); + } + else if(strcmp(filter_by, "rule") == 0) + { + if(!(prev_filter & REPORT_REL_RULE)) + { + prev_filter|=REPORT_REL_RULE; + } + return(prev_filter); + } + else if(strcmp(filter_by, "level") == 0) + { + if(!(prev_filter & REPORT_REL_LEVEL)) + { + prev_filter|=REPORT_REL_LEVEL; + } + return(prev_filter); + } + else if(strcmp(filter_by, "location") == 0) + { + if(!(prev_filter & REPORT_REL_LOCATION)) + { + prev_filter|=REPORT_REL_LOCATION; + } + return(prev_filter); + } + else if(strcmp(filter_by, "srcip") == 0) + { + if(!(prev_filter & REPORT_REL_SRCIP)) + { + prev_filter|=REPORT_REL_SRCIP; + } + return(prev_filter); + } + else if(strcmp(filter_by, "user") == 0) + { + if(!(prev_filter & REPORT_REL_USER)) + { + prev_filter|=REPORT_REL_USER; + } + return(prev_filter); + } + else + { + merror("%s: ERROR: Invalid relation '%s'.", ARGV0, filter_by); + return(-1); + } +} + + + +/* Prints related entries. */ +int _os_report_print_related(int print_related, OSList *st_data) +{ + OSListNode *list_entry; + alert_data *list_aldata; + alert_data *saved_aldata; + + + list_entry = OSList_GetFirstNode(st_data); + while(list_entry) + { + saved_aldata = (alert_data *)list_entry->data; + + /* Removing duplicates. */ + list_entry = list_entry->prev; + while(list_entry) + { + if(print_related & REPORT_REL_LOCATION) + { + list_aldata = (alert_data *)list_entry->data; + if(strcmp(list_aldata->location, saved_aldata->location) == 0) + { + break; + } + } + + else if(print_related & REPORT_REL_GROUP) + { + list_aldata = (alert_data *)list_entry->data; + if(strcmp(list_aldata->group, saved_aldata->group) == 0) + { + break; + } + } + + else if(print_related & REPORT_REL_RULE) + { + list_aldata = (alert_data *)list_entry->data; + if(list_aldata->rule == saved_aldata->rule) + { + break; + } + } + + else if(print_related & REPORT_REL_USER) + { + list_aldata = (alert_data *)list_entry->data; + if(strcmp(list_aldata->user, saved_aldata->user) == 0) + { + break; + } + } + + else if(print_related & REPORT_REL_SRCIP) + { + list_aldata = (alert_data *)list_entry->data; + if(strcmp(list_aldata->srcip, saved_aldata->srcip) == 0) + { + break; + } + } + + else if(print_related & REPORT_REL_LEVEL) + { + list_aldata = (alert_data *)list_entry->data; + if(list_aldata->level == saved_aldata->level) + { + break; + } + } + list_entry = list_entry->prev; + } + + if(!list_entry) + { + if(print_related & REPORT_REL_LOCATION) + print_out(" location: '%s'", saved_aldata->location); + else if(print_related & REPORT_REL_GROUP) + print_out(" group: '%s'", saved_aldata->group); + else if(print_related & REPORT_REL_RULE) + print_out(" rule: '%d'", saved_aldata->rule); + else if(print_related & REPORT_REL_SRCIP) + print_out(" srcip: '%s'", saved_aldata->srcip); + else if(print_related & REPORT_REL_USER) + print_out(" user: '%s'", saved_aldata->user); + else if(print_related & REPORT_REL_LEVEL) + print_out(" level: '%d'", saved_aldata->level); + } + + list_entry = OSList_GetNextNode(st_data); + } + + return(0); +} + + + +/* Add the entry to the hash. */ +int _os_report_add_tostore(char *key, OSStore *top, void *data) +{ + OSList *top_list; + + /* Adding data to the hash. */ + top_list = OSStore_Get(top, key); + if(top_list) + { + OSList_AddData(top_list, data); + } + else + { + top_list = OSList_Create(); + if(!top_list) + { + merror(MEM_ERROR, ARGV0); + return(0); + } + OSList_AddData(top_list, data); + + OSStore_Put(top, key, top_list); + } + + return(1); +} + + + +void os_report_printtop(void *topstore_pt, char *hname, int print_related) +{ + OSStore *topstore = (OSStore *)topstore_pt; + OSStoreNode *next_node; + + if(!print_related) + { + print_out("Top entries for '%s':", hname); + print_out("------------------------------------------------"); + } + else + { + print_out("Related entries for '%s':", hname); + print_out("------------------------------------------------"); + } + + + next_node = OSStore_GetFirstNode(topstore); + while(next_node) + { + OSList *st_data = (OSList *)next_node->data; + char *lkey = (char *)next_node->key; + + + /* With location we leave more space to be clearer. */ + if(!print_related) + { + if(strlen(lkey) > 46) + { + lkey[44] = '.'; + lkey[45] = '.'; + lkey[46] = '\0'; + } + + print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size); + } + + + /* Print each destination. */ + else + { + print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size); + + if(print_related & REPORT_REL_LOCATION) + _os_report_print_related(REPORT_REL_LOCATION, st_data); + if(print_related & REPORT_REL_SRCIP) + _os_report_print_related(REPORT_REL_SRCIP, st_data); + if(print_related & REPORT_REL_USER) + _os_report_print_related(REPORT_REL_USER, st_data); + if(print_related & REPORT_REL_RULE) + _os_report_print_related(REPORT_REL_RULE, st_data); + if(print_related & REPORT_REL_GROUP) + _os_report_print_related(REPORT_REL_GROUP, st_data); + if(print_related & REPORT_REL_LEVEL) + _os_report_print_related(REPORT_REL_LEVEL, st_data); + + } + + next_node = next_node->next; + } + + + print_out(" "); + print_out(" "); + return; +} + + + +void os_ReportdStart(report_filter *r_filter) +{ + int alerts_processed = 0; + int alerts_filtered = 0; + char *first_alert = NULL; + char *last_alert = NULL; + + + time_t tm; + struct tm *p; + + + file_queue *fileq; + alert_data *al_data; + + + /* Getting current time before starting */ + tm = time(NULL); + p = localtime(&tm); + + + + /* Creating top hashes. */ + r_filter->top_user = OSStore_Create(); + r_filter->top_srcip = OSStore_Create(); + r_filter->top_level = OSStore_Create(); + r_filter->top_rule = OSStore_Create(); + r_filter->top_group = OSStore_Create(); + r_filter->top_location = OSStore_Create(); + + + + /* Initating file queue - to read the alerts */ + os_calloc(1, sizeof(file_queue), fileq); + fileq->fp = stdin; + Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET); + + + /* Reading the alerts. */ + while(1) + { + /* Get message if available */ + al_data = Read_FileMon(fileq, p, 1); + if(!al_data) + { + verbose("%s: Report completed. Creating output...", ARGV0); + break; + } + + alerts_processed++; + + + /* Checking the filters. */ + if(!_os_report_check_filters(al_data, r_filter)) + { + FreeAlertData(al_data); + continue; + } + + + alerts_filtered++; + + + /* Setting first and last alert for summary. */ + if(!first_alert) + first_alert = al_data->date; + last_alert = al_data->date; + + + /* Adding source ip if it is set properly. */ + if(strcmp(al_data->srcip, "(none)") != 0) + _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data); + + + /* Adding user if it is set properly. */ + if(strcmp(al_data->user, "(none)") != 0) + _os_report_add_tostore(al_data->user, r_filter->top_user, al_data); + + + /* Adding level and severity. */ + { + char mlevel[16]; + char mrule[76 +1]; + mrule[76] = '\0'; + snprintf(mlevel, 16, "Severity %d" , al_data->level); + snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment); + + _os_report_add_tostore(strdup(mlevel), r_filter->top_level, + al_data); + _os_report_add_tostore(strdup(mrule), r_filter->top_rule, + al_data); + } + + /* Dealing with the group. */ + { + char *tmp_str; + char **mgroup; + + mgroup = OS_StrBreak(',', al_data->group, 32); + if(mgroup) + { + while(*mgroup) + { + tmp_str = *mgroup; + while(*tmp_str == ' ') + tmp_str++; + if(*tmp_str == '\0') + { + mgroup++; + continue; + } + + _os_report_add_tostore(tmp_str, r_filter->top_group, + al_data); + mgroup++; + } + } + else + { + tmp_str = al_data->group; + while(*tmp_str == ' ') + tmp_str++; + if(*tmp_str != '\0') + { + _os_report_add_tostore(tmp_str, r_filter->top_group, + al_data); + } + } + } + + + /* Adding to the location top filter. */ + _os_report_add_tostore(al_data->location, r_filter->top_location, + al_data); + } + + + + print_out(" "); + if(r_filter->report_name) + print_out("Report '%s' completed.", r_filter->report_name); + else + print_out("Report completed. =="); + print_out("------------------------------------------------"); + + print_out("->Processed alerts: %d", alerts_processed); + print_out("->Post-filtering alerts: %d", alerts_filtered); + print_out("->First alert: %s", first_alert); + print_out("->Last alert: %s", last_alert); + print_out(" "); + print_out(" "); + + OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare); + OSStore_Sort(r_filter->top_user, _os_report_sort_compare); + OSStore_Sort(r_filter->top_level, _os_report_sort_compare); + OSStore_Sort(r_filter->top_group, _os_report_sort_compare); + OSStore_Sort(r_filter->top_location, _os_report_sort_compare); + OSStore_Sort(r_filter->top_rule, _os_report_sort_compare); + + if(r_filter->top_srcip) + os_report_printtop(r_filter->top_srcip, "Source ip", 0); + + if(r_filter->top_user) + os_report_printtop(r_filter->top_user, "Username", 0); + + if(r_filter->top_level) + os_report_printtop(r_filter->top_level, "Level", 0); + + if(r_filter->top_group) + os_report_printtop(r_filter->top_group, "Group", 0); + + if(r_filter->top_location) + os_report_printtop(r_filter->top_location, "Location", 0); + + if(r_filter->top_rule) + os_report_printtop(r_filter->top_rule, "Rule", 0); + + + /* Print related events. */ + if(r_filter->related_srcip) + os_report_printtop(r_filter->top_srcip, "Source ip", + r_filter->related_srcip); + + if(r_filter->related_user) + os_report_printtop(r_filter->top_user, "Username", + r_filter->related_user); + + if(r_filter->related_level) + os_report_printtop(r_filter->top_level, "Level", + r_filter->related_level); + + if(r_filter->related_group) + os_report_printtop(r_filter->top_group, "Group", + r_filter->related_group); + + if(r_filter->related_location) + os_report_printtop(r_filter->top_location, "Location", + r_filter->related_location); + + if(r_filter->related_rule) + os_report_printtop(r_filter->top_rule, "Rule", + r_filter->related_rule); +} + + + + + +/** int os_report_check_filters(char *filter_by, char *filter_value, + * report_filter *r_filter) + * Checks the configuration filters. + */ +int os_report_configfilter(char *filter_by, char *filter_value, + report_filter *r_filter, int arg_type) +{ + if(!filter_by || !filter_value) + { + return(-1); + } + + if(arg_type == REPORT_FILTER) + { + if(strcmp(filter_by, "group") == 0) + { + r_filter->group = filter_value; + } + else if(strcmp(filter_by, "rule") == 0) + { + r_filter->rule = filter_value; + } + else if(strcmp(filter_by, "level") == 0) + { + r_filter->level = filter_value; + } + else if(strcmp(filter_by, "location") == 0) + { + r_filter->location = filter_value; + } + else + { + merror("%s: ERROR: Invalid filter '%s'.", ARGV0, filter_by); + return(-1); + } + } + else + { + if(strcmp(filter_by, "group") == 0) + { + r_filter->related_group = + _report_filter_value(filter_value, r_filter->related_group); + + if(r_filter->related_group == -1) + return(-1); + } + else if(strcmp(filter_by, "rule") == 0) + { + r_filter->related_rule = + _report_filter_value(filter_value, r_filter->related_rule); + + if(r_filter->related_rule == -1) + return(-1); + } + else if(strcmp(filter_by, "level") == 0) + { + r_filter->related_level = + _report_filter_value(filter_value, r_filter->related_level); + + if(r_filter->related_level == -1) + return(-1); + } + else if(strcmp(filter_by, "location") == 0) + { + r_filter->related_location = + _report_filter_value(filter_value, r_filter->related_location); + + if(r_filter->related_location == -1) + return(-1); + } + else if(strcmp(filter_by, "srcip") == 0) + { + r_filter->related_srcip = + _report_filter_value(filter_value, r_filter->related_srcip); + + if(r_filter->related_srcip == -1) + return(-1); + } + else if(strcmp(filter_by, "user") == 0) + { + r_filter->related_user = + _report_filter_value(filter_value, r_filter->related_user); + + if(r_filter->related_user == -1) + return(-1); + } + else + { + merror("%s: ERROR: Invalid related entry '%s'.", ARGV0, filter_by); + return(-1); + } + } + + return(0); +} + + + +/* EOF */ diff --git a/src/shared/rules_op.c b/src/shared/rules_op.c new file mode 100755 index 0000000..203b3ba --- /dev/null +++ b/src/shared/rules_op.c @@ -0,0 +1,1307 @@ +/* @(#) $Id: rules_op.c,v 1.6 2009/06/24 18:53:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#include "rules_op.h" + + +/** Prototypes **/ +int _OS_GetRulesAttributes(char **attributes, + char **values, + RuleInfo *ruleinfo_pt); +RuleInfo *_OS_AllocateRule(); + + + + +/* Rules_OP_ReadRules, v0.3, 2005/03/21 + * Read the log rules. + * v0.3: Fixed many memory problems. + */ +int OS_ReadXMLRules(char *rulefile, + void *(*ruleact_function)(RuleInfo *rule, void *data), + void *data) +{ + OS_XML xml; + XML_NODE node = NULL; + + + /** XML variables **/ + /* These are the available options for the rule configuration */ + + char *xml_group = "group"; + char *xml_rule = "rule"; + + char *xml_regex = "regex"; + char *xml_match = "match"; + char *xml_decoded = "decoded_as"; + char *xml_category = "category"; + char *xml_cve = "cve"; + char *xml_info = "info"; + char *xml_day_time = "time"; + char *xml_week_day = "weekday"; + char *xml_comment = "description"; + char *xml_ignore = "ignore"; + char *xml_check_if_ignored = "check_if_ignored"; + + char *xml_srcip = "srcip"; + char *xml_srcport = "srcport"; + char *xml_dstip = "dstip"; + char *xml_dstport = "dstport"; + char *xml_user = "user"; + char *xml_url = "url"; + char *xml_id = "id"; + char *xml_data = "extra_data"; + char *xml_hostname = "hostname"; + char *xml_program_name = "program_name"; + char *xml_status = "status"; + char *xml_action = "action"; + char *xml_compiled = "compiled_rule"; + + char *xml_if_sid = "if_sid"; + char *xml_if_group = "if_group"; + char *xml_if_level = "if_level"; + char *xml_fts = "if_fts"; + + char *xml_if_matched_regex = "if_matched_regex"; + char *xml_if_matched_group = "if_matched_group"; + char *xml_if_matched_sid = "if_matched_sid"; + + char *xml_same_source_ip = "same_source_ip"; + char *xml_same_src_port = "same_src_port"; + char *xml_same_dst_port = "same_dst_port"; + char *xml_same_user = "same_user"; + char *xml_same_location = "same_location"; + char *xml_same_id = "same_id"; + + char *xml_different_url = "different_url"; + + char *xml_notsame_source_ip = "not_same_source_ip"; + char *xml_notsame_user = "not_same_user"; + char *xml_notsame_agent = "not_same_agent"; + char *xml_notsame_id = "not_same_id"; + + char *xml_options = "options"; + + char *rulepath; + + int i; + + + /* Building the rule file name + path */ + i = strlen(RULEPATH) + strlen(rulefile) + 2; + rulepath = (char *)calloc(i,sizeof(char)); + if(!rulepath) + { + ErrorExit(MEM_ERROR,__local_name); + } + snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile); + + + /* Reading the XML */ + if(OS_ReadXML(rulepath,&xml) < 0) + { + merror(XML_ERROR, __local_name, rulepath, xml.err, xml.err_line); + free(rulepath); + return(-1); + } + + + /* Debug wrapper */ + debug1("%s: DEBUG: read xml for rule '%s'.", __local_name, rulepath); + + + /* Applying any variable found */ + if(OS_ApplyVariables(&xml) != 0) + { + merror(XML_ERROR_VAR, __local_name, rulepath, xml.err); + return(-1); + } + + + /* Debug wrapper */ + debug1("%s: DEBUG: XML Variables applied.", __local_name); + + + /* Getting the root elements */ + node = OS_GetElementsbyNode(&xml, NULL); + if(!node) + { + merror(CONFIG_ERROR, __local_name, rulepath); + OS_ClearXML(&xml); + return(-1); + } + + + /* Zeroing the rule memory -- not used anymore */ + free(rulepath); + + + /* Checking if there is any invalid global option */ + i = 0; + while(node[i]) + { + if(node[i]->element) + { + /* Verifying group */ + if(strcasecmp(node[i]->element,xml_group) != 0) + { + merror(RL_INV_ROOT, __local_name, node[i]->element); + OS_ClearXML(&xml); + return(-1); + } + /* Checking group attribute -- only name is allowed */ + if((!node[i]->attributes) || (!node[i]->values)|| + (!node[i]->values[0]) || (!node[i]->attributes[0]) || + (strcasecmp(node[i]->attributes[0],"name") != 0) || + (node[i]->attributes[1])) + { + merror(RL_INV_ROOT, __local_name, node[i]->element); + OS_ClearXML(&xml); + return(-1); + } + } + else + { + merror(XML_READ_ERROR, __local_name); + OS_ClearXML(&xml); + return(-1); + } + i++; + } + + + /* Getting the rules now */ + i = 0; + while(node[i]) + { + int j = 0; + XML_NODE rule = NULL; + + + /* Getting all rules for a global group */ + rule = OS_GetElementsbyNode(&xml,node[i]); + if(rule == NULL) + { + i++; + continue; + } + + /* Looping on the rules node */ + while(rule[j]) + { + /* Rules options */ + int k = 0; + char *regex = NULL, *match = NULL, *url = NULL, + *if_matched_regex = NULL, *if_matched_group = NULL, + *user = NULL, *id = NULL, *srcport = NULL, + *dstport = NULL, *status = NULL, *hostname = NULL, + *extra_data = NULL, *program_name = NULL; + + RuleInfo *config_ruleinfo = NULL; + XML_NODE rule_opt = NULL; + + + /* Checking if the rule element is correct */ + if((!rule[j]->element)|| + (strcasecmp(rule[j]->element,xml_rule) != 0)) + { + merror(RL_INV_RULE, __local_name, node[i]->element); + OS_ClearXML(&xml); + return(-1); + } + + + /* Checking for the attributes of the rule */ + if((!rule[j]->attributes) || (!rule[j]->values)) + { + merror(RL_INV_RULE, __local_name, rulefile); + OS_ClearXML(&xml); + return(-1); + } + + + /* Attribute block */ + config_ruleinfo = _OS_AllocateRule(); + + if(_OS_GetRulesAttributes(rule[j]->attributes, rule[j]->values, + config_ruleinfo) < 0) + { + merror(RL_INV_ATTR, __local_name, rulefile); + OS_ClearXML(&xml); + return(-1); + } + + /* We must have an id or level */ + if((config_ruleinfo->sigid == -1)||(config_ruleinfo->level == -1)) + { + merror(RL_INV_ATTR, __local_name, rulefile); + OS_ClearXML(&xml); + return(-1); + } + + + /* Here we can assign the group name to the rule. + * The level is correct so the rule is probably going to + * be fine + */ + os_strdup(node[i]->values[0], config_ruleinfo->group); + + + /* Getting rules options */ + rule_opt = OS_GetElementsbyNode(&xml, rule[j]); + if(rule_opt == NULL) + { + merror(RL_NO_OPT, __local_name, config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + + + /* Reading the whole rule block */ + while(rule_opt[k]) + { + if((!rule_opt[k]->element)||(!rule_opt[k]->content)) + { + break; + } + else if(strcasecmp(rule_opt[k]->element,xml_regex)==0) + { + regex = + os_LoadString(regex, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_match)==0) + { + match = + os_LoadString(match, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, xml_decoded) == 0) + { + } + else if(strcasecmp(rule_opt[k]->element,xml_info) == 0) + { + config_ruleinfo->info= + os_LoadString(config_ruleinfo->info, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_day_time) == 0) + { + config_ruleinfo->day_time = + OS_IsValidTime(rule_opt[k]->content); + if(!config_ruleinfo->day_time) + { + merror(INVALID_CONFIG, __local_name, + rule_opt[k]->element, + rule_opt[k]->content); + return(-1); + } + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_week_day) == 0) + { + config_ruleinfo->week_day = + OS_IsValidDay(rule_opt[k]->content); + + if(!config_ruleinfo->week_day) + { + merror(INVALID_CONFIG, __local_name, + rule_opt[k]->element, + rule_opt[k]->content); + return(-1); + } + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_group) == 0) + { + config_ruleinfo->group = + os_LoadString(config_ruleinfo->group, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_cve) == 0) + { + config_ruleinfo->cve= + os_LoadString(config_ruleinfo->cve, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_comment) == 0) + { + char *newline; + + newline = strchr(rule_opt[k]->content, '\n'); + if(newline) + { + *newline = ' '; + } + config_ruleinfo->comment= + os_LoadString(config_ruleinfo->comment, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_srcip)==0) + { + int ip_s = 0; + + /* Getting size of source ip list */ + while(config_ruleinfo->srcip && + config_ruleinfo->srcip[ip_s]) + { + ip_s++; + } + + config_ruleinfo->srcip = + realloc(config_ruleinfo->srcip, + (ip_s + 2) * sizeof(os_ip *)); + + + /* Allocating memory for the individual entries */ + os_calloc(1, sizeof(os_ip), + config_ruleinfo->srcip[ip_s]); + config_ruleinfo->srcip[ip_s +1] = NULL; + + + /* Checking if the ip is valid */ + if(!OS_IsValidIP(rule_opt[k]->content, + config_ruleinfo->srcip[ip_s])) + { + merror(INVALID_IP, __local_name, rule_opt[k]->content); + return(-1); + } + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_dstip)==0) + { + int ip_s = 0; + + /* Getting size of source ip list */ + while(config_ruleinfo->dstip && + config_ruleinfo->dstip[ip_s]) + { + ip_s++; + } + + config_ruleinfo->dstip = + realloc(config_ruleinfo->dstip, + (ip_s + 2) * sizeof(os_ip *)); + + + /* Allocating memory for the individual entries */ + os_calloc(1, sizeof(os_ip), + config_ruleinfo->dstip[ip_s]); + config_ruleinfo->dstip[ip_s +1] = NULL; + + + /* Checking if the ip is valid */ + if(!OS_IsValidIP(rule_opt[k]->content, + config_ruleinfo->dstip[ip_s])) + { + merror(INVALID_IP, __local_name, rule_opt[k]->content); + return(-1); + } + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_user) == 0) + { + user = os_LoadString(user, rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_id) == 0) + { + id = os_LoadString(id, rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_srcport) == 0) + { + srcport = os_LoadString(srcport, rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_dstport) == 0) + { + dstport = os_LoadString(dstport, rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_PACKETINFO)) + config_ruleinfo->alert_opts |= DO_PACKETINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_status)==0) + { + status = os_LoadString(status, rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_hostname) == 0) + { + hostname = os_LoadString(hostname, rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element,xml_data)==0) + { + extra_data = os_LoadString(extra_data, rule_opt[k]->content); + + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_program_name)==0) + { + program_name = os_LoadString(program_name, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_action) == 0) + { + config_ruleinfo->action = + os_LoadString(config_ruleinfo->action, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_url) == 0) + { + url= os_LoadString(url, rule_opt[k]->content); + } + + else if(strcasecmp(rule_opt[k]->element, xml_compiled)==0) + { + /* Not using this in here. */ + } + + /* We allow these categories so far */ + else if(strcasecmp(rule_opt[k]->element, xml_category)==0) + { + if(strcmp(rule_opt[k]->content, "firewall") == 0) + { + config_ruleinfo->category = FIREWALL; + } + else if(strcmp(rule_opt[k]->content, "ids") == 0) + { + config_ruleinfo->category = IDS; + } + else if(strcmp(rule_opt[k]->content, "syslog") == 0) + { + config_ruleinfo->category = SYSLOG; + } + else if(strcmp(rule_opt[k]->content, "web-log") == 0) + { + config_ruleinfo->category = WEBLOG; + } + else if(strcmp(rule_opt[k]->content, "squid") == 0) + { + config_ruleinfo->category = SQUID; + } + else if(strcmp(rule_opt[k]->content,"windows") == 0) + { + config_ruleinfo->category = WINDOWS; + } + else if(strcmp(rule_opt[k]->content,"ossec") == 0) + { + config_ruleinfo->category = OSSEC_RL; + } + else + { + merror(INVALID_CAT, __local_name, rule_opt[k]->content); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element,xml_if_sid)==0) + { + config_ruleinfo->if_sid= + os_LoadString(config_ruleinfo->if_sid, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_if_level)==0) + { + if(!OS_StrIsNum(rule_opt[k]->content)) + { + merror(INVALID_CONFIG, __local_name, + xml_if_level, + rule_opt[k]->content); + return(-1); + } + + config_ruleinfo->if_level= + os_LoadString(config_ruleinfo->if_level, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element,xml_if_group)==0) + { + config_ruleinfo->if_group= + os_LoadString(config_ruleinfo->if_group, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, + xml_if_matched_regex) == 0) + { + config_ruleinfo->context = 1; + if_matched_regex= + os_LoadString(if_matched_regex, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, + xml_if_matched_group) == 0) + { + config_ruleinfo->context = 1; + if_matched_group= + os_LoadString(if_matched_group, + rule_opt[k]->content); + } + else if(strcasecmp(rule_opt[k]->element, + xml_if_matched_sid) == 0) + { + config_ruleinfo->context = 1; + if(!OS_StrIsNum(rule_opt[k]->content)) + { + merror(INVALID_CONFIG, __local_name, + rule_opt[k]->element, + rule_opt[k]->content); + return(-1); + } + config_ruleinfo->if_matched_sid = + atoi(rule_opt[k]->content); + + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_source_ip)==0) + { + config_ruleinfo->context_opts|= SAME_SRCIP; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_src_port)==0) + { + config_ruleinfo->context_opts|= SAME_SRCPORT; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_dst_port) == 0) + { + config_ruleinfo->context_opts|= SAME_DSTPORT; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_notsame_source_ip)==0) + { + config_ruleinfo->context_opts&= NOT_SAME_SRCIP; + } + else if(strcmp(rule_opt[k]->element, xml_same_id) == 0) + { + config_ruleinfo->context_opts|= SAME_ID; + } + else if(strcmp(rule_opt[k]->element, + xml_different_url) == 0) + { + config_ruleinfo->context_opts|= DIFFERENT_URL; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcmp(rule_opt[k]->element,xml_notsame_id) == 0) + { + config_ruleinfo->context_opts&= NOT_SAME_ID; + } + else if(strcasecmp(rule_opt[k]->element, + xml_fts) == 0) + { + config_ruleinfo->alert_opts |= DO_FTS; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_user)==0) + { + config_ruleinfo->context_opts|= SAME_USER; + + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_notsame_user)==0) + { + config_ruleinfo->context_opts&= NOT_SAME_USER; + } + else if(strcasecmp(rule_opt[k]->element, + xml_same_location)==0) + { + config_ruleinfo->context_opts|= SAME_LOCATION; + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) + config_ruleinfo->alert_opts |= SAME_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, + xml_notsame_agent)==0) + { + config_ruleinfo->context_opts&= NOT_SAME_AGENT; + } + else if(strcasecmp(rule_opt[k]->element, + xml_options) == 0) + { + if(strcmp("alert_by_email", + rule_opt[k]->content) == 0) + { + if(!(config_ruleinfo->alert_opts & DO_MAILALERT)) + { + config_ruleinfo->alert_opts|= DO_MAILALERT; + } + } + else if(strcmp("no_email_alert", + rule_opt[k]->content) == 0) + { + if(config_ruleinfo->alert_opts & DO_MAILALERT) + { + config_ruleinfo->alert_opts&=0xfff-DO_MAILALERT; + } + } + else if(strcmp("log_alert", + rule_opt[k]->content) == 0) + { + if(!(config_ruleinfo->alert_opts & DO_LOGALERT)) + { + config_ruleinfo->alert_opts|= DO_LOGALERT; + } + } + else if(strcmp("no_log", rule_opt[k]->content) == 0) + { + if(config_ruleinfo->alert_opts & DO_LOGALERT) + { + config_ruleinfo->alert_opts &=0xfff-DO_LOGALERT; + } + } + else + { + merror(XML_VALUEERR, __local_name, xml_options, + rule_opt[k]->content); + + merror(INVALID_ELEMENT, __local_name, + rule_opt[k]->element, + rule_opt[k]->content); + OS_ClearXML(&xml); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element, + xml_ignore) == 0) + { + if(strstr(rule_opt[k]->content, "user") != NULL) + { + config_ruleinfo->ignore|=FTS_USER; + } + if(strstr(rule_opt[k]->content, "srcip") != NULL) + { + config_ruleinfo->ignore|=FTS_SRCIP; + } + if(strstr(rule_opt[k]->content, "dstip") != NULL) + { + config_ruleinfo->ignore|=FTS_DSTIP; + } + if(strstr(rule_opt[k]->content, "id") != NULL) + { + config_ruleinfo->ignore|=FTS_ID; + } + if(strstr(rule_opt[k]->content,"location")!= NULL) + { + config_ruleinfo->ignore|=FTS_LOCATION; + } + if(strstr(rule_opt[k]->content,"data")!= NULL) + { + config_ruleinfo->ignore|=FTS_DATA; + } + if(strstr(rule_opt[k]->content, "name") != NULL) + { + config_ruleinfo->ignore|=FTS_NAME; + + } + if(!config_ruleinfo->ignore) + { + merror(INVALID_ELEMENT, __local_name, + rule_opt[k]->element, + rule_opt[k]->content); + + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->element, + xml_check_if_ignored) == 0) + { + if(strstr(rule_opt[k]->content, "user") != NULL) + { + config_ruleinfo->ckignore|=FTS_USER; + } + if(strstr(rule_opt[k]->content, "srcip") != NULL) + { + config_ruleinfo->ckignore|=FTS_SRCIP; + } + if(strstr(rule_opt[k]->content, "dstip") != NULL) + { + config_ruleinfo->ckignore|=FTS_DSTIP; + } + if(strstr(rule_opt[k]->content, "id") != NULL) + { + config_ruleinfo->ckignore|=FTS_ID; + } + if(strstr(rule_opt[k]->content,"location")!= NULL) + { + config_ruleinfo->ckignore|=FTS_LOCATION; + } + if(strstr(rule_opt[k]->content,"data")!= NULL) + { + config_ruleinfo->ignore|=FTS_DATA; + } + if(strstr(rule_opt[k]->content, "name") != NULL) + { + config_ruleinfo->ckignore|=FTS_NAME; + + } + if(!config_ruleinfo->ckignore) + { + merror(INVALID_ELEMENT, __local_name, + rule_opt[k]->element, + rule_opt[k]->content); + + return(-1); + } + } + else + { + merror(XML_INVELEM, __local_name, rule_opt[k]->element); + OS_ClearXML(&xml); + return(-1); + } + + k++; + } + + + /* Checking for a valid use of frequency */ + if((config_ruleinfo->context_opts || + config_ruleinfo->frequency) && + !config_ruleinfo->context) + { + merror("%s: Invalid use of frequency/context options. " + "Missing if_matched on rule '%d'.", + __local_name, config_ruleinfo->sigid); + OS_ClearXML(&xml); + return(-1); + } + + + /* If if_matched_group we must have a if_sid or if_group */ + if(if_matched_group) + { + if(!config_ruleinfo->if_sid && !config_ruleinfo->if_group) + { + os_strdup(if_matched_group, config_ruleinfo->if_group); + } + } + + + /* If_matched_sid, we need to get the if_sid */ + if(config_ruleinfo->if_matched_sid && + !config_ruleinfo->if_sid && + !config_ruleinfo->if_group) + { + os_calloc(16, sizeof(char), config_ruleinfo->if_sid); + snprintf(config_ruleinfo->if_sid, 15, "%d", + config_ruleinfo->if_matched_sid); + } + + + /* Checking the regexes */ + if(regex) + { + os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex); + if(!OSRegex_Compile(regex, config_ruleinfo->regex, 0)) + { + merror(REGEX_COMPILE, __local_name, regex, + config_ruleinfo->regex->error); + return(-1); + } + free(regex); + regex = NULL; + } + + + /* Adding in match */ + if(match) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->match); + if(!OSMatch_Compile(match, config_ruleinfo->match, 0)) + { + merror(REGEX_COMPILE, __local_name, match, + config_ruleinfo->match->error); + return(-1); + } + free(match); + match = NULL; + } + + + /* Adding in id */ + if(id) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->id); + if(!OSMatch_Compile(id, config_ruleinfo->id, 0)) + { + merror(REGEX_COMPILE, __local_name, id, + config_ruleinfo->id->error); + return(-1); + } + free(id); + id = NULL; + } + + + /* Adding srcport */ + if(srcport) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport); + if(!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0)) + { + merror(REGEX_COMPILE, __local_name, srcport, + config_ruleinfo->id->error); + return(-1); + } + free(srcport); + srcport = NULL; + } + + + /* Adding dstport */ + if(dstport) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport); + if(!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0)) + { + merror(REGEX_COMPILE, __local_name, dstport, + config_ruleinfo->id->error); + return(-1); + } + free(dstport); + dstport = NULL; + } + + + /* Adding in status */ + if(status) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->status); + if(!OSMatch_Compile(status, config_ruleinfo->status, 0)) + { + merror(REGEX_COMPILE, __local_name, status, + config_ruleinfo->status->error); + return(-1); + } + free(status); + status = NULL; + } + + + /* Adding in hostname */ + if(hostname) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname); + if(!OSMatch_Compile(hostname, config_ruleinfo->hostname,0)) + { + merror(REGEX_COMPILE, __local_name, hostname, + config_ruleinfo->hostname->error); + return(-1); + } + free(hostname); + hostname = NULL; + } + + + /* Adding extra data */ + if(extra_data) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data); + if(!OSMatch_Compile(extra_data, + config_ruleinfo->extra_data, 0)) + { + merror(REGEX_COMPILE, __local_name, extra_data, + config_ruleinfo->extra_data->error); + return(-1); + } + free(extra_data); + extra_data = NULL; + } + + + /* Adding in program name */ + if(program_name) + { + os_calloc(1,sizeof(OSMatch),config_ruleinfo->program_name); + if(!OSMatch_Compile(program_name, + config_ruleinfo->program_name,0)) + { + merror(REGEX_COMPILE, __local_name, program_name, + config_ruleinfo->program_name->error); + return(-1); + } + free(program_name); + program_name = NULL; + } + + + /* Adding in user */ + if(user) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->user); + if(!OSMatch_Compile(user, config_ruleinfo->user, 0)) + { + merror(REGEX_COMPILE, __local_name, user, + config_ruleinfo->user->error); + return(-1); + } + free(user); + user = NULL; + } + + + /* Adding in url */ + if(url) + { + os_calloc(1, sizeof(OSMatch), config_ruleinfo->url); + if(!OSMatch_Compile(url, config_ruleinfo->url, 0)) + { + merror(REGEX_COMPILE, __local_name, url, + config_ruleinfo->url->error); + return(-1); + } + free(url); + url = NULL; + } + + + /* Adding matched_group */ + if(if_matched_group) + { + os_calloc(1,sizeof(OSMatch),config_ruleinfo->if_matched_group); + + if(!OSMatch_Compile(if_matched_group, + config_ruleinfo->if_matched_group,0)) + { + merror(REGEX_COMPILE, __local_name, if_matched_group, + config_ruleinfo->if_matched_group->error); + return(-1); + } + free(if_matched_group); + if_matched_group = NULL; + } + + + /* Adding matched_regex */ + if(if_matched_regex) + { + os_calloc(1, sizeof(OSRegex), + config_ruleinfo->if_matched_regex); + if(!OSRegex_Compile(if_matched_regex, + config_ruleinfo->if_matched_regex, 0)) + { + merror(REGEX_COMPILE, __local_name, if_matched_regex, + config_ruleinfo->if_matched_regex->error); + return(-1); + } + free(if_matched_regex); + if_matched_regex = NULL; + } + + + /* Calling the function provided. */ + ruleact_function(config_ruleinfo, data); + + + j++; /* next rule */ + + + } /* while(rule[j]) */ + OS_ClearNode(rule); + i++; + + } /* while (node[i]) */ + + /* Cleaning global node */ + OS_ClearNode(node); + OS_ClearXML(&xml); + + + /* Done over here */ + return(0); +} + + + +/** RuleInfo *_OS_AllocateRule() + * Allocates the memory for the rule. + */ +RuleInfo *_OS_AllocateRule() +{ + RuleInfo *ruleinfo_pt = NULL; + + + /* Allocation memory for structure */ + ruleinfo_pt = (RuleInfo *)calloc(1,sizeof(RuleInfo)); + if(ruleinfo_pt == NULL) + { + ErrorExit(MEM_ERROR,__local_name); + } + + + /* Default values */ + ruleinfo_pt->level = -1; + + /* Default category is syslog */ + ruleinfo_pt->category = SYSLOG; + + ruleinfo_pt->ar = NULL; + + ruleinfo_pt->context = 0; + + /* Default sigid of -1 */ + ruleinfo_pt->sigid = -1; + ruleinfo_pt->firedtimes = 0; + ruleinfo_pt->maxsize = 0; + ruleinfo_pt->frequency = 0; + ruleinfo_pt->ignore_time = 0; + ruleinfo_pt->timeframe = 0; + ruleinfo_pt->time_ignored = 0; + + ruleinfo_pt->context_opts = 0; + ruleinfo_pt->alert_opts = 0; + ruleinfo_pt->ignore = 0; + ruleinfo_pt->ckignore = 0; + + ruleinfo_pt->day_time = NULL; + ruleinfo_pt->week_day = NULL; + + ruleinfo_pt->group = NULL; + ruleinfo_pt->regex = NULL; + ruleinfo_pt->match = NULL; + ruleinfo_pt->decoded_as = 0; + + ruleinfo_pt->comment = NULL; + ruleinfo_pt->info = NULL; + ruleinfo_pt->cve = NULL; + + ruleinfo_pt->if_sid = NULL; + ruleinfo_pt->if_group = NULL; + ruleinfo_pt->if_level = NULL; + + ruleinfo_pt->if_matched_regex = NULL; + ruleinfo_pt->if_matched_group = NULL; + ruleinfo_pt->if_matched_sid = 0; + + ruleinfo_pt->user = NULL; + ruleinfo_pt->srcip = NULL; + ruleinfo_pt->srcport = NULL; + ruleinfo_pt->dstip = NULL; + ruleinfo_pt->dstport = NULL; + ruleinfo_pt->url = NULL; + ruleinfo_pt->id = NULL; + ruleinfo_pt->status = NULL; + ruleinfo_pt->hostname = NULL; + ruleinfo_pt->program_name = NULL; + ruleinfo_pt->action = NULL; + + /* Zeroing last matched events */ + ruleinfo_pt->__frequency = 0; + ruleinfo_pt->last_events = NULL; + + /* zeroing the list of previous matches */ + ruleinfo_pt->sid_prev_matched = NULL; + ruleinfo_pt->group_prev_matched = NULL; + + ruleinfo_pt->sid_search = NULL; + ruleinfo_pt->group_search = NULL; + + ruleinfo_pt->event_search = NULL; + + return(ruleinfo_pt); +} + + + +/** int _OS_GetRulesAttributes + * Reads the rules attributes and assign them. + */ +int _OS_GetRulesAttributes(char **attributes, char **values, + RuleInfo *ruleinfo_pt) +{ + int k = 0; + + char *xml_id = "id"; + char *xml_level = "level"; + char *xml_maxsize = "maxsize"; + char *xml_timeframe = "timeframe"; + char *xml_frequency = "frequency"; + char *xml_accuracy = "accuracy"; + char *xml_noalert = "noalert"; + char *xml_ignore_time = "ignore"; + char *xml_overwrite = "overwrite"; + + + /* Getting attributes */ + while(attributes[k]) + { + if(!values[k]) + { + merror(RL_EMPTY_ATTR, __local_name, attributes[k]); + return(-1); + } + /* Getting rule Id */ + else if(strcasecmp(attributes[k], xml_id) == 0) + { + if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 6 )) + { + ruleinfo_pt->sigid = atoi(values[k]); + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + /* Getting level */ + else if(strcasecmp(attributes[k],xml_level) == 0) + { + if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 3)) + { + ruleinfo_pt->level = atoi(values[k]); + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + /* Getting maxsize */ + else if(strcasecmp(attributes[k],xml_maxsize) == 0) + { + if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4)) + { + ruleinfo_pt->maxsize = atoi(values[k]); + + /* adding EXTRAINFO options */ + if(ruleinfo_pt->maxsize > 0 && + !(ruleinfo_pt->alert_opts & DO_EXTRAINFO)) + { + ruleinfo_pt->alert_opts |= DO_EXTRAINFO; + } + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + /* Getting timeframe */ + else if(strcasecmp(attributes[k],xml_timeframe) == 0) + { + if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 5)) + { + ruleinfo_pt->timeframe = atoi(values[k]); + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + /* Getting frequency */ + else if(strcasecmp(attributes[k],xml_frequency) == 0) + { + if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4)) + { + ruleinfo_pt->frequency = atoi(values[k]); + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + /* Rule accuracy */ + else if(strcasecmp(attributes[k],xml_accuracy) == 0) + { + merror("%s: XXX: Use of 'accuracy' isn't supported. Ignoring.", + __local_name); + } + /* Rule ignore_time */ + else if(strcasecmp(attributes[k],xml_ignore_time) == 0) + { + if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4)) + { + ruleinfo_pt->ignore_time = atoi(values[k]); + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + /* Rule noalert */ + else if(strcasecmp(attributes[k],xml_noalert) == 0) + { + ruleinfo_pt->alert_opts |= NO_ALERT; + } + else if(strcasecmp(attributes[k], xml_overwrite) == 0) + { + if(strcmp(values[k], "yes") == 0) + { + ruleinfo_pt->alert_opts |= DO_OVERWRITE; + } + else if(strcmp(values[k], "no") == 0) + { + } + else + { + merror(XML_VALUEERR,__local_name, attributes[k], values[k]); + return(-1); + } + } + else + { + merror(XML_INVELEM, __local_name, attributes[k]); + return(-1); + } + k++; + } + return(0); +} + + + +/* print rule */ +void OS_PrintRuleinfo(RuleInfo *rule) +{ + debug1("%s: __local_name: Print Rule:%d, level %d, ignore: %d, frequency:%d", + __local_name, + rule->sigid, + rule->level, + rule->ignore_time, + rule->frequency); +} + + + +/* EOF */ diff --git a/src/shared/sig_op.c b/src/shared/sig_op.c new file mode 100755 index 0000000..7820f21 --- /dev/null +++ b/src/shared/sig_op.c @@ -0,0 +1,73 @@ +/* @(#) $Id: sig_op.c,v 1.8 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* Functions to handle signal manipulation + */ + +#ifndef WIN32 + +#include +#include +#include + +#include "sig_op.h" +#include "file_op.h" +#include "debug_op.h" + +#include "error_messages/error_messages.h" + +char *pidfile = NULL; + +void HandleSIG() +{ + merror(SIGNAL_RECV, pidfile); + + DeletePID(pidfile); + + exit(1); +} + + +/* To avoid client-server communication problems */ +void HandleSIGPIPE() +{ + return; +} + +void StartSIG(char *process_name) +{ + /* Signal Manipulation + go to HandleSIG() */ + pidfile = process_name; + + signal(SIGHUP, SIG_IGN); + signal(SIGINT, HandleSIG); + signal(SIGQUIT, HandleSIG); + signal(SIGTERM, HandleSIG); + signal(SIGALRM, HandleSIG); + signal(SIGPIPE, HandleSIGPIPE); +} + +void StartSIG2(char *process_name, void (*func)(int)) +{ + pidfile = process_name; + + signal(SIGHUP, SIG_IGN); + signal(SIGINT, func); + signal(SIGQUIT, func); + signal(SIGTERM, func); + signal(SIGALRM, func); + signal(SIGPIPE, HandleSIGPIPE); +} + +#endif +/* EOF */ diff --git a/src/shared/store_op.c b/src/shared/store_op.c new file mode 100644 index 0000000..8566a2e --- /dev/null +++ b/src/shared/store_op.c @@ -0,0 +1,445 @@ +/* @(#) $Id: store_op.c,v 1.11 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Common API for dealing with ordered lists. + * Provides a fast search on average (n/2). + */ + + +#include "shared.h" + + +/* Create the list storage + * Return NULL on error + */ +OSStore *OSStore_Create() +{ + OSStore *my_list; + + my_list = calloc(1, sizeof(OSStore)); + if(!my_list) + return(NULL); + + my_list->first_node = NULL; + my_list->last_node = NULL; + my_list->cur_node = NULL; + my_list->currently_size = 0; + my_list->max_size = 0; + my_list->free_data_function = NULL; + + return(my_list); +} + + + +/* Deletes the list storage + * Return NULL on error + */ +OSStore *OSStore_Free(OSStore *list) +{ + OSStoreNode *delnode; + list->cur_node = list->first_node; + + while(list->cur_node) + { + if(list->cur_node->key) + { + free(list->cur_node->key); + list->cur_node->key = NULL; + } + if(list->cur_node->data) + { + free(list->cur_node->data); + list->cur_node->data = NULL; + } + + /* Deleting each node. */ + delnode = list->cur_node; + list->cur_node = list->cur_node->next; + free(delnode); + } + + list->first_node = NULL; + list->last_node = NULL; + + free(list); + list = NULL; + + return(list); +} + + + +/* Set the maximum number of elements + * in the storage. Returns 0 on error or + * 1 on success. + */ +int OSStore_SetMaxSize(OSStore *list, int max_size) +{ + if(!list) + { + return(0); + } + + /* Minimum size is 1 */ + if(max_size <= 1) + { + return(0); + } + + list->max_size = max_size; + + return(1); +} + + + +/* Set the pointer to the function to free the memory + * data. + */ +int OSStore_SetFreeDataPointer(OSStore *list, void *free_data_function) +{ + if(!list) + { + return(0); + } + + list->free_data_function = free_data_function; + return(1); +} + + + +/* Sorts the storage by size. + * + */ +int OSStore_Sort(OSStore *list, void*(sort_data_function)(void *d1, void *d2)) +{ + OSStoreNode *newnode = NULL; + OSStoreNode *movenode = NULL; + list->cur_node = list->first_node; + + while(list->cur_node) + { + movenode = list->cur_node->prev; + + /* Here we check for all the previous entries, using the sort . */ + while(movenode) + { + + if(sort_data_function(list->cur_node->data, movenode->data)) + { + movenode = movenode->prev; + } + + /* In here, this node should stay where it is. */ + else if(movenode == list->cur_node->prev) + { + break; + } + + /* In here we need to replace the nodes. */ + else + { + newnode = list->cur_node; + + if(list->cur_node->prev) + list->cur_node->prev->next = list->cur_node->next; + + if(list->cur_node->next) + list->cur_node->next->prev = list->cur_node->prev; + else + list->last_node = list->cur_node->prev; + + list->cur_node = list->cur_node->prev; + + + newnode->next = movenode->next; + newnode->prev = movenode; + + if(movenode->next) + movenode->next->prev = newnode; + + movenode->next = newnode; + + + break; + } + } + + + /* If movenode is not set, we need to put the current node in first.*/ + if(!movenode && (list->cur_node != list->first_node)) + { + newnode = list->cur_node; + + if(list->cur_node->prev) + list->cur_node->prev->next = list->cur_node->next; + + if(list->cur_node->next) + list->cur_node->next->prev = list->cur_node->prev; + else + list->last_node = list->cur_node->prev; + + list->cur_node = list->cur_node->prev; + + newnode->prev = NULL; + newnode->next = list->first_node; + list->first_node->prev = newnode; + + list->first_node = newnode; + } + + list->cur_node = list->cur_node->next; + } + + return(1); +} + + + +/* Get key position from storage + * Returns 0 if not present or the key + * if available. + * (position may change after each PUT) + */ +int OSStore_GetPosition(OSStore *list, char *key) +{ + int chk_rc, pos = 1; + list->cur_node = list->first_node; + + while(list->cur_node) + { + if((chk_rc = strcmp(list->cur_node->key, key)) >= 0) + { + /* Found */ + if(chk_rc == 0) + return(pos); + + /* Not found */ + return(0); + } + + list->cur_node = list->cur_node->next; + pos++; + } + return(0); +} + + + +/* Get first node from storage. + * Returns NULL if not present. + */ +OSStoreNode *OSStore_GetFirstNode(OSStore *list) +{ + return(list->first_node); +} + + + +/* Get data from storage. + * Returns NULL if not present. + */ +void *OSStore_Get(OSStore *list, char *key) +{ + int chk_rc; + list->cur_node = list->first_node; + + while(list->cur_node) + { + if((chk_rc = strcmp(list->cur_node->key, key)) >= 0) + { + /* Found */ + if(chk_rc == 0) + return(list->cur_node->data); + + /* Not found */ + return(NULL); + } + + list->cur_node = list->cur_node->next; + } + return(NULL); +} + + + +/* Check if key is present on storage. + * Returns 0 if not present. + */ +int OSStore_Check(OSStore *list, char *key) +{ + int chk_rc; + list->cur_node = list->first_node; + + while(list->cur_node) + { + if((chk_rc = strcmp(list->cur_node->key, key)) >= 0) + { + /* Found */ + if(chk_rc == 0) + return(1); + + /* Not found */ + return(0); + } + + list->cur_node = list->cur_node->next; + } + return(0); +} + + + +/* Check if key is present on storage (using strncmp). + * Returns 0 if not present. + */ +int OSStore_NCheck(OSStore *list, char *key) +{ + int chk_rc; + list->cur_node = list->first_node; + + while(list->cur_node) + { + if((chk_rc = strncmp(list->cur_node->key, key, + list->cur_node->key_size)) >= 0) + { + /* Found */ + if(chk_rc == 0) + return(1); + + /* Not found */ + return(0); + } + + list->cur_node = list->cur_node->next; + } + return(0); +} + + + +/* Check if key is present on storage (case insensitive). + * Returns 0 if not present. + */ +int OSStore_NCaseCheck(OSStore *list, char *key) +{ + int chk_rc; + list->cur_node = list->first_node; + + while(list->cur_node) + { + if((chk_rc = strncasecmp(list->cur_node->key, key, + list->cur_node->key_size)) == 0) + { + return(1); + } + + list->cur_node = list->cur_node->next; + } + return(0); +} + + + +/* Delete this node from list + * Pointer goes to the next node available. + */ +void OSStore_Delete(OSStore *list, char *key) +{ + return; +} + + + +/* Add data to the list + * Returns 1 on success and 0 on failure + */ +int OSStore_Put(OSStore *list, char *key, void *data) +{ + int chk_rc; + OSStoreNode *newnode; + + + /* Allocating memory for new node */ + newnode = calloc(1, sizeof(OSStoreNode)); + if(!newnode) + { + merror(MEM_ERROR, __local_name); + return(0); + } + + newnode->prev = NULL; + newnode->next = NULL; + newnode->data = data; + newnode->key = key; + newnode->key_size = strlen(key); + + + /* If we don't have first node, assign it */ + if(!list->first_node) + { + list->first_node = newnode; + list->last_node = newnode; + } + + + /* Store the data in order */ + else + { + list->cur_node = list->first_node; + while(list->cur_node) + { + if((chk_rc = strcmp(list->cur_node->key, key)) >= 0) + { + /* Duplicated entry */ + if(chk_rc == 0) + { + return(1); + } + + /* If there is no prev node, it is because + * this is the first node. + */ + if(list->cur_node->prev) + list->cur_node->prev->next = newnode; + else + list->first_node = newnode; + + + newnode->prev = list->cur_node->prev; + + list->cur_node->prev = newnode; + newnode->next = list->cur_node; + break; + } + + list->cur_node = list->cur_node->next; + } + + /* New node is the higher key */ + if(!newnode->next) + { + list->last_node->next = newnode; + newnode->prev = list->last_node; + list->last_node = newnode; + } + } + + + /* Increment list size */ + list->currently_size++; + + return(1); +} + +/* EOF */ diff --git a/src/shared/tests/Makefile b/src/shared/tests/Makefile new file mode 100755 index 0000000..ed01595 --- /dev/null +++ b/src/shared/tests/Makefile @@ -0,0 +1,10 @@ +# Makefile for misc tests + +maketest: + $(CC) -g -o prime_test prime_test.c ../math_op.c -I../ -I../../ -I../../headers/ -I../headers/ -Wall + $(CC) -g -o hash_test hash_test.c ../hash_op.c ../math_op.c -I../ -I../../ -I../../headers/ -I../headers/ -Wall + $(CC) -g -o merge_test merge_test.c ../file_op.c ../debug_op.c -I../ -I../../ -I../../headers/ -I../headers/ -Wall + $(CC) -DARGV0=\"ip_test\" -g -o ip_test ip_test.c ../validate_op.c ../debug_op.c ../regex_op.c -I../ -I../../ -I../../headers/ -I../headers/ -Wall + +clean: + -rm regex regex_str *.core diff --git a/src/shared/tests/hash_test.c b/src/shared/tests/hash_test.c new file mode 100755 index 0000000..d1464cf --- /dev/null +++ b/src/shared/tests/hash_test.c @@ -0,0 +1,39 @@ +#include +#include +#include "hash_op.h" + + +int main(int argc, char **argv) +{ + int i = 0; + char *tmp; + char buf[1024]; + OSHash *mhash; + + mhash = OSHash_Create(); + + while(1) + { + fgets(buf, 1024, stdin); + tmp = strchr(buf, '\n'); + if(tmp) + *tmp = '\0'; + + if(strncmp(buf, "get ", 4) == 0) + { + printf("Getting key: '%s'\n", buf + 4); + printf("Found: '%s'\n", (char *)OSHash_Get(mhash, buf + 4)); + } + else + { + printf("Adding key: '%s'\n", buf); + i = OSHash_Add(mhash, strdup(buf), strdup(buf)); + + printf("rc = %d\n", i); + } + } + return(0); +} + + +/* EOF */ diff --git a/src/shared/tests/ip_test.c b/src/shared/tests/ip_test.c new file mode 100755 index 0000000..149f1b9 --- /dev/null +++ b/src/shared/tests/ip_test.c @@ -0,0 +1,26 @@ +#include +#include +#include "validate_op.h" + + +int main(int argc, char **argv) +{ + os_ip myip; + + if(!argv[1]) + return(1); + + if(!OS_IsValidIP(argv[1], &myip)) + { + printf("Invalid ip\n"); + } + + if(OS_IPFound(argv[2], &myip)) + { + printf("IP MATCHED!\n"); + } + return(0); +} + + +/* EOF */ diff --git a/src/shared/tests/merge_test.c b/src/shared/tests/merge_test.c new file mode 100755 index 0000000..83fc313 --- /dev/null +++ b/src/shared/tests/merge_test.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include "file_op.h" + + +int main(int argc, char **argv) +{ + if(!argv[1]) + { + printf("%s [mu] ..\n", argv[0]); + exit(1); + } + + if(strcmp(argv[1], "m") == 0) + { + MergeFiles(argv[2], argv + 3); + } + else if(strcmp(argv[1], "u") == 0) + { + UnmergeFiles(argv[2]); + } + else + { + printf("ERROR\n"); + } + + return(0); +} + + +/* EOF */ diff --git a/src/shared/tests/prime_test.c b/src/shared/tests/prime_test.c new file mode 100755 index 0000000..8ee3757 --- /dev/null +++ b/src/shared/tests/prime_test.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include "math_op.h" + + +int main(int argc, char **argv) +{ + if(!argv[1]) + { + printf("%s \n", argv[0]); + exit(1); + } + + printf("Value: %d\n", os_getprime(atoi(argv[1]))); + + return(0); +} + + +/* EOF */ diff --git a/src/shared/validate_op.c b/src/shared/validate_op.c new file mode 100755 index 0000000..98e94fb --- /dev/null +++ b/src/shared/validate_op.c @@ -0,0 +1,898 @@ +/* @(#) $Id: validate_op.c,v 1.28 2009/08/05 18:02:13 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +/* Part of the OSSEC. + * Available at http://www.ossec.net + */ + + + +#include "shared.h" +char *ip_address_regex = + "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/?" + "([0-9]{0,2}|[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})$"; + +/* Global vars */ +int _mask_inited = 0; +int _netmasks[33]; + + +/* Read the file and return a string the matches the following + * format: high_name.low_name. + * If return is not null, value must be free. + */ +static char *_read_file(char *high_name, char *low_name, char *defines_file) +{ + FILE *fp; + char def_file[OS_FLSIZE +1]; + char buf[OS_SIZE_1024 +1]; + char *buf_pt; + char *tmp_buffer; + char *ret; + + #ifndef WIN32 + if(isChroot()) + { + snprintf(def_file,OS_FLSIZE,"%s", defines_file); + } + else + { + snprintf(def_file,OS_FLSIZE,"%s%s",DEFAULTDIR, defines_file); + } + #else + snprintf(def_file,OS_FLSIZE,"%s", defines_file); + #endif + + + fp = fopen(def_file, "r"); + if(!fp) + { + if(strcmp(defines_file, OSSEC_LDEFINES) != 0) + { + merror(FOPEN_ERROR, __local_name, def_file); + } + return(NULL); + } + + /* Invalid call */ + if(!high_name || !low_name) + { + merror(NULL_ERROR, __local_name); + fclose(fp); + return(NULL); + } + + /* Reading it */ + buf[OS_SIZE_1024] = '\0'; + while(fgets(buf, OS_SIZE_1024 , fp) != NULL) + { + /* Commented or blank lines */ + if(buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') + { + continue; + } + + /* Messages not formatted correctly */ + buf_pt = strchr(buf, '.'); + if(!buf_pt) + { + merror(FGETS_ERROR, __local_name, def_file, buf); + continue; + } + + /* Checking for the high name */ + *buf_pt = '\0'; buf_pt++; + if(strcmp(buf, high_name) != 0) + { + continue; + } + + tmp_buffer = buf_pt; + + /* Getting the equal */ + buf_pt = strchr(buf_pt, '='); + if(!buf_pt) + { + merror(FGETS_ERROR, __local_name, def_file, buf); + continue; + } + + /* Checking for the low name */ + *buf_pt = '\0'; buf_pt++; + if(strcmp(tmp_buffer, low_name) != 0) + { + continue; + } + + /* Removing new lines or anything that we cause errors */ + tmp_buffer = strrchr(buf_pt, '\n'); + if(tmp_buffer) + { + *tmp_buffer = '\0'; + } + + tmp_buffer = strrchr(buf_pt, '\r'); + if(tmp_buffer) + { + *tmp_buffer = '\0'; + } + + os_strdup(buf_pt, ret); + fclose(fp); + return(ret); + } + + fclose(fp); + return(NULL); +} + + + +/* Getting the netmask based on the integer value. */ +int getNetmask(int mask, char *strmask, int size) +{ + int i = 0; + + strmask[0] = '\0'; + + if(mask == 0) + { + snprintf(strmask, size, "/any"); + return(1); + } + + for(i = 0;i<=31;i++) + { + if(htonl(_netmasks[i]) == mask) + { + snprintf(strmask, size, "/%d", i); + break; + } + } + + return(1); +} + + + +/* Initialize netmasks -- took from snort util.c */ +void _init_masks() +{ + _mask_inited = 1; + _netmasks[0] = 0x0; + _netmasks[1] = 0x80000000; + _netmasks[2] = 0xC0000000; + _netmasks[3] = 0xE0000000; + _netmasks[4] = 0xF0000000; + _netmasks[5] = 0xF8000000; + _netmasks[6] = 0xFC000000; + _netmasks[7] = 0xFE000000; + _netmasks[8] = 0xFF000000; + _netmasks[9] = 0xFF800000; + _netmasks[10] = 0xFFC00000; + _netmasks[11] = 0xFFE00000; + _netmasks[12] = 0xFFF00000; + _netmasks[13] = 0xFFF80000; + _netmasks[14] = 0xFFFC0000; + _netmasks[15] = 0xFFFE0000; + _netmasks[16] = 0xFFFF0000; + _netmasks[17] = 0xFFFF8000; + _netmasks[18] = 0xFFFFC000; + _netmasks[19] = 0xFFFFE000; + _netmasks[20] = 0xFFFFF000; + _netmasks[21] = 0xFFFFF800; + _netmasks[22] = 0xFFFFFC00; + _netmasks[23] = 0xFFFFFE00; + _netmasks[24] = 0xFFFFFF00; + _netmasks[25] = 0xFFFFFF80; + _netmasks[26] = 0xFFFFFFC0; + _netmasks[27] = 0xFFFFFFE0; + _netmasks[28] = 0xFFFFFFF0; + _netmasks[29] = 0xFFFFFFF8; + _netmasks[30] = 0xFFFFFFFC; + _netmasks[31] = 0xFFFFFFFE; + _netmasks[32] = 0xFFFFFFFF; +} + + +/** getDefine_Int. + * Gets an integer definition. This function always return on + * success or exit on error. + */ +int getDefine_Int(char *high_name, char *low_name, int min, int max) +{ + int ret; + char *value; + char *pt; + + + /* We first try to read from the local define file. */ + value = _read_file(high_name, low_name, OSSEC_LDEFINES); + if(!value) + { + value = _read_file(high_name, low_name, OSSEC_DEFINES); + if(!value) + ErrorExit(DEF_NOT_FOUND, __local_name, high_name, low_name); + } + + pt = value; + while(*pt != '\0') + { + if(!isdigit((int)*pt)) + { + ErrorExit(INV_DEF, __local_name, high_name, low_name, value); + } + pt++; + } + + ret = atoi(value); + if((ret < min) || (ret > max)) + { + ErrorExit(INV_DEF, __local_name, high_name, low_name, value); + } + + /* Clearing memory */ + free(value); + + return(ret); +} + + +/** int OS_IPFound(char *ip_address, os_ip *that_ip) + * Checks if ip_address is present at that_ip. + * Returns 1 on success or 0 on failure. + */ +int OS_IPFound(char *ip_address, os_ip *that_ip) +{ + int _true = 1; + struct in_addr net; + + /* Extracting ip address */ + if((net.s_addr = inet_addr(ip_address)) <= 0) + { + return(!_true); + } + + /* If negate is set */ + if(that_ip->ip[0] == '!') + { + _true = 0; + } + + /* Checking if ip is in thatip & netmask */ + if((net.s_addr & that_ip->netmask) == that_ip->ip_address) + { + return(_true); + } + + /* Didn't match */ + return(!_true); +} + + +/** int OS_IPFoundList(char *ip_address, os_ip **list_of_ips) + * Checks if ip_address is present on the "list_of_ips". + * Returns 1 on success or 0 on failure. + * The list MUST be NULL terminated + */ +int OS_IPFoundList(char *ip_address, os_ip **list_of_ips) +{ + struct in_addr net; + int _true = 1; + + /* Extracting ip address */ + if((net.s_addr = inet_addr(ip_address)) <= 0) + { + return(!_true); + } + + while(*list_of_ips) + { + os_ip *l_ip = *list_of_ips; + + if(l_ip->ip[0] == '!') + { + _true = 0; + } + + if((net.s_addr & l_ip->netmask) == l_ip->ip_address) + { + return(_true); + } + list_of_ips++; + } + + return(!_true); +} + + +/** int OS_IsValidIP(char *ip) + * Validates if an ip address is in the right + * format. + * Returns 0 if doesn't match or 1 if it is an ip or 2 an ip with cidr. + * ** On success this function may modify the value of ip_address + */ +int OS_IsValidIP(char *ip_address, os_ip *final_ip) +{ + unsigned int nmask = 0; + char *tmp_str; + + /* Can't be null */ + if(!ip_address) + { + return(0); + } + + /* Assigning the ip address */ + if(final_ip) + { + os_strdup(ip_address, final_ip->ip); + } + + if(*ip_address == '!') + { + ip_address++; + } + + #ifndef WIN32 + /* checking against the basic regex */ + if(!OS_PRegex(ip_address, ip_address_regex)) + { + if(strcmp(ip_address, "any") != 0) + { + return(0); + } + } + #else + + if(strcmp(ip_address, "any") != 0) + { + char *tmp_ip; + int dots = 0; + tmp_ip = ip_address; + while(*tmp_ip != '\0') + { + if((*tmp_ip < '0' || + *tmp_ip > '9') && + *tmp_ip != '.' && + *tmp_ip != '/') + { + /* Invalid ip */ + return(0); + } + if(*tmp_ip == '.') + dots++; + tmp_ip++; + } + if(dots < 3 || dots > 6) + return(0); + } + #endif + + + + /* Getting the cidr/netmask if available */ + tmp_str = strchr(ip_address,'/'); + if(tmp_str) + { + int cidr; + struct in_addr net; + + *tmp_str = '\0'; + tmp_str++; + + /* Cidr */ + if(strlen(tmp_str) <= 2) + { + cidr = atoi(tmp_str); + if((cidr >= 0) && (cidr <= 32)) + { + if(!_mask_inited) + _init_masks(); + nmask = _netmasks[cidr]; + nmask = htonl(nmask); + } + else + { + return(0); + } + } + /* Full netmask */ + else + { + /* Init the masks */ + if(!_mask_inited) + _init_masks(); + + if(strcmp(tmp_str, "255.255.255.255") == 0) + { + nmask = htonl(_netmasks[32]); + } + else + { + if((nmask = inet_addr(ip_address)) <= 0) + { + return(0); + } + } + } + + if((net.s_addr = inet_addr(ip_address)) <= 0) + { + if(strcmp("0.0.0.0", ip_address) == 0) + { + net.s_addr = 0; + } + else + { + return(0); + } + } + + if(final_ip) + { + final_ip->ip_address = net.s_addr & nmask; + final_ip->netmask = nmask; + } + + tmp_str--; + *tmp_str = '/'; + + return(2); + } + + /* No cidr available */ + else + { + struct in_addr net; + nmask = 32; + + if(strcmp("any", ip_address) == 0) + { + net.s_addr = 0; + nmask = 0; + } + else if((net.s_addr = inet_addr(ip_address)) <= 0) + { + return(0); + } + + if(final_ip) + { + final_ip->ip_address = net.s_addr; + + if(!_mask_inited) + _init_masks(); + + final_ip->netmask = htonl(_netmasks[nmask]); + } + + /* Ip without cidr */ + if(nmask) + { + return(1); + } + + return(2); + } + + /* Should never reach here */ + return(0); +} + + +/** int OS_IsonTime(char *time_str, char *ossec_time) + * Must be a valid string, called after OS_IsValidTime. + * Returns 1 on success or 0 on failure. + */ +int OS_IsonTime(char *time_str, char *ossec_time) +{ + int _true = 1; + + if(*ossec_time == '!') + { + _true = 0; + } + ossec_time++; + + /* Comparing against min/max value */ + if((strncmp(time_str, ossec_time, 5) >= 0)&& + (strncmp(time_str, ossec_time+5,5) <= 0)) + { + return(_true); + } + + return(!_true); +} + + +/** char *OS_IsValidTime(char *time_str) + * Validates if a time is in an acceptable format + * for ossec. + * Returns 0 if doesn't match or a valid string for + * ossec usage in success. + * ** On success this function may modify the value of date + * Acceptable formats: + * hh:mm - hh:mm (24 hour format) + * !hh:mm -hh:mm (24 hour format) + * hh - hh (24 hour format) + * hh:mm am - hh:mm pm (12 hour format) + * hh am - hh pm (12 hour format) + */ +#define RM_WHITE(x)while(*x == ' ')x++; +char *__gethour(char *str, char *ossec_hour) +{ + int _size = 0; + int chour = 0; + int cmin = 0; + + /* Invalid time format */ + if(!isdigit((int)*str)) + { + merror(INVALID_TIME, __local_name, str); + } + + + /* Hour */ + chour = atoi(str); + + + /* Getting a valid hour */ + if(chour < 0 || chour >= 24) + { + merror(INVALID_TIME, __local_name, str); + return(NULL); + + } + + /* Going after the hour */ + while(isdigit((int)*str)) + { + _size++; + str++; + } + + /* Invalid hour */ + if(_size > 2) + { + merror(INVALID_TIME, __local_name, str); + return(NULL); + } + + + /* Getting minute */ + if(*str == ':') + { + str++; + if((!isdigit((int)*str)|| + !isdigit((int)*(str +1))) && isdigit((int)*(str +2))) + { + merror(INVALID_TIME, __local_name, str); + return(NULL); + } + + cmin = atoi(str); + str+=2; + } + + /* Removing spaces */ + RM_WHITE(str); + + if((*str == 'a') || (*str == 'A')) + { + str++; + if((*str == 'm') || (*str == 'M')) + { + snprintf(ossec_hour, 6, "%02d:%02d", chour, cmin); + str++; + return(str); + } + } + else if((*str == 'p') || (*str == 'P')) + { + str++; + if((*str == 'm') || (*str == 'M')) + { + chour += 12; + + /* New hour must be valid */ + if(chour < 0 || chour >= 24) + { + merror(INVALID_TIME, __local_name, str); + return(NULL); + } + + snprintf(ossec_hour, 6, "%02d:%02d", chour, cmin); + str++; + return(str); + } + + } + else + { + snprintf(ossec_hour, 6, "%02d:%02d", chour, cmin); + return(str); + } + + /* Here is error */ + merror(INVALID_TIME, __local_name, str); + return(NULL); +} + + +char *OS_IsValidTime(char *time_str) +{ + char *ret; + char first_hour[7]; + char second_hour[7]; + int ng = 0; + + /* Must be not null */ + if(!time_str) + return(NULL); + + + /* Clearing memory */ + memset(first_hour, '\0', 7); + memset(second_hour, '\0', 7); + + + /* Removing white spaces */ + RM_WHITE(time_str); + + + /* Checking for negative */ + if(*time_str == '!') + { + ng = 1; + time_str++; + + /* We may have white spaces after the '!' */ + RM_WHITE(time_str); + } + + + /* Getting first hour */ + time_str = __gethour(time_str, first_hour); + if(!time_str) + return(NULL); + + /* Removing white spaces */ + RM_WHITE(time_str); + + if(*time_str != '-') + { + return(NULL); + } + + time_str++; + + /* Removing white spaces */ + RM_WHITE(time_str); + + /* Getting second hour */ + time_str = __gethour(time_str, second_hour); + if(!time_str) + return(NULL); + + RM_WHITE(time_str); + if(*time_str != '\0') + { + return(NULL); + } + + os_calloc(13, sizeof(char), ret); + + /* Fixing dump hours */ + if(strcmp(first_hour,second_hour) > 0) + { + snprintf(ret, 12, "!%s%s", second_hour, first_hour); + return(ret); + } + + /* For the normal times */ + snprintf(ret, 12, "%c%s%s", ng == 0?'.':'!', first_hour, second_hour); + return(ret); +} + + + +/** int OS_IsAfterTime(char *time_str, char *ossec_time) + * Checks if the current time is the same or has passed the + * specified one. + */ +int OS_IsAfterTime(char *time_str, char *ossec_time) +{ + /* Unique times can't have a !. */ + if(*ossec_time == '!') + return(0); + + + ossec_time++; + + /* Comparing against min/max value */ + if(strncmp(time_str, ossec_time, 5) >= 0) + { + return(1); + } + + return(0); +} + + + +/** char *OS_IsValidUniqueTime(char *time_str) + * Creates a unique time, not a range. Must be used with OS_IsAfterTime. + */ +char *OS_IsValidUniqueTime(char *time_str) +{ + char mytime[128 +1]; + + if(*time_str == '!') + return(NULL); + + memset(mytime, '\0', 128 +1); + snprintf(mytime, 128, "%s-%s", time_str, time_str); + + + return(OS_IsValidTime(mytime)); +} + + + +/** int OS_IsonDay(int week_day, char *ossec_day) + * Checks if the specified week day is in the + * range. + */ +int OS_IsonDay(int week_day, char *ossec_day) +{ + int _true = 1; + + /* Negative */ + if(ossec_day[7] == '!') + _true = 0; + + if(week_day < 0 || week_day > 7) + { + return(0); + } + + /* It is on the right day */ + if(ossec_day[week_day] == 1) + return(_true); + + return(!_true); +} + + + +/** char *OS_IsValidDay(char *day_str) + * Validates if an day is in an acceptable format + * for ossec. + * Returns 0 if doesn't match or a valid string for + * ossec usage in success. + * ** On success this function may modify the value of date + * Acceptable formats: + * weekdays, weekends, monday, tuesday, thursday,.. + * monday,tuesday + * mon,tue wed + */ +#define RM_SEP(x)while((*x == ' ') || (*x == ','))x++; +#define IS_SEP(x) (*x == ' ' || *x == ',') +char *OS_IsValidDay(char *day_str) +{ + int i = 0, ng = 0; + char *ret; + char day_ret[9] = {0,0,0,0,0,0,0,0,0}; + char *(days[]) = + { + "sunday", "sun", "monday", "mon", "tuesday", "tue", + "wednesday", "wed", "thursday", "thu", "friday", + "fri", "saturday", "sat", "weekdays", "weekends", NULL + }; + int days_int[] = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,8}; + + /* Must be a valid string */ + if(!day_str) + return(NULL); + + + RM_WHITE(day_str); + + /* checking for negatives */ + if(*day_str == '!') + { + ng = 1; + RM_WHITE(day_str); + } + + while(*day_str != '\0') + { + i = 0; + while(days[i]) + { + if(strncasecmp(day_str, days[i], strlen(days[i])) == 0) + { + /* Weekdays */ + if(days_int[i] == 7) + { + day_ret[1] = 1; + day_ret[2] = 1; + day_ret[3] = 1; + day_ret[4] = 1; + day_ret[5] = 1; + } + /* weekends */ + else if(days_int[i] == 8) + { + day_ret[0] = 1; + day_ret[6] = 1; + } + else + { + day_ret[days_int[i]] = 1; + } + break; + } + i++; + } + + if(!days[i]) + { + merror(INVALID_DAY, __local_name, day_str); + return(NULL); + } + + day_str += strlen(days[i]); + + if(IS_SEP(day_str)) + { + RM_SEP(day_str); + continue; + } + else if(*day_str == '\0') + break; + else + { + merror(INVALID_DAY, __local_name, day_str); + return(NULL); + } + } + + /* Assigning values */ + os_calloc(9, sizeof(char), ret); + if(ng == 1) + { + /* Setting nevative */ + ret[7] = '!'; + } + + ng = 0; + for(i = 0;i<=6;i++) + { + /* Checking if some is checked */ + if(day_ret[i] == 1) + ng = 1; + ret[i] = day_ret[i]; + } + + /* At least one day must be checked */ + if(ng == 0) + { + free(ret); + merror(INVALID_DAY, __local_name, day_str); + return(NULL); + } + + return(ret); +} + +/* EOF */ diff --git a/src/shared/wait_op.c b/src/shared/wait_op.c new file mode 100755 index 0000000..5c59205 --- /dev/null +++ b/src/shared/wait_op.c @@ -0,0 +1,138 @@ +/* @(#) $Id: wait_op.c,v 1.5 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#define LOCK_LOOP 5 +int __wait_lock = 0; + + +/* Creates global lock */ +void os_setwait() +{ + FILE *fp = NULL; + + /* For same threads. */ + __wait_lock = 1; + + + if(isChroot()) + { + fp = fopen(WAIT_FILE, "w"); + } + else + { + fp = fopen(WAIT_FILE_PATH, "w"); + } + + if(fp) + { + fprintf(fp, "l"); + fclose(fp); + } + + return; +} + + +/* Removes global lock */ +void os_delwait() +{ + __wait_lock = 0; + + if(isChroot()) + { + unlink(WAIT_FILE); + } + else + { + unlink(WAIT_FILE_PATH); + } + return; +} + + + +/* Check for the wait file. If present, wait. + * Works as a simple inter process lock (only the main + * process is allowed to lock). + */ +#ifdef WIN32 +void os_wait() +{ + if(!__wait_lock) + return; + + + /* Wait until the lock is gone. */ + verbose(WAITING_MSG, __local_name); + while(1) + { + if(!__wait_lock) + break; + + /* Sleep LOCK_LOOP seconds and check it lock is gone. */ + sleep(LOCK_LOOP); + } + + + verbose(WAITING_FREE, __local_name); + return; + +} +#else + + +void os_wait() +{ + struct stat file_status; + + + /* If the wait file is not present, keep going. + */ + if(isChroot()) + { + if(stat(WAIT_FILE, &file_status) == -1) + return; + } + else + { + if(stat(WAIT_FILE_PATH, &file_status) == -1) + return; + } + + + /* Wait until the lock is gone. */ + verbose(WAITING_MSG, __local_name); + while(1) + { + if(isChroot()) + { + if(stat(WAIT_FILE, &file_status) == -1) + break; + } + else + { + if(stat(WAIT_FILE_PATH, &file_status) == -1) + break; + } + + /* Sleep LOCK_LOOP seconds and check it lock is gone. */ + sleep(LOCK_LOOP); + } + + verbose(WAITING_FREE, __local_name); + return; +} +#endif + + +/* EOF */ diff --git a/src/syscheckd/Makefile b/src/syscheckd/Makefile new file mode 100755 index 0000000..162edca --- /dev/null +++ b/src/syscheckd/Makefile @@ -0,0 +1,23 @@ +# Makefile for OSSEC syscheckd +# Daniel B. Cid +# http://www.ossec.net + +PT=../ +NAME=ossec-syscheckd + +include ../Config.Make + + +OBJS = syscheck.c config.c run_realtime.c create_db.c run_check.c ${OS_CONFIG} ${OS_ROOTCHECK} ${OS_SHARED} ${OS_XML} ${OS_REGEX} ${OS_NET} ${OS_CRYPTO} +OBJS2 = syscheck-baseline.c config.c create_db.c run_check.c ${OS_CONFIG} ${OS_ROOTCHECK} ${OS_SHARED} ${OS_XML} ${OS_REGEX} ${OS_NET} ${OS_CRYPTO} + +syscheck: + $(CC) $(CFLAGS) ${OS_LINK} $(OBJS) -o ${NAME} + +baseline: + $(CC) $(CFLAGS) ${OS_LINK} $(OBJS2) -o syscheck-baseline + +clean: + ${CLEAN} +build: + ${BUILD} diff --git a/src/syscheckd/config.c b/src/syscheckd/config.c new file mode 100755 index 0000000..9b57837 --- /dev/null +++ b/src/syscheckd/config.c @@ -0,0 +1,60 @@ +/* @(#) $Id: config.c,v 1.32 2009/11/04 15:19:00 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "syscheck.h" +#include "config/config.h" + +int Read_Syscheck_Config(char * cfgfile) +{ + int modules = 0; + + modules|= CSYSCHECK; + + syscheck.rootcheck = 0; + syscheck.disabled = 0; + syscheck.scan_on_start = 1; + syscheck.time = SYSCHECK_WAIT * 2; + syscheck.ignore = NULL; + syscheck.ignore_regex = NULL; + syscheck.scan_day = NULL; + syscheck.scan_time = NULL; + syscheck.dir = NULL; + syscheck.opts = NULL; + syscheck.realtime = NULL; + #ifdef WIN32 + syscheck.registry = NULL; + syscheck.reg_fp = NULL; + #endif + + + /* Reading config */ + if(ReadConfig(modules, cfgfile, &syscheck, NULL) < 0) + return(OS_INVALID); + + + #ifdef CLIENT + /* Reading shared config */ + modules|= CAGENT_CONFIG; + ReadConfig(modules, AGENTCONFIG, &syscheck, NULL); + #endif + + + /* We must have at least one directory to check */ + if(!syscheck.dir || syscheck.dir[0] == NULL) + { + return(1); + } + + + return(0); +} diff --git a/src/syscheckd/create_db.c b/src/syscheckd/create_db.c new file mode 100755 index 0000000..63610ba --- /dev/null +++ b/src/syscheckd/create_db.c @@ -0,0 +1,475 @@ +/* @(#) $Id: create_db.c,v 1.28 2009/10/02 19:28:34 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "syscheck.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/sha1/sha1_op.h" +#include "os_crypto/md5_sha1/md5_sha1_op.h" + + +/* flags for read_dir and read_file */ +#define CREATE_DB 1 +#define CHECK_DB 2 +int __counter = 0; + + +/** Prototypes **/ +int read_dir(char *dir_name, int opts, int flag); + + +/* int check_file(char *file_name) + * Checks if the file is already in the database. + */ +int check_file(char *file_name) +{ + char buf[MAX_LINE +2]; + buf[MAX_LINE +1] = '\0'; + + while(fgets(buf, MAX_LINE, syscheck.fp) != NULL) + { + if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n')) + { + char *n_buf; + + /* Removing the new line */ + n_buf = strchr(buf,'\n'); + if(n_buf == NULL) + continue; + + *n_buf = '\0'; + + + /* First 6 characters are for internal use */ + n_buf = buf; + n_buf+=6; + + n_buf = strchr(n_buf, ' '); + if(n_buf) + { + n_buf++; + + /* Checking if name matches */ + if(strcmp(n_buf, file_name) == 0) + return(1); + } + } + } + + /* New file */ + sleep(1); + + debug2("%s: DEBUG: new file '%s'.", ARGV0, file_name); + return(0); +} + + + +/* int read_file(char *file_name, int opts, int flag) + * Reads and generates the integrity data of a file. + */ +int read_file(char *file_name, int opts, int flag) +{ + int check_file_new = 0; + struct stat statbuf; + + /* Checking if file is to be ignored */ + if(syscheck.ignore) + { + int i = 0; + while(syscheck.ignore[i] != NULL) + { + if(strncasecmp(syscheck.ignore[i], file_name, + strlen(syscheck.ignore[i])) == 0) + { + return(0); + } + + i++; + } + } + + /* Checking in the regex entry */ + if(syscheck.ignore_regex) + { + int i = 0; + while(syscheck.ignore_regex[i] != NULL) + { + if(OSMatch_Execute(file_name, strlen(file_name), + syscheck.ignore_regex[i])) + { + return(0); + } + i++; + } + } + + + /* Win32 does not have lstat */ + #ifdef WIN32 + if(stat(file_name, &statbuf) < 0) + #else + if(lstat(file_name, &statbuf) < 0) + #endif + { + merror("%s: Error accessing '%s'.",ARGV0, file_name); + return(-1); + } + + if(S_ISDIR(statbuf.st_mode)) + { + #ifdef DEBUG + verbose("%s: Reading dir: %s\n",ARGV0, file_name); + #endif + + return(read_dir(file_name, opts, flag)); + } + + + /* No S_ISLNK on windows */ + #ifdef WIN32 + else if(S_ISREG(statbuf.st_mode)) + #else + else if(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) + #endif + { + os_md5 mf_sum; + os_sha1 sf_sum; + + + /* If check_db, we just need to verify that the file is + * already present. If not, we add it. + */ + if(flag == CHECK_DB) + { + /* File in the database already */ + fseek(syscheck.fp, 0, SEEK_SET); + if(check_file(file_name)) + { + /* Sleeping in here too */ + #ifndef WIN32 + if(__counter >= (3 * syscheck.sleep_after)) + #else + if(__counter >= (syscheck.sleep_after)) + #endif + { + sleep(syscheck.tsleep); + __counter = 0; + } + __counter++; + + return(0); + } + fseek(syscheck.fp, 0, SEEK_END); + check_file_new = 1; + } + + + /* Cleaning sums */ + strncpy(mf_sum, "xxx", 4); + strncpy(sf_sum, "xxx", 4); + + + /* Generating checksums. */ + if((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM)) + { + /* If it is a link, we need to check if dest is valid. */ + #ifndef WIN32 + if(S_ISLNK(statbuf.st_mode)) + { + struct stat statbuf_lnk; + if(stat(file_name, &statbuf_lnk) == 0) + { + if(S_ISREG(statbuf_lnk.st_mode)) + { + if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0) + { + strncpy(mf_sum, "xxx", 4); + strncpy(sf_sum, "xxx", 4); + } + } + } + } + else if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0) + + #else + if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0) + #endif + + { + strncpy(mf_sum, "xxx", 4); + strncpy(sf_sum, "xxx", 4); + } + } + + + /* Adding file */ + fprintf(syscheck.fp,"%c%c%c%c%c%c%d:%d:%d:%d:%s:%s %s\n", + opts & CHECK_SIZE?'+':'-', + opts & CHECK_PERM?'+':'-', + opts & CHECK_OWNER?'+':'-', + opts & CHECK_GROUP?'+':'-', + opts & CHECK_MD5SUM?'+':'-', + opts & CHECK_SHA1SUM?'+':'-', + opts & CHECK_SIZE?(int)statbuf.st_size:0, + opts & CHECK_PERM?(int)statbuf.st_mode:0, + opts & CHECK_OWNER?(int)statbuf.st_uid:0, + opts & CHECK_GROUP?(int)statbuf.st_gid:0, + opts & CHECK_MD5SUM?mf_sum:"xxx", + opts & CHECK_SHA1SUM?sf_sum:"xxx", + file_name); + + + /* Send new file */ + if(check_file_new) + { + char alert_msg[912 +2]; + + /* Sending the new checksum to the analysis server */ + alert_msg[912 +1] = '\0'; + snprintf(alert_msg, 912, "%d:%d:%d:%d:%s:%s %s", + opts & CHECK_SIZE?(int)statbuf.st_size:0, + opts & CHECK_PERM?(int)statbuf.st_mode:0, + opts & CHECK_OWNER?(int)statbuf.st_uid:0, + opts & CHECK_GROUP?(int)statbuf.st_gid:0, + opts & CHECK_MD5SUM?mf_sum:"xxx", + opts & CHECK_SHA1SUM?sf_sum:"xxx", + file_name); + send_syscheck_msg(alert_msg); + } + + + /* Sleeping in here too */ + #ifndef WIN32 + if(__counter >= (3 * syscheck.sleep_after)) + #else + if(__counter >= (2 * syscheck.sleep_after)) + #endif + { + sleep(syscheck.tsleep); + __counter = 0; + } + __counter++; + + + #ifdef DEBUG + verbose("%s: file '%s %s'",ARGV0, file_name, mf_sum); + #endif + } + else + { + #ifdef DEBUG + verbose("%s: *** IRREG file: '%s'\n",ARGV0,file_name); + #endif + } + + return(0); +} + + +/* read_dir v0.1 + * + */ +int read_dir(char *dir_name, int opts, int flag) +{ + int dir_size; + + char f_name[PATH_MAX +2]; + DIR *dp; + + struct dirent *entry; + + f_name[PATH_MAX +1] = '\0'; + + + /* Directory should be valid */ + if((dir_name == NULL)||((dir_size = strlen(dir_name)) > PATH_MAX)) + { + if(flag == CREATE_DB) + merror(NULL_ERROR, ARGV0); + + return(-1); + } + + + /* Opening the directory given */ + dp = opendir(dir_name); + if(!dp) + { + if(errno == ENOTDIR) + { + if(read_file(dir_name, opts, flag) == 0) + return(0); + } + + if(flag == CREATE_DB) + { + #ifdef WIN32 + int di = 0; + char *(defaultfilesn[])= { + "C:\\autoexec.bat", + "C:\\config.sys", + "C:\\WINDOWS/System32/eventcreate.exe", + "C:\\WINDOWS/System32/eventtriggers.exe", + "C:\\WINDOWS/System32/tlntsvr.exe", + "C:\\WINDOWS/System32/Tasks", + NULL + }; + while(defaultfilesn[di] != NULL) + { + if(strcmp(defaultfilesn[di], dir_name) == 0) + { + break; + } + di++; + } + + if(defaultfilesn[di] == NULL) + { + merror("%s: WARN: Error opening directory: '%s': %s ", + ARGV0, dir_name, strerror(errno)); + } + + #else + + merror("%s: WARN: Error opening directory: '%s': %s ", + ARGV0, + dir_name, + strerror(errno)); + #endif + } + + return(-1); + } + + + /* Checking for real time flag. */ + if(opts & CHECK_REALTIME) + { + #ifdef USEINOTIFY + realtime_adddir(dir_name); + #endif + } + + + while((entry = readdir(dp)) != NULL) + { + char *s_name; + + /* Just ignore . and .. */ + if((strcmp(entry->d_name,".") == 0) || + (strcmp(entry->d_name,"..") == 0)) + continue; + + strncpy(f_name, dir_name, PATH_MAX); + + s_name = f_name; + + s_name += dir_size; + + + /* checking if the file name is already null terminated */ + if(*(s_name-1) != '/') + *s_name++ = '/'; + + *s_name = '\0'; + + strncpy(s_name, entry->d_name, PATH_MAX - dir_size -2); + read_file(f_name, opts, flag); + } + + closedir(dp); + return(0); +} + + +/* int check_db() + * Checks database for new files. + */ +int check_db() +{ + int i = 0; + + /* Read all available directories */ + __counter = 0; + do + { + read_dir(syscheck.dir[i], syscheck.opts[i], CHECK_DB); + i++; + }while(syscheck.dir[i] != NULL); + + return(0); +} + + + +/* int create_db + * Creates the file database. + */ +int create_db(int delete_db) +{ + int i = 0; + + syscheck.fp = fopen(syscheck.db, "w+"); /* Read and write */ + if(!syscheck.fp) + { + ErrorExit("%s: Unable to create syscheck database " + "at '%s'. Exiting.",ARGV0,syscheck.db); + return(0); + } + + + /* Creating a local fp only */ + if(delete_db) + { + unlink(syscheck.db); + } + + + /* dir_name can't be null */ + if((syscheck.dir == NULL) || (syscheck.dir[0] == NULL)) + { + merror("%s: No directories to check.",ARGV0); + return(-1); + } + + + merror("%s: INFO: Starting syscheck database (pre-scan).", ARGV0); + + + /* Read all available directories */ + __counter = 0; + do + { + if(read_dir(syscheck.dir[i], syscheck.opts[i], CREATE_DB) == 0) + { + #ifdef WIN32 + if(syscheck.opts[i] & CHECK_REALTIME) + { + realtime_adddir(syscheck.dir[i]); + } + #endif + } + i++; + }while(syscheck.dir[i] != NULL); + + + merror("%s: INFO: Finished creating syscheck database (pre-scan " + "completed).", ARGV0); + return(0); + +} + +/* EOF */ diff --git a/src/syscheckd/run_check.c b/src/syscheckd/run_check.c new file mode 100755 index 0000000..26c5a93 --- /dev/null +++ b/src/syscheckd/run_check.c @@ -0,0 +1,710 @@ +/* @(#) $Id: run_check.c,v 1.49 2009/11/05 15:15:14 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* SCHED_BATCH is Linux specific and is only picked up with _GNU_SOURCE */ +#ifdef __linux__ + #define _GNU_SOURCE + #include +#endif + +#include "shared.h" +#include "syscheck.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/sha1/sha1_op.h" +#include "os_crypto/md5_sha1/md5_sha1_op.h" + +#include "rootcheck/rootcheck.h" + + +/** Prototypes **/ +int c_read_file(char *file_name, char *oldsum, char *newsum); + + +/* Send syscheck message. + * Send a message related to syscheck change/addition. + */ +int send_syscheck_msg(char *msg) +{ + if(SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + + if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + + /* If we reach here, we can try to send it again */ + SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ); + } + + return(0); +} + + + +/* Send rootcheck message. + * Send a message related to rootcheck change/addition. + */ +int send_rootcheck_msg(char *msg) +{ + if(SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + + if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + + /* If we reach here, we can try to send it again */ + SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ); + } + + return(0); +} + + +/* Sends syscheck db to the server. + */ +void send_sk_db() +{ + char buf[MAX_LINE +1]; + int file_count = 0; + + buf[MAX_LINE] = '\0'; + + if(fseek(syscheck.fp, 0, SEEK_SET) == -1) + { + ErrorExit(FSEEK_ERROR, ARGV0, "syscheck_db"); + } + + + /* Sending scan start message */ + if(syscheck.dir[0]) + { + merror("%s: INFO: Starting syscheck scan (forwarding database).", ARGV0); + send_rootcheck_msg("Starting syscheck scan."); + } + else + { + sleep(syscheck.tsleep +10); + return; + } + + + + while(fgets(buf,MAX_LINE, syscheck.fp) != NULL) + { + if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n')) + { + char *n_buf; + + /* Removing the \n before sending to the analysis server */ + n_buf = strchr(buf,'\n'); + if(n_buf == NULL) + continue; + + *n_buf = '\0'; + + + /* First 6 characters are for internal use */ + n_buf = buf; + n_buf+=6; + + send_syscheck_msg(n_buf); + + + /* A count and a sleep to avoid flooding the server. + * Time or speed are not requirements in here + */ + file_count++; + + + /* sleep X every Y files */ + if(file_count >= syscheck.sleep_after) + { + sleep(syscheck.tsleep); + file_count = 0; + } + } + } + + + /* Sending scan ending message */ + sleep(syscheck.tsleep +10); + + if(syscheck.dir[0]) + { + merror("%s: INFO: Ending syscheck scan (forwarding database).", ARGV0); + send_rootcheck_msg("Ending syscheck scan."); + } +} + + + +/* start_daemon + * Run periodicaly the integrity checking + */ +void start_daemon() +{ + int day_scanned = 0; + int curr_day = 0; + + time_t curr_time = 0; + + time_t prev_time_rk = 0; + time_t prev_time_sk = 0; + + char curr_hour[12]; + + struct tm *p; + + + /* To be used by select. */ + #ifdef USEINOTIFY + struct timeval selecttime; + fd_set rfds; + #endif + + + /* + * SCHED_BATCH forces the kernel to assume this is a cpu intensive + * process + * and gives it a lower priority. This keeps ossec-syscheckd + * from reducing + * the interactity of an ssh session when checksumming large files. + * This is available in kernel flavors >= 2.6.16 + */ + #ifdef SCHED_BATCH + struct sched_param pri; + int status; + + pri.sched_priority = 0; + status = sched_setscheduler(0, SCHED_BATCH, &pri); + + debug1("%s: Setting SCHED_BATCH returned: %d", ARGV0, status); + #endif + + + #ifdef DEBUG + verbose("%s: Starting daemon ..",ARGV0); + #endif + + + + /* Some time to settle */ + memset(curr_hour, '\0', 12); + sleep(syscheck.tsleep * 10); + + + + /* If the scan time/day is set, reset the + * syscheck.time/rootcheck.time + */ + if(syscheck.scan_time || syscheck.scan_day) + { + /* At least once a week. */ + syscheck.time = 604800; + rootcheck.time = 604800; + } + + + /* Will create the db to store syscheck data */ + if(syscheck.scan_on_start) + { + create_db(1); + fflush(syscheck.fp); + + sleep(syscheck.tsleep * 60); + send_sk_db(); + } + else + { + prev_time_rk = time(0); + } + + + + /* Before entering in daemon mode itself */ + prev_time_sk = time(0); + sleep(syscheck.tsleep * 10); + + + /* If the scan_time or scan_day is set, we need to handle the + * current day/time on the loop. + */ + if(syscheck.scan_time || syscheck.scan_day) + { + curr_time = time(0); + p = localtime(&curr_time); + + + /* Assign hour/min/sec values */ + snprintf(curr_hour, 9, "%02d:%02d:%02d", + p->tm_hour, + p->tm_min, + p->tm_sec); + + + curr_day = p->tm_mday; + + + + if(syscheck.scan_time && syscheck.scan_day) + { + if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) && + (OS_IsonDay(p->tm_wday, syscheck.scan_day))) + { + day_scanned = 1; + } + } + + else if(syscheck.scan_time) + { + if(OS_IsAfterTime(curr_hour, syscheck.scan_time)) + { + day_scanned = 1; + } + } + else if(syscheck.scan_day) + { + if(OS_IsonDay(p->tm_wday, syscheck.scan_day)) + { + day_scanned = 1; + } + } + } + + + #if defined (USEINOTIFY) || defined (WIN32) + if(syscheck.realtime && (syscheck.realtime->fd >= 0)) + verbose("%s: INFO: Starting real time file monitoring.", ARGV0); + #endif + + + /* Checking every SYSCHECK_WAIT */ + while(1) + { + int run_now = 0; + curr_time = time(0); + + + /* Checking if syscheck should be restarted, */ + run_now = os_check_restart_syscheck(); + + + /* Checking if a day_time or scan_time is set. */ + if(syscheck.scan_time || syscheck.scan_day) + { + p = localtime(&curr_time); + + + /* Day changed. */ + if(curr_day != p->tm_mday) + { + day_scanned = 0; + curr_day = p->tm_mday; + } + + + /* Checking for the time of the scan. */ + if(!day_scanned && syscheck.scan_time && syscheck.scan_day) + { + if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) && + (OS_IsonDay(p->tm_wday, syscheck.scan_day))) + { + day_scanned = 1; + run_now = 1; + } + } + + else if(!day_scanned && syscheck.scan_time) + { + /* Assign hour/min/sec values */ + snprintf(curr_hour, 9, "%02d:%02d:%02d", + p->tm_hour, p->tm_min, p->tm_sec); + + if(OS_IsAfterTime(curr_hour, syscheck.scan_time)) + { + run_now = 1; + day_scanned = 1; + } + } + + /* Checking for the day of the scan. */ + else if(!day_scanned && syscheck.scan_day) + { + if(OS_IsonDay(p->tm_wday, syscheck.scan_day)) + { + run_now = 1; + day_scanned = 1; + } + } + } + + + + /* If time elapsed is higher than the rootcheck_time, + * run it. + */ + if(syscheck.rootcheck) + { + if(((curr_time - prev_time_rk) > rootcheck.time) || run_now) + { + run_rk_check(); + prev_time_rk = time(0); + } + } + + + /* If time elapsed is higher than the syscheck time, + * run syscheck time. + */ + if(((curr_time - prev_time_sk) > syscheck.time) || run_now) + { + /* We need to create the db, if scan on start is not set. */ + if(syscheck.scan_on_start == 0) + { + create_db(1); + fflush(syscheck.fp); + + sleep(syscheck.tsleep * 10); + send_sk_db(); + sleep(syscheck.tsleep * 10); + + syscheck.scan_on_start = 1; + } + + + else + { + /* Sending scan start message */ + if(syscheck.dir[0]) + { + merror("%s: INFO: Starting syscheck scan.", ARGV0); + send_rootcheck_msg("Starting syscheck scan."); + } + + + #ifdef WIN32 + /* Checking for registry changes on Windows */ + os_winreg_check(); + #endif + + + check_db(); + + + /* Set syscheck.fp to the begining of the file */ + fseek(syscheck.fp, 0, SEEK_SET); + + + /* Checking for changes */ + run_check(); + } + + + /* Sending scan ending message */ + sleep(syscheck.tsleep + 20); + if(syscheck.dir[0]) + { + merror("%s: INFO: Ending syscheck scan.", ARGV0); + send_rootcheck_msg("Ending syscheck scan."); + } + + + + /* Sending database completed message */ + send_syscheck_msg(HC_SK_DB_COMPLETED); + debug2("%s: DEBUG: Sending database completed message.", ARGV0); + + + prev_time_sk = time(0); + } + + + #ifdef USEINOTIFY + if(syscheck.realtime && (syscheck.realtime->fd >= 0)) + { + selecttime.tv_sec = SYSCHECK_WAIT; + selecttime.tv_usec = 0; + + /* zero-out the fd_set */ + FD_ZERO (&rfds); + + FD_SET(syscheck.realtime->fd, &rfds); + + run_now = select(syscheck.realtime->fd + 1, &rfds, + NULL, NULL, &selecttime); + if(run_now < 0) + { + merror("%s: ERROR: Select failed (for realtime fim).", ARGV0); + sleep(SYSCHECK_WAIT); + } + else if(run_now == 0) + { + /* Timeout. */ + } + else if (FD_ISSET (syscheck.realtime->fd, &rfds)) + { + realtime_process(); + } + } + else + { + sleep(SYSCHECK_WAIT); + } + + #elif WIN32 + if(syscheck.realtime && (syscheck.realtime->fd >= 0)) + { + run_now = WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE); + if(run_now == WAIT_FAILED) + { + merror("%s: ERROR: WaitForSingleObjectEx failed (for realtime fim).", ARGV0); + sleep(SYSCHECK_WAIT); + } + else + { + sleep(1); + } + } + else + { + sleep(SYSCHECK_WAIT); + } + + + #else + sleep(SYSCHECK_WAIT); + #endif + } +} + + +/* run_check: v0.1 + * Read the database and check if the binary has changed + */ +void run_check() +{ + char c_sum[256 +2]; + char alert_msg[912 +2]; + char buf[MAX_LINE +2]; + int file_count = 0; + + + /* Cleaning buffer */ + memset(buf, '\0', MAX_LINE +1); + memset(alert_msg, '\0', 912 +1); + memset(c_sum, '\0', 256 +1); + + /* fgets garantee the null termination */ + while(fgets(buf, MAX_LINE, syscheck.fp) != NULL) + { + /* Buf should be in the following format: + * header checksum file_name (checksum space filename) + */ + char *n_file; /* file read from the db */ + char *n_sum; /* md5sum read from the db */ + char *tmp_c; /* tmp_char */ + + + /* Avoiding wrong formats in the database. Alert about them */ + if(buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') + { + merror("%s: Invalid entry in the integrity database: '%s'", + ARGV0, buf); + continue; + } + + /* Adding a sleep in here -- avoid floods and extreme CPU usage + * on the client side -- speed not necessary + */ + file_count++; + if(file_count >= (syscheck.sleep_after)) + { + sleep(syscheck.tsleep); + file_count = 0; + } + + + /* Finding the file name */ + n_file = strchr(buf, ' '); + if(n_file == NULL) + { + merror("%s: Invalid entry in the integrity check database.",ARGV0); + continue; + } + + /* Zeroing the ' ' and messing up with buf */ + *n_file = '\0'; + + + /* Setting n_file to the begining of the file name */ + n_file++; + + + /* Removing the '\n' if present and setting it to \0 */ + tmp_c = strchr(n_file,'\n'); + if(tmp_c) + { + *tmp_c = '\0'; + } + + + /* Setting n_sum to the begining of buf */ + n_sum = buf; + + + /* Cleaning up c_sum */ + memset(c_sum, '\0', 16); + c_sum[255] = '\0'; + + + /* If it returns < 0, we will already have alerted. */ + if(c_read_file(n_file, n_sum, c_sum) < 0) + continue; + + + if(strcmp(c_sum, n_sum+6) != 0) + { + /* Sending the new checksum to the analysis server */ + alert_msg[912 +1] = '\0'; + snprintf(alert_msg, 912, "%s %s", c_sum, n_file); + send_syscheck_msg(alert_msg); + + continue; + } + + /* FILE OK if reached here */ + } +} + + +/* c_read_file + * Read file information and return a pointer + * to the checksum + */ +int c_read_file(char *file_name, char *oldsum, char *newsum) +{ + int size = 0, perm = 0, owner = 0, group = 0, md5sum = 0, sha1sum = 0; + + struct stat statbuf; + + os_md5 mf_sum; + os_sha1 sf_sum; + + + /* Cleaning sums */ + strncpy(mf_sum, "xxx", 4); + strncpy(sf_sum, "xxx", 4); + + + + /* Stating the file */ + #ifdef WIN32 + if(stat(file_name, &statbuf) < 0) + #else + if(lstat(file_name, &statbuf) < 0) + #endif + { + char alert_msg[912 +2]; + + alert_msg[912 +1] = '\0'; + snprintf(alert_msg, 912,"-1 %s", file_name); + send_syscheck_msg(alert_msg); + + return(-1); + } + + /* Getting the old sum values */ + + /* size */ + if(oldsum[0] == '+') + size = 1; + + /* perm */ + if(oldsum[1] == '+') + perm = 1; + + /* owner */ + if(oldsum[2] == '+') + owner = 1; + + /* group */ + if(oldsum[3] == '+') + group = 1; + + /* md5 sum */ + if(oldsum[4] == '+') + md5sum = 1; + + /* sha1 sum */ + if(oldsum[5] == '+') + sha1sum = 1; + + + /* Generating new checksum */ + #ifdef WIN32 + if(S_ISREG(statbuf.st_mode)) + #else + if(S_ISREG(statbuf.st_mode)) + #endif + { + if(sha1sum || md5sum) + { + /* Generating checksums of the file. */ + if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0) + { + strncpy(sf_sum, "xxx", 4); + strncpy(mf_sum, "xxx", 4); + } + } + } + #ifndef WIN32 + /* If it is a link, we need to check if the actual file is valid. */ + else if(S_ISLNK(statbuf.st_mode)) + { + struct stat statbuf_lnk; + if(stat(file_name, &statbuf_lnk) == 0) + { + if(S_ISREG(statbuf_lnk.st_mode)) + { + if(sha1sum || md5sum) + { + /* Generating checksums of the file. */ + if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0) + { + strncpy(sf_sum, "xxx", 4); + strncpy(mf_sum, "xxx", 4); + } + } + } + } + } + #endif + + newsum[0] = '\0'; + newsum[255] = '\0'; + snprintf(newsum,255,"%d:%d:%d:%d:%s:%s", + size == 0?0:(int)statbuf.st_size, + perm == 0?0:(int)statbuf.st_mode, + owner== 0?0:(int)statbuf.st_uid, + group== 0?0:(int)statbuf.st_gid, + md5sum == 0?"xxx":mf_sum, + sha1sum == 0?"xxx":sf_sum); + + return(0); +} + +/* EOF */ diff --git a/src/syscheckd/run_realtime.c b/src/syscheckd/run_realtime.c new file mode 100755 index 0000000..efae806 --- /dev/null +++ b/src/syscheckd/run_realtime.c @@ -0,0 +1,491 @@ +/* @(#) $Id: run_realtime.c,v 1.12 2009/12/01 15:40:08 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef WIN32 +#include +#include +#include + +#define sleep(x) Sleep(x * 1000) +#define os_calloc(x,y,z) (z = calloc(x,y))?(void)1:ErrorExit(MEM_ERROR, ARGV0) +#define os_strdup(x,y) (y = strdup(x))?(void)1:ErrorExit(MEM_ERROR, ARGV0) +#endif + + +#include "hash_op.h" +#include "debug_op.h" +#include "syscheck.h" +#include "error_messages/error_messages.h" + + +#ifdef USEINOTIFY +#include +#endif + + + +/** Global functions for all realtime options. **/ +int c_read_file(char *file_name, char *oldsum, char *newsum); + + +/* Checking sum of the realtime file being monitored. */ +int realtime_checksumfile(char *file_name) +{ + char buf[MAX_LINE +2]; + buf[MAX_LINE +1] = '\0'; + + + fseek(syscheck.fp, 0, SEEK_SET); + while(fgets(buf, MAX_LINE, syscheck.fp) != NULL) + { + if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n')) + { + char *n_buf; + + /* Removing the new line */ + n_buf = strchr(buf,'\n'); + if(n_buf == NULL) + continue; + + *n_buf = '\0'; + + + /* First 6 characters are for internal use */ + n_buf = buf; + n_buf+=6; + + n_buf = strchr(n_buf, ' '); + if(n_buf) + { + n_buf++; + + /* Checking if name matches */ + if(strcmp(n_buf, file_name) == 0) + { + char c_sum[256 +2]; + c_sum[0] = '\0'; + c_sum[255] = '\0'; + + + /* If it returns < 0, we will already have alerted. */ + if(c_read_file(file_name, buf, c_sum) < 0) + continue; + + + if(strcmp(c_sum, buf+6) != 0) + { + char alert_msg[912 +2]; + + /* Sending the new checksum to the analysis server */ + alert_msg[912 +1] = '\0'; + snprintf(alert_msg, 912, "%s %s", c_sum, file_name); + send_syscheck_msg(alert_msg); + + return(1); + } + + return(0); + + } + } + } + } + + + /* Adding entry if not in there. */ + fseek(syscheck.fp, 0, SEEK_END); + return(0); +} + + + + +#ifdef USEINOTIFY +#include + + +#define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_TO|IN_DELETE|IN_MOVED_FROM +#define REALTIME_EVENT_SIZE (sizeof (struct inotify_event)) +#define REALTIME_EVENT_BUFFER (2048 * (REALTIME_EVENT_SIZE + 16)) + + + +/* Starts real time monitoring using inotify. */ +int realtime_start() +{ + verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0); + + syscheck.realtime = calloc(1, sizeof(rtfim)); + if(syscheck.realtime == NULL) + { + ErrorExit(MEM_ERROR, ARGV0); + } + syscheck.realtime->dirtb = (void *)OSHash_Create(); + syscheck.realtime->fd = -1; + + #ifdef USEINOTIFY + syscheck.realtime->fd = inotify_init(); + if(syscheck.realtime->fd < 0) + { + merror("%s: ERROR: Unable to initialize inotify.", ARGV0); + return(-1); + } + #endif + + return(1); +} + + + +/* Adds a directory to real time checking. */ +int realtime_adddir(char *dir) +{ + if(!syscheck.realtime) + { + realtime_start(); + } + + + /* Checking if it is ready to use. */ + if(syscheck.realtime->fd < 0) + { + return(-1); + } + else + { + int wd = 0; + + wd = inotify_add_watch(syscheck.realtime->fd, + dir, + REALTIME_MONITOR_FLAGS); + if(wd < 0) + { + merror("%s: ERROR: Unable to add directory to real time " + "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno); + } + else + { + char wdchar[32 +1]; + wdchar[32] = '\0'; + snprintf(wdchar, 32, "%d", wd); + + /* Entry not present. */ + if(!OSHash_Get(syscheck.realtime->dirtb, wdchar)) + { + char *ndir; + + ndir = strdup(dir); + if(ndir == NULL) + { + ErrorExit("%s: ERROR: Out of memory. Exiting.", ARGV0); + } + + OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), ndir); + debug1("%s: DEBUG: Directory added for real time monitoring: " + "'%s'.", ARGV0, ndir); + } + } + } + + return(1); +} + + +/* Process events in the real time queue. */ +int realtime_process() +{ + int len, i = 0; + char buf[REALTIME_EVENT_BUFFER +1]; + struct inotify_event *event; + + buf[REALTIME_EVENT_BUFFER] = '\0'; + + + len = read(syscheck.realtime->fd, buf, REALTIME_EVENT_BUFFER); + if (len < 0) + { + merror("%s: ERROR: Unable to read from real time buffer.", ARGV0); + } + else if (len > 0) + { + while (i < len) + { + event = (struct inotify_event *) &buf[i]; + + if(event->len) + { + char wdchar[32 +1]; + char final_name[MAX_LINE +1]; + + wdchar[32] = '\0'; + final_name[MAX_LINE] = '\0'; + + snprintf(wdchar, 32, "%d", event->wd); + + snprintf(final_name, MAX_LINE, "%s/%s", + (char *)OSHash_Get(syscheck.realtime->dirtb, wdchar), + event->name); + realtime_checksumfile(final_name); + } + + i += REALTIME_EVENT_SIZE + event->len; + } + } + + return(0); +} + + + +#elif WIN32 +typedef struct _win32rtfim +{ + HANDLE h; + OVERLAPPED overlap; + + char *dir; + TCHAR buffer[12288]; +}win32rtfim; + +int realtime_win32read(win32rtfim *rtlocald); + +void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap) +{ + int lcount; + size_t offset = 0; + + char *ptfile; + char wdchar[32 +1]; + char final_path[MAX_LINE +1]; + + win32rtfim *rtlocald; + + PFILE_NOTIFY_INFORMATION pinfo; + TCHAR finalfile[MAX_PATH]; + + if(dwBytes == 0) + { + merror("%s: ERROR: real time call back called, but 0 bytes.", ARGV0); + return; + } + + if(dwerror != ERROR_SUCCESS) + { + merror("%s: ERROR: real time call back called, but error is set.", + ARGV0); + return; + } + + + /* Getting hash to parse the data. */ + wdchar[32] = '\0'; + snprintf(wdchar, 32, "%d", (int)overlap->Offset); + rtlocald = OSHash_Get(syscheck.realtime->dirtb, wdchar); + if(rtlocald == NULL) + { + merror("%s: ERROR: real time call back called, but hash is empty.", + ARGV0); + return; + } + + + + do + { + pinfo = (PFILE_NOTIFY_INFORMATION) &rtlocald->buffer[offset]; + offset += pinfo->NextEntryOffset; + + lcount = WideCharToMultiByte(CP_ACP, 0, pinfo->FileName, + pinfo->FileNameLength / sizeof(WCHAR), + finalfile, MAX_PATH - 1, NULL, NULL); + finalfile[lcount] = TEXT('\0'); + + + /* Change forward slashes to backslashes on finalfile. */ + ptfile = strchr(finalfile, '\\'); + while(ptfile) + { + *ptfile = '/'; + ptfile++; + + ptfile = strchr(ptfile, '\\'); + } + + final_path[MAX_LINE] = '\0'; + snprintf(final_path, MAX_LINE, "%s/%s", rtlocald->dir, finalfile); + + + /* Checking the change. */ + realtime_checksumfile(final_path); + + + /* + if(pinfo->Action == FILE_ACTION_ADDED) + else if(pinfo->Action == FILE_ACTION_REMOVED) + else if(pinfo->Action == FILE_ACTION_MODIFIED) + else if(pinfo->Action == FILE_ACTION_RENAMED_OLD_NAME) + else if(pinfo->Action == FILE_ACTION_RENAMED_NEW_NAME) + else + */ + + }while(pinfo->NextEntryOffset != 0); + + + realtime_win32read(rtlocald); + + + return; +} + + + +int realtime_start() +{ + verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0); + + os_calloc(1, sizeof(rtfim), syscheck.realtime); + syscheck.realtime->dirtb = (void *)OSHash_Create(); + syscheck.realtime->fd = -1; + syscheck.realtime->evt = CreateEvent(NULL, TRUE, FALSE, NULL); + return(0); +} + +int realtime_win32read(win32rtfim *rtlocald) +{ + int rc; + + rc = ReadDirectoryChangesW(rtlocald->h, + rtlocald->buffer, + sizeof(rtlocald->buffer) / sizeof(TCHAR), + TRUE, + FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE, + 0, + &rtlocald->overlap, + RTCallBack); + if(rc == 0) + { + merror("%s: ERROR: Unable to set directory for monitoring: %s", + ARGV0, rtlocald->dir); + sleep(2); + } + + return(0); +} + +int realtime_adddir(char *dir) +{ + char wdchar[32 +1]; + win32rtfim *rtlocald; + + + if(!syscheck.realtime) + { + realtime_start(); + } + + + /* Maximum limit for realtime on Windows. */ + if(syscheck.realtime->fd > 256) + { + merror("%s: ERROR: Unable to add directory to real time " + "monitoring: '%s' - Maximum size permitted.", ARGV0, dir); + return(0); + } + + + os_calloc(1, sizeof(win32rtfim), rtlocald); + + + rtlocald->h = CreateFile(dir, + FILE_LIST_DIRECTORY, + FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, + NULL); + + + if(rtlocald->h == INVALID_HANDLE_VALUE || + rtlocald->h == NULL) + { + free(rtlocald); + rtlocald = NULL; + merror("%s: ERROR: Unable to add directory to real time " + "monitoring: '%s'.", ARGV0, dir); + return(0); + } + + rtlocald->overlap.Offset = ++syscheck.realtime->fd; + + + + /* Setting key for hash. */ + wdchar[32] = '\0'; + snprintf(wdchar, 32, "%d", (int)rtlocald->overlap.Offset); + + + if(OSHash_Get(syscheck.realtime->dirtb, wdchar)) + { + merror("%s: ERROR: Entry already in the real time hash: %s", + ARGV0, wdchar); + CloseHandle(rtlocald->overlap.hEvent); + free(rtlocald); + rtlocald = NULL; + return(0); + } + + + /* Adding final elements to the hash. */ + os_strdup(dir, rtlocald->dir); + + OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), rtlocald); + + + /* Adding directory to be monitored. */ + realtime_win32read(rtlocald); + + + return(1); +} + + + + + +#else +int realtime_start() +{ + verbose("%s: ERROR: Unable to initalize real time file monitoring.", ARGV0); + return(0); +} + +int realtime_adddir(char *dir) +{ + return(0); +} + +int realtime_process() +{ + return(0); +} + +#endif +/* EOF */ diff --git a/src/syscheckd/syscheck-baseline.c b/src/syscheckd/syscheck-baseline.c new file mode 100755 index 0000000..ea755b8 --- /dev/null +++ b/src/syscheckd/syscheck-baseline.c @@ -0,0 +1,201 @@ +/* @(#) $Id: syscheck-baseline.c,v 1.2 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "shared.h" +#include "syscheck.h" + + +/* Help information for syscheck-baseline. + */ +void sb_help(char *argv0) +{ + /* -s sleep between files. + * -c config + * -D workdir (where ossec is installed to read internal_options.conf) + * -o output_file + * -i input_file (only used with compare) + * -v (compare) + */ +} + + +/* void read_internal() + * Reads syscheck internal options. + */ +void read_internal(no_stop) +{ + if(no_stop) + { + syscheck.tsleep = 0; + syscheck.sleep_after = 9999; + } + else + { + syscheck.tsleep = getDefine_Int("syscheck","sleep",1,64); + syscheck.sleep_after = getDefine_Int("syscheck","sleep_after",1,128); + } + return; +} + + + + +/* Unix main. + */ +int main(int argc, char **argv) +{ + int c,r,no_stop = 1; + int test_config = 0; + + char *cfg = DEFAULTCPATH; + char *input_f = NULL; + char *output_f = NULL; + + + /* Zeroing the structure */ + syscheck.workdir = NULL; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "VtdshD:c:i:o:")) != -1) + { + switch(c) + { + case 'V': + print_version(); + break; + case 'h': + sb_help(ARGV0); + break; + case 's': + no_stop = 0; + break; + case 'd': + nowDebug(); + break; + case 'i': + if(!optarg) + ErrorExit("%s: -i needs an argument",ARGV0); + input_f = optarg; + break; + case 'o': + if(!optarg) + ErrorExit("%s: -o needs an argument",ARGV0); + output_f = optarg; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + syscheck.workdir = optarg; + break; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + } + + + /* Checking if the configuration is present */ + if(File_DateofChange(cfg) < 0) + ErrorExit(NO_CONFIG, ARGV0, cfg); + + + /* Read syscheck config */ + if((r = Read_Syscheck_Config(cfg)) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + else if((r == 1) || (syscheck.disabled == 1)) + { + syscheck.dir[0] = NULL; + if(!test_config) + { + merror("%s: WARN: Syscheck disabled.", ARGV0); + } + } + + + /* Reading internal options */ + read_internal(no_stop); + + + /* Exit if testing config */ + if(test_config) + exit(0); + + + /* Setting default values */ + if(syscheck.workdir == NULL) + syscheck.workdir = DEFAULTDIR; + + + /* Creating a temporary fp */ + syscheck.db = (char *)calloc(1024,sizeof(char)); + if(syscheck.db == NULL) + ErrorExit(MEM_ERROR,ARGV0); + + snprintf(syscheck.db,1023, output_f); + + + /* Printing options */ + #ifdef WIN32 + r = 0; + while(syscheck.registry[r] != NULL) + { + verbose("%s: INFO: Monitoring registry entry: '%s'.", + ARGV0, syscheck.registry[r]); + r++; + } + #endif + + r = 0; + while(syscheck.dir[r] != NULL) + { + verbose("%s: INFO: Monitoring directory: '%s'.", + ARGV0, syscheck.dir[r]); + r++; + } + + /* Start the signal handling */ + StartSIG(ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, getpid()); + + + /* Create local database */ + create_db(0); + + + fflush(syscheck.fp); + + + return(0); +} + + +/* EOF */ diff --git a/src/syscheckd/syscheck.c b/src/syscheckd/syscheck.c new file mode 100755 index 0000000..ff88da4 --- /dev/null +++ b/src/syscheckd/syscheck.c @@ -0,0 +1,376 @@ +/* @(#) $Id: syscheck.c,v 1.49 2009/11/18 19:07:42 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* + * Syscheck v 0.3 + * Copyright (C) 2003 Daniel B. Cid + * http://www.ossec.net + * + * syscheck.c, 2004/03/17, Daniel B. Cid + */ + +/* Inclusion of syscheck into OSSEC */ + + +#include "shared.h" +#include "syscheck.h" + +#include "rootcheck/rootcheck.h" + +/* Definitions only used in here. */ +#define SYSCHECK_DB SYSCHECK_DIR "/syschecklocal.db" +#define SYS_WIN_DB "syscheck/syschecklocal.db" + +int dump_syscheck_entry(config *syscheck, char *entry, int vals, int reg); + + + +/* void read_internal() + * Reads syscheck internal options. + */ +void read_internal() +{ + syscheck.tsleep = getDefine_Int("syscheck","sleep",0,64); + syscheck.sleep_after = getDefine_Int("syscheck","sleep_after",1,9999); + + return; +} + + +#ifdef WIN32 +/* int Start_win32_Syscheck() + * syscheck main for windows + */ +int Start_win32_Syscheck() +{ + int r = 0; + char *cfg = DEFAULTCPATH; + + + /* Zeroing the structure */ + syscheck.workdir = DEFAULTDIR; + + + /* Checking if the configuration is present */ + if(File_DateofChange(cfg) < 0) + ErrorExit(NO_CONFIG, ARGV0, cfg); + + + /* Read syscheck config */ + if((r = Read_Syscheck_Config(cfg)) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + /* Disabled */ + else if((r == 1) || (syscheck.disabled == 1)) + { + if(!syscheck.dir) + { + merror(SK_NO_DIR, ARGV0); + dump_syscheck_entry(&syscheck, "", 0, 0); + } + else if(!syscheck.dir[0]) + { + merror(SK_NO_DIR, ARGV0); + } + syscheck.dir[0] = NULL; + + if(!syscheck.registry) + { + dump_syscheck_entry(&syscheck, "", 0, 1); + } + syscheck.registry[0] = NULL; + + merror("%s: WARN: Syscheck disabled.", ARGV0); + } + + + /* Reading internal options */ + read_internal(); + + + /* Rootcheck config */ + if(rootcheck_init(0) == 0) + { + syscheck.rootcheck = 1; + } + else + { + syscheck.rootcheck = 0; + merror("%s: WARN: Rootcheck module disabled.", ARGV0); + } + + + + /* Opening syscheck db file */ + os_calloc(1024,sizeof(char), syscheck.db); + snprintf(syscheck.db,1023,"%s",SYS_WIN_DB); + + + /* Printing options */ + r = 0; + while(syscheck.registry[r] != NULL) + { + verbose("%s: INFO: Monitoring registry entry: '%s'.", + ARGV0, syscheck.registry[r]); + r++; + } + + r = 0; + while(syscheck.dir[r] != NULL) + { + verbose("%s: INFO: Monitoring directory: '%s'.", + ARGV0, syscheck.dir[r]); + r++; + } + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, getpid()); + + + + /* Some sync time */ + sleep(syscheck.tsleep + 10); + + + /* Waiting if agent started properly. */ + os_wait(); + + + /* Start the daemon checking against the syscheck.db */ + start_daemon(); + + + exit(0); +} +#endif + + + +/* Syscheck unix main. + */ +#ifndef WIN32 +int main(int argc, char **argv) +{ + int c,r; + int test_config = 0,run_foreground = 0; + + char *cfg = DEFAULTCPATH; + + + /* Zeroing the structure */ + syscheck.workdir = NULL; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + while((c = getopt(argc, argv, "VtdhfD:c:")) != -1) + { + switch(c) + { + case 'V': + print_version(); + break; + case 'h': + help(ARGV0); + break; + case 'd': + nowDebug(); + break; + case 'f': + run_foreground = 1; + break; + case 'D': + if(!optarg) + ErrorExit("%s: -D needs an argument",ARGV0); + syscheck.workdir = optarg; + break; + case 'c': + if(!optarg) + ErrorExit("%s: -c needs an argument",ARGV0); + cfg = optarg; + break; + case 't': + test_config = 1; + break; + default: + help(ARGV0); + break; + } + } + + + /* Checking if the configuration is present */ + if(File_DateofChange(cfg) < 0) + ErrorExit(NO_CONFIG, ARGV0, cfg); + + + /* Read syscheck config */ + if((r = Read_Syscheck_Config(cfg)) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + else if((r == 1) || (syscheck.disabled == 1)) + { + if(!syscheck.dir) + { + if(!test_config) + merror(SK_NO_DIR, ARGV0); + dump_syscheck_entry(&syscheck, "", 0, 0); + } + else if(!syscheck.dir[0]) + { + if(!test_config) + merror(SK_NO_DIR, ARGV0); + } + syscheck.dir[0] = NULL; + if(!test_config) + { + merror("%s: WARN: Syscheck disabled.", ARGV0); + } + } + + + /* Reading internal options */ + read_internal(); + + + + /* Rootcheck config */ + if(rootcheck_init(test_config) == 0) + { + syscheck.rootcheck = 1; + } + else + { + syscheck.rootcheck = 0; + merror("%s: WARN: Rootcheck module disabled.", ARGV0); + } + + + /* Exit if testing config */ + if(test_config) + exit(0); + + + /* Setting default values */ + if(syscheck.workdir == NULL) + syscheck.workdir = DEFAULTDIR; + + + /* Creating a temporary fp */ + syscheck.db = (char *)calloc(1024,sizeof(char)); + if(syscheck.db == NULL) + ErrorExit(MEM_ERROR,ARGV0); + + snprintf(syscheck.db,1023,"%s%s-%d%d.tmp", + syscheck.workdir, + SYSCHECK_DB, + (int)time(NULL), + (int)getpid()); + + + + if (!run_foreground) + { + nowDaemon(); + goDaemon(); + } + + /* Initial time to settle */ + sleep(syscheck.tsleep + 2); + + + /* Connect to the queue */ + if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno)); + + sleep(5); + if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + /* more 10 seconds of wait.. */ + merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno)); + sleep(10); + if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + ErrorExit(QUEUE_FATAL,ARGV0,DEFAULTQPATH); + } + } + + + /* Start the signal handling */ + StartSIG(ARGV0); + + + /* Creating pid */ + if(CreatePID(ARGV0, getpid()) < 0) + merror(PID_ERROR,ARGV0); + + + /* Start up message */ + verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + if(syscheck.rootcheck) + { + verbose(STARTUP_MSG, "ossec-rootcheck", (int)getpid()); + } + + + /* Printing directories to be monitored. */ + r = 0; + while(syscheck.dir[r] != NULL) + { + verbose("%s: INFO: Monitoring directory: '%s'.", + ARGV0, syscheck.dir[r]); + r++; + } + + /* Checking directories set for real time. */ + r = 0; + while(syscheck.dir[r] != NULL) + { + if(syscheck.opts[r] & CHECK_REALTIME) + { + #ifdef USEINOTIFY + verbose("%s: INFO: Directory set for real time monitoring: " + "'%s'.", ARGV0, syscheck.dir[r]); + #elif WIN32 + verbose("%s: INFO: Directory set for real time monitoring: " + "'%s'.", ARGV0, syscheck.dir[r]); + #else + verbose("%s: WARN: Ignoring flag for real time monitoring on " + "directory: '%s'.", ARGV0, syscheck.dir[r]); + #endif + } + r++; + } + + + /* Some sync time */ + sleep(syscheck.tsleep + 10); + + + /* Start the daemon */ + start_daemon(); + + return(0); +} +#endif /* ifndef WIN32 */ + + +/* EOF */ diff --git a/src/syscheckd/syscheck.h b/src/syscheckd/syscheck.h new file mode 100755 index 0000000..53f5989 --- /dev/null +++ b/src/syscheckd/syscheck.h @@ -0,0 +1,76 @@ +/* @(#) $Id: syscheck.h,v 1.16 2009/06/30 17:08:19 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#ifndef __SYSCHECK_H + +#define __SYSCHECK_H + +#include "config/syscheck-config.h" +#define MAX_LINE PATH_MAX+256 + +/* Notify list size */ +#define NOTIFY_LIST_SIZE 32 + + +/* Global config */ +config syscheck; + + +/** Function Prototypes **/ + +/* run_check: checks the integrity of the files against the + * saved database + */ +void run_check(); + + +/* start_daemon: Runs run_check periodically. + */ +void start_daemon(); + + +/* Read the XML config */ +int Read_Syscheck_Config(char * cfgfile); + + +/* create the database */ +int create_db(); + + +/* int check_db() + * Checks database for new files. + */ +int check_db(); + +/** void os_winreg_check() + * Checks the registry for changes. + */ +void os_winreg_check(); + +/* starts real time */ +int realtime_start(); + +/* Adds a directory to real time monitoring. */ +int realtime_adddir(char *dir); + +/* Process real time queue. */ +int realtime_process(); + +/** Sends syscheck message. + */ +int send_syscheck_msg(char *msg); +int send_rootcheck_msg(char *msg); + + +#endif + +/* EOF */ diff --git a/src/syscheckd/win-registry.c b/src/syscheckd/win-registry.c new file mode 100644 index 0000000..0031ab4 --- /dev/null +++ b/src/syscheckd/win-registry.c @@ -0,0 +1,502 @@ +/* @(#) $Id: win-registry.c,v 1.15 2009/08/31 18:26:04 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +/* Windows only */ +#ifdef WIN32 + + +#include "shared.h" +#include "syscheck.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/sha1/sha1_op.h" +#include "os_crypto/md5_sha1/md5_sha1_op.h" + + +/* Default values */ +#define MAX_KEY_LENGTH 255 +#define MAX_KEY 2048 +#define MAX_VALUE_NAME 16383 + +/* Places to story the registry values. */ +#define SYS_WIN_REG "syscheck/syscheckregistry.db" +#define SYS_REG_TMP "syscheck/syscheck_sum.tmp" + + + +/* Global variables */ +HKEY sub_tree; +int ig_count = 0; +int run_count = 0; + + + + +/** Function prototypes 8*/ +void os_winreg_open_key(char *subkey, char *fullkey_name); + + +int os_winreg_changed(char *key, char *md5, char *sha1) +{ + char buf[MAX_LINE +1]; + + buf[MAX_LINE] = '\0'; + + + /* Seeking to the beginning of the db */ + fseek(syscheck.reg_fp, 0, SEEK_SET); + + while(fgets(buf, MAX_LINE, syscheck.reg_fp) != NULL) + { + if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n')) + { + char *n_buf; + + /* Removing the \n before reading */ + n_buf = strchr(buf, '\n'); + if(n_buf == NULL) + continue; + + *n_buf = '\0'; + + n_buf = strchr(buf, ' '); + if(n_buf == NULL) + continue; + + if(strcmp(n_buf +1, key) != 0) + continue; + + /* Entry found, checking if checksum is the same */ + *n_buf = '\0'; + if((strncmp(buf, md5, sizeof(os_md5) -1) == 0)&& + (strcmp(buf + sizeof(os_md5) -1, sha1) == 0)) + { + /* File didn't change. */ + return(0); + } + + /* File did changed */ + return(1); + } + } + + fseek(syscheck.reg_fp, 0, SEEK_END); + fprintf(syscheck.reg_fp, "%s%s %s\n", md5, sha1, key); + return(1); +} + + +/** int notify_registry(char *msg) + * Notifies of registry changes. + */ +int notify_registry(char *msg, int send_now) +{ + if(SendMSG(syscheck.queue, msg, + SYSCHECK_REG, SYSCHECK_MQ) < 0) + { + merror(QUEUE_SEND, ARGV0); + + if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) + { + ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); + } + + /* If we reach here, we can try to send it again */ + SendMSG(syscheck.queue, msg, SYSCHECK_REG, SYSCHECK_MQ); + } + + return(0); +} + + +/** char *os_winreg_sethkey(char *reg_entry) + * Checks if the registry entry is valid. + */ +char *os_winreg_sethkey(char *reg_entry) +{ + char *ret = NULL; + char *tmp_str; + + /* Getting only the sub tree first */ + tmp_str = strchr(reg_entry, '\\'); + if(tmp_str) + { + *tmp_str = '\0'; + ret = tmp_str+1; + } + + /* Setting sub tree */ + if(strcmp(reg_entry, "HKEY_LOCAL_MACHINE") == 0) + { + sub_tree = HKEY_LOCAL_MACHINE; + } + else if(strcmp(reg_entry, "HKEY_CLASSES_ROOT") == 0) + { + sub_tree = HKEY_CLASSES_ROOT; + } + else if(strcmp(reg_entry, "HKEY_CURRENT_CONFIG") == 0) + { + sub_tree = HKEY_CURRENT_CONFIG; + } + else if(strcmp(reg_entry, "HKEY_USERS") == 0) + { + sub_tree = HKEY_USERS; + } + else + { + /* Returning tmp_str to the previous value */ + if(tmp_str && (*tmp_str == '\0')) + *tmp_str = '\\'; + return(NULL); + } + + /* Checking if ret has nothing else. */ + if(ret && (*ret == '\0')) + ret = NULL; + + /* fixing tmp_str and the real name of the registry */ + if(tmp_str && (*tmp_str == '\0')) + *tmp_str = '\\'; + + return(ret); +} + + +/* void os_winreg_querykey(HKEY hKey, char *p_key) + * Query the key and get all its values. + */ +void os_winreg_querykey(HKEY hKey, char *p_key, char *full_key_name) +{ + int i, rc; + DWORD j; + + /* QueryInfo and EnumKey variables */ + TCHAR sub_key_name_b[MAX_KEY_LENGTH +2]; + TCHAR class_name_b[MAX_PATH +1]; + DWORD sub_key_name_s; + DWORD class_name_s = MAX_PATH; + + /* Number of sub keys */ + DWORD subkey_count = 0; + + /* Number of values */ + DWORD value_count; + + /* Variables for RegEnumValue */ + TCHAR value_buffer[MAX_VALUE_NAME +1]; + TCHAR data_buffer[MAX_VALUE_NAME +1]; + DWORD value_size; + DWORD data_size; + + /* Data type for RegEnumValue */ + DWORD data_type = 0; + + + /* Initializing the memory for some variables */ + class_name_b[0] = '\0'; + class_name_b[MAX_PATH] = '\0'; + sub_key_name_b[0] = '\0'; + sub_key_name_b[MAX_KEY_LENGTH] = '\0'; + sub_key_name_b[MAX_KEY_LENGTH +1] = '\0'; + + + /* We use the class_name, subkey_count and the value count. */ + rc = RegQueryInfoKey(hKey, class_name_b, &class_name_s, NULL, + &subkey_count, NULL, NULL, &value_count, + NULL, NULL, NULL, NULL); + + /* Check return code of QueryInfo */ + if(rc != ERROR_SUCCESS) + { + return; + } + + + + /* Checking if we have sub keys */ + if(subkey_count) + { + /* We open each subkey and call open_key */ + for(i=0;i= syscheck.sleep_after) + { + sleep(syscheck.tsleep +1); + ig_count = 1; + } + ig_count++; + + + /* Registry ignore list */ + if(full_key_name && syscheck.registry_ignore) + { + while(syscheck.registry_ignore[i] != NULL) + { + if(strcasecmp(syscheck.registry_ignore[i], full_key_name) == 0) + { + return; + } + i++; + } + } + else if(full_key_name && syscheck.registry_ignore_regex) + { + i = 0; + while(syscheck.registry_ignore_regex[i] != NULL) + { + if(OSMatch_Execute(full_key_name, strlen(full_key_name), + syscheck.registry_ignore_regex[i])) + { + return; + } + i++; + } + } + + + if(RegOpenKeyEx(sub_tree, subkey, 0, KEY_READ, &oshkey) != ERROR_SUCCESS) + { + merror(SK_REG_OPEN, ARGV0, subkey); + return; + } + + os_winreg_querykey(oshkey, subkey, full_key_name); + RegCloseKey(oshkey); + return; +} + + +/** void os_winreg_check() + * Main function to read the registry. + */ +void os_winreg_check() +{ + int i = 0; + char *rk; + + /* Debug entries */ + debug1("%s: DEBUG: Starting os_winreg_check", ARGV0); + + + /* Zeroing ig_count before checking */ + ig_count = 1; + + + /* Checking if the registry fp is open */ + if(syscheck.reg_fp == NULL) + { + syscheck.reg_fp = fopen(SYS_WIN_REG, "w+"); + if(!syscheck.reg_fp) + { + merror(FOPEN_ERROR, ARGV0, SYS_WIN_REG); + return; + } + } + + + /* Getting sub class and a valid registry entry */ + while(syscheck.registry[i] != NULL) + { + sub_tree = NULL; + rk = NULL; + + /* Ignored entries are zeroed */ + if(*syscheck.registry[i] == '\0') + { + i++; + continue; + } + + + /* Reading syscheck registry entry */ + debug1("%s: DEBUG: Attempt to read: %s", ARGV0, syscheck.registry[i]); + + + rk = os_winreg_sethkey(syscheck.registry[i]); + if(sub_tree == NULL) + { + merror(SK_INV_REG, ARGV0, syscheck.registry[i]); + *syscheck.registry[i] = '\0'; + i++; + continue; + } + + os_winreg_open_key(rk, syscheck.registry[i]); + i++; + sleep(syscheck.tsleep *5); + } + + + /* Notify of db completed. */ + if(run_count > 1) + { + sleep(syscheck.tsleep *5); + notify_registry(HC_SK_DB_COMPLETED, 1); + } + + run_count++; + return; +} + + +#endif /* WIN32 */ + +/* EOF */ diff --git a/src/sysinfo/df.c b/src/sysinfo/df.c new file mode 100755 index 0000000..0b95871 --- /dev/null +++ b/src/sysinfo/df.c @@ -0,0 +1,9 @@ +#include +#include "statfs.h" + +int main() + { + if(getstatfspath() != 0) + printf("error..\n"); + return(0); + } diff --git a/src/sysinfo/statfs.c b/src/sysinfo/statfs.c new file mode 100755 index 0000000..2e3200a --- /dev/null +++ b/src/sysinfo/statfs.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#ifdef __linux__ + #include + #include +#endif + +#include "statfs.h" + + +int getstatfspath() + { + /* For OpenBSD */ + #ifdef __OpenBSD__ + int mntsize=0; + int i=0; + struct statfs *fs; + mntsize = getmntinfo(&fs, MNT_NOWAIT); + if(mntsize == 0) + { + return(-1); + } + + for(i=0;imnt_dir); + endmntent(f); + #endif + + return(0); + } + + + +int getstatfs(char *path) +{ + struct statfs fs; + int percentbfree=0; + int percentnfree=0; + + if(statfs(path, &fs) != 0) + return(-1); + + if((fs.f_bfree == 0)||(fs.f_ffree == 0)) + return(-1); + percentbfree = (int)(100*fs.f_bfree)/fs.f_blocks; + percentnfree = (int)(100*fs.f_ffree)/fs.f_files; + printf("file system for %s has %d free blocks out of a total of %d - %d. Total of %d%% FREE \n",path,fs.f_ffree,fs.f_blocks,percentbfree,percentnfree); + return(0); +} diff --git a/src/sysinfo/statfs.h b/src/sysinfo/statfs.h new file mode 100755 index 0000000..9eacec5 --- /dev/null +++ b/src/sysinfo/statfs.h @@ -0,0 +1,8 @@ + +#ifndef __OS__statfs_H + +#define __OS__statfs_H +int getstatfs(char *path); +int getstatfspath(); +#endif + diff --git a/src/util/Makefile b/src/util/Makefile new file mode 100755 index 0000000..36205f2 --- /dev/null +++ b/src/util/Makefile @@ -0,0 +1,23 @@ +# Makefile for util. +# Daniel B. Cid || +# http://www.ossec.net/hids/ + +PT=../ +NAME=util + +SUP=../addagent/manage_agents.c ../addagent/manage_keys.c ../addagent/validate.c ../addagent/read_from_user.c ../addagent/b64.c +include $(PT)Config.Make + +OBJS = ${OS_ZLIB} ${OS_CRYPTO} ${OS_SHARED} ${OS_REGEX} ${OS_NET} + +me: + $(CC) $(CFLAGS) ${OS_LINK} ${SUP} syscheck_update.c $(OBJS) -o syscheck_update + $(CC) $(CFLAGS) ${OS_LINK} clear_stats.c $(OBJS) -o clear_stats + $(CC) $(CFLAGS) ${OS_LINK} list_agents.c $(OBJS) -o list_agents + $(CC) $(CFLAGS) ${OS_LINK} ${SUP} agent_control.c $(OBJS) -o agent_control + $(CC) $(CFLAGS) ${OS_LINK} ${SUP} syscheck_control.c $(OBJS) -o syscheck_control + $(CC) $(CFLAGS) ${OS_LINK} ${SUP} rootcheck_control.c $(OBJS) -o rootcheck_control +clean: + $(CLEAN) syscheck_update clear_stats list_agents agent_control syscheck_control rootcheck_control +build: + cp -pr syscheck_update clear_stats list_agents syscheck_control rootcheck_control agent_control ${PT}../bin diff --git a/src/util/agent_control.c b/src/util/agent_control.c new file mode 100755 index 0000000..d81355b --- /dev/null +++ b/src/util/agent_control.c @@ -0,0 +1,536 @@ +/* @(#) $Id: agent_control.c,v 1.11 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "addagent/manage_agents.h" +#include "sec.h" + + +#undef ARGV0 +#define ARGV0 "agent_control" + + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: Control remote agents.\n", ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-l List available (active or not) agents.\n"); + printf("\t-lc List active agents.\n"); + printf("\t-i Extracts information from an agent.\n"); + printf("\t-R Restarts agent.\n"); + printf("\t-r -a Runs the integrity/rootkit checking on all agents now.\n"); + printf("\t-r -u Runs the integrity/rootkit checking on one agent now.\n\n"); + printf("\t-b Blocks the specified ip address.\n"); + printf("\t-f Used with -b, specifies which response to run.\n"); + printf("\t-L List available active responses.\n"); + printf("\t-s Changes the output to CSV (comma delimited).\n"); + exit(1); +} + + +/** main **/ +int main(int argc, char **argv) +{ + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *user = USER; + char *agent_id = NULL; + char *ip_address = NULL; + char *ar = NULL; + + int arq = 0; + int gid = 0; + int uid = 0; + int c = 0, restart_syscheck = 0, restart_all_agents = 0, list_agents = 0; + int info_agent = 0, agt_id = 0, active_only = 0, csv_output = 0; + int list_responses = 0, end_time = 0, restart_agent = 0; + + char shost[512]; + + keystore keys; + + + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* user arguments */ + if(argc < 2) + { + helpmsg(); + } + + + while((c = getopt(argc, argv, "VehdlLcsaru:i:b:f:R:")) != -1) + { + switch(c){ + case 'V': + print_version(); + break; + case 'h': + helpmsg(); + break; + case 'd': + nowDebug(); + break; + case 'L': + list_responses = 1; + break; + case 'e': + end_time = 1; + break; + case 'r': + restart_syscheck = 1; + break; + case 'l': + list_agents++; + break; + case 's': + csv_output = 1; + break; + case 'c': + active_only++; + break; + case 'i': + info_agent++; + case 'u': + if(!optarg) + { + merror("%s: -u needs an argument",ARGV0); + helpmsg(); + } + agent_id = optarg; + break; + case 'b': + if(!optarg) + { + merror("%s: -b needs an argument",ARGV0); + helpmsg(); + } + ip_address = optarg; + break; + case 'f': + if(!optarg) + { + merror("%s: -e needs an argument",ARGV0); + helpmsg(); + } + ar = optarg; + break; + case 'R': + if(!optarg) + { + merror("%s: -R needs an argument",ARGV0); + helpmsg(); + } + agent_id = optarg; + restart_agent = 1; + case 'a': + restart_all_agents = 1; + break; + default: + helpmsg(); + break; + } + + } + + + /* Getting the group name */ + gid = Privsep_GetGroup(group); + uid = Privsep_GetUser(user); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR,ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR, ARGV0, user); + } + + + + /* Getting servers hostname */ + memset(shost, '\0', 512); + if(gethostname(shost, 512 -1) != 0) + { + strncpy(shost, "localhost", 32); + return(0); + } + + + /* Listing responses. */ + if(list_responses) + { + FILE *fp; + if(!csv_output) + { + printf("\nOSSEC HIDS %s. Available active responses:\n", ARGV0); + } + + fp = fopen(DEFAULTAR, "r"); + if(fp) + { + char buffer[256]; + + while(fgets(buffer, 255, fp) != NULL) + { + char *r_name; + char *r_cmd; + char *r_timeout; + + r_name = buffer; + r_cmd = strchr(buffer, ' '); + if(!r_cmd) + continue; + + *r_cmd = '\0'; + r_cmd++; + if(*r_cmd == '-') + r_cmd++; + if(*r_cmd == ' ') + r_cmd++; + + r_timeout = strchr(r_cmd, ' '); + if(!r_timeout) + continue; + *r_timeout = '\0'; + + if(strcmp(r_name, "restart-ossec0") == 0) + { + continue; + } + printf("\n Response name: %s, command: %s", r_name, r_cmd); + } + + printf("\n\n"); + fclose(fp); + } + else + { + printf("\n No active response available.\n\n"); + } + + exit(0); + } + + + /* Listing available agents. */ + if(list_agents) + { + if(!csv_output) + { + printf("\nOSSEC HIDS %s. List of available agents:", + ARGV0); + printf("\n ID: 000, Name: %s (server), IP: 127.0.0.1, Active/Local\n", + shost); + } + else + { + printf("000,%s (server),127.0.0.1,Active/Local,\n", shost); + } + print_agents(1, active_only, csv_output); + printf("\n"); + exit(0); + } + + + + /* Checking if the provided ID is valid. */ + if(agent_id != NULL) + { + if(strcmp(agent_id, "000") != 0) + { + OS_ReadKeys(&keys); + + agt_id = OS_IsAllowedID(&keys, agent_id); + if(agt_id < 0) + { + printf("\n** Invalid agent id '%s'.\n", agent_id); + helpmsg(); + } + } + else + { + /* server. */ + agt_id = -1; + } + } + + + + /* Printing information from an agent. */ + if(info_agent) + { + int agt_status = 0; + char final_ip[128 +1]; + char final_mask[128 +1]; + agent_info *agt_info; + + final_ip[128] = '\0'; + final_mask[128] = '\0'; + + + if(!csv_output) + printf("\nOSSEC HIDS %s. Agent information:", ARGV0); + + if(agt_id != -1) + { + agt_status = get_agent_status(keys.keyentries[agt_id]->name, + keys.keyentries[agt_id]->ip->ip); + + agt_info = get_agent_info(keys.keyentries[agt_id]->name, + keys.keyentries[agt_id]->ip->ip); + + /* Getting netmask from ip. */ + getNetmask(keys.keyentries[agt_id]->ip->netmask, final_mask, 128); + snprintf(final_ip, 128, "%s%s",keys.keyentries[agt_id]->ip->ip, + final_mask); + + + if(!csv_output) + { + printf("\n Agent ID: %s\n", keys.keyentries[agt_id]->id); + printf(" Agent Name: %s\n", keys.keyentries[agt_id]->name); + printf(" IP address: %s\n", final_ip); + printf(" Status: %s\n\n",print_agent_status(agt_status)); + } + else + { + printf("%s,%s,%s,%s,", + keys.keyentries[agt_id]->id, + keys.keyentries[agt_id]->name, + final_ip, + print_agent_status(agt_status)); + } + } + else + { + agt_status = get_agent_status(NULL, NULL); + agt_info = get_agent_info(NULL, "127.0.0.1"); + + if(!csv_output) + { + printf("\n Agent ID: 000 (local instance)\n"); + printf(" Agent Name: %s\n", shost); + printf(" IP address: 127.0.0.1\n"); + printf(" Status: %s/Local\n\n",print_agent_status(agt_status)); + } + + else + { + printf("000,%s,127.0.0.1,%s/Local,", + shost, + print_agent_status(agt_status)); + + } + } + + + if(!csv_output) + { + printf(" Operating system: %s\n", agt_info->os); + printf(" Client version: %s\n", agt_info->version); + printf(" Last keep alive: %s\n\n", agt_info->last_keepalive); + + + if(end_time) + { + printf(" Syscheck last started at: %s\n", agt_info->syscheck_time); + printf(" Syscheck last ended at: %s\n", agt_info->syscheck_endtime); + printf(" Rootcheck last started at: %s\n", agt_info->rootcheck_time); + printf(" Rootcheck last ended at: %s\n\n", agt_info->rootcheck_endtime); + } + else + { + printf(" Syscheck last started at: %s\n", agt_info->syscheck_time); + printf(" Rootcheck last started at: %s\n", agt_info->rootcheck_time); + } + } + else + { + printf("%s,%s,%s,%s,%s,\n", + agt_info->os, + agt_info->version, + agt_info->last_keepalive, + agt_info->syscheck_time, + agt_info->rootcheck_time); + } + + exit(0); + } + + + + /* Restarting syscheck every where. */ + if(restart_all_agents && restart_syscheck) + { + + /* Connecting to remoted. */ + debug1("%s: DEBUG: Connecting to remoted...", ARGV0); + arq = connect_to_remoted(); + if(arq < 0) + { + printf("\n** Unable to connect to remoted.\n"); + exit(1); + } + debug1("%s: DEBUG: Connected...", ARGV0); + + + /* Sending restart message to all agents. */ + if(send_msg_to_agent(arq, HC_SK_RESTART, NULL, NULL) == 0) + { + printf("\nOSSEC HIDS %s: Restarting Syscheck/Rootcheck on all agents.", + ARGV0); + } + else + { + printf("\n** Unable to restart syscheck on all agents.\n"); + exit(1); + } + + exit(0); + } + + + + if(restart_syscheck && agent_id) + { + + /* Restart on the server. */ + if(strcmp(agent_id, "000") == 0) + { + os_set_restart_syscheck(); + + printf("\nOSSEC HIDS %s: Restarting Syscheck/Rootcheck " + "locally.\n", ARGV0); + + exit(0); + } + + + + /* Connecting to remoted. */ + debug1("%s: DEBUG: Connecting to remoted...", ARGV0); + arq = connect_to_remoted(); + if(arq < 0) + { + printf("\n** Unable to connect to remoted.\n"); + exit(1); + } + debug1("%s: DEBUG: Connected...", ARGV0); + + + if(send_msg_to_agent(arq, HC_SK_RESTART, agent_id, NULL) == 0) + { + printf("\nOSSEC HIDS %s: Restarting Syscheck/Rootcheck on agent: %s\n", + ARGV0, agent_id); + } + else + { + printf("\n** Unable to restart syscheck on agent: %s\n", agent_id); + exit(1); + } + + exit(0); + } + + + if(restart_agent && agent_id) + { + /* Connecting to remoted. */ + debug1("%s: DEBUG: Connecting to remoted...", ARGV0); + arq = connect_to_remoted(); + if(arq < 0) + { + printf("\n** Unable to connect to remoted.\n"); + exit(1); + } + debug1("%s: DEBUG: Connected...", ARGV0); + + + if(send_msg_to_agent(arq, "restart-ossec0", agent_id, "null") == 0) + { + printf("\nOSSEC HIDS %s: Restarting agent: %s\n", + ARGV0, agent_id); + } + else + { + printf("\n** Unable to restart agent: %s\n", agent_id); + exit(1); + } + + exit(0); + } + + + /* running active response on the specified agent id. */ + if(ip_address && ar && agent_id) + { + /* Connecting to remoted. */ + debug1("%s: DEBUG: Connecting to remoted...", ARGV0); + arq = connect_to_remoted(); + if(arq < 0) + { + printf("\n** Unable to connect to remoted.\n"); + exit(1); + } + debug1("%s: DEBUG: Connected...", ARGV0); + + + if(send_msg_to_agent(arq, ar, agent_id, ip_address) == 0) + { + printf("\nOSSEC HIDS %s: Running active response '%s' on: %s\n", + ARGV0, ar, agent_id); + } + else + { + printf("\n** Unable to restart syscheck on agent: %s\n", agent_id); + exit(1); + } + + exit(0); + } + + + printf("\n** Invalid argument combination.\n"); + helpmsg(); + + + return(0); +} + + +/* EOF */ diff --git a/src/util/clear_stats.c b/src/util/clear_stats.c new file mode 100755 index 0000000..662375b --- /dev/null +++ b/src/util/clear_stats.c @@ -0,0 +1,196 @@ +/* @(#) $Id: clear_stats.c,v 1.6 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +/* This tool will clear the project statistics */ + +#include "shared.h" + +#undef ARGV0 +#define ARGV0 "clear_stats" + + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: Clear the events stats (averages).\n", ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-a Clear all the stats (averages).\n"); + printf("\t-d Clear the daily averages.\n"); + printf("\t-w Clear the weekly averages.\n\n"); + exit(1); +} + + +/** main **/ +int main(int argc, char **argv) +{ + int clear_daily = 0; + int clear_weekly = 0; + + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *user = USER; + int gid; + int uid; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* user arguments */ + if(argc != 2) + { + helpmsg(); + } + + /* Getting the group name */ + gid = Privsep_GetGroup(group); + uid = Privsep_GetUser(user); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR,ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR, ARGV0, user); + } + + /* User options */ + if(strcmp(argv[1], "-h") == 0) + { + helpmsg(); + } + else if(strcmp(argv[1], "-a") == 0) + { + clear_daily = 1; + clear_weekly = 1; + } + else if(strcmp(argv[1], "-d") == 0) + { + clear_daily = 1; + } + else if(strcmp(argv[1], "-w") == 0) + { + clear_weekly = 1; + } + else + { + printf("\n** Invalid option '%s'.\n", argv[1]); + helpmsg(); + } + + + /* Clear daily files */ + if(clear_daily) + { + char *daily_dir = STATQUEUE; + DIR *daily; + struct dirent *entry; + + daily = opendir(daily_dir); + if(!daily) + { + ErrorExit("%s: Unable to open: '%s'", ARGV0, daily_dir); + } + + while((entry = readdir(daily)) != NULL) + { + char full_path[OS_MAXSTR +1]; + + /* Do not even attempt to delete . and .. :) */ + if((strcmp(entry->d_name,".") == 0)|| + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + /* Remove file */ + full_path[OS_MAXSTR] = '\0'; + snprintf(full_path, OS_MAXSTR, "%s/%s", daily_dir, entry->d_name); + unlink(full_path); + } + + closedir(daily); + } + + + /* Clear weekly averages */ + if(clear_weekly) + { + int i = 0; + while(i <= 6) + { + char *daily_dir = STATWQUEUE; + char dir_path[OS_MAXSTR +1]; + DIR *daily; + struct dirent *entry; + + snprintf(dir_path, OS_MAXSTR, "%s/%d", daily_dir, i); + daily = opendir(dir_path); + if(!daily) + { + ErrorExit("%s: Unable to open: '%s' (no stats)", + ARGV0, dir_path); + } + + while((entry = readdir(daily)) != NULL) + { + char full_path[OS_MAXSTR +1]; + + /* Do not even attempt to delete . and .. :) */ + if((strcmp(entry->d_name,".") == 0)|| + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + /* Remove file */ + full_path[OS_MAXSTR] = '\0'; + snprintf(full_path, OS_MAXSTR, "%s/%s", dir_path, + entry->d_name); + unlink(full_path); + } + + i++; + closedir(daily); + } + } + + printf("\n** Internal stats clear.\n\n"); + return(0); +} + + +/* EOF */ diff --git a/src/util/list_agents.c b/src/util/list_agents.c new file mode 100755 index 0000000..a3624ce --- /dev/null +++ b/src/util/list_agents.c @@ -0,0 +1,137 @@ +/* @(#) $Id: list_agents.c,v 1.7 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "shared.h" +#include "read-agents.h" + +#undef ARGV0 +#define ARGV0 "list_agents" + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: List available agents.\n", ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-a List all agents.\n"); + printf("\t-c List the connected (active) agents.\n"); + printf("\t-n List the not connected (active) agents.\n"); + exit(1); +} + + +/** main **/ +int main(int argc, char **argv) +{ + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *user = USER; + + char *msg; + char **agent_list; + int gid; + int uid; + int flag; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* user arguments */ + if(argc < 2) + { + helpmsg(); + } + + /* Getting the group name */ + gid = Privsep_GetGroup(group); + uid = Privsep_GetUser(user); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR,ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR, ARGV0, user); + } + + /* User options */ + if(strcmp(argv[1], "-h") == 0) + { + helpmsg(); + } + else if(strcmp(argv[1], "-a") == 0) + { + flag = GA_ALL; + msg = "is available."; + } + else if(strcmp(argv[1], "-c") == 0) + { + flag = GA_ACTIVE; + msg = "is active."; + } + else if(strcmp(argv[1], "-n") == 0) + { + flag = GA_NOTACTIVE; + msg = "is not active."; + } + else + { + printf("\n** Invalid option '%s'.\n", argv[1]); + helpmsg(); + } + + + agent_list = get_agents(flag); + if(agent_list) + { + char **agent_list_pt = agent_list; + + while(*agent_list) + { + printf("%s %s\n", *agent_list, msg); + agent_list++; + } + + free_agents(agent_list_pt); + } + else + { + printf("** No agent available.\n"); + } + return(0); +} + + +/* EOF */ diff --git a/src/util/rootcheck_control.c b/src/util/rootcheck_control.c new file mode 100755 index 0000000..5387914 --- /dev/null +++ b/src/util/rootcheck_control.c @@ -0,0 +1,345 @@ +/* @(#) $Id: rootcheck_control.c,v 1.5 2009/06/24 18:53:09 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "addagent/manage_agents.h" +#include "sec.h" + + +#undef ARGV0 +#define ARGV0 "rootcheck_control" + + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: Manages the policy and auditing database.\n", + ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-l List available (active or not) agents.\n"); + printf("\t-lc List only active agents.\n"); + printf("\t-u Updates (clear) the database for the agent.\n"); + printf("\t-u all Updates (clear) the database for all agents.\n"); + printf("\t-i Prints database for the agent.\n"); + printf("\t-r Used with -i, prints all the resolved issues.\n"); + printf("\t-q Used with -i, prints all the outstanding issues.\n"); + printf("\t-L Used with -i, prints the last scan.\n"); + printf("\t-s Changes the output to CSV (comma delimited).\n"); + exit(1); +} + + +/** main **/ +int main(int argc, char **argv) +{ + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *user = USER; + char *agent_id = NULL; + + int gid = 0; + int uid = 0; + int c = 0, info_agent = 0, update_rootcheck = 0, + list_agents = 0, show_last = 0, + resolved_only = 0; + int active_only = 0, csv_output = 0; + + char shost[512]; + + + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* user arguments */ + if(argc < 2) + { + helpmsg(); + } + + + while((c = getopt(argc, argv, "VhqrDdLlcsu:i:")) != -1) + { + switch(c){ + case 'V': + print_version(); + break; + case 'h': + helpmsg(); + break; + case 'D': + nowDebug(); + break; + case 'l': + list_agents++; + break; + case 's': + csv_output = 1; + break; + case 'c': + active_only++; + break; + case 'r': + resolved_only = 1; + break; + case 'q': + resolved_only = 2; + break; + case 'L': + show_last = 1; + break; + case 'i': + info_agent++; + if(!optarg) + { + merror("%s: -u needs an argument",ARGV0); + helpmsg(); + } + agent_id = optarg; + break; + case 'u': + if(!optarg) + { + merror("%s: -u needs an argument",ARGV0); + helpmsg(); + } + agent_id = optarg; + update_rootcheck = 1; + break; + default: + helpmsg(); + break; + } + + } + + + /* Getting the group name */ + gid = Privsep_GetGroup(group); + uid = Privsep_GetUser(user); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR,ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR, ARGV0, user); + } + + + + /* Getting servers hostname */ + memset(shost, '\0', 512); + if(gethostname(shost, 512 -1) != 0) + { + strncpy(shost, "localhost", 32); + return(0); + } + + + + /* Listing available agents. */ + if(list_agents) + { + if(!csv_output) + { + printf("\nOSSEC HIDS %s. List of available agents:", + ARGV0); + printf("\n ID: 000, Name: %s (server), IP: 127.0.0.1, " + "Active/Local\n", shost); + } + else + { + printf("000,%s (server),127.0.0.1,Active/Local,\n", shost); + } + print_agents(1, active_only, csv_output); + printf("\n"); + exit(0); + } + + + + /* Update rootcheck database. */ + if(update_rootcheck) + { + /* Cleaning all agents (and server) db. */ + if(strcmp(agent_id, "all") == 0) + { + DIR *sys_dir; + struct dirent *entry; + + sys_dir = opendir(ROOTCHECK_DIR); + if(!sys_dir) + { + ErrorExit("%s: Unable to open: '%s'", ARGV0, ROOTCHECK_DIR); + } + + while((entry = readdir(sys_dir)) != NULL) + { + FILE *fp; + char full_path[OS_MAXSTR +1]; + + /* Do not even attempt to delete . and .. :) */ + if((strcmp(entry->d_name,".") == 0)|| + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + snprintf(full_path, OS_MAXSTR,"%s/%s", ROOTCHECK_DIR, + entry->d_name); + + fp = fopen(full_path, "w"); + if(fp) + { + fclose(fp); + } + if(entry->d_name[0] == '.') + { + unlink(full_path); + } + } + + closedir(sys_dir); + printf("\n** Policy and auditing database updated.\n\n"); + exit(0); + } + + else if((strcmp(agent_id, "000") == 0) || + (strcmp(agent_id, "local") == 0)) + { + char final_dir[1024]; + FILE *fp; + snprintf(final_dir, 1020, "/%s/rootcheck", ROOTCHECK_DIR); + + fp = fopen(final_dir, "w"); + if(fp) + { + fclose(fp); + } + unlink(final_dir); + printf("\n** Policy and auditing database updated.\n\n"); + exit(0); + } + + /* Database from remote agents. */ + else + { + int i; + keystore keys; + + OS_ReadKeys(&keys); + + i = OS_IsAllowedID(&keys, agent_id); + if(i < 0) + { + printf("\n** Invalid agent id '%s'.\n", agent_id); + helpmsg(); + } + + /* Deleting syscheck */ + delete_rootcheck(keys.keyentries[i]->name, + keys.keyentries[i]->ip->ip, 0); + + printf("\n** Policy and auditing database updated.\n\n"); + exit(0); + } + } + + + /* Printing information from an agent. */ + if(info_agent) + { + int i; + char final_ip[128 +1]; + char final_mask[128 +1]; + keystore keys; + + + if((strcmp(agent_id, "000") == 0) || + (strcmp(agent_id, "local") == 0)) + { + if(!csv_output) + printf("\nPolicy and auditing events for local system '%s - %s':\n", + shost, "127.0.0.1"); + + print_rootcheck(NULL, + NULL, NULL, resolved_only, csv_output, show_last); + } + else + { + + OS_ReadKeys(&keys); + + i = OS_IsAllowedID(&keys, agent_id); + if(i < 0) + { + printf("\n** Invalid agent id '%s'.\n", agent_id); + helpmsg(); + } + + /* Getting netmask from ip. */ + final_ip[128] = '\0'; + final_mask[128] = '\0'; + getNetmask(keys.keyentries[i]->ip->netmask, + final_mask, 128); + snprintf(final_ip, 128, "%s%s",keys.keyentries[i]->ip->ip, + final_mask); + + if(!csv_output) + printf("\nPolicy and auditing events for agent " + "'%s (%s) - %s':\n", + keys.keyentries[i]->name, keys.keyentries[i]->id, + final_ip); + + print_rootcheck(keys.keyentries[i]->name, + keys.keyentries[i]->ip->ip, NULL, + resolved_only, csv_output, show_last); + + } + + exit(0); + } + + + + printf("\n** Invalid argument combination.\n"); + helpmsg(); + + + return(0); +} + + +/* EOF */ diff --git a/src/util/syscheck_control.c b/src/util/syscheck_control.c new file mode 100755 index 0000000..8fc66e9 --- /dev/null +++ b/src/util/syscheck_control.c @@ -0,0 +1,395 @@ +/* @(#) $Id: syscheck_control.c,v 1.5 2009/08/05 18:02:14 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "addagent/manage_agents.h" +#include "sec.h" + + +#undef ARGV0 +#define ARGV0 "syscheck_control" + + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: Manages the integrity checking database.\n", + ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-l List available (active or not) agents.\n"); + printf("\t-lc List only active agents.\n"); + printf("\t-u Updates (clear) the database for the agent.\n"); + printf("\t-u all Updates (clear) the database for all agents.\n"); + printf("\t-i List modified files for the agent.\n"); + printf("\t-r -i List modified registry entries for the agent " + "(Windows only).\n"); + printf("\t-f Prints information about a modified file.\n"); + printf("\t-z Used with the -f, zeroes the auto-ignore counter.\n"); + printf("\t-d Used with the -f, ignores that file.\n"); + printf("\t-s Changes the output to CSV (comma delimited).\n"); + exit(1); +} + + +/** main **/ +int main(int argc, char **argv) +{ + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *user = USER; + char *agent_id = NULL; + char *fname = NULL; + + int gid = 0; + int uid = 0; + int c = 0, info_agent = 0, update_syscheck = 0, + list_agents = 0, zero_counter = 0, + registry_only = 0; + int active_only = 0, csv_output = 0; + + char shost[512]; + + + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* user arguments */ + if(argc < 2) + { + helpmsg(); + } + + + while((c = getopt(argc, argv, "VhzrDdlcsu:i:f:")) != -1) + { + switch(c){ + case 'V': + print_version(); + break; + case 'h': + helpmsg(); + break; + case 'D': + nowDebug(); + break; + case 'l': + list_agents++; + break; + case 'z': + zero_counter = 1; + break; + case 'd': + zero_counter = 2; + break; + case 's': + csv_output = 1; + case 'c': + active_only++; + break; + case 'r': + registry_only = 1; + break; + case 'i': + info_agent++; + if(!optarg) + { + merror("%s: -u needs an argument",ARGV0); + helpmsg(); + } + agent_id = optarg; + break; + case 'f': + if(!optarg) + { + merror("%s: -u needs an argument",ARGV0); + helpmsg(); + } + fname = optarg; + break; + case 'u': + if(!optarg) + { + merror("%s: -u needs an argument",ARGV0); + helpmsg(); + } + agent_id = optarg; + update_syscheck = 1; + break; + default: + helpmsg(); + break; + } + + } + + + /* Getting the group name */ + gid = Privsep_GetGroup(group); + uid = Privsep_GetUser(user); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR,ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR, ARGV0, user); + } + + + + /* Getting servers hostname */ + memset(shost, '\0', 512); + if(gethostname(shost, 512 -1) != 0) + { + strncpy(shost, "localhost", 32); + return(0); + } + + + + /* Listing available agents. */ + if(list_agents) + { + if(!csv_output) + { + printf("\nOSSEC HIDS %s. List of available agents:", + ARGV0); + printf("\n ID: 000, Name: %s (server), IP: 127.0.0.1, " + "Active/Local\n", shost); + } + else + { + printf("000,%s (server),127.0.0.1,Active/Local,\n", shost); + } + print_agents(1, active_only, csv_output); + printf("\n"); + exit(0); + } + + + + /* Update syscheck database. */ + if(update_syscheck) + { + /* Cleaning all agents (and server) db. */ + if(strcmp(agent_id, "all") == 0) + { + DIR *sys_dir; + struct dirent *entry; + + sys_dir = opendir(SYSCHECK_DIR); + if(!sys_dir) + { + ErrorExit("%s: Unable to open: '%s'", ARGV0, SYSCHECK_DIR); + } + + while((entry = readdir(sys_dir)) != NULL) + { + FILE *fp; + char full_path[OS_MAXSTR +1]; + + /* Do not even attempt to delete . and .. :) */ + if((strcmp(entry->d_name,".") == 0)|| + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + snprintf(full_path, OS_MAXSTR,"%s/%s", SYSCHECK_DIR, + entry->d_name); + + fp = fopen(full_path, "w"); + if(fp) + { + fclose(fp); + } + if(entry->d_name[0] == '.') + { + unlink(full_path); + } + } + + closedir(sys_dir); + printf("\n** Integrity check database updated.\n\n"); + exit(0); + } + + else if((strcmp(agent_id, "000") == 0) || + (strcmp(agent_id, "local") == 0)) + { + char final_dir[1024]; + FILE *fp; + snprintf(final_dir, 1020, "/%s/syscheck", SYSCHECK_DIR); + + fp = fopen(final_dir, "w"); + if(fp) + { + fclose(fp); + } + unlink(final_dir); + + + /* Deleting cpt file */ + snprintf(final_dir, 1020, "/%s/.syscheck.cpt", SYSCHECK_DIR); + + fp = fopen(final_dir, "w"); + if(fp) + { + fclose(fp); + } + unlink(final_dir); + + printf("\n** Integrity check database updated.\n\n"); + exit(0); + } + + /* Database from remote agents. */ + else + { + int i; + keystore keys; + + OS_ReadKeys(&keys); + + i = OS_IsAllowedID(&keys, agent_id); + if(i < 0) + { + printf("\n** Invalid agent id '%s'.\n", agent_id); + helpmsg(); + } + + /* Deleting syscheck */ + delete_syscheck(keys.keyentries[i]->name, + keys.keyentries[i]->ip->ip, 0); + + printf("\n** Integrity check database updated.\n\n"); + exit(0); + } + } + + + /* Printing information from an agent. */ + if(info_agent) + { + int i; + char final_ip[128 +1]; + char final_mask[128 +1]; + keystore keys; + + + if((strcmp(agent_id, "000") == 0) || + (strcmp(agent_id, "local") == 0)) + { + printf("\nIntegrity checking changes for local system '%s - %s':\n", + shost, "127.0.0.1"); + if(fname) + { + printf("Detailed information for entries matching: '%s'\n", + fname); + } + + print_syscheck(NULL, + NULL, fname, 0, 0, + csv_output, zero_counter); + } + else if(strchr(agent_id, '@')) + { + if(fname) + { + printf("Detailed information for entries matching: '%s'\n", + fname); + } + print_syscheck(agent_id, NULL, fname, registry_only, 0, + csv_output, zero_counter); + } + else + { + + OS_ReadKeys(&keys); + + i = OS_IsAllowedID(&keys, agent_id); + if(i < 0) + { + printf("\n** Invalid agent id '%s'.\n", agent_id); + helpmsg(); + } + + /* Getting netmask from ip. */ + final_ip[128] = '\0'; + final_mask[128] = '\0'; + getNetmask(keys.keyentries[i]->ip->netmask, final_mask, 128); + snprintf(final_ip, 128, "%s%s",keys.keyentries[i]->ip->ip, + final_mask); + + if(registry_only) + { + printf("\nIntegrity changes for 'Windows Registry' of" + " agent '%s (%s) - %s':\n", + keys.keyentries[i]->name, keys.keyentries[i]->id, + final_ip); + } + else + { + printf("\nIntegrity changes for agent " + "'%s (%s) - %s':\n", + keys.keyentries[i]->name, keys.keyentries[i]->id, + final_ip); + } + + if(fname) + { + printf("Detailed information for entries matching: '%s'\n", + fname); + } + print_syscheck(keys.keyentries[i]->name, + keys.keyentries[i]->ip->ip, fname, + registry_only, 0, csv_output, zero_counter); + + } + + exit(0); + } + + + + printf("\n** Invalid argument combination.\n"); + helpmsg(); + + + return(0); +} + + +/* EOF */ diff --git a/src/util/syscheck_update.c b/src/util/syscheck_update.c new file mode 100755 index 0000000..ce58d45 --- /dev/null +++ b/src/util/syscheck_update.c @@ -0,0 +1,205 @@ +/* @(#) $Id: syscheck_update.c,v 1.16 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "addagent/manage_agents.h" +#include "sec.h" + +#undef ARGV0 +#define ARGV0 "syscheck_update" + + +/** help **/ +void helpmsg() +{ + printf("\nOSSEC HIDS %s: Updates the integrity check database.\n", ARGV0); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\t-l List available agents.\n"); + printf("\t-a Update syscheck database for all agents.\n"); + printf("\t-u Update syscheck database for a specific agent.\n"); + printf("\t-u local Update syscheck database locally.\n\n"); + exit(1); +} + + +/** main **/ +int main(int argc, char **argv) +{ + char *dir = DEFAULTDIR; + char *group = GROUPGLOBAL; + char *user = USER; + int gid; + int uid; + + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* user arguments */ + if(argc < 2) + { + helpmsg(); + } + + /* Getting the group name */ + gid = Privsep_GetGroup(group); + uid = Privsep_GetUser(user); + if(gid < 0) + { + ErrorExit(USER_ERROR, ARGV0, user, group); + } + + + /* Setting the group */ + if(Privsep_SetGroup(gid) < 0) + { + ErrorExit(SETGID_ERROR,ARGV0, group); + } + + + /* Chrooting to the default directory */ + if(Privsep_Chroot(dir) < 0) + { + ErrorExit(CHROOT_ERROR, ARGV0, dir); + } + + + /* Inside chroot now */ + nowChroot(); + + + /* Setting the user */ + if(Privsep_SetUser(uid) < 0) + { + ErrorExit(SETUID_ERROR, ARGV0, user); + } + + /* User options */ + if(strcmp(argv[1], "-h") == 0) + { + helpmsg(); + } + else if(strcmp(argv[1], "-l") == 0) + { + printf("\nOSSEC HIDS %s: Updates the integrity check database.", + ARGV0); + print_agents(0, 0, 0); + printf("\n"); + exit(0); + } + else if(strcmp(argv[1], "-u") == 0) + { + if(argc != 3) + { + printf("\n** Option -u requires an extra argument\n"); + helpmsg(); + } + } + else if(strcmp(argv[1], "-a") == 0) + { + DIR *sys_dir; + struct dirent *entry; + + sys_dir = opendir(SYSCHECK_DIR); + if(!sys_dir) + { + ErrorExit("%s: Unable to open: '%s'", ARGV0, SYSCHECK_DIR); + } + + while((entry = readdir(sys_dir)) != NULL) + { + FILE *fp; + char full_path[OS_MAXSTR +1]; + + /* Do not even attempt to delete . and .. :) */ + if((strcmp(entry->d_name,".") == 0)|| + (strcmp(entry->d_name,"..") == 0)) + { + continue; + } + + snprintf(full_path, OS_MAXSTR,"%s/%s", SYSCHECK_DIR, entry->d_name); + + fp = fopen(full_path, "w"); + if(fp) + { + fclose(fp); + } + if(entry->d_name[0] == '.') + { + unlink(full_path); + } + } + + closedir(sys_dir); + printf("\n** Integrity check database updated.\n\n"); + exit(0); + } + else + { + printf("\n** Invalid option '%s'.\n", argv[1]); + helpmsg(); + } + + + /* local */ + if(strcmp(argv[2],"local") == 0) + { + char final_dir[1024]; + FILE *fp; + snprintf(final_dir, 1020, "/%s/syscheck", SYSCHECK_DIR); + + fp = fopen(final_dir, "w"); + if(fp) + { + fclose(fp); + } + unlink(final_dir); + + + /* Deleting cpt file */ + snprintf(final_dir, 1020, "/%s/.syscheck.cpt", SYSCHECK_DIR); + + fp = fopen(final_dir, "w"); + if(fp) + { + fclose(fp); + } + /* unlink(final_dir); */ + } + + /* external agents */ + else + { + int i; + keystore keys; + + OS_ReadKeys(&keys); + + i = OS_IsAllowedID(&keys, argv[2]); + if(i < 0) + { + printf("\n** Invalid agent id '%s'.\n", argv[2]); + helpmsg(); + } + + /* Deleting syscheck */ + delete_syscheck(keys.keyentries[i]->name,keys.keyentries[i]->ip->ip,0); + } + + printf("\n** Integrity check database updated.\n\n"); + return(0); +} + + +/* EOF */ diff --git a/src/win32/add-localfile.c b/src/win32/add-localfile.c new file mode 100755 index 0000000..f62342c --- /dev/null +++ b/src/win32/add-localfile.c @@ -0,0 +1,202 @@ +/* @(#) $Id: add-localfile.c,v 1.13 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include +#include +#include "os_regex/os_regex.h" + +#define OSSECCONF "ossec.conf" +#define OS_MAXSTR 1024 + +int total; + +int fileexist(char *file) +{ + FILE *fp; + + /* Opening file */ + fp = fopen(file, "r"); + if(!fp) + return(0); + + fclose(fp); + return(1); +} + +int dogrep(char *file, char *str) +{ + char line[OS_MAXSTR +1]; + FILE *fp; + + /* Opening file */ + fp = fopen(file, "r"); + if(!fp) + return(0); + + /* Clearing memory */ + memset(line, '\0', OS_MAXSTR +1); + + /* Reading file and looking for str */ + while(fgets(line, OS_MAXSTR, fp) != NULL) + { + if(OS_Match(str, line)) + { + fclose(fp); + return(1); + } + } + + fclose(fp); + return(0); +} + + + +/* Check is syscheck is present in the config */ +int config_file(char *name, char *file, int quiet) +{ + int add = 0; + + char ffile[256]; + FILE *fp; + + ffile[255] = '\0'; + + + /* Checking if the file has a variable format */ + if(strchr(file, '%') != NULL) + { + time_t tm; + struct tm *p; + + tm = time(NULL); + p = localtime(&tm); + + if(strftime(ffile, 255, file, p) == 0) + { + return(-1); + } + } + else + { + strncpy(ffile, file, 255); + } + + + /* Looking for ffile */ + if(!fileexist(ffile)) + { + if(quiet == 0) + { + printf("%s: Log file not existent: '%s'.\n", name, file); + } + return(-1); + } + + if(dogrep(OSSECCONF, file)) + { + printf("%s: Log file already configured: '%s'.\n", + name, file); + return(0); + } + + + /* Add iis config config */ + fp = fopen(OSSECCONF, "a"); + if(!fp) + { + printf("%s: Unable to edit configuration file.\n", name); + return(0); + } + + printf("%s: Adding log file to be monitored: '%s'.\n", name,file); + printf("%s: Continue? (y/n):", name); + while(1) + { + char u_buffer[256]; + memset(u_buffer, '\0', 256); + if((fgets(u_buffer, 254, stdin) != NULL) && + (strlen(u_buffer) < 250)) + { + if((u_buffer[0] == 'y') || (u_buffer[0] == 'Y')) + { + add = 1; + break; + } + else if((u_buffer[0] == 'n') || (u_buffer[0] == 'N')) + { + add = 0; + break; + } + } + printf("%s: Continue? (y/n):", name); + } + + if(add == 0) + { + printf("%s: Action not taken.\n", name); + fclose(fp); + return(0); + } + + fprintf(fp, "\r\n" + "\r\n" + "\r\n" + "\r\n" + " \r\n" + " %s\r\n" + " syslog\r\n" + " \r\n" + "\r\n\r\n", file); + + + printf("%s: Action completed.\n", name); + fclose(fp); + + return(0); + +} + +/* Setup windows after install */ +int main(int argc, char **argv) +{ + int quiet = 0; + + if(argc < 2) + { + printf("%s: Invalid syntax.\n", argv[0]); + printf("Try: '%s '\n\n", argv[0]); + } + + /* Looking for the quiet option */ + if((argc == 3) && (strcmp(argv[2],"--quiet") == 0)) + { + quiet = 1; + } + + + /* Checking if ossec was installed already */ + if(!fileexist(OSSECCONF)) + { + printf("%s: Unable to find ossec config: '%s'.\n", argv[0], OSSECCONF); + } + + else + { + config_file(argv[0], argv[1], quiet); + } + + return(0); +} diff --git a/src/win32/doc.html b/src/win32/doc.html new file mode 100644 index 0000000..98a349b --- /dev/null +++ b/src/win32/doc.html @@ -0,0 +1,9 @@ + + + + + + + Redirecting to the online documentation at http://www.ossec.net/en/win.html...
+ + diff --git a/src/win32/extract-win-el.c b/src/win32/extract-win-el.c new file mode 100755 index 0000000..037e4e9 --- /dev/null +++ b/src/win32/extract-win-el.c @@ -0,0 +1,427 @@ +/* @(#) $Id: extract-win-el.c,v 1.7 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All right reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include + +#include + +#define BUFFER_SIZE 2048*64 +#define DEFAULT_FILE "C:\\ossec-extracted-evt.log" + +FILE *fp; +char *file = DEFAULT_FILE; +char *name = "ossec-extract-evtlog.exe"; + +/* Event logging local structure */ +typedef struct _os_el +{ + int time_of_last; + char *name; + + EVENTLOGRECORD *er; + HANDLE h; + + DWORD record; +}os_el; +os_el el[3]; +int el_last = 0; + + +/** int startEL(char *app, os_el *el) + * Starts the event logging for each el + */ +int startEL(char *app, os_el *el) +{ + /* Opening the event log */ + el->h = OpenEventLog(NULL, app); + if(!el->h) + { + return(0); + } + + el->name = app; + GetOldestEventLogRecord(el->h, &el->record); + + return(1); +} + + + +/** char *el_getCategory(int category_id) + * Returns a string related to the category id of the log. + */ +char *el_getCategory(int category_id) +{ + char *cat; + switch(category_id) + { + case EVENTLOG_ERROR_TYPE: + cat = "ERROR"; + break; + case EVENTLOG_WARNING_TYPE: + cat = "WARNING"; + break; + case EVENTLOG_INFORMATION_TYPE: + cat = "INFORMATION"; + break; + case EVENTLOG_AUDIT_SUCCESS: + cat = "AUDIT_SUCCESS"; + break; + case EVENTLOG_AUDIT_FAILURE: + cat = "AUDIT_FAILURE"; + break; + default: + cat = "Unknown"; + break; + } + return(cat); +} + + +/** int el_getEventDLL(char *evt_name, char *source, char *event) + * Returns the event. + */ +int el_getEventDLL(char *evt_name, char *source, char *event) +{ + HKEY key; + DWORD ret; + char keyname[256]; + + + keyname[255] = '\0'; + + snprintf(keyname, 254, + "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s", + evt_name, + source); + + /* Opening registry */ + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_ALL_ACCESS, &key) + != ERROR_SUCCESS) + { + return(0); + } + + + ret = MAX_PATH -1; + if (RegQueryValueEx(key, "EventMessageFile", NULL, + NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS) + { + event[0] = '\0'; + return(0); + } + + RegCloseKey(key); + return(1); +} + + + +/** char *el_getmessage() + * Returns a descriptive message of the event. + */ +char *el_getMessage(EVENTLOGRECORD *er, char *name, + char * source, LPTSTR *el_sstring) +{ + DWORD fm_flags = 0; + char tmp_str[257]; + char event[MAX_PATH +1]; + char *curr_str; + char *next_str; + LPSTR message = NULL; + + HMODULE hevt; + + /* Initializing variables */ + event[MAX_PATH] = '\0'; + tmp_str[256] = '\0'; + + /* Flags for format event */ + fm_flags |= FORMAT_MESSAGE_FROM_HMODULE; + fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; + fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY; + + /* Get the file name from the registry (stored on event) */ + if(!el_getEventDLL(name, source, event)) + { + return(NULL); + } + + curr_str = event; + + /* If our event has multiple libraries, try each one of them */ + while((next_str = strchr(curr_str, ';'))) + { + *next_str = '\0'; + next_str++; + + ExpandEnvironmentStrings(curr_str, tmp_str, 255); + hevt = LoadLibraryEx(tmp_str, NULL, DONT_RESOLVE_DLL_REFERENCES); + if(hevt) + { + if(!FormatMessage(fm_flags, hevt, er->EventID, + 0, + (LPTSTR) &message, 0, el_sstring)) + { + message = NULL; + } + FreeLibrary(hevt); + + /* If we have a message, we can return it */ + if(message) + return(message); + } + + curr_str = next_str; + } + + ExpandEnvironmentStrings(curr_str, tmp_str, 255); + hevt = LoadLibraryEx(tmp_str, NULL, DONT_RESOLVE_DLL_REFERENCES); + if(hevt) + { + int hr; + if(!(hr = FormatMessage(fm_flags, hevt, er->EventID, + 0, + (LPTSTR) &message, 0, el_sstring))) + { + message = NULL; + } + FreeLibrary(hevt); + + /* If we have a message, we can return it */ + if(message) + return(message); + } + + return(NULL); +} + + + +/** void readel(os_el *el) + * Reads the event log. + */ +void readel(os_el *el, int printit) +{ + DWORD nstr; + DWORD user_size; + DWORD domain_size; + DWORD read, needed; + int size_left; + int str_size; + + char mbuffer[BUFFER_SIZE]; + LPSTR sstr = NULL; + + char *tmp_str = NULL; + char *category; + char *source; + char *computer_name; + char *descriptive_msg; + + char el_user[257]; + char el_domain[257]; + char el_string[1025]; + char final_msg[1024]; + LPSTR el_sstring[57]; + + /* Er must point to the mbuffer */ + el->er = (EVENTLOGRECORD *) &mbuffer; + + /* Zeroing the last values */ + el_string[1024] = '\0'; + el_user[256] = '\0'; + el_domain[256] = '\0'; + final_msg[1023] = '\0'; + el_sstring[56] = NULL; + + /* Reading the event log */ + while(ReadEventLog(el->h, + EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ, + 0, + el->er, BUFFER_SIZE -1, &read, &needed)) + { + while(read > 0) + { + + /* We need to initialize every variable before the loop */ + category = el_getCategory(el->er->EventType); + source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD)); + computer_name = source + strlen(source) + 1; + descriptive_msg = NULL; + + + /* Initialing domain/user size */ + user_size = 255; domain_size = 255; + el_domain[0] = '\0'; + el_user[0] = '\0'; + + + /* We must have some description */ + if(el->er->NumStrings) + { + size_left = 1020; + + sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset); + el_string[0] = '\0'; + + for (nstr = 0;nstr < el->er->NumStrings;nstr++) + { + str_size = strlen(sstr); + strncat(el_string, sstr, size_left); + + tmp_str= strchr(el_string, '\0'); + if(tmp_str) + { + *tmp_str = ' '; + tmp_str++; *tmp_str = '\0'; + } + size_left-=str_size + 1; + + if(nstr <= 54) + el_sstring[nstr] = (LPSTR)sstr; + + sstr = strchr( (LPSTR)sstr, '\0'); + sstr++; + } + + /* Get a more descriptive message (if available) */ + descriptive_msg = el_getMessage(el->er, el->name, source, + el_sstring); + if(descriptive_msg != NULL) + { + /* Remove any \n or \r */ + tmp_str = descriptive_msg; + while((tmp_str = strchr(tmp_str, '\n'))) + { + *tmp_str = ' '; + tmp_str++; + } + + tmp_str = descriptive_msg; + while((tmp_str = strchr(tmp_str, '\r'))) + { + *tmp_str = ' '; + tmp_str++; + } + } + } + else + { + strncpy(el_string, "(no message)", 1020); + } + + + /* Getting username */ + if (el->er->UserSidLength) + { + SID_NAME_USE account_type; + if(!LookupAccountSid(NULL, (SID *)((LPSTR)el->er + el->er->UserSidOffset), + el_user, &user_size, el_domain, &domain_size, &account_type)) + { + strncpy(el_user, "(no user)", 255); + strncpy(el_domain, "no domain", 255); + } + + } + + else + { + strncpy(el_user, "(no user)", 255); + strncpy(el_domain, "no domain", 255); + } + + + if(printit) + { + DWORD _evtid = 65535; + int id = (int)el->er->EventID & _evtid; + + snprintf(final_msg, 1022, + "%d WinEvtLog: %s: %s(%d): %s: %s(%s): %s", + (int)el->er->TimeGenerated, + el->name, + category, + id, + source, + el_user, + el_domain, + descriptive_msg != NULL?descriptive_msg:el_string); + + fprintf(fp, "%s\n", final_msg); + } + + if(descriptive_msg != NULL) + LocalFree(descriptive_msg); + + /* Changing the point to the er */ + read -= el->er->Length; + el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length); + } + + /* Setting er to the beginning of the buffer */ + el->er = (EVENTLOGRECORD *)&mbuffer; + } +} + + +/** void win_startel() + * Starts the event logging for windows + */ +void win_startel(char *evt_log) +{ + startEL(evt_log, &el[el_last]); + readel(&el[el_last],1); + el_last++; +} + +void help() +{ + printf(" OSSEC HIDS - Windows event log extract\n"); + printf("%s -h Shows this help message\n", name); + printf("%s -e Extract logs to '%s'\n", name, DEFAULT_FILE); + printf("%s -f Extract logs to the file specified\n", name); + exit(0); +} +/** main **/ +int main(int argc, char **argv) +{ + name = argv[0]; + if((argc == 2)&&(strcmp(argv[1], "-e") == 0)) + { + } + else if((argc == 3)&&(strcmp(argv[1], "-f") == 0)) + { + file = argv[2]; + } + else + help(); + + fp = fopen(file, "w"); + if(!fp) + { + printf("Unable to open file '%s'\n", file); + exit(1); + } + + win_startel("Application"); + win_startel("System"); + win_startel("Security"); + + fclose(fp); + return(0); +} + +/* EOF */ diff --git a/src/win32/favicon.ico b/src/win32/favicon.ico new file mode 100644 index 0000000..d7f3a12 Binary files /dev/null and b/src/win32/favicon.ico differ diff --git a/src/win32/favicon2.ico b/src/win32/favicon2.ico new file mode 100644 index 0000000..cdcf4ea Binary files /dev/null and b/src/win32/favicon2.ico differ diff --git a/src/win32/gen_win.sh b/src/win32/gen_win.sh new file mode 100755 index 0000000..38c4a2a --- /dev/null +++ b/src/win32/gen_win.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# Generate windows packages +DIR=`dirname $0`; +FILE="win-files.txt" +CAT=`cat ${FILE}` +WINPKG="win-pkg" + +# Generating configs +./unix2dos.pl ossec.conf > ossec-win.conf +./unix2dos.pl help.txt > help_win.txt +./unix2dos.pl ../../etc/internal_options.conf > internal_options-win.conf +./unix2dos.pl ../../LICENSE > LICENSE.txt +./unix2dos.pl ../../active-response/win/route-null.cmd > route-null.cmd +./unix2dos.pl ../../active-response/win/restart-ossec.cmd > restart-ossec.cmd + +# Going to the source dir +cd ${DIR} +CAT=`cat ${FILE}` +cd .. +mkdir ${WINPKG} +mkdir ${WINPKG}/setup + +source="" +dest="" +for i in ${CAT}; do + echo $i; + if [ "X${source}" = "X" ]; then + source=$i; + elif [ "X${dest}" = "X" ]; then + dest=$i; + echo "cp -pr ${source} ${WINPKG}/${dest}" + cp -pr ${source} "${WINPKG}/${dest}" + if [ ! $? = 0 ]; then + echo "Error copying ${source} to ${WINPKG}/${dest}" + exit 1; + fi + source="" + dest="" + fi +done + +# Final cleanup +rm ${WINPKG}/os_crypto/md5/main.c +rm ${WINPKG}/os_crypto/blowfish/main.c +rm ${WINPKG}/os_crypto/sha1/main.c +rm ${WINPKG}/os_crypto/md5_sha1/main.c +rm ${WINPKG}/shared/rules_op.c diff --git a/src/win32/help.txt b/src/win32/help.txt new file mode 100755 index 0000000..19663b5 --- /dev/null +++ b/src/win32/help.txt @@ -0,0 +1,57 @@ +** OSSEC Windows Agent v2.3 ** +** Copyright (C) 2009 Trend Micro Inc. ** + + +Thanks for installing 'OSSEC Windows Agent version 1.6'. Before you continue, +make sure that you have an instance of the OSSEC server running and configured +to accept this system as an agent. + +For more information on how to install the server version of OSSEC, look at: +http://www.ossec.net/main/manual/#installtypes +http://www.ossec.net/wiki/index.php/InstallGuides + + + +** Table of contents ** + +1- How to obtain more information? +2- What this agent does? +3- Questions/Support? + + + +** Responses ** + +1- How to obtain more information? + +You can obtain more information about OSSEC on the following links: +http://www.ossec.net/main/manual/ (Manual) +http://www.ossec.net/wiki/index.php/FAQ (FAQ) +http://www.ossec.net (OSSEC site) +http://www.ossec.net/dcid/ (OSSEC blog) + + +2- What this agent does? + +The Windows agent does the following tasks: + +-Monitors the Windows event log on real time. +-Monitors IIS logs (Web, FTP, SMTP) and any other logs present on your + system (including Symantec Anti-Virus, MySQL, Apache, etc) on real time. +-Periodically checks the Windows Registry for changes. +-Periodically checks your Windows folders for changes. +-Periodically does policy verifications to make sure your system is + configured properly. + + +3- Questions/Support? + +Visit the following link for information on how to get help or +support for OSSEC: + +http://www.ossec.net/main/support/ + +For commercial support, please send an e-mail to contact@ossec.net + + +** EOF ** diff --git a/src/win32/icofile.rc b/src/win32/icofile.rc new file mode 100644 index 0000000..4bd5cec --- /dev/null +++ b/src/win32/icofile.rc @@ -0,0 +1 @@ +101 ICON favicon.ico diff --git a/src/win32/iis-logs.bat b/src/win32/iis-logs.bat new file mode 100755 index 0000000..ca51417 --- /dev/null +++ b/src/win32/iis-logs.bat @@ -0,0 +1,57 @@ +@echo off + +rem Searching for IIS logs. +rem If we find any log in the NCSA or W3C extended format, +rem change the config to support that. If not, let the user know. +rem Example of log to look: nc060215.log or ex060723.log + +echo. +echo Looking for IIS log files to monitor. +echo For more information visit: +echo http://www.ossec.net/en/manual.html#iis +echo. +echo. + +IF EXIST %WinDir%\System32\LogFiles\W3SVC1\nc??????.log ( + echo * IIS NCSA log found. Changing config to read it. + echo. >> ossec.conf + echo ^ >> ossec.conf + echo ^ >> ossec.conf + echo ^%WinDir%\System32\LogFiles\W3SVC1\nc%%y%%m%%d.log^ >> ossec.conf + echo ^iis^ >> ossec.conf + echo ^ >> ossec.conf + echo ^ >> ossec.conf + pause + ) + +IF EXIST %WinDir%\System32\LogFiles\W3SVC1\ex??????.log ( + echo * IIS W3C extended log found. Changing config to read it. + echo. >> ossec.conf + echo ^ >> ossec.conf + echo ^ >> ossec.conf + echo ^%WinDir%\System32\LogFiles\W3SVC1\ex%%y%%m%%d.log^ >> ossec.conf + echo ^iis^ >> ossec.conf + echo ^ >> ossec.conf + echo ^ >> ossec.conf + pause + ) + +IF EXIST %WinDir%\System32\LogFiles\W3SVC3\ex??????.log ( + echo * IIS W3C extended log found. Changing config to read it. + echo. >> ossec.conf + echo ^ >> ossec.conf + echo ^ >> ossec.conf + echo ^%WinDir%\System32\LogFiles\W3SVC3\nc%%y%%m%%d.log^ >> ossec.conf + echo ^iis^ >> ossec.conf + echo ^ >> ossec.conf + echo ^ >> ossec.conf + pause + ) + +IF EXIST %WinDir%\System32\LogFiles\W3SVC1 ( + echo * IIS Log found. Look at the link above if you want to monitor it. + pause + exit ) + +rem EOF + diff --git a/src/win32/make.bat b/src/win32/make.bat new file mode 100755 index 0000000..d3984c4 --- /dev/null +++ b/src/win32/make.bat @@ -0,0 +1,14 @@ +echo Making windows agent + +"C:\MinGW\bin\windres.exe" -i icofile.rc -o icon.o +"C:\MinGW\bin\gcc.exe" -o "ossec-agent" -Wall -DARGV0=\"ossec-agent\" -DCLIENT -DWIN32 -DOSSECHIDS icon.o os_regex/*.c os_net/*.c os_xml/*.c zlib-1.2.3/*.c config/*.c shared/*.c os_execd/*.c os_crypto/blowfish/*.c os_crypto/md5/*.c os_crypto/sha1/*.c os_crypto/md5_sha1/*.c os_crypto/shared/*.c rootcheck/*.c *.c -Iheaders/ -I./ -lwsock32 +"C:\MinGW\bin\gcc.exe" -o "ossec-rootcheck" -Wall -DARGV0=\"ossec-rootcheck\" -DCLIENT -DWIN32 icon.o os_regex/*.c os_net/*.c os_xml/*.c config/*.c shared/*.c win_service.c rootcheck/*.c -Iheaders/ -I./ -lwsock32 +"C:\MinGW\bin\gcc.exe" -o "manage_agents" -Wall -DARGV0=\"ossec-agent\" -DCLIENT -DWIN32 -DMA os_regex/*.c zlib-1.2.3/*.c os_zlib.c shared/*.c os_crypto/blowfish/*.c os_crypto/md5/*.c os_crypto/shared/*.c addagent/*.c -Iheaders/ -I./ -lwsock32 +"C:\MinGW\bin\gcc.exe" -o setup-windows -Wall os_regex/*.c -DARGV0=\"setup-windows\" -DCLIENT -DWIN32 win_service.c shared/file_op.c shared/debug_op.c setup/setup-win.c setup/setup-shared.c -Iheaders/ -I./ -lwsock32 +"C:\MinGW\bin\gcc.exe" -o setup-syscheck -Wall os_regex/*.c os_xml/*.c setup/setup-syscheck.c setup/setup-shared.c -I./ -Iheaders/ +"C:\MinGW\bin\gcc.exe" -o service-start -Wall icon.o os_regex/*.c setup/service-start.c -I./ +"C:\MinGW\bin\gcc.exe" -o service-stop -Wall os_regex/*.c setup/service-stop.c -I./ +"C:\MinGW\bin\gcc.exe" -o setup-iis -Wall os_regex/*.c setup/setup-iis.c -I./ +"C:\MinGW\bin\gcc.exe" -o add-localfile -Wall os_regex/*.c setup/add-localfile.c -I./ +cd ui\ +make diff --git a/src/win32/make.sh b/src/win32/make.sh new file mode 100755 index 0000000..20784d6 --- /dev/null +++ b/src/win32/make.sh @@ -0,0 +1,19 @@ +echo Making windows agent + +i586-mingw32msvc-windres -i icofile.rc -o icon.o +i586-mingw32msvc-gcc -o ossec-agent.exe -Wall -DARGV0=\"ossec-agent\" -DCLIENT -DWIN32 -DOSSECHIDS icon.o os_regex/*.c os_net/*.c os_xml/*.c zlib-1.2.3/*.c config/*.c shared/*.c os_execd/*.c os_crypto/blowfish/*.c os_crypto/md5/*.c os_crypto/sha1/*.c os_crypto/md5_sha1/*.c os_crypto/shared/*.c rootcheck/*.c *.c -Iheaders/ -I./ -lwsock32 +i586-mingw32msvc-gcc -o ossec-rootcheck.exe -Wall -DARGV0=\"ossec-rootcheck\" -DCLIENT -DWIN32 icon.o os_regex/*.c os_net/*.c os_xml/*.c config/*.c shared/*.c win_service.c rootcheck/*.c -Iheaders/ -I./ -lwsock32 +i586-mingw32msvc-gcc -o manage_agents.exe -Wall -DARGV0=\"ossec-agent\" -DCLIENT -DWIN32 -DMA os_regex/*.c zlib-1.2.3/*.c os_zlib.c shared/*.c os_crypto/blowfish/*.c os_crypto/md5/*.c os_crypto/shared/*.c addagent/*.c -Iheaders/ -I./ -lwsock32 +i586-mingw32msvc-gcc -o setup-windows.exe -Wall os_regex/*.c -DARGV0=\"setup-windows\" -DCLIENT -DWIN32 win_service.c shared/file_op.c shared/debug_op.c setup/setup-win.c setup/setup-shared.c -Iheaders/ -I./ -lwsock32 +i586-mingw32msvc-gcc -o setup-syscheck.exe -Wall os_regex/*.c os_xml/*.c setup/setup-syscheck.c setup/setup-shared.c -I./ -Iheaders/ +i586-mingw32msvc-gcc -o service-start.exe -Wall icon.o os_regex/*.c setup/service-start.c -I./ +i586-mingw32msvc-gcc -o service-stop.exe -Wall os_regex/*.c setup/service-stop.c -I./ +i586-mingw32msvc-gcc -o setup-iis.exe -Wall os_regex/*.c setup/setup-iis.c -I./ +i586-mingw32msvc-gcc -o add-localfile.exe -Wall os_regex/*.c setup/add-localfile.c -I./ + +cd ui +sh ./make.sh +cd ../ + +makensis ui.nsi +makensis ossec-installer.nsi diff --git a/src/win32/os_win.h b/src/win32/os_win.h new file mode 100755 index 0000000..a84e445 --- /dev/null +++ b/src/win32/os_win.h @@ -0,0 +1,55 @@ +/* @(#) $Id: os_win.h,v 1.8 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + +#ifndef _OS_WIN__H +#define _OS_WIN__H + + +/** int InstallService(char *path) + * Install the OSSEC HIDS agent service. + */ +int InstallService(char *path); + + +/** int UninstallService() + * Uninstall the OSSEC HIDS agent service. + */ +int UninstallService(); + + +/** int QueryService(): + * Checks if service is running. + * Return 1 on success (running) or 0 if not. + */ +int CheckServiceRunning(); + + +/* os_start_service: Starts ossec service */ +int os_start_service(); + + +/* os_stop_service: Stops ossec service */ +int os_stop_service(); + + +/** int os_WinMain(int argc, char **argv) + * Starts the process from the services. + */ +int os_WinMain(int argc, char **argv); + + +/** int local_start(); + * Locally starts the process (after the services initialization). + */ +int local_start(); + +#endif +/* EOF */ diff --git a/src/win32/ossec-installer.nsi b/src/win32/ossec-installer.nsi new file mode 100755 index 0000000..4597860 --- /dev/null +++ b/src/win32/ossec-installer.nsi @@ -0,0 +1,197 @@ +;-------------------------------- +;Include Modern UI + +!include "MUI.nsh" + +;-------------------------------- +;General + +!define VERSION "2.3" +!define NAME "Ossec HIDS" +!define /date CDATE "%b %d %Y at %H:%M:%S" + + +Name "${NAME} Windows Agent v${VERSION}" +BrandingText "Copyright (C) 2009 Trend Micro Inc." +OutFile "ossec-win32-agent.exe" + + +InstallDir $PROGRAMFILES\ossec-agent +InstallDirRegKey HKLM "ossec" "Install_Dir" + + +;-------------------------------- +;Interface Settings + +!define MUI_ABORTWARNING + +;-------------------------------- +;Pages + !define MUI_ICON favicon.ico + !define MUI_UNICON ossec-uninstall.ico + !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the install of ${Name}.\r\n\r\nClick next to continue." + + ; Page for choosing components. + !define MUI_COMPONENTSPAGE_TEXT_TOP "Select the options you want to be executed. Click next to continue." + + ;!define MUI_COMPONENTSPAGE_TEXT_COMPLIST "text complist" + + ;!define MUI_COMPONENTSPAGE_TEXT_INSTTYPE "Select components to install:" + + ;!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE "text abac" + + ;!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO "text info oi" + + !define MUI_COMPONENTSPAGE_NODESC + + !insertmacro MUI_PAGE_WELCOME + !insertmacro MUI_PAGE_LICENSE "LICENSE.txt" + !insertmacro MUI_PAGE_COMPONENTS + !insertmacro MUI_PAGE_DIRECTORY + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_WELCOME + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + !insertmacro MUI_UNPAGE_FINISH + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" + +;-------------------------------- + +Function .onInit + SetOutPath $INSTDIR + IfFileExists $INSTDIR\ossec.conf 0 +3 + MessageBox MB_OKCANCEL "${NAME} is already installed. We will stop it before continuing." IDOK NoAbort + Abort + NoAbort: + + ;; Stopping ossec service. + ExecWait '"net" "stop" "OssecSvc"' +FunctionEnd + + +Section "OSSEC Agent (required)" MainSec + +;Required section. +SectionIn RO +SetOutPath $INSTDIR + +ClearErrors + +File ossec-agent.exe default-ossec.conf manage_agents.exe os_win32ui.exe win32ui.exe ossec-rootcheck.exe internal_options.conf setup-windows.exe setup-syscheck.exe setup-iis.exe service-start.exe service-stop.exe doc.html rootkit_trojans.txt rootkit_files.txt add-localfile.exe LICENSE.txt rootcheck\rootcheck.conf rootcheck\db\win_applications_rcl.txt rootcheck\db\win_malware_rcl.txt rootcheck\db\win_audit_rcl.txt help.txt vista_sec.csv route-null.cmd restart-ossec.cmd +WriteRegStr HKLM SOFTWARE\ossec "Install_Dir" "$INSTDIR" + +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ossec" "DisplayName" "OSSEC Hids Agent" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ossec" "UninstallString" '"$INSTDIR\uninstall.exe"' +WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ossec" "NoModify" 1 +WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ossec" "NoRepair" 1 +WriteUninstaller "uninstall.exe" + + +; Writing version and install information +FileOpen $0 $INSTDIR\VERSION.txt w +IfErrors done +FileWrite $0 "${NAME} v${VERSION} - " +FileWrite $0 "Installed on ${CDATE}" +FileClose $0 +done: + + +CreateDirectory "$INSTDIR\rids" +CreateDirectory "$INSTDIR\syscheck" +CreateDirectory "$INSTDIR\shared" +CreateDirectory "$INSTDIR\active-response" +CreateDirectory "$INSTDIR\active-response\bin" +Delete "$INSTDIR\active-response\bin\route-null.cmd" +Delete "$INSTDIR\active-response\bin\restart-ossec.cmd" +Rename "$INSTDIR\rootkit_trojans.txt" "$INSTDIR\shared\rootkit_trojans.txt" +Rename "$INSTDIR\rootkit_files.txt" "$INSTDIR\shared\rootkit_files.txt" +Rename "$INSTDIR\win_malware_rcl.txt" "$INSTDIR\shared\win_malware_rcl.txt" +Rename "$INSTDIR\win_audit_rcl.txt" "$INSTDIR\shared\win_audit_rcl.txt" +Rename "$INSTDIR\win_applications_rcl.txt" "$INSTDIR\shared\win_applications_rcl.txt" +Rename "$INSTDIR\route-null.cmd" "$INSTDIR\active-response\bin\route-null.cmd" +Rename "$INSTDIR\restart-ossec.cmd" "$INSTDIR\active-response\bin\restart-ossec.cmd" +Delete "$SMPROGRAMS\ossec\Edit.lnk" +Delete "$SMPROGRAMS\ossec\Uninstall.lnk" +Delete "$SMPROGRAMS\ossec\Documentation.lnk" +Delete "$SMPROGRAMS\ossec\Edit Config.lnk" +Delete "$SMPROGRAMS\ossec\*.*" + +; Remove directories used +RMDir "$SMPROGRAMS\ossec" + +; Creating SMS directory +CreateDirectory "$SMPROGRAMS\ossec" + +CreateShortCut "$SMPROGRAMS\ossec\Manage Agent.lnk" "$INSTDIR\win32ui.exe" "" "$INSTDIR\win32ui.exe" 0 +CreateShortCut "$SMPROGRAMS\ossec\Documentation.lnk" "$INSTDIR\doc.html" "" "$INSTDIR\doc.html" 0 +CreateShortCut "$SMPROGRAMS\ossec\Edit Config.lnk" "$INSTDIR\ossec.conf" "" "$INSTDIR\ossec.conf" 0 +CreateShortCut "$SMPROGRAMS\ossec\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + + +; Install in the services +ExecWait '"$INSTDIR\ossec-agent.exe" install-service' +ExecWait '"$INSTDIR\setup-windows.exe" "$INSTDIR"' +Exec '"$INSTDIR\os_win32ui.exe" "$INSTDIR"' + +SectionEnd + +Section "Scan and monitor IIS logs (recommended)" IISLogs + +ExecWait '"$INSTDIR\setup-iis.exe" "$INSTDIR"' + +SectionEnd + +Section "Enable integrity checking (recommended)" IntChecking + +ExecWait '"$INSTDIR\setup-syscheck.exe" "$INSTDIR" "enable"' + +SectionEnd + + + +Section "Uninstall" + + ; Stop ossec + ExecWait '"net" "stop" "OssecSvc"' + + ; Uninstall from the services + Exec '"$INSTDIR\ossec-agent.exe" uninstall-service' + + ; Remove registry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ossec" + DeleteRegKey HKLM SOFTWARE\ossec + + ; Remove files and uninstaller + Delete "$INSTDIR\ossec-agent.exe" + Delete "$INSTDIR\manage_agents.exe" + Delete "$INSTDIR\ossec.conf" + Delete "$INSTDIR\uninstall.exe" + Delete "$INSTDIR\*" + Delete "$INSTDIR\rids\*" + Delete "$INSTDIR\syscheck\*" + Delete "$INSTDIR\shared\*" + Delete "$INSTDIR\active-response\bin\*" + Delete "$INSTDIR\active-response\*" + Delete "$INSTDIR" + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\ossec\*.*" + Delete "$SMPROGRAMS\ossec\*" + + ; Remove directories used + RMDir "$SMPROGRAMS\ossec" + RMDir "$INSTDIR\shared" + RMDir "$INSTDIR\syscheck" + RMDir "$INSTDIR\rids" + RMDir "$INSTDIR\active-response\bin" + RMDir "$INSTDIR\active-response" + RMDir "$INSTDIR" + +SectionEnd + diff --git a/src/win32/ossec-uninstall.ico b/src/win32/ossec-uninstall.ico new file mode 100644 index 0000000..8bd2d18 Binary files /dev/null and b/src/win32/ossec-uninstall.ico differ diff --git a/src/win32/ossec.conf b/src/win32/ossec.conf new file mode 100755 index 0000000..b9c2aee --- /dev/null +++ b/src/win32/ossec.conf @@ -0,0 +1,147 @@ + + + + + + + + + + Application + eventlog + + + + Security + eventlog + + + + System + eventlog + + + + + + ./shared/win_audit_rcl.txt + ./shared/win_applications_rcl.txt + ./shared/win_malware_rcl.txt + + + + + + + + 72000 + + + yes + + + + %WINDIR%/win.ini + %WINDIR%/system.ini + C:\autoexec.bat + C:\config.sys + C:\boot.ini + %WINDIR%/System32/CONFIG.NT + %WINDIR%/System32/AUTOEXEC.NT + %WINDIR%/System32/at.exe + %WINDIR%/System32/attrib.exe + %WINDIR%/System32/cacls.exe + %WINDIR%/System32/debug.exe + %WINDIR%/System32/drwatson.exe + %WINDIR%/System32/drwtsn32.exe + %WINDIR%/System32/edlin.exe + %WINDIR%/System32/eventcreate.exe + %WINDIR%/System32/eventtriggers.exe + %WINDIR%/System32/ftp.exe + %WINDIR%/System32/net.exe + %WINDIR%/System32/net1.exe + %WINDIR%/System32/netsh.exe + %WINDIR%/System32/rcp.exe + %WINDIR%/System32/reg.exe + %WINDIR%/regedit.exe + %WINDIR%/System32/regedt32.exe + %WINDIR%/System32/regsvr32.exe + %WINDIR%/System32/rexec.exe + %WINDIR%/System32/rsh.exe + %WINDIR%/System32/runas.exe + %WINDIR%/System32/sc.exe + %WINDIR%/System32/subst.exe + %WINDIR%/System32/telnet.exe + %WINDIR%/System32/tftp.exe + %WINDIR%/System32/tlntsvr.exe + %WINDIR%/System32/drivers/etc + C:\Documents and Settings/All Users/Start Menu/Programs/Startup + .log$|.htm$|.jpg$|.png$|.chm$|.pnf$|.evtx$ + + + + HKEY_LOCAL_MACHINE\Software\Classes\batfile + HKEY_LOCAL_MACHINE\Software\Classes\cmdfile + HKEY_LOCAL_MACHINE\Software\Classes\comfile + HKEY_LOCAL_MACHINE\Software\Classes\exefile + HKEY_LOCAL_MACHINE\Software\Classes\piffile + HKEY_LOCAL_MACHINE\Software\Classes\AllFilesystemObjects + HKEY_LOCAL_MACHINE\Software\Classes\Directory + HKEY_LOCAL_MACHINE\Software\Classes\Folder + HKEY_LOCAL_MACHINE\Software\Classes\Protocols + HKEY_LOCAL_MACHINE\Software\Policies + HKEY_LOCAL_MACHINE\Security + HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer + + + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurePipeServers\winreg + + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnceEx + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\URL + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon + + HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components + + + + + HKEY_LOCAL_MACHINE\Security\Policy\Secrets + HKEY_LOCAL_MACHINE\Security\SAM\Domains\Account\Users + \Enum$ + + + + yes + + + + + + + diff --git a/src/win32/read-registry.c b/src/win32/read-registry.c new file mode 100755 index 0000000..b5f4d68 --- /dev/null +++ b/src/win32/read-registry.c @@ -0,0 +1,210 @@ +#include "shared.h" +#include "os_crypto/md5/md5_op.h" +#include "os_crypto/sha1/sha1_op.h" + +/* Default values */ +#define MAX_KEY_LENGTH 255 +#define MAX_KEY 2048 +#define MAX_VALUE_NAME 16383 + +char *(os_winreg_ignore_list[]) = {"SOFTWARE\\Classes","test123",NULL}; + +HKEY sub_tree; +int os_winreg_open_key(char *subkey); + +void os_winreg_querykey(HKEY hKey, char *p_key) +{ + int i, rc; + DWORD j; + + /* QueryInfo and EnumKey variables */ + TCHAR sub_key_name_b[MAX_KEY_LENGTH +1]; + TCHAR class_name_b[MAX_PATH +1]; + DWORD sub_key_name_s; + DWORD class_name_s = MAX_PATH; + + /* Number of sub keys */ + DWORD subkey_count = 0; + + /* Number of values */ + DWORD value_count; + + /* Variables for RegEnumValue */ + TCHAR value_buffer[MAX_VALUE_NAME +1]; + TCHAR data_buffer[MAX_VALUE_NAME +1]; + DWORD value_size; + DWORD data_size; + + /* Data type for RegEnumValue */ + DWORD data_type = 0; + + + /* Initializing the memory for some variables */ + class_name_b[0] = '\0'; + class_name_b[MAX_PATH] = '\0'; + sub_key_name_b[0] = '\0'; + sub_key_name_b[MAX_KEY_LENGTH] = '\0'; + + + /* We use the class_name, subkey_count and the value count. */ + rc = RegQueryInfoKey(hKey, class_name_b, &class_name_s, NULL, + &subkey_count, NULL, NULL, &value_count, + NULL, NULL, NULL, NULL); + + /* Check return code of QueryInfo */ + if(rc != ERROR_SUCCESS) + { + return; + } + + + + /* Checking if we have sub keys */ + if(subkey_count) + { + /* We open each subkey and call open_key */ + for(i=0;i +#include +#include +#include + + +/* Setup windows after install */ +int main(int argc, char **argv) +{ + printf("%s: Attempting to start ossec.", argv[0]); + + system("net start OssecSvc"); + + system("pause"); + return(0); +} diff --git a/src/win32/service-stop.c b/src/win32/service-stop.c new file mode 100644 index 0000000..6db442b --- /dev/null +++ b/src/win32/service-stop.c @@ -0,0 +1,28 @@ +/* @(#) $Id: service-stop.c,v 1.4 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include + + +/* Setup windows after install */ +int main(int argc, char **argv) +{ + printf("%s: Attempting to stop ossec.", argv[0]); + + system("net stop OssecSvc"); + + system("pause"); + return(0); +} diff --git a/src/win32/setup-iis.c b/src/win32/setup-iis.c new file mode 100755 index 0000000..9874b45 --- /dev/null +++ b/src/win32/setup-iis.c @@ -0,0 +1,330 @@ +/* @(#) $Id: setup-iis.c,v 1.16 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_regex/os_regex.h" + + +#define OSSECCONF "ossec.conf" +#define OS_MAXSTR 1024 + + +int total; + + +int direxist(char *dir) +{ + DIR *dp; + + /* Opening dir */ + dp = opendir(dir); + if(dp == NULL) + return(0); + + closedir(dp); + return(1); +} + + +int fileexist(char *file) +{ + FILE *fp; + + /* Opening file */ + fp = fopen(file, "r"); + if(!fp) + return(0); + + fclose(fp); + return(1); +} + +int dogrep(char *file, char *str) +{ + char line[OS_MAXSTR +1]; + FILE *fp; + + /* Opening file */ + fp = fopen(file, "r"); + if(!fp) + return(0); + + /* Clearing memory */ + memset(line, '\0', OS_MAXSTR +1); + + /* Reading file and looking for str */ + while(fgets(line, OS_MAXSTR, fp) != NULL) + { + if(OS_Match(str, line)) + { + fclose(fp); + return(1); + } + } + + fclose(fp); + return(0); +} + + +/* Getting Windows directory */ +static void get_win_dir(char *file, int f_size) +{ + ExpandEnvironmentStrings("%WINDIR%", file, f_size); + + if(!direxist(file)) + { + strncpy(file, "C:\\WINDOWS", f_size); + } +} + + + +int config_dir(char *name, char *dir, char *vfile) +{ + FILE *fp; + + if(!direxist(dir)) + { + return(0); + } + + if(dogrep(OSSECCONF, vfile)) + { + printf("%s: Log file already configured: '%s'.\n", + name, vfile); + return(1); + } + + printf("%s: IIS directory found, but no valid log.\n", name); + printf("%s: You may have it configured in a format different\n" + " than W3C Extended or you just don't have today's\n" + " log available.\n", name); + printf("%s: http://www.ossec.net/en/manual.html#iis\n\n", name); + + + /* Add iis config config */ + fp = fopen(OSSECCONF, "a"); + if(!fp) + { + printf("%s: Unable to edit configuration file.\n", name); + return(1); + } + + fprintf(fp, "\r\n" + "\r\n" + "\r\n" + "\r\n" + " \r\n" + " %s\r\n" + " iis\r\n" + " \r\n" + "\r\n\r\n", vfile); + + printf("%s: Action completed.\n", name); + + total++; + fclose(fp); + + return(1); + + +} + + +/* Check if the iis file is present in the config */ +int config_iis(char *name, char *file, char *vfile) +{ + FILE *fp; + + if(!fileexist(file)) + { + return(0); + } + + total++; + + if(dogrep(OSSECCONF, vfile)) + { + printf("%s: Log file already configured: '%s'.\n", + name, vfile); + return(1); + } + + printf("%s: Adding IIS log file to be monitored: '%s'.\n", name,vfile); + + + /* Add iis config config */ + fp = fopen(OSSECCONF, "a"); + if(!fp) + { + printf("%s: Unable to edit configuration file.\n", name); + return(1); + } + + fprintf(fp, "\r\n" + "\r\n" + "\r\n" + "\r\n" + " \r\n" + " %s\r\n" + " iis\r\n" + " \r\n" + "\r\n\r\n", vfile); + + printf("%s: Action completed.\n", name); + fclose(fp); + + return(1); + +} + +/* Setup windows after install */ +int main(int argc, char **argv) +{ + int i = 0; + + time_t tm; + struct tm *p; + + char win_dir[2048]; + + + if(argc >= 2) + { + if(chdir(argv[1]) != 0) + { + printf("%s: Invalid directory: '%s'.\n", argv[0], argv[1]); + return(0); + } + } + + /* Checking if ossec was installed already */ + if(!fileexist(OSSECCONF)) + { + printf("%s: Unable to find ossec config: '%s'", argv[0], OSSECCONF); + exit(0); + } + + /* Getting todays day */ + tm = time(NULL); + p = localtime(&tm); + + total = 0; + + printf("%s: Looking for IIS log files to monitor.\r\n", + argv[0]); + printf("%s: For more information: http://www.ossec.net/en/win.html\r\n", + argv[0]); + printf("\r\n"); + + + /* Getting windows directory */ + get_win_dir(win_dir, sizeof(win_dir) -1); + + + /* Looking for IIS log files */ + while(i <= 254) + { + char lfile[OS_MAXSTR +1]; + char vfile[OS_MAXSTR +1]; + + i++; + + /* Searching for NCSA */ + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\W3SVC%d\\nc%02d%02d%02d.log", + win_dir,i, (p->tm_year+1900)-2000, p->tm_mon+1, p->tm_mday); + snprintf(vfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\W3SVC%d\\nc%%y%%m%%d.log", + win_dir, i); + + /* Try dir-based */ + config_iis(argv[0], lfile, vfile); + + + /* Searching for W3C extended */ + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\W3SVC%d\\ex%02d%02d%02d.log", + win_dir, i, (p->tm_year+1900)-2000, p->tm_mon+1, p->tm_mday); + + snprintf(vfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\W3SVC%d\\ex%%y%%m%%d.log", + win_dir, i); + + /* Try dir-based */ + if(config_iis(argv[0], lfile, vfile) == 0) + { + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\W3SVC%d", win_dir, i); + config_dir(argv[0], lfile, vfile); + } + + + /* Searching for FTP Extended format */ + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\MSFTPSVC%d\\ex%02d%02d%02d.log", + win_dir, i, (p->tm_year+1900)-2000, p->tm_mon+1, p->tm_mday); + + snprintf(vfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\MSFTPSVC%d\\ex%%y%%m%%d.log", + win_dir, i); + if(config_iis(argv[0], lfile, vfile) == 0) + { + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\MSFTPSVC%d", win_dir, i); + config_dir(argv[0], lfile, vfile); + } + + + /* Searching for IIS SMTP logs */ + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\SMTPSVC%d\\ex%02d%02d%02d.log", + win_dir, i, (p->tm_year+1900)-2000, p->tm_mon+1, p->tm_mday); + + snprintf(vfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\SMTPSVC%d\\ex%%y%%m%%d.log", + win_dir, i); + if(config_iis(argv[0], lfile, vfile) == 0) + { + snprintf(lfile, + OS_MAXSTR, + "%s\\System32\\LogFiles\\SMTPSVC%d",win_dir, i); + config_dir(argv[0], lfile, vfile); + } + } + + if(total == 0) + { + printf("%s: No IIS log added. Look at the link above for more " + "information.\r\n", argv[0]); + } + + return(0); +} diff --git a/src/win32/setup-shared.c b/src/win32/setup-shared.c new file mode 100755 index 0000000..837768a --- /dev/null +++ b/src/win32/setup-shared.c @@ -0,0 +1,98 @@ +/* @(#) $Id: setup-shared.c,v 1.3 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_regex/os_regex.h" + +#define OSSECCONF "ossec.conf" +#define OS_MAXSTR 1024 + + +/* Checks if a file exist. */ +int fileexist(char *file) +{ + FILE *fp; + + /* Opening file */ + fp = fopen(file, "r"); + if(!fp) + return(0); + + fclose(fp); + return(1); +} + + +/* Grep for a string in a file. */ +int dogrep(char *file, char *str) +{ + char line[OS_MAXSTR +1]; + FILE *fp; + + /* Opening file */ + fp = fopen(file, "r"); + if(!fp) + return(0); + + /* Clearing memory */ + memset(line, '\0', OS_MAXSTR +1); + + /* Reading file and looking for str */ + while(fgets(line, OS_MAXSTR, fp) != NULL) + { + if(OS_Match(str, line)) + { + fclose(fp); + return(1); + } + } + + fclose(fp); + return(0); +} + + +/* Check if dir exists */ +int direxist(char *dir) +{ + DIR *dp; + + /* Opening dir */ + dp = opendir(dir); + if(dp == NULL) + return(0); + + closedir(dp); + return(1); +} + + +/* Get Windows main directory */ +void get_win_dir(char *file, int f_size) +{ + ExpandEnvironmentStrings("%WINDIR%", file, f_size); + + if(!direxist(file)) + { + strncpy(file, "C:\\WINDOWS", f_size); + } +} + + +/* EOF */ diff --git a/src/win32/setup-shared.h b/src/win32/setup-shared.h new file mode 100755 index 0000000..581a893 --- /dev/null +++ b/src/win32/setup-shared.h @@ -0,0 +1,44 @@ +/* @(#) $Id: setup-shared.h,v 1.4 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_regex/os_regex.h" +#include "headers/file_op.h" + +#define OSSECCONF "ossec.conf" +#define OSSECDEF "default-ossec.conf" +#define OSSECLAST "ossec.conf.bak" +#define CLIENTKEYS "client.keys" +#define OS_MAXSTR 1024 + + +/* Checks if a file exist. */ +int fileexist(char *file); + +/* Grep for a string in a file. */ +int dogrep(char *file, char *str); + +/* Check if dir exists */ +int direxist(char *dir); + +/* Get Windows main directory */ +void get_win_dir(char *file, int f_size); + + +/* EOF */ diff --git a/src/win32/setup-syscheck.c b/src/win32/setup-syscheck.c new file mode 100755 index 0000000..47f4347 --- /dev/null +++ b/src/win32/setup-syscheck.c @@ -0,0 +1,77 @@ +/* @(#) $Id: setup-syscheck.c,v 1.5 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "setup-shared.h" +#include "os_xml/os_xml.h" +#include "os_xml/os_xml_writer.h" + +#define OSSEC_CONFIG_TMP ".tmp.ossec.conf" + + +/* Enable Syscheck.*/ +int main(int argc, char **argv) +{ + char *status; + char *(xml_syscheck_status[])={"ossec_config","syscheck","disabled", NULL}; + + if(argc < 3) + { + printf("%s: Invalid syntax.\n", argv[0]); + printf("Try: '%s [enable|disable]'\n\n", argv[0]); + return(0); + } + + /* Checking for directory. */ + if(chdir(argv[1]) != 0) + { + printf("%s: Invalid directory: '%s'.\n", argv[0], argv[1]); + return(0); + } + + + /* Checking if ossec was installed already */ + if(!fileexist(OSSECCONF)) + { + printf("%s: OSSEC not installed yet. Exiting.\n", argv[0]); + return(0); + } + + + /* Checking status. */ + if(strcmp(argv[2], "enable") == 0) + { + status = "no"; + } + else + { + status = "yes"; + } + + + /* Writing to the XML. */ + if(OS_WriteXML(OSSECCONF, OSSEC_CONFIG_TMP, xml_syscheck_status, + NULL, "no", status, 0) != 0) + { + printf("%s: Error writing to the Config file. Exiting.\n", argv[0]); + return(0); + } + + /* Renaming config files */ + unlink(OSSECLAST); + rename(OSSECCONF, OSSECLAST); + rename(OSSEC_CONFIG_TMP, OSSECCONF); + + return(0); +} + + +/* EOF */ diff --git a/src/win32/setup-win.c b/src/win32/setup-win.c new file mode 100755 index 0000000..ed54ee1 --- /dev/null +++ b/src/win32/setup-win.c @@ -0,0 +1,104 @@ +/* @(#) $Id: setup-win.c,v 1.42 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation + */ + + +#include "setup-shared.h" + + +/* Setup windows after install */ +int main(int argc, char **argv) +{ + if(argc < 2) + { + printf("%s: Invalid syntax.\n", argv[0]); + printf("Try: '%s directory'\n\n", argv[0]); + return(0); + } + + /* Trying to chdir to ossec directory. */ + if(chdir(argv[1]) != 0) + { + printf("%s: Invalid directory: '%s'.\n", argv[0], argv[1]); + return(0); + } + + /* Checking if ossec was installed already (upgrade) */ + if(!fileexist(OSSECCONF)) + { + char cmd[OS_MAXSTR +1]; + + /* Copy default config to ossec.conf */ + snprintf(cmd, OS_MAXSTR, "copy %s %s", OSSECDEF, OSSECCONF); + system(cmd); + } + + + /* Setting up local files */ + system("add-localfile.exe \"C:\\Windows\\pfirewall.log\" --quiet"); + system("add-localfile.exe \"C:\\Documents and Settings\\All Users\\Application Data\\Symantec\\Symantec AntiVirus Corporate Edition\\7.5\\Logs\\\%m\%d20\%y.log\" --quiet"); + + + /* Configure ossec for automatic startup */ + system("sc config OssecSvc start= auto"); + + + /* Changing permissions. */ + checkVista(); + + + if(isVista) + { + char cmd[OS_MAXSTR +1]; + + /* Copy some files to outside */ + snprintf(cmd, OS_MAXSTR, "move os_win32ui.exe ../"); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move win32ui.exe ../"); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move uninstall.exe ../"); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move doc.html ../"); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move help.txt ../"); + system(cmd); + + + /* Changing permissions. */ + system("echo y|cacls * /T /G Administrators:f "); + + + /* Copying them back. */ + snprintf(cmd, OS_MAXSTR, "move ..\\os_win32ui.exe ."); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move ..\\win32ui.exe ."); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move ..\\uninstall.exe ."); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move ..\\doc.html ."); + system(cmd); + + snprintf(cmd, OS_MAXSTR, "move ..\\help.txt ."); + system(cmd); + } + else + { + system("echo y|cacls . /T /G Administrators:f "); + } + + return(0); +} diff --git a/src/win32/ui.nsi b/src/win32/ui.nsi new file mode 100644 index 0000000..4073b59 --- /dev/null +++ b/src/win32/ui.nsi @@ -0,0 +1,36 @@ +; This is for Vista. For some reason it is not reading +; my template correctly. + +!include "MUI.nsh" +!define VERSION "1.5.1" +!define NAME "Ossec HIDS" +!define /date CDATE "%b %d %Y at %H:%M:%S" + + +Name "${NAME} Windows Agent v${VERSION}" +BrandingText "Copyright (C) 2009 Trend Micro Inc." +OutFile "win32ui.exe" + + +InstallDir $PROGRAMFILES\ossec-agent + + + !define MUI_ICON favicon.ico + + + !insertmacro MUI_LANGUAGE "English" + +;-------------------------------- + +Function .onInit + SetOutPath $INSTDIR + Exec '"$INSTDIR\os_win32ui.exe" "$INSTDIR"' + Abort +FunctionEnd + + + +Section "OSSEC UI - Should not be called." MainSec +;Required section. +SectionIn RO +SectionEnd diff --git a/src/win32/ui/common.c b/src/win32/ui/common.c new file mode 100644 index 0000000..7b16451 --- /dev/null +++ b/src/win32/ui/common.c @@ -0,0 +1,505 @@ +/* @(#) $Id: common.c,v 1.13 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include "os_win32ui.h" +#include "os_win.h" +#include "os_xml/os_xml.h" +#include "os_xml/os_xml_writer.h" +#include "os_net/os_net.h" +#include "validate_op.h" +#include "shared.h" + + +/* Generate server info (for the main status */ +int gen_server_info(HWND hwnd) +{ + memset(ui_server_info, '\0', 2048 +1); + snprintf(ui_server_info, 2048, + "Agent: %s (%s) - %s\r\n\r\n" + "Status: %s", + config_inst.agentname, + config_inst.agentid, + config_inst.agentip, + config_inst.status); + + + /* Initializing top */ + if(config_inst.version) + { + SetDlgItemText(hwnd, UI_SERVER_TOP, config_inst.version); + SetDlgItemText(hwnd, UI_SERVER_INFO, ui_server_info); + } + + /* Initializing auth key */ + SetDlgItemText(hwnd, UI_SERVER_AUTH, config_inst.key); + + /* Initializing server ip */ + SetDlgItemText(hwnd, UI_SERVER_TEXT, config_inst.server); + + SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"http://www.ossec.net"); + return(0); +} + + +/* Reads the first line of a specific file --must free after */ +char *cat_file(char *file, FILE *fp2) +{ + FILE *fp; + + if(!fp2) + { + fp = fopen(file, "r"); + } + else + { + fp = fp2; + } + + if(fp) + { + char buf[1024 +1]; + char *ret = NULL; + + buf[1024] = '\0'; + if(fgets(buf, 1024, fp) != NULL) + { + ret = strchr(buf, '\n'); + if(ret) + { + *ret = '\0'; + } + ret = strchr(buf, '\r'); + if(ret) + { + *ret = '\0'; + } + + ret = strdup(buf); + } + + if(!fp2) + { + fclose(fp); + } + return(ret); + } + + return(NULL); +} + + +/* Check if a file exists */ +int is_file(char *file) +{ + FILE *fp; + fp = fopen(file, "r"); + if(fp) + { + fclose(fp); + return(1); + } + return(0); +} + + +/* Clear configuration */ +void config_clear() +{ + debug2("read config 1"); + if(config_inst.version) + { + free(config_inst.version); + } + + debug2("read config 2"); + if(config_inst.key) + { + free(config_inst.key); + } + + debug2("read config 3"); + if(config_inst.agentid) + { + free(config_inst.agentid); + } + + debug2("read config 4"); + if(config_inst.server) + { + free(config_inst.server); + } + debug2("read config 5"); + + + /* Initializing config instance */ + config_inst.dir = NULL; + config_inst.key = FL_NOKEY; + config_inst.server = strdup(FL_NOSERVER); + config_inst.config = NULL; + + config_inst.agentid = NULL; + config_inst.agentname= NULL; + config_inst.agentip = NULL; + + config_inst.version = NULL; + config_inst.install_date = NULL; + config_inst.status = ST_UNKNOWN; + config_inst.msg_sent = 0; + + debug2("read config 6"); +} + + +/* Initializes the config */ +void init_config() +{ + /* Initializing config instance */ + config_inst.dir = NULL; + config_inst.key = FL_NOKEY; + config_inst.server = NULL; + config_inst.config = NULL; + + config_inst.agentid = NULL; + config_inst.agentname= NULL; + config_inst.agentip = NULL; + + config_inst.version = NULL; + config_inst.install_date = NULL; + config_inst.status = ST_UNKNOWN; + config_inst.msg_sent = 0; + config_inst.admin_access = 1; + + + /* Checking if ui is on the right path */ + if(!is_file(CONFIG)) + { + chdir(DEFDIR); + if(!is_file(CONFIG)) + { + config_inst.admin_access = -1; + } + } + + + /* Testing for permission - this is a vista thing. + * For some reason vista is not reporting the return codes + * properly. + */ + { + FILE *fp; + fp = fopen(CONFIG, "a"); + if(fp) + { + fclose(fp); + } + else + { + config_inst.admin_access = 0; + } + + + fp = fopen(".test-file.tst", "w"); + if(fp) + { + if(fprintf(fp, ".test\n") == -1) + { + config_inst.admin_access = 0; + } + + fclose(fp); + + /* trying to open it to read. */ + fp = fopen(".test-file.tst", "r"); + if(fp) + { + fclose(fp); + } + else + { + config_inst.admin_access = 0; + } + + if(unlink(".test-file.tst")) + { + config_inst.admin_access = 0; + } + } + else + { + config_inst.admin_access = 0; + } + } +} + + +/* Reads ossec config */ +int config_read(HWND hwnd) +{ + char *tmp_str; + + + /* Clearing config */ + config_clear(); + + + /* Getting OSSEC status */ + if(CheckServiceRunning()) + { + config_inst.status = ST_RUNNING; + } + else + { + config_inst.status = ST_STOPPED; + } + + + /* Getting version/install date */ + config_inst.version = cat_file(VERSION_FILE, NULL); + if(config_inst.version) + { + config_inst.install_date = strchr(config_inst.version, '-'); + if(config_inst.install_date) + { + *config_inst.install_date = '\0'; + config_inst.install_date++; + } + } + + + /* Getting number of messages sent */ + tmp_str = cat_file(SENDER_FILE, NULL); + if(tmp_str) + { + unsigned long int tmp_val = 0; + char *to_free = tmp_str; + + tmp_val = atol(tmp_str); + if(tmp_val) + { + config_inst.msg_sent = tmp_val * 9999; + + tmp_str = strchr(tmp_str, ':'); + if(tmp_str) + { + tmp_str++; + tmp_val = atol(tmp_str); + config_inst.msg_sent += tmp_val; + } + } + + free(to_free); + } + + + /* Getting agent id, name and ip */ + tmp_str = cat_file(AUTH_FILE, NULL); + if(tmp_str) + { + /* Getting base 64 */ + config_inst.key = encode_base64(strlen(tmp_str),tmp_str); + if(config_inst.key == NULL) + { + config_inst.key = FL_NOKEY; + } + + /* Getting id */ + config_inst.agentid = tmp_str; + + tmp_str = strchr(tmp_str, ' '); + if(tmp_str) + { + *tmp_str = '\0'; + tmp_str++; + + /* Getting name */ + config_inst.agentname = tmp_str; + tmp_str = strchr(tmp_str, ' '); + if(tmp_str) + { + *tmp_str = '\0'; + tmp_str++; + + /* Getting ip */ + config_inst.agentip = tmp_str; + + tmp_str = strchr(tmp_str, ' '); + if(tmp_str) + { + *tmp_str = '\0'; + } + } + } + } + + + if(config_inst.agentip == NULL) + { + config_inst.agentid = strdup(ST_NOTSET); + config_inst.agentname = strdup("Auth key not imported."); + config_inst.agentip = ST_NOTSET; + + config_inst.status = ST_MISSING_IMPORT; + } + + + /* Getting server ip */ + if(!get_ossec_server()) + { + if(config_inst.status == ST_MISSING_IMPORT) + { + config_inst.status = ST_MISSING_ALL; + } + else + { + config_inst.status = ST_MISSING_SERVER; + } + } + + return(0); +} + + +/* Get OSSEC Server IP */ +int get_ossec_server() +{ + OS_XML xml; + + char *str = NULL; + + + /* Definitions */ + char *(xml_serverip[])={"ossec_config","client","server-ip", NULL}; + char *(xml_serverhost[])={"ossec_config","client","server-hostname", NULL}; + + + /* Reading XML */ + if(OS_ReadXML(CONFIG, &xml) < 0) + { + return(0); + } + + + /* We need to remove the entry for the server */ + if(config_inst.server) + { + free(config_inst.server); + config_inst.server = NULL; + } + config_inst.server_type = 0; + + + /* Getting ip */ + str = OS_GetOneContentforElement(&xml, xml_serverip); + if(str && (OS_IsValidIP(str, NULL) == 1)) + { + config_inst.server_type = SERVER_IP_USED; + config_inst.server = str; + + OS_ClearXML(&xml); + return(1); + } + /* If we dont find the ip, try the server-hostname */ + else + { + if(str) + { + free(str); + str = NULL; + } + + str = OS_GetOneContentforElement(&xml, xml_serverhost); + if(str) + { + char *s_ip; + s_ip = OS_GetHost(str, 0); + if(s_ip) + { + /* Clearing the host memory */ + free(s_ip); + + /* Assigning the hostname to the server info */ + config_inst.server_type = SERVER_HOST_USED; + config_inst.server = str; + OS_ClearXML(&xml); + return(1); + } + free(str); + } + } + + + /* Setting up final server name when not available */ + config_inst.server = strdup(FL_NOSERVER); + + + OS_ClearXML(&xml); + return(0); +} + + +/* Set OSSEC Server IP */ +int set_ossec_server(char *ip, HWND hwnd) +{ + char **xml_pt = NULL; + char *(xml_serverip[])={"ossec_config","client","server-ip", NULL}; + char *(xml_serverhost[])={"ossec_config","client","server-hostname", NULL}; + + + /* Verifying IP Address */ + if(OS_IsValidIP(ip, NULL) != 1) + { + char *s_ip; + s_ip = OS_GetHost(ip, 0); + + if(!s_ip) + { + MessageBox(hwnd, "Invalid Server IP Address.\r\n" + "It must be the valid Ipv4 address of the " + "OSSEC server or its resolvable hostname.", + "Invalid Server IP Address.",MB_OK); + return(0); + } + config_inst.server_type = SERVER_HOST_USED; + xml_pt = xml_serverhost; + } + else + { + config_inst.server_type = SERVER_IP_USED; + xml_pt = xml_serverip; + } + + + + /* Reading the XML. Printing error and line number */ + if(OS_WriteXML(CONFIG, NEWCONFIG, xml_pt, + NULL, NULL, ip, 0) != 0) + { + MessageBox(hwnd, "Unable to set OSSEC Server IP Address.\r\n" + "(Internal error on the XML Write).", + "Unable to set Server IP Address.",MB_OK); + return(0); + } + + /* Renaming config files */ + unlink(LASTCONFIG); + rename(CONFIG, LASTCONFIG); + rename(NEWCONFIG, CONFIG); + + + return(1); +} + + +/* EOF */ diff --git a/src/win32/ui/favicon.ico b/src/win32/ui/favicon.ico new file mode 100644 index 0000000..d7f3a12 Binary files /dev/null and b/src/win32/ui/favicon.ico differ diff --git a/src/win32/ui/make.bat b/src/win32/ui/make.bat new file mode 100755 index 0000000..4c63321 --- /dev/null +++ b/src/win32/ui/make.bat @@ -0,0 +1,6 @@ +echo Making windows agent UI + +"C:\MinGW\bin\windres.exe" -o resource.o win32ui.rc +"C:\MinGW\bin\gcc.exe" -o "os_win32ui" -Wall -DARGV0=\"ossec-agent\" -DCLIENT -DWIN32 resource.o ../os_net/*.c ../os_xml/*.c ../addagent/b64.c ../shared/validate_op.c ../shared/debug_op.c ../win_service.c *.c -I../headers/ -I../ -lcomctl32 -mwindows -lwsock32 +copy os_win32ui.exe ..\ +cd ../ diff --git a/src/win32/ui/make.sh b/src/win32/ui/make.sh new file mode 100755 index 0000000..3c2c6df --- /dev/null +++ b/src/win32/ui/make.sh @@ -0,0 +1,6 @@ +echo Making windows agent UI + +i586-mingw32msvc-windres -o resource.o win32ui.rc +i586-mingw32msvc-gcc -o os_win32ui.exe -Wall -DARGV0=\"ossec-agent\" -DCLIENT -DWIN32 resource.o ../os_net/*.c ../os_xml/*.c ../addagent/b64.c ../shared/validate_op.c ../shared/debug_op.c ../win_service.c *.c -I../headers/ -I../ -lcomctl32 -mwindows -lwsock32 +cp -pr os_win32ui.exe ../ +cd ../ diff --git a/src/win32/ui/os_win32ui.c b/src/win32/ui/os_win32ui.c new file mode 100644 index 0000000..62a8e87 --- /dev/null +++ b/src/win32/ui/os_win32ui.c @@ -0,0 +1,508 @@ +/* @(#) $Id: os_win32ui.c,v 1.10 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#include "os_win32ui.h" +#include +#include "os_win.h" + + +/* Dialog -- About OSSEC */ +BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, + WPARAM wParam, LPARAM lParam) +{ + switch(Message) + { + case WM_CREATE: + case WM_INITDIALOG: + + return TRUE; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case UI_ID_CLOSE: + EndDialog(hwnd, IDOK); + break; + } + break; + + case WM_CLOSE: + EndDialog(hwnd, IDOK); + break; + default: + return FALSE; + } + return TRUE; +} + + +/* Main Dialog */ +BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + int ret_code = 0; + + + switch(Message) + { + case WM_INITDIALOG: + { + int statwidths[] = {130, -1}; + HMENU hMenu, hSubMenu; + + UINT menuflags = MF_STRING; + + if(config_inst.admin_access == 0) + { + menuflags = MF_STRING|MF_GRAYED; + } + + hMenu = CreateMenu(); + + /* Creating management menu */ + hSubMenu = CreatePopupMenu(); + AppendMenu(hSubMenu, menuflags, UI_MENU_MANAGE_START,"&Start OSSEC"); + AppendMenu(hSubMenu, menuflags, UI_MENU_MANAGE_STOP,"&Stop OSSEC"); + AppendMenu(hSubMenu, MF_SEPARATOR, UI_MENU_NONE,""); + AppendMenu(hSubMenu, menuflags, UI_MENU_MANAGE_RESTART,"&Restart"); + AppendMenu(hSubMenu, menuflags, UI_MENU_MANAGE_STATUS,"&Status"); + AppendMenu(hSubMenu, MF_SEPARATOR, UI_MENU_NONE,""); + AppendMenu(hSubMenu, MF_STRING,UI_MENU_MANAGE_EXIT,"&Exit"); + AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu,"&Manage"); + + /* Create view menu */ + hSubMenu = CreatePopupMenu(); + AppendMenu(hSubMenu, MF_STRING, UI_MENU_VIEW_LOGS, "&View Logs"); + AppendMenu(hSubMenu, MF_STRING, UI_MENU_VIEW_CONFIG,"V&iew Config"); + AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu,"&View"); + + hSubMenu = CreatePopupMenu(); + AppendMenu(hSubMenu, MF_STRING, UI_MENU_HELP_ABOUT, "A&bout"); + AppendMenu(hSubMenu, MF_STRING, UI_MENU_HELP_HELP, "Help"); + AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help"); + + + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + SetMenu(hwnd, hMenu); + + + hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, + WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP, + 0, 0, 0, 0, + hwnd, (HMENU)IDC_MAIN_STATUS, + GetModuleHandle(NULL), NULL); + + SendMessage(hStatus, SB_SETPARTS, + sizeof(statwidths)/sizeof(int), + (LPARAM)statwidths); + SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"http://www.ossec.net"); + + + + /* Initializing config */ + config_read(hwnd); + gen_server_info(hwnd); + + + /* Setting the icons */ + SendMessage(hwnd, WM_SETICON, ICON_SMALL, + (LPARAM)LoadIcon(GetModuleHandle(NULL), + MAKEINTRESOURCE(IDI_OSSECICON))); + SendMessage(hwnd, WM_SETICON, ICON_BIG, + (LPARAM)LoadIcon(GetModuleHandle(NULL), + MAKEINTRESOURCE(IDI_OSSECICON))); + + if(config_inst.admin_access == 0) + { + MessageBox(hwnd, "Admin access required. Some features may not work properly. \n\n" + "**If on Vista (or Server 2008), choose the \"Run as administrator\" option.", + "Admin access required.", MB_OK); + break; + } + + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + /* In case of SAVE */ + case IDC_ADD: + { + int chd = 0; + int len; + + + if(config_inst.admin_access == 0) + { + MessageBox(hwnd, "Unable to edit configuration. " + "Admin access required.", + "Error Saving.", MB_OK); + break; + } + + /** Getting values from the user (if chosen save) + * We should probably create another function for it... + **/ + + /* Getting server ip */ + len = GetWindowTextLength(GetDlgItem(hwnd, UI_SERVER_TEXT)); + if(len > 0) + { + char *buf; + + + /* Allocating buffer */ + buf = (char*)GlobalAlloc(GPTR, len + 1); + if(!buf) + { + exit(-1); + } + + GetDlgItemText(hwnd, UI_SERVER_TEXT, buf, len + 1); + + /* If auth key changed, set it */ + if(strcmp(buf, config_inst.server) != 0) + { + if(set_ossec_server(buf, hwnd)) + { + chd = 1; + } + } + else + { + GlobalFree(buf); + } + } + + + /* Getting auth key */ + len = GetWindowTextLength(GetDlgItem(hwnd, UI_SERVER_AUTH)); + if(len > 0) + { + char *buf; + + /* Allocating buffer */ + buf = (char*)GlobalAlloc(GPTR, len + 1); + if(!buf) + { + exit(-1); + } + + GetDlgItemText(hwnd, UI_SERVER_AUTH, buf, len + 1); + + /* If auth key changed, set it */ + if(strcmp(buf, config_inst.key) != 0) + { + int ret; + char *tmp_str; + char *decd_buf = NULL; + char *decd_to_write = NULL; + char *id = NULL; + char *name = NULL; + char *ip = NULL; + + + /* Getting new fields */ + decd_buf = decode_base64(buf); + if(decd_buf) + { + decd_to_write = strdup(decd_buf); + + /* Getting id, name and ip */ + id = decd_buf; + name = strchr(id, ' '); + if(name) + { + *name = '\0'; + name++; + + ip = strchr(name, ' '); + if(ip) + { + *ip = '\0'; + ip++; + + tmp_str = strchr(ip, ' '); + if(tmp_str) + { + *tmp_str = '\0'; + } + } + } + } + + /* If ip isn't set, it is because we have an invalid + * auth key. + */ + if(!ip) + { + MessageBox(hwnd, "Unable to import " + "authentication key. Invalid.", + "Error Saving.", MB_OK); + } + else + { + char mbox_msg[1024 +1]; + mbox_msg[1024] = '\0'; + + snprintf(mbox_msg, 1024, "Adding key for:\r\n\r\n" + "Agent ID: %s\r\n" + "Agent Name: %s\r\n" + "IP Address: %s\r\n", + id, name, ip); + + ret = MessageBox(hwnd, mbox_msg, + "Confirm Importing Key", MB_OKCANCEL); + if(ret == IDOK) + { + FILE *fp; + fp = fopen(AUTH_FILE, "w"); + if(fp) + { + chd+=2; + fprintf(fp, "%s", decd_to_write); + fclose(fp); + } + } + + + } + + /* Free used memory */ + if(decd_buf) + { + free(decd_to_write); + free(decd_buf); + } + } + else + { + GlobalFree(buf); + } + + } /* Finished adding AUTH KEY */ + + /* Re-printing messages */ + if(chd) + { + config_read(hwnd); + + /* Set status to restart */ + if(strcmp(config_inst.status,ST_RUNNING) == 0) + { + config_inst.status = ST_RUNNING_RESTART; + } + + gen_server_info(hwnd); + + if(chd == 1) + { + SendMessage(hStatus, SB_SETTEXT, 0, + (LPARAM)"Server IP Saved .."); + } + else if(chd == 2) + { + SendMessage(hStatus, SB_SETTEXT, 0, + (LPARAM)"Auth key imported .."); + + } + else + { + SendMessage(hStatus, SB_SETTEXT, 0, + (LPARAM)"Auth key and server ip saved .."); + + } + } + } + break; + + case UI_MENU_MANAGE_EXIT: + PostMessage(hwnd, WM_CLOSE, 0, 0); + break; + + case UI_MENU_VIEW_LOGS: + _spawnlp( _P_NOWAIT, "notepad", "notepad " OSSECLOGS, NULL ); + break; + case UI_MENU_VIEW_CONFIG: + _spawnlp( _P_NOWAIT, "notepad", "notepad " CONFIG, NULL ); + break; + case UI_MENU_HELP_HELP: + _spawnlp( _P_NOWAIT, "notepad", "notepad " HELPTXT, NULL ); + break; + case UI_MENU_HELP_ABOUT: + { + DialogBox(GetModuleHandle(NULL), + MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc); + } + break; + case IDC_CANCEL: + config_read(hwnd); + gen_server_info(hwnd); + break; + + case UI_MENU_MANAGE_START: + + /* Starting OSSEC -- must have a valid config before. */ + if((strcmp(config_inst.key, FL_NOKEY) != 0) && + (strcmp(config_inst.server, FL_NOSERVER) != 0)) + { + ret_code = os_start_service(); + } + else + { + ret_code = 0; + } + + if(ret_code == 0) + { + MessageBox(hwnd, "Unable to start OSSEC (check config).", + "Error -- Unable to start", MB_OK); + } + else if(ret_code == 1) + { + config_read(hwnd); + gen_server_info(hwnd); + + SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Started.."); + + MessageBox(hwnd, "OSSEC Agent Started.", + "Started..", MB_OK); + } + else + { + MessageBox(hwnd, "Agent already running (try restart).", + "Already running..", MB_OK); + } + break; + case UI_MENU_MANAGE_STOP: + + /* Stopping OSSEC */ + ret_code = os_stop_service(); + if(ret_code == 1) + { + config_read(hwnd); + gen_server_info(hwnd); + + SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Stopped.."); + MessageBox(hwnd, "OSSEC Agent Stopped.", + "Stopped..", MB_OK); + } + else + { + MessageBox(hwnd, "Agent already stopped.", + "Already stopped..", MB_OK); + } + break; + case UI_MENU_MANAGE_STATUS: + if(CheckServiceRunning()) + { + MessageBox(hwnd, "OSSEC Agent running.", + "Agent running..", MB_OK); + + } + else + { + MessageBox(hwnd, "OSSEC Agent stopped.", + "Agent stopped.", MB_OK); + } + break; + case UI_MENU_MANAGE_RESTART: + + if((strcmp(config_inst.key, FL_NOKEY) == 0) || + (strcmp(config_inst.server, FL_NOSERVER) == 0)) + { + MessageBox(hwnd, "Unable to restart OSSEC (check config).", + "Error -- Unable to restart", MB_OK); + break; + + } + + ret_code = os_stop_service(); + + /* Starting OSSEC */ + ret_code = os_start_service(); + if(ret_code == 0) + { + MessageBox(hwnd, "Unable to restart OSSEC (check config).", + "Error -- Unable to restart", MB_OK); + } + else + { + config_read(hwnd); + gen_server_info(hwnd); + + SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Restarted.."); + MessageBox(hwnd, "OSSEC Agent Restarted.", + "Restarted..", MB_OK); + } + break; + } + break; + + case WM_CLOSE: + EndDialog(hwnd, 0); + break; + + default: + return FALSE; + } + return TRUE; +} + + + + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nCmdShow) +{ + int ret; + WSADATA wsaData; + + + /* Starting Winsock -- for name resolution. */ + WSAStartup(MAKEWORD(2, 0), &wsaData); + + + /* Initializing config */ + init_config(); + + /* Initializing controls */ + InitCommonControls(); + + /* Creating main dialogbox */ + DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc); + + + /* Check if service is running and try to start it */ + if((strcmp(config_inst.key, FL_NOKEY) != 0)&& + (strcmp(config_inst.server, FL_NOSERVER) != 0) && + !CheckServiceRunning() && + (config_inst.admin_access != 0)) + { + ret = MessageBox(NULL, "OSSEC Agent not running. " + "Do you wish to start it?", + "Wish to start the agent?", MB_OKCANCEL); + if(ret == IDOK) + { + /* Starting the service */ + os_start_service(); + } + } + + return(0); +} + + +/* EOF */ diff --git a/src/win32/ui/os_win32ui.exe.manifest b/src/win32/ui/os_win32ui.exe.manifest new file mode 100644 index 0000000..b2cb8b7 --- /dev/null +++ b/src/win32/ui/os_win32ui.exe.manifest @@ -0,0 +1,15 @@ + + + OSSEC win32 Agent UI + + + + + + + + diff --git a/src/win32/ui/os_win32ui.h b/src/win32/ui/os_win32ui.h new file mode 100644 index 0000000..d7a7208 --- /dev/null +++ b/src/win32/ui/os_win32ui.h @@ -0,0 +1,161 @@ +/* @(#) $Id: os_win32ui.h,v 1.8 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + + +#ifndef WIN_32UI_H +#define WIN_32UI_H + +#include +#include +#include +#include + + + +/* Default values */ +#define CONFIG "ossec.conf" +#define NEWCONFIG "new-ossec.conf" +#define LASTCONFIG "last-ossec.conf" +#define VERSION_FILE "VERSION.txt" +#define OSSECLOGS "ossec.log" +#define HELPTXT "help.txt" +#define AUTH_FILE "client.keys" +#define SENDER_FILE "rids\\sender_counter" +#define DEFDIR "C:\\Program Files\\ossec-agent" + + +/* Status messages */ +#define ST_RUNNING "Running..." +#define ST_RUNNING_RESTART "Running (pending restart)" +#define ST_STOPPED "Stopped." +#define ST_UNKNOWN "Unknown." +#define ST_NOTSET "0" +#define ST_MISSING_IMPORT "Require import of authentication key.\r\n" \ + " - Not Running..." +#define ST_MISSING_SERVER "Require OSSEC Server IP address.\r\n" \ + " - Not Running..." +#define ST_MISSING_ALL "Require import of authentication key.\r\n" \ + " Missing OSSEC Server IP address.\r\n" \ + " - Not Running..." + + + +/* Pre-def fields */ +#define FL_NOKEY "" +#define FL_NOSERVER "" +#define SERVER_IP_USED 1 +#define SERVER_HOST_USED 2 + + +/* Prototypes */ +char *decode_base64(const char *src); +char *encode_base64(int size, char *src); + + +/* Global ossec config structure */ +typedef struct _ossec_config +{ + unsigned short int server_type; + unsigned short int admin_access; + unsigned long int msg_sent; + char *dir; + char *config; + char *key; + char *server; + + char *agentid; + char *agentname; + char *agentip; + + char *version; + char *install_date; + char *status; +}ossec_config; + + +/** Global variables **/ + +/* Agent status */ +char ui_server_info[2048 +1]; + +/* Configuration */ +ossec_config config_inst; + +/* Status bar */ +HWND hStatus; + + + +/* Ossec icon */ +#define IDI_OSSECICON 201 +#define UI_MANIFEST_ID 202 + +/* User input */ +#define UI_SERVER_TEXT 1501 +#define UI_SERVER_AUTH 1502 +#define UI_SERVER_MSG 1503 +#define UI_SERVER_TOP 1504 +#define UI_SERVER_INFO 1505 +#define UI_ID_CLOSE 1510 + + +/* Menu values */ +#define UI_MENU_MANAGE_STOP 1601 +#define UI_MENU_MANAGE_START 1602 +#define UI_MENU_MANAGE_STATUS 1603 +#define UI_MENU_MANAGE_RESTART 1604 +#define UI_MENU_MANAGE_EXIT 1605 +#define UI_MENU_VIEW_LOGS 1606 +#define UI_MENU_VIEW_CONFIG 1607 +#define UI_MENU_HELP_HELP 1608 +#define UI_MENU_HELP_ABOUT 1609 +#define UI_MENU_NONE 1610 + + +#define IDD_MAIN 1700 +#define IDC_MAIN_STATUS 1701 +#define IDC_ADD 1702 +#define IDC_CANCEL 1703 +#define IDD_ABOUT 1704 +#define IDC_STATIC -1 + + +/** Prototypes **/ + +/* Generate server info */ +int gen_server_info(HWND hwnd); + +/* cat file */ +char *cat_file(char *file, FILE *fp2); + +/* is_file present */ +int is_file(char *file); + +/* Reads ossec config */ +int config_read(HWND hwnd); + +/* Initializes the config */ +void init_config(); + +/* Set OSSEC Server IP */ +int set_ossec_server(char *ip, HWND hwnd); + +/* Get OSSEC Server IP */ +int get_ossec_server(); + + +#endif + +/* EOF */ diff --git a/src/win32/ui/win32ui.rc b/src/win32/ui/win32ui.rc new file mode 100644 index 0000000..e6cace7 --- /dev/null +++ b/src/win32/ui/win32ui.rc @@ -0,0 +1,58 @@ +/* @(#) $Id: win32ui.rc,v 1.7 2009/06/24 18:53:11 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#include + +#include "os_win32ui.h" + +IDI_OSSECICON ICON "favicon.ico" +UI_MANIFEST_ID RT_MANIFEST "os_win32ui.exe.manifest" + + + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 259, 106 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About OSSEC" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "&Close",UI_ID_CLOSE,90,90,50,14 + GROUPBOX " Copyright (C) 2009 Trend Micro Inc.", + IDC_STATIC,7,7,245,82 + CTEXT "This program is a free software; you can redistribute it" \ + " and/or modify it under the terms of the GNU General" \ + " Public License (GPL) version 3 as published by the FSF" \ + " - Free Software Foundation\r\n\r\n" \ + "For more information, visit us online at http://www.ossec.net", + IDC_STATIC,16,18,200,63 +END + + +IDD_MAIN DIALOG DISCARDABLE 0, 0, 207, 156 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "OSSEC Agent Manager" +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX " ~OSSEC Windows Agent Manager~ ", UI_SERVER_TOP, 7,7, 193, 57 + LTEXT " No Information available.", UI_SERVER_INFO, 16, 22, 150, 40 + + LTEXT "OSSEC Server IP: ",IDC_STATIC,7,76,62,8 + EDITTEXT UI_SERVER_TEXT,75,74,105,12,ES_AUTOHSCROLL + + LTEXT "Authentication key: ",IDC_STATIC,7,92,62,8 + EDITTEXT UI_SERVER_AUTH,75,90,105,12,ES_AUTOHSCROLL + + PUSHBUTTON "&Save",IDC_ADD,50,112,50,14 + PUSHBUTTON "&Refresh",IDC_CANCEL,105,112,50,14 +END diff --git a/src/win32/unix2dos.pl b/src/win32/unix2dos.pl new file mode 100755 index 0000000..33a8146 --- /dev/null +++ b/src/win32/unix2dos.pl @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +my $file; + +if(@ARGV < 1) +{ + die "$0: \n"; +} + +$file = shift (@ARGV); + +# File +open(FILE,"<$file")|| die "Unable to open file: $file\n"; + +while() +{ + my $line = $_; + + $line =~ s/\n/\r\n/; + print $line; +} diff --git a/src/win32/vista_sec.csv b/src/win32/vista_sec.csv new file mode 100644 index 0000000..f5bfc81 --- /dev/null +++ b/src/win32/vista_sec.csv @@ -0,0 +1,355 @@ +4608, Windows is starting up. This event is logged when LSASS.EXE starts and the auditing subsystem is initialized. +4609, Windows is shutting down. All logon sessions will be terminated by this shutdown. +4610, An authentication package has been loaded by the Local Security Authority. This authentication package will be used to authenticate logon attempts. Authentication Package Name: %1 +4611, This logon process will be trusted to submit logon requests. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Logon Process Name: %5 +4612, Internal resources allocated for the queuing of audit messages have been exhausted, leading to the loss of some audits. Number of audit messages discarded: %1 This event is generated when audit queues are filled and events must be discarded. This most commonly occurs when security events are being generated faster than they are being written to disk, or when the auditing system loses connectivity to the event log, such as when the event log service is stopped. +4614, A notification package has been loaded by the Security Account Manager. This package will be notified of any account or password changes. Notification Package Name: %1 +4615, Invalid use of LPC port. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process Information: PID: %7 Name: %8 Invalid Use: %5 LPC Server Port Name: %6 Windows Local Security Authority (LSA) communicates with the Windows kernel using Local Procedure Call (LPC) ports. If you see this event, an application has inadvertently or intentionally accessed this port which is reserved exclusively for LSA's use. The application (process) should be investigated to ensure that it is not attempting to tamper with this communications channel. +4616, The system time was changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process Information: Process ID: %9 Name: %10 Previous Time: %6 %5 New Time: %8 %7 This event is generated when the system time is changed. It is normal for the Windows Time Service, which runs with System privilege, to change the system time on a regular basis. Other system time changes may be indicative of attempts to tamper with the computer. +4618, A monitored security event pattern has occurred. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Alert Information: Computer: %2 Event ID: %1 Number of Events: %7 Duration: %8 This event is generated when Windows is configured to generate alerts in accordance with the Common Criteria Security Audit Analysis requirements (FAU_SAA) and an auditable event pattern occurs. +4621, Administrator recovered system from CrashOnAuditFail. Users who are not administrators will now be allowed to log on. Some auditable activity might not have been recorded. Value of CrashOnAuditFail: %1 This event is logged after a system reboots following CrashOnAuditFail. +4622, A security package has been loaded by the Local Security Authority. Security Package Name: %1 +4624, An account was successfully logged on. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Logon Type: %9 New Logon: Security ID: %5 Account Name: %6 Account Domain: %7 Logon ID: %8 Logon GUID: %13 Process Information: Process ID: %17 Process Name: %18 Network Information: Workstation Name: %12 Source Network Address: %19 Source Port: %20 Detailed Authentication Information: Logon Process: %10 Authentication Package: %11 Transited Services: %14 Package Name (NTLM only): %15 Key Length: %16 This event is generated when a logon session is created. It is generated on the computer that was accessed. +4625, An account failed to log on. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Logon Type: %11 Account For Which Logon Failed: Security ID: %5 Account Name: %6 Account Domain: %7 Failure Information: Failure Reason: %9 Status: %8 Sub Status: %10 Process Information: Caller Process ID: %18 Caller Process Name: %19 Network Information: Workstation Name: %14 Source Network Address: %20 Source Port: %21 Detailed Authentication Information: Logon Process: %12 Authentication Package: %13 Transited Services: %15 Package Name (NTLM only): %16 Key Length: %17 This event is generated when a logon request fails. It is generated on the computer where access was attempted. +4634, An account was logged off. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Logon Type: %5 This event is generated when a logon session is destroyed. It may be positively correlated with a logon event using the Logon ID value. Logon IDs are only unique between reboots on the same computer." 4646,1 +4647, User initiated logoff: Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 This event is generated when a logoff is initiated but the token reference count is not zero and the logon session cannot be destroyed. No further user-initiated activity can occur. This event can be interpreted as a logoff event. +4648, A logon was attempted using explicit credentials. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Logon GUID: %5 Account Whose Credentials Were Used: Account Name: %6 Account Domain: %7 Logon GUID: %8 Target Server: Target Server Name: %9 Additional Information: %10 Process Information: Process ID: %11 Process Name: %12 Network Information: Network Address: %13 Port: %14 This event is generated when a process attempts to log on an account by explicitly specifying that account’s credentials. This most commonly occurs in batch-type configurations such as scheduled tasks, or when using the RUNAS command. +4649, A replay attack was detected. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Credentials Which Were Replayed: Account Name: %5 Account Domain: %6 Process Information: Process ID: %12 Process Name: %13 Network Information: Workstation Name: %10 Detailed Authentication Information: Request Type: %7 Logon Process: %8 Authentication Package: %9 Transited Services: %11 This event indicates that a Kerberos replay attack was detected- a request was received twice with identical information. This condition could be caused by network misconfiguration. +4650, An IPsec Main Mode security association was established. Extended Mode was not enabled. Certificate authentication was not used. Local Endpoint: Principal Name: %1 Network Address: %3 Keying Module Port: %4 Remote Endpoint: Principal Name: %2 Network Address: %5 Keying Module Port: %6 Security Association Information: Lifetime (minutes): %12 Quick Mode Limit: %13 Main Mode SA ID: %17 Cryptographic Information: Cipher Algorithm: %9 Integrity Algorithm: %10 Diffie-Hellman Group: %11 Additional Information: Keying Module Name: %7 Authentication Method: %8 Role: %14 Impersonation State: %15 Main Mode Filter ID: %16 +4651, An IPsec Main Mode security association was established. Extended Mode was not enabled. A certificate was used for authentication. Local Endpoint: Principal Name: %1 Network Address: %9 Keying Module Port: %10 Local Certificate: SHA Thumbprint: %2 Issuing CA: %3 Root CA: %4 Remote Endpoint: Principal Name: %5 Network Address: %11 Keying Module Port: %12 Remote Certificate: SHA thumbprint: %6 Issuing CA: %7 Root CA: %8 Cryptographic Information: Cipher Algorithm: %15 Integrity Algorithm: %16 Diffie-Hellman Group: %17 Security Association Information: Lifetime (minutes): %18 Quick Mode Limit: %19 Main Mode SA ID: %23 Additional Information: Keying Module Name: %13 Authentication Method: %14 Role: %20 Impersonation State: %21 Main Mode Filter ID: %22 +4652, An IPsec Main Mode negotiation failed. Local Endpoint: Principal Name: %1 Network Address: %9 Keying Module Port: %10 Local Certificate: SHA Thumbprint: %2 Issuing CA: %3 Root CA: %4 Remote Endpoint: Principal Name: %5 Network Address: %11 Keying Module Port: %12 Remote Certificate: SHA thumbprint: %6 Issuing CA: %7 Root CA: %8 Additional Information: Keying Module Name: %13 Authentication Method: %16 Role: %18 Impersonation State: %19 Main Mode Filter ID: %20 Failure Information: Failure Point: %14 Failure Reason: %15 State: %17 Initiator Cookie: %21 Responder Cookie: %22 +4653, An IPsec Main Mode negotiation failed. Local Endpoint: Local Principal Name: %1 Network Address: %3 Keying Module Port: %4 Remote Endpoint: Principal Name: %2 Network Address: %5 Keying Module Port: %6 Additional Information: Keying Module Name: %7 Authentication Method: %10 Role: %12 Impersonation State: %13 Main Mode Filter ID: %14 Failure Information: Failure Point: %8 Failure Reason: %9 State: %11 Initiator Cookie: %15 Responder Cookie: %16 +4654, An IPsec Quick Mode negotiation failed. Local Endpoint: Network Address: %1 Network Address mask: %2 Port: %3 Tunnel Endpoint: %4 Remote Endpoint: Network Address: %5 Address Mask: %6 Port: %7 Tunnel Endpoint: %8 Private Address: %10 Additional Information: Protocol: %9 Keying Module Name: %11 Mode: %14 Role: %16 Quick Mode Filter ID: %18 Main Mode SA ID: %19 Failure Information: State: %15 Message ID: %17 Failure Point: %12 Failure Reason: %13 +4655, An IPsec Main Mode security association ended. Local Network Address: %1 Remote Network Address: %2 Keying Module Name: %3 Main Mode SA ID: %4 +4656, A handle to an object was requested. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %8 Process Information: Process ID: %14 Process Name: %15 Access Request Information: Transaction ID: %9 Accesses: %10 Access Mask: %11 Privileges Used for Access Check: %12 Restricted SID Count: %13 +4657, A registry value was modified. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Name: %5 Object Value Name: %6 Handle ID: %7 Operation Type: %8 Process Information: Process ID: %13 Process Name: %14 Change Information: Old Value Type: %9 Old Value: %10 New Value Type: %11 New Value: %12 +4658, The handle to an object was closed. Subject : Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Handle ID: %6 Process Information: Process ID: %7 Process Name: %8 +4659, A handle to an object was requested with intent to delete. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %8 Process Information: Process ID: %13 Access Request Information: Transaction ID: %9 Accesses: %10 Access Mask: %11 Privileges Used for Access Check: %12 +4660, An object was deleted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Handle ID: %6 Process Information: Process ID: %7 Process Name: %8 Transaction ID: %9 +4661, A handle to an object was requested. Subject : Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %8 Process Information: Process ID: %15 Process Name: %16 Access Request Information: Transaction ID: %9 Accesses: %10 Access Mask: %11 Privileges Used for Access Check: %12 Properties: %13 Restricted SID Count: %14 +4662, An operation was performed on an object. Subject : Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %9 Operation: Operation Type: %8 Accesses: %10 Access Mask: %11 Properties: %12 Additional Information: Parameter 1: %13 Parameter 2: %14 +4663, An attempt was made to access an object. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %8 Process Information: Process ID: %11 Process Name: %12 Access Request Information: Accesses: %9 Access Mask: %10 +4664, An attempt was made to create a hard link. Subject: Account Name: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Link Information: File Name: %5 Link Name: %6 Transaction ID: %7 +4665, An attempt was made to create an application client context. Subject: Client Name: %3 Client Domain: %4 Client Context ID: %5 Application Information: Application Name: %1 Application Instance ID: %2 Status: %6 +4666, An application attempted an operation: Subject: Client Name: %5 Client Domain: %6 Client Context ID: %7 Object: Object Name: %3 Scope Names: %4 Application Information: Application Name: %1 Application Instance ID: %2 Access Request Information: Role: %8 Groups: %9 Operation Name: %10 (%11) +4667, An application client context was deleted. Subject: Client Name: %3 Client Domain: %4 Client Context ID: %5 Application Information: Application Name: %1 Application Instance ID: %2 +4668, An application was initialized. Subject: Client Name: %3 Client Domain: %4 Client ID: %5 Application Information: Application Name: %1 Application Instance ID: %2 Additional Information: Policy Store URL: %6 +4670, Permissions on an object were changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %8 Process: Process ID: %11 Process Name: %12 Permissions Change: Original Security Descriptor: %9 New Security Descriptor: %10 +4671, An application attempted to access a blocked ordinal through the TBS. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Ordinal: %5 +4672, Special privileges assigned to new logon. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Privileges: %5 +4673, A privileged service was called. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Service: Server: %5 Service Name: %6 Process: Process ID: %8 Process Name: %9 Service Request Information: Privileges: %7 +4674, An operation was attempted on a privileged object. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Object Handle: %8 Process Information: Process ID: %11 Process Name: %12 Requested Operation: Desired Access: %9 Privileges: %10 +4675, SIDs were filtered. Target Account: Security ID: %1 Account Name: %2 Account Domain: %3 Trust Information: Trust Direction: %4 Trust Attributes: %5 Trust Type: %6 TDO Domain SID: %7 Filtered SIDs: %8 +4688, A new process has been created. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process Information: New Process ID: %5 New Process Name: %6 Token Elevation Type: %7 Creator Process ID: %8 +4689, A process has exited. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process Information: Process ID: %6 Process Name: %7 Exit Status: %5 +4690, An attempt was made to duplicate a handle to an object. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Source Handle Information: Source Handle ID: %5 Source Process ID: %6 New Handle Information: Target Handle ID: %7 Target Process ID: %8 +4691, Indirect access to an object was requested. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Type: %5 Object Name: %6 Process Information: Process ID: %9 Access Request Information: Accesses: %7 Access Mask: %8 +4692, Backup of data protection master key was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Key Information: Key Identifier: %5 Recovery Server: %6 Recovery Key ID: %7 Status Information: Status Code: %8 +4693, Recovery of data protection master key was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Key Information: Key Identifier: %5 Recovery Server: %6 Recovery Key ID: %8 Recovery Reason: %7 Status Information: Status Code: %9 +4694, Protection of auditable protected data was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Protected Data: Data Description: %6 Key Identifier: %5 Protected Data Flags: %7 Protection Algorithms: %8 Status Information: Status Code: %9 +4695, Unprotection of auditable protected data was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Protected Data: Data Description: %6 Key Identifier: %5 Protected Data Flags: %7 Protection Algorithms: %8 Status Information: Status Code: %9 +4696, A primary token was assigned to process. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process Information: Process ID: %11 Process Name: %12 Target Process: Target Process ID: %9 Target Process Name: %10 New Token Information: Security ID: %5 Account Name: %6 Account Domain: %7 Logon ID: %8 +4697, A service was installed in the system. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Service Information: Service Name: %5 Service File Name: %6 Service Type: %7 Service Start Type: %8 Service Account: %9 +4698, A scheduled task was created. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Task Information: Task Name: %5 Task Content: %6 +4699, A scheduled task was deleted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Task Information: Task Name: %5 Task Content: %6 +4700, A scheduled task was enabled. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Task Information: Task Name: %5 Task Content: %6 +4701, A scheduled task was disabled. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Task Information: Task Name: %5 Task Content: %6 +4702, A scheduled task was updated. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Task Information: Task Name: %5 Task New Content: %6 +4704, A user right was assigned. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Target Account: Account Name: %5 New Right: User Right: %6 +4705, A user right was removed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Target Account: Account Name: %5 Removed Right: User Right: %6 +4706, A new trust was created to a domain. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Trusted Domain: Domain Name: %1 Domain ID: %2 Trust Information: Trust Type: %7 Trust Direction: %8 Trust Attributes: %9 SID Filtering: %10 +4707, A trust to a domain was removed. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Domain Information: Domain Name: %1 Domain ID: %2 +4709, IPsec Services was started. %1 Policy Source: %2 %3 +4710, IPsec Services was disabled. %1 %2" 4711,1 +4712, IPsec Services encountered a potentially serious failure.%1 +4713, Kerberos policy was changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Changes Made: ('--' means no changes, otherwise each change is shown as: (Parameter Name): (new value) (old value)) %5 +4714, Encrypted data recovery policy was changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Changes Made: ('--' means no changes, otherwise each change is shown as: (Parameter Name): (new value) (old value)) %5 +4715, The audit policy (SACL) on an object was changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Audit Policy Change: Original Security Descriptor: %5 New Security Descriptor: %6 +4716, Trusted domain information was modified. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Trusted Domain: Domain Name: %5 Domain ID: %6 New Trust Information: Trust Type: %7 Trust Direction: %8 Trust Attributes: %9 SID Filtering: %10 +4717, System security access was granted to an account. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Account Modified: Account Name: %5 Access Granted: Access Right: %6 +4718, System security access was removed from an account. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Account Modified: Account Name: %5 Access Removed: Access Right: %6 +4719, System audit policy was changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Audit Policy Change: Category: %5 Subcategory: %6 Subcategory GUID: %7 Changes: %8 +4720, A user account was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 New Account: Security ID: %3 Account Name: %1 Account Domain: %2 Attributes: SAM Account Name: %9 Display Name: %10 User Principal Name: %11 Home Directory: %12 Home Drive: %13 Script Path: %14 Profile Path: %15 User Workstations: %16 Password Last Set: %17 Account Expires: %18 Primary Group ID: %19 Allowed To Delegate To: %20 Old UAC Value: %21 New UAC Value: %22 User Account Control: %23 User Parameters: %24 SID History: %25 Logon Hours: %26 Additional Information: Privileges %8 +4722, A user account was enabled. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 +4723, An attempt was made to change an account's password. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 Additional Information: Privileges %8 +4724, An attempt was made to reset an account's password. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 +4725, A user account was disabled. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 +4726, A user account was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 Additional Information: Privileges %8 +4727, A security-enabled global group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 New Group: Security ID: %3 Group Name: %1 Group Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4728, A member was added to a security-enabled global group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4729, A member was removed from a security-enabled global group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4730, A security-enabled global group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Deleted Group: Security ID: %3 Group Name: %1 Group Domain: %2 Additional Information: Privileges: %8 +4731, A security-enabled local group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 New Group: Security ID: %3 Group Name: %1 Group Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4732, A member was added to a security-enabled local group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4733, A member was removed from a security-enabled local group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4734, A security-enabled local group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Additional Information: Privileges: %8 +4735, A security-enabled local group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Changed Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4737, A security-enabled global group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Changed Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4738, A user account was changed. Subject: Security ID: %5 Account Name: %6 Account Domain: %7 Logon ID: %8 Target Account: Security ID: %4 Account Name: %2 Account Domain: %3 Changed Attributes: SAM Account Name: %10 Display Name: %11 User Principal Name: %12 Home Directory: %13 Home Drive: %14 Script Path: %15 Profile Path: %16 User Workstations: %17 Password Last Set: %18 Account Expires: %19 Primary Group ID: %20 AllowedToDelegateTo: %21 Old UAC Value: %22 New UAC Value: %23 User Account Control: %24 User Parameters: %25 SID History: %26 Logon Hours: %27 Additional Information: Privileges: %9 +4739, Domain Policy was changed. Change Type: %1 modified Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Domain: Domain Name: %2 Domain ID: %3 Changed Attributes: Min. Password Age: %9 Max. Password Age: %10 Force Logoff: %11 Lockout Threshold: %12 Lockout Observation Window: %13 Lockout Duration: %14 Password Properties: %15 Min. Password Length: %16 Password History Length: %17 Machine Account Quota: %18 Mixed Domain Mode: %19 Domain Behavior Version: %20 OEM Information: %21 Additional Information: Privileges: %8 +4740, 0x8000000000000000 message: A user account was locked out. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Account That Was Locked Out: Security ID: %3 Account Name: %1 Additional Information: Caller Computer Name: %2 +4741, A computer account was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 New Computer Account: Security ID: %3 Account Name: %1 Account Domain: %2 Attributes: SAM Account Name: %9 Display Name: %10 User Principal Name: %11 Home Directory: %12 Home Drive: %13 Script Path: %14 Profile Path: %15 User Workstations: %16 Password Last Set: %17 Account Expires: %18 Primary Group ID: %19 AllowedToDelegateTo: %20 Old UAC Value: %21 New UAC Value: %22 User Account Control: %23 User Parameters: %24 SID History: %25 Logon Hours: %26 DNS Host Name: %27 Service Principal Names: %28 Additional Information: Privileges %8 +4742, A computer account was changed. Subject: Security ID: %5 Account Name: %6 Account Domain: %7 Logon ID: %8 Computer Account That Was Changed: Security ID: %4 Account Name: %2 Account Domain: %3 Changed Attributes: SAM Account Name: %10 Display Name: %11 User Principal Name: %12 Home Directory: %13 Home Drive: %14 Script Path: %15 Profile Path: %16 User Workstations: %17 Password Last Set: %18 Account Expires: %19 Primary Group ID: %20 AllowedToDelegateTo: %21 Old UAC Value: %22 New UAC Value: %23 User Account Control: %24 User Parameters: %25 SID History: %26 Logon Hours: %27 DNS Host Name: %28 Service Principal Names: %29 Additional Information: Privileges: %9 +4743, A computer account was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Computer: Security ID: %3 Account Name: %1 Account Domain: %2 Additional Information: Privileges: %8 +4744, A security-disabled local group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 New Group: Security ID: %3 Group Name: %1 Group Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4745, A security-disabled local group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Changed Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4746, A member was added to a security-disabled local group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4747, A member was removed from a security-disabled local group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4748, A security-disabled local group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Additional Information: Privileges: %8 +4749, A security-disabled global group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4750, A security-disabled global group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Changed Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4751, A member was added to a security-disabled global group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4752, A member was removed from a security-disabled global group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4753, A security-disabled global group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Additional Information: Privileges: %8 +4754, A security-enabled universal group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4755, A security-enabled universal group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Changed Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4756, A member was added to a security-enabled universal group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Account Name: %3 Account Domain: %4 Additional Information: Privileges: %10 +4757, A member was removed from a security-enabled universal group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4758, A security-enabled universal group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Additional Information: Privileges: %8 +4759, A security-disabled universal group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4760, A security-disabled universal group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Changed Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4761, A member was added to a security-disabled universal group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4762, A member was removed from a security-disabled universal group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4763, A security-disabled universal group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Group Name: %1 Group Domain: %2 Additional Information: Privileges: %8 +4764, A group’s type was changed. Subject: Security ID: %5 Account Name: %6 Account Domain: %7 Logon ID: %8 Change Type: %1 Group: Security ID: %4 Group Name: %2 Group Domain: %3 Additional Information: Privileges: %9 +4765, SID History was added to an account. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Target Account: Security ID: %5 Account Name: %3 Account Domain: %4 Source Account: Security ID: %2 Account Name: %1 Additional Information: Privileges: %10 SID List: %11 +4766, An attempt to add SID History to an account failed. Subject: Security ID: Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %4 Account Name: %2 Account Domain: %3 Source Account Account Name: %1 Additional Information: Privileges: %8 +4767, A user account was unlocked. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 +4768, A Kerberos authentication ticket (TGT) was requested. Account Information: Account Name: %1 Supplied Realm Name: %2 User ID: %3 Service Information: Service Name: %4 Service ID: %5 Network Information: Client Address: %10 Client Port: %11 Additional Information: Ticket Options: %6 Result Code: %7 Ticket Encryption Type: %8 Pre-Authentication Type: %9 Certificate Information: Certificate Issuer Name: %12 Certificate Serial Number: %13 Certificate Thumbprint: %14 Certificate information is only provided if a certificate was used for pre-authentication. Pre-authentication types, ticket options, encryption types and result codes are defined in RFC 4120. +4769, A Kerberos service ticket was requested. Account Information: Account Name: %1 Account Domain: %2 Logon GUID: %10 Service Information: Service Name: %3 Service ID: %4 Network Information: Client Address: %7 Client Port: %8 Additional Information: Ticket Options: %5 Ticket Encryption Type: %6 Failure Code: %9 Transited Services: %11 This event is generated every time access is requested to a resource such as a computer or a Windows service. The service name indicates the resource to which access was requested. +4770, A Kerberos service ticket was renewed. Account Information: Account Name: %1 Account Domain: %2 Service Information: Service Name: %3 Service ID: %4 Network Information: Client Address: %7 Client Port: %8 Additional Information: Ticket Options: %5 Ticket Encryption Type: %6 Ticket options and encryption types are defined in RFC 4120. +4771, Kerberos pre-authentication failed. Account Information: Security ID: %2 Account Name: %1 Service Information: Service Name: %3 Network Information: Client Address: %7 Client Port: %8 Additional Information: Ticket Options: %4 Failure Code: %5 Pre-Authentication Type: %6 Certificate Information: Certificate Issuer Name: %9 Certificate Serial Number: %10 Certificate Thumbprint: %11 Certificate information is only provided if a certificate was used for pre-authentication. Pre-authentication types, ticket options and failure codes are defined in RFC 4120. If the ticket was malformed or damaged during transit and could not be decrypted, then many fields in this event might not be present. +4772, A Kerberos authentication ticket request failed. Account Information: Account Name: %1 Supplied Realm Name: %2 Service Information: Service Name: %3 Network Information: Client Address: %6 Client Port: %7 Additional Information: Ticket Options: %4 Failure Code: %5 Ticket options and failure codes are defined in RFC 4120. +4773, A Kerberos service ticket request failed. Account Information: Account Name: %1 Account Domain: %2 Service Information: Service Name: %3 Network Information: Client Address: %6 Client Port: %7 Additional Information: Ticket Options: %4 Failure Code: %5 Ticket options and failure codes are defined in RFC 4120. +4774, An account was mapped for logon. Authentication Package: %1 Account UPN: %2 Mapped Name: %3 +4775, An account could not be mapped for logon. Authentication Package: %1 Account Name: %2 +4776, The domain controller attempted to validate the credentials for an account. Authentication Package: %1 Logon Account: %2 Source Workstation: %3 Error Code: %4 +4777, The domain controller failed to validate the credentials for an account. Authentication Package: %1 Logon Account: %2 Source Workstation: %3 Error Code: %4 +4778, A session was reconnected to a Window Station. Subject: Account Name: %1 Account Domain: %2 Logon ID: %3 Session: Session Name: %4 Additional Information: Client Name: %5 Client Address: %6 This event is generated when a user reconnects to an existing Terminal Services session, or when a user switches to an existing desktop using Fast User Switching. +4779, A session was disconnected from a Window Station. Subject: Account Name: %1 Account Domain: %2 Logon ID: %3 Session: Session Name: %4 Additional Information: Client Name: %5 Client Address: %6 This event is generated when a user disconnects from an existing Terminal Services session, or when a user switches away from an existing desktop using Fast User Switching. +4780, The ACL was set on accounts which are members of administrators groups. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Target Account: Security ID: %3 Account Name: %1 Account Domain: %2 Additional Information: Privileges: %8 +4781, The name of an account was changed: Subject: Security ID: %5 Account Name: %6 Account Domain: %7 Logon ID: %8 Target Account: Security ID: %4 Account Domain: %3 Old Account Name: %1 New Account Name: %2 Additional Information: Privileges: %9 +4782, The password hash an account was accessed. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Target Account: Account Name: %1 Account Domain: %2 +4783, A basic application group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Account Name: %1 Account Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4784, A basic application group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Account Name: %1 Account Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4785, A member was added to a basic application group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4786, A member was removed from a basic application group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Group Name: %3 Group Domain: %4 Additional Information: Privileges: %10 +4787, A non-member was added to a basic application group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Account Name: %3 Account Domain: %4 Additional Information: Privileges: %10 A non-member is an account that is explicitly excluded from membership in a basic application group. Even if the account is specified as a member of the application group, either explicitly or through nested group membership, the account will not be treated as a group member if it is listed as a non-member. +4788, A non-member was removed from a basic application group. Subject: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Member: Security ID: %2 Account Name: %1 Group: Security ID: %5 Account Name: %3 Account Domain: %4 Additional Information: Privileges: %10 A non-member is an account that is explicitly excluded from membership in a basic application group. Even if the account is specified as a member of the application group, either explicitly or through nested group membership, the account will not be treated as a group member if it is listed as a non-member. +4789, A basic application group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Account Name: %1 Account Domain: %2 Additional Information: Privileges: %8 +4790, An LDAP query group was created. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Account Name: %1 Account Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4791, A basic application group was changed. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Account Name: %1 Account Domain: %2 Attributes: SAM Account Name: %9 SID History: %10 Additional Information: Privileges: %8 +4792, An LDAP query group was deleted. Subject: Security ID: %4 Account Name: %5 Account Domain: %6 Logon ID: %7 Group: Security ID: %3 Account Name: %1 Account Domain: %2 Additional Information: Privileges: %8 +4793, The Password Policy Checking API was called. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Additional Information: Caller Workstation: %5 Provided Account Name (unauthenticated): %6 Status Code: %7 +4794, An attempt was made to set the Directory Services Restore Modeadministrator password. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Additional Information: Caller Workstation: %5 Status Code: %6 +4800, The workstation was locked. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Session ID: %5 +4801, The workstation was unlocked. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Session ID: %5 +4802, The screen saver was invoked. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Session ID: %5 +4803, The screen saver was dismissed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Session ID: %5 +4816, RPC detected an integrity violation while decrypting an incoming message. Peer Name: %1 Protocol Sequence: %2 Security Error: %3 +4864, A namespace collision was detected. Target Type: %1 Target Name: %2 Forest Root: %3 Top Level Name: %4 DNS Name: %5 NetBIOS Name: %6 Security ID: %7 New Flags: %8 +4865, A trusted forest information entry was added. Subject: Security ID: %10 Account Name: %11 Account Domain: %12 Logon ID: %13 Trust Information: Forest Root: %1 Forest Root SID: %2 Operation ID: %3 Entry Type: %4 Flags: %5 Top Level Name: %6 DNS Name: %7 NetBIOS Name: %8 Domain SID: %9 +4866, A trusted forest information entry was removed. Subject: Security ID: %10 Account Name: %11 Account Domain: %12 Logon ID: %13 Trust Information: Forest Root: %1 Forest Root SID: %2 Operation ID: %3 Entry Type: %4 Flags: %5 Top Level Name: %6 DNS Name: %7 NetBIOS Name: %8 Domain SID: %9 +4867, A trusted forest information entry was modified. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Trust Information: Forest Root: %5 Forest Root SID: %6 Operation ID: %7 Entry Type: %8 Flags: %9 Top Level Name: %10 DNS Name: %11 NetBIOS Name: %12 Domain SID: %13 +4868, The certificate manager denied a pending certificate request. Request ID: %1 +4869, Certificate Services received a resubmitted certificate request. Request ID: %1 +4870, Certificate Services revoked a certificate. Serial Number: %1 Reason: %2 +4871, Certificate Services received a request to publish the certificate revocation list (CRL). Next Update: %1 Publish Base: %2 Publish Delta: %3 +4872, Certificate Services published the certificate revocation list (CRL). Base CRL: %1 CRL Number: %2 Key Container: %3 Next Publish: %4 Publish URLs: %5 +4873, A certificate request extension changed. Request ID: %1 Name: %2 Type: %3 Flags: %4 Data: %5 +4874, One or more certificate request attributes changed. Request ID: %1 Attributes: %2 +4875, Certificate Services received a request to shut down +4876, Certificate Services backup started. Backup Type: %1 +4877, Certificate Services backup completed +4878, Certificate Services restore started +4879, Certificate Services restore completed +4880, Certificate Services started. Certificate Database Hash: %1 Private Key Usage Count: %2 CA Certificate Hash: %3 CA Public Key Hash: %4 +4881, Certificate Services stopped. Certificate Database Hash: %1 Private Key Usage Count: %2 CA Certificate Hash: %3 CA Public Key Hash: %4 +4882, The security permissions for Certificate Services changed. %1 +4883, Certificate Services retrieved an archived key. Request ID: %1 +4884, Certificate Services imported a certificate into its database. Certificate: %1 Request ID: %2 +4885, The audit filter for Certificate Services changed. Filter: %1 +4886, Certificate Services received a certificate request. Request ID: %1 Requester: %2 Attributes: %3 +4887, Certificate Services approved a certificate request and issued a certificate. Request ID: %1 Requester: %2 Attributes: %3 Disposition: %4 SKI: %5 Subject: %6 +4888, Certificate Services denied a certificate request. Request ID: %1 Requester: %2 Attributes: %3 Disposition: %4 SKI: %5 Subject: %6 +4889, Certificate Services set the status of a certificate request to pending. Request ID: %1 Requester: %2 Attributes: %3 Disposition: %4 SKI: %5 Subject: %6 +4890, The certificate manager settings for Certificate Services changed. Enable: %1 %2 +4891, A configuration entry changed in Certificate Services. Node: %1 Entry: %2 Value: %3 +4892, A property of Certificate Services changed. Property: %1 Index: %2 Type: %3 Value: %4 +4893, Certificate Services archived a key. Request ID: %1 Requester: %2 KRA Hashes: %3 +4894, Certificate Services imported and archived a key. Request ID: %1 +4895, Certificate Services published the CA certificate to Active Directory Domain Services. Certificate Hash: %1 Valid From: %2 Valid To: %3 +4896, One or more rows have been deleted from the certificate database. Table ID: %1 Filter: %2 Rows Deleted: %3 +4897, Role separation enabled: % +4898, Certificate Services loaded a template. %1 v%2 (Schema V%3) %4 %5 Template Information: Template Content: %7 Security Descriptor: %8 Additional Information: Domain Controller: %6 +4899, A Certificate Services template was updated. %1 v%2 (Schema V%3) %4 %5 Template Change Information: Old Template Content: %8 New Template Content: %7 Additional Information: Domain Controller: %6 +4900, Certificate Services template security was updated. %1 v%2 (Schema V%3) %4 %5 Template Change Information: Old Template Content: %9 New Template Content: %7 Old Security Descriptor: %10 New Security Descriptor: %8 Additional Information: Domain Controller: %6 +4902, The Per-user audit policy table was created. Number of Elements: %1 Policy ID: %2 +4904, An attempt was made to register a security event source. Subject : Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process: Process ID: %7 Process Name: %8 Event Source: Source Name: %5 Event Source ID: %6 +4905, An attempt was made to unregister a security event source. Subject Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Process: Process ID: %7 Process Name: %8 Event Source: Source Name: %5 Event Source ID: %6 +4906, The CrashOnAuditFail value has changed. New Value of CrashOnAuditFail: %1 +4907, Auditing settings on object were changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Object Server: %5 Object Type: %6 Object Name: %7 Handle ID: %8 Process Information: Process ID: %11 Process Name: %12 Auditing Settings: Original Security Descriptor: %9 New Security Descriptor: %10 +4908, Special Groups Logon table modified. Special Groups: %1 This event is generated when the list of special groups is updated in the registry or through security policy. The updated list of special groups is indicated in the event. +4909, The local policy settings for the TBS were changed. Old Blocked Ordinals: %1 New Blocked Ordinals: %2 +4910, The group policy settings for the TBS were changed. Group Policy Setting: Ignore Default Settings Old Value: %1 New Value: %2 Group Policy Setting: Ignore Local Settings Old Value: %3 New Value: %4 Old Blocked Ordinals: %5 New Blocked Ordinals: %6 +4912, Per User Audit Policy was changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Policy For Account: Security ID: %5 Policy Change Details: Category: %6 Subcategory: %7 Subcategory GUID: %8 Changes: %9 +4928, An Active Directory replica source naming context was established. Destination DRA: %1 Source DRA: %2 Source Address: %3 Naming Context: %4 Options: %5 Status Code: %6 +4929, An Active Directory replica source naming context was removed. Destination DRA: %1 Source DRA: %2 Source Address: %3 Naming Context: %4 Options: %5 Status Code: %6 +4930, An Active Directory replica source naming context was modified. Destination DRA: %1 Source DRA: %2 Source Address: %3 Naming Context: %4 Options: %5 Status Code: %6 +4931, An Active Directory replica destination naming context was modified. Destination DRA: %1 Source DRA: %2 Destination Address: %3 Naming Context: %4 Options: %5 Status Code: %6 +4932, Synchronization of a replica of an Active Directory naming context has begun. Destination DRA: %1 Source DRA: %2 Naming Context: %3 Options: %4 Session ID: %5 Start USN: %6 +4933, Synchronization of a replica of an Active Directory naming context has ended. Destination DRA: %1 Source DRA: %2 Naming Context: %3 Options: %4 Session ID: %5 End USN: %6 Status Code: %7 +4934, Attributes of an Active Directory object were replicated. Session ID: %1 Object: %2 Attribute: %3 Type of change: %4 New Value: %5 USN: %6 Status Code: %7 +4935, Replication failure begins. Replication Event: %1 Audit Status Code: %2 +4936, Replication failure ends. Replication Event: %1 Audit Status Code: %2 Replication Status Code: %3 +4937, A lingering object was removed from a replica. Destination DRA: %1 Source DRA: %2 Object: %3 Options: %4 Status Code: %5 +4944, The following policy was active when the Windows Firewall started. Group Policy Applied: %1 Profile Used: %2 Operational mode: %3 Allow Remote Administration: %4 Allow Unicast Responses to Multicast/Broadcast Traffic: %5 Security Logging: Log Dropped Packets: %6 Log Successful Connections: %7 +4945, A rule was listed when the Windows Firewall started. Profile used: %1 Rule: Rule ID: %2 Rule Name: %3 +4946, A change has been made to Windows Firewall exception list. A rule was added. Profile Changed: %1 Added Rule: Rule ID: %2 Rule Name: %3 +4947, A change has been made to Windows Firewall exception list. A rule was modified. Profile Changed: %1 Modified Rule: Rule ID: %2 Rule Name: %3 +4948, A change has been made to Windows Firewall exception list. A rule was deleted. Profile Changed: %1 Deleted Rule: Rule ID: %2 Rule Name: %3 +4949, Windows Firewall settings were restored to the default values +4950, A Windows Firewall setting has changed. Profile That Was Changed: %1 New Setting: Type: %2 Value: %3 +4951, A rule has been ignored because its major version number was not recognized by Windows Firewall. Profile: %1 Ignored Rule: ID: %2 Name: %3 +4952, Parts of a rule have been ignored because its minor version number was not recognized by Windows Firewall. The other parts of the rule will be enforced. Profile: %1 Partially Ignored Rule: ID: %2 Name: %3 +4953, A rule has been ignored by Windows Firewall because it could not parse the rule. Profile: %1 Reason for Rejection: %2 Rule: ID: %3 Name: %4 +4954, Windows Firewall Group Policy settings has changed. The new settings have been applied +4956, Windows Firewall has changed the active profile. New Active Profile: %1 +4957, Windows Firewall did not apply the following rule: Rule Information: ID: %1 Name: %2 Error Information: Reason: %3 resolved to an empty set. +4958, Windows Firewall did not apply the following rule because the rule referred to items not configured on this computer: Rule Information: ID: %1 Name: %2 Error Information: Error: %3 Reason: %4 +4960, IPsec dropped an inbound packet that failed an integrity check. If this problem persists, it could indicate a network issue or that packets are being modified in transit to this computer. Verify that the packets sent from the remote computer are the same as those received by this computer. This error might also indicate interoperability problems with other IPsec implementations. Remote Network Address: %1 Inbound SA SPI: %2 +4961, IPsec dropped an inbound packet that failed a replay check. If this problem persists, it could indicate a replay attack against this computer. Remote Network Address: %1 Inbound SA SPI: %2 +4962, IPsec dropped an inbound packet that failed a replay check. The inbound packet had too low a sequence number to ensure it was not a replay. Remote Network Address: %1 Inbound SA SPI: %2 +4963, IPsec dropped an inbound clear text packet that should have been secured. This is usually due to the remote computer changing its IPsec policy without informing this computer. This could also be a spoofing attack attempt. Remote Network Address: %1 Inbound SA SPI: %2 +4964, Special groups have been assigned to a new logon. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Logon GUID: %5 New Logon: Security ID: %6 Account Name: %7 Account Domain: %8 Logon ID: %9 Logon GUID: %10 Special Groups Assigned: %11 +4965, IPsec received a packet from a remote computer with an incorrect Security Parameter Index (SPI). This is usually caused by malfunctioning hardware that is corrupting packets. If these errors persist, verify that the packets sent from the remote computer are the same as those received by this computer. This error may also indicate interoperability problems with other IPsec implementations. In that case, if connectivity is not impeded, then these events can be ignored. Remote Network Address: %1 Inbound SA SPI: %2 +4976, During Main Mode negotiation, IPsec received an invalid negotiation packet. If this problem persists, it could indicate a network issue or an attempt to modify or replay this negotiation. Local Network Address: %1 Remote Network Address: %2 Keying Module Name: %3 +4977, During Quick Mode negotiation, IPsec received an invalid negotiation packet. If this problem persists, it could indicate a network issue or an attempt to modify or replay this negotiation. Local Network Address: %1 Remote Network Address: %2 Keying Module Name: %3 +4978, During Extended Mode negotiation, IPsec received an invalid negotiation packet. If this problem persists, it could indicate a network issue or an attempt to modify or replay this negotiation. Local Network Address: %1 Remote Network Address: %2 Keying Module Name: %3 +4979, IPsec Main Mode and Extended Mode security associations were established. Main Mode Local Endpoint: Principal Name: %1 Network Address: %3 Keying Module Port: %4 Main Mode Remote Endpoint: Principal Name: %2 Network Address: %5 Keying Module Port: %6 Main Mode Cryptographic Information: Cipher Algorithm: %8 Integrity Algorithm: %9 Diffie-Hellman Group: %10 Main Mode Security Association: Lifetime (minutes): %11 Quick Mode Limit: %12 Main Mode SA ID: %16 Main Mode Additional Information: Keying Module Name: AuthIP Authentication Method: %7 Role: %13 Impersonation State: %14 Main Mode Filter ID: %15 Extended Mode Information: Local Principal Name: %17 Remote Principal Name: %18 Authentication Method: %19 Impersonation State: %20 Quick Mode Filter ID: %21 +4980, IPsec Main Mode and Extended Mode security associations were established. Main Mode Local Endpoint: Principal Name: %1 Network Address: %3 Keying Module Port: %4 Main Mode Remote Endpoint: Principal Name: %2 Network Address: %5 Keying Module Port: %6 Main Mode Cryptographic Information: Cipher Algorithm: %8 Integrity Algorithm: %9 Diffie-Hellman Group: %10 Main Mode Security Association: Lifetime (minutes): %11 Quick Mode Limit: %12 Main Mode SA ID: %16 Main Mode Additional Information: Keying Module Name: AuthIP Authentication Method: %7 Role: %13 Impersonation State: %14 Main Mode Filter ID: %15 Extended Mode Local Endpoint: Principal Name: %17 Certificate SHA Thumbprint: %18 Certificate Issuing CA: %19 Certificate Root CA: %20 Extended Mode Remote Endpoint: Principal Name: %21 Certificate SHA Thumbprint: %22 Certificate Issuing CA: %23 Certificate Root CA: %24 Extended Mode Additional Information: Authentication Method: SSL Impersonation State: %25 Quick Mode Filter ID: %26 +4981, IPsec Main Mode and Extended Mode security associations were established. Local Endpoint: Principal Name: %1 Network Address: %9 Keying Module Port: %10 Local Certificate: SHA Thumbprint: %2 Issuing CA: %3 Root CA: %4 Remote Endpoint: Principal Name: %5 Network Address: %11 Keying Module Port: %12 Remote Certificate: SHA Thumbprint: %6 Issuing CA: %7 Root CA: %8 Cryptographic Information: Cipher Algorithm: %13 Integrity Algorithm: %14 Diffie-Hellman Group: %15 Security Association Information: Lifetime (minutes): %16 Quick Mode Limit: %17 Main Mode SA ID: %21 Additional Information: Keying Module Name: AuthIP Authentication Method: SSL Role: %18 Impersonation State: %19 Main Mode Filter ID: %20 Extended Mode Information: Local Principal Name: %22 Remote Principal Name: %23 Authentication Method: %24 Impersonation State: %25 Quick Mode Filter ID: %26 +4982, IPsec Main Mode and Extended Mode security associations were established. Local Endpoint: Principal Name: %1 Network Address: Keying Module Port: %9 Local Certificate: SHA Thumbprint: %2 Issuing CA: %3 Root CA: %4 Remote Endpoint: Principal Name: %5 Network Address: %11 Keying Module Port: %12 Remote Certificate: SHA Thumbprint: %6 Issuing CA: %7 Root CA: %8 Cryptographic Information: Cipher Algorithm: %12 Integrity Algorithm: %13 Diffie-Hellman Group: %14 Security Association Information: Lifetime (minutes): %15 Quick Mode Limit: %16 Main Mode SA ID: %20 Additional Information: Keying Module Name: AuthIP Authentication Method: SSL Role: %17 Impersonation State: %18 Main Mode Filter ID: %19 Extended Mode Local Endpoint: Principal Name: %21 Certificate SHA Thumbprint: %22 Certificate Issuing CA: %23 Certificate Root CA: %24 Extended Mode Remote Endpoint: Principal Name: %25 Certificate SHA Thumbprint: %26 Certificate Issuing CA: %27 Certificate Root CA: %28 Extended Mode Additional Information: Authentication Method: SSL Impersonation State: %29 Quick Mode Filter ID: %30 +4983, An IPsec Extended Mode negotiation failed. The corresponding Main Mode security association has been deleted. Local Endpoint: Principal Name: %1 Network Address: %9 Keying Module Port: %10 Local Certificate: SHA Thumbprint: %2 Issuing CA: %3 Root CA: %4 Remote Endpoint: Principal Name: %5 Network Address: %11 Keying Module Port: %12 Remote Certificate: SHA Thumbprint: %6 Issuing CA: %7 Root CA: %8 Additional Information: Keying Module Name: AuthIP Authentication Method: SSL Role: %16 Impersonation State: %17 Quick Mode Filter ID: %18 Failure Information: Failure Point: %13 Failure Reason: %14 State: %15 +4984, An IPsec Extended Mode negotiation failed. The corresponding Main Mode security association has been deleted. Local Endpoint: Principal Name: %1 Network Address: %3 Keying Module Port: %4 Remote Endpoint: Principal Name: %2 Network Address: %5 Keying Module Port: %6 Additional Information: Keying Module Name: AuthIP Authentication Method: %9 Role: %11 Impersonation State: %12 Quick Mode Filter ID: %13 Failure Information: Failure Point: %7 Failure Reason: %8 State: %10 +4985, The state of a transaction has changed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Transaction Information: RM Transaction ID: %5 New State: %6 Resource Manager: %7 Process Information: Process ID: %8 Process Name: %9 +5024, The Windows Firewall Service has started successfully +5025, The Windows Firewall Service has been stopped +5027, The Windows Firewall Service was unable to retrieve the security policy from the local storage. The service will continue enforcing the current policy. Error Code: %1 +5028, The Windows Firewall Service was unable to parse the new security policy. The service will continue with currently enforced policy. Error Code: %1 +5029, The Windows Firewall Service failed to initialize the driver. The service will continue to enforce the current policy. Error Code: %1 +5030, The Windows Firewall Service failed to start. Error Code: %1 +5031, The Windows Firewall Service blocked an application from accepting incoming connections on the network. Profiles: %1 Application: %2 +5032, Windows Firewall was unable to notify the user that it blocked an application from accepting incoming connections on the network. Error Code: %1 +5033, The Windows Firewall Driver has started successfully +5034, The Windows Firewall Driver has been stopped +5035, The Windows Firewall Driver failed to start. Error Code: %1 +5037, The Windows Firewall Driver detected critical runtime error. Terminating. Error Code: %1 +5038, 0x8000000000000000 message: Code integrity determined that the image hash of a file is not valid. The file could be corrupt due to unauthorized modification or the invalid hash could indicate a potential disk device error. File Name: %1 +5039, A registry key was virtualized. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: Key Name: %5 Virtual Key Name: %6 Process Information: Process ID: %7 Process Name: %8 +5040, A change has been made to IPsec settings. An Authentication Set was added. Profile Changed: %1 Added Authentication Set: ID: %2 Name: %3 +5041, A change has been made to IPsec settings. An Authentication Set was modified. Profile Changed: %1 Modified Authentication Set: ID: %2 Name: %3 +5042, A change has been made to IPsec settings. An Authentication Set was deleted. Profile Changed: %1 Deleted Authentication Set: ID: %2 Name: %3 +5043, A change has been made to IPsec settings. A Connection Security Rule was added. Profile Changed: %1 Added Connection Security Rule: ID: %2 Name: %3 +5044, A change has been made to IPsec settings. A Connection Security Rule was modified. Profile Changed: %1 Modified Connection Security Rule: ID: %2 Name: %3 +5045, A change has been made to IPsec settings. A Connection Security Rule was deleted. Profile Changed: %1 Deleted Connection Security Rule: ID: %2 Name: %3 +5046, A change has been made to IPsec settings. A Crypto Set was added. Profile Changed: %1 Added Crypto Set: ID: %2 Name: %3 +5047, A change has been made to IPsec settings. A Crypto Set was modified. Profile Changed: %1 Modified Crypto Set: ID: %2 Name: %3 +5048, A change has been made to IPsec settings. A Crypto Set was deleted. Profile Changed: %1 Deleted Crypto Set: ID: %2 Name: %3 +5049, An IPsec Security Association was deleted. Profile Changed: %1 Deleted SA: ID: %2 Name: %3 +5050, An attempt to programmatically disable the Windows Firewall using a call to INetFwProfile.FirewallEnabled(FALSE) interface was rejected because this API is not supported on Windows Vista. This has most likely occurred due to a program which is incompatible with Windows Vista. Please contact the program's manufacturer to make sure you have a Windows Vista compatible program version. Error Code: E_NOTIMPL Caller Process Name: %1 Process Id: %2 Publisher: %3 +5051, A file was virtualized. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: File Name: %5 Virtual File Name: %6 Process Information: Process ID: %7 Process Name: %8 +5056, A cryptographic self test was performed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Module: %5 Return Code: %6 +5057, A cryptographic primitive operation failed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Cryptographic Parameters: Provider Name: %5 Algorithm Name: %6 Failure Information: Reason: %7 Return Code: %8 +5058, Key file operation. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Cryptographic Parameters: Provider Name: %5 Algorithm Name: %6 Key Name: %7 Key Type: %8 Key File Operation Information: File Path: %9 Operation: %10 Return Code: %11 +5059, Key migration operation. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Cryptographic Parameters: Provider Name: %5 Algorithm Name: %6 Key Name: %7 Key Type: %8 Additional Information: Operation: %9 Return Code: %10 +5060, Verification operation failed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Cryptographic Parameters: Provider Name: %5 Algorithm Name: %6 Key Name: %7 Key Type: %8 Failure Information: Reason: %9 Return Code: %10 +5061, Cryptographic operation. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Cryptographic Parameters: Provider Name: %5 Algorithm Name: %6 Key Name: %7 Key Type: %8 Cryptographic Operation: Operation: %9 Return Code: %10 +5062, A kernel-mode cryptographic self test was performed. Module: %1 Return Code: %2 +5063, A cryptographic provider operation was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Cryptographic Provider: Name: %5 Module: %6 Operation: %7 Return Code: %8 +5064, A cryptographic context operation was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Configuration Parameters: Scope: %5 Context: %6 Operation: %7 Return Code: %8 +5065, A cryptographic context modification was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 %Configuration Parameters: Scope: %5 Context: %6 Change Information: Old Value: %7 New Value: %8 Return Code: %9 +5066, A cryptographic function operation was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Configuration Parameters: Scope: %5 Context: %6 Interface: %7 Function: %8 Position: %9 Operation: %10 Return Code: %11 +5067, A cryptographic function modification was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Configuration Parameters: Scope: %5 Context: %6 Interface: %7 Function: %8 Change Information: Old Value: %9 New Value: %10 Return Code: %11 +5068, A cryptographic function provider operation was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Configuration Parameters: Scope: %5 Context: %6 Interface: %7 Function: %8 Provider: %9 Position: %10 Operation: %11 Return Code: %12 +5069, A cryptographic function property operation was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Configuration Parameters: Scope: %5 Context: %6 Interface: %7 Function: %8 Property: %9 Operation: %10 Value: %11 Return Code: %12 +5070, A cryptographic function property modification was attempted. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Configuration Parameters: Scope: %5 Context: %6 Interface: %7 Function: %8 Property: %9 Change Information: Old Value: %10 New Value: %11 Return Code: %12 +5120, OCSP Responder Service Started +5121, OCSP Responder Service Stopped +5122, A Configuration entry changed in the OCSP Responder Service. CA Configuration ID: %1 New Value: %2 +5123, A configuration entry changed in the OCSP Responder Service. Property Name: %1 New Value: %2 +5124, A security setting was updated on OCSP Responder Service. New Value: %1 +5125, A request was submitted to OCSP Responder Service +5126, Signing Certificate was automatically updated by the OCSP Responder Service. CA Configuration ID: %1 New Signing Certificate Hash: %2 +5127, The OCSP Revocation Provider successfully updated the revocation information. CA Configuration ID: %1 Base CRL Number: %2 Base CRL This Update: %3 Base CRL Hash: %4 Delta CRL Number: %5 Delta CRL Indicator: %6 Delta CRL This Update: %7 Delta CRL Hash: %8 +5136, A directory service object was modified. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Directory Service: Name: %7 Type: %8 Object: DN: %9 GUID: %10 Class: %11 Attribute: LDAP Display Name: %12 Syntax (OID): %13 Value: %14 Operation: Type: %15 Correlation ID: %1 Application Correlation ID: %2 +5137, A directory service object was created. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Directory Service: Name: %7 Type: %8 Object: DN: %9 GUID: %10 Class: %11 Operation: Correlation ID: %1 Application Correlation ID: %2 +5138, A directory service object was undeleted. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Directory Service: Name: %7 Type: %8 Object: Old DN: %9 New DN: %10 GUID: %11 Class: %12 Operation: Correlation ID: %1 Application Correlation ID: %2 +5139, A directory service object was moved. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Directory Service: Name: %7 Type: %8 Object: Old DN: %9 New DN: %10 GUID: %11 Class: %12 Operation: Correlation ID: %1 Application Correlation ID: %2 +5140, A network share object was accessed. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Network Information: Source Address: %5 Source Port: %6 Share Name: %7 +5141, A directory service object was deleted. Subject: Security ID: %3 Account Name: %4 Account Domain: %5 Logon ID: %6 Directory Service: Name: %7 Type: %8 Object: DN: %9 GUID: %10 Class: %11 Operation: Tree Delete: %12 Correlation ID: %1 Application Correlation ID: %2 +5152, The Windows Filtering Platform blocked a packet. Application Information: Process ID: %1 Application Name: %2 Network Information: Direction: %3 Source Address: %4 Source Port: %5 Destination Address: %6 Destination Port: %7 Protocol: %8 Filter Information: Filter Run-Time ID: %9 Layer Name: %10 Layer Run-Time ID: %11 +5153, A more restrictive Windows Filtering Platform filter has blocked a packet. Application Information: Process ID: %1 Application Name: %2 Network Information: Direction: %3 Source Address: %4 Source Port: %5 Destination Address: %6 Destination Port: %7 Protocol: %8 Filter Information: Filter Run-Time ID: %9 Layer Name: %10 Layer Run-Time ID: %11 +5154, The Windows Filtering Platform has permitted an application or service to listen on a port for incoming connections. Application Information: Process ID: %1 Application Name: %2 Network Information: Source Address: %3 Source Port: %4 Protocol: %5 Filter Information: Filter Run-Time ID: %6 Layer Name: %7 Layer Run-Time ID: %8 +5155, The Windows Filtering Platform has blocked an application or service from listening on a port for incoming connections. Application Information: Process ID: %1 Application Name: %2 Network Information: Source Address: %3 Source Port: %4 Protocol: %5 Filter Information: Filter Run-Time ID: %6 Layer Name: %7 Layer Run-Time ID: %8 +5156, The Windows Filtering Platform has allowed a connection. Application Information: Process ID: %1 Application Name: %2 Network Information: Direction: %3 Source Address: %4 Source Port: %5 Destination Address: %6 Destination Port: %7 Protocol: %8 Filter Information: Filter Run-Time ID: %9 Layer Name: %10 Layer Run-Time ID: %11 +5157, The Windows Filtering Platform has blocked a connection. Application Information: Process ID: %1 Application Name: %2 Network Information: Direction: %3 Source Address: %4 Source Port: %5 Destination Address: %6 Destination Port: %7 Protocol: %8 Filter Information: Filter Run-Time ID: %9 Layer Name: %10 Layer Run-Time ID: %11 +5158, The Windows Filtering Platform has permitted a bind to a local port. Application Information: Process ID: %1 Application Name: %2 Network Information: Source Address: %3 Source Port: %4 Protocol: %5 Filter Information: Filter Run-Time ID: %6 Layer Name: %7 Layer Run-Time ID: %8 +5159, The Windows Filtering Platform has blocked a bind to a local port. Application Information: Process ID: %1 Application Name: %2 Network Information: Source Address: %3 Source Port: %4 Protocol: %5 Filter Information: Filter Run-Time ID: %6 Layer Name: %7 Layer Run-Time ID: %8 +5376, Credential Manager credentials were backed up. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 This event occurs when a user backs up their own Credential Manager credentials. A user (even an Administrator) cannot back up the credentials of an account other than his own. +5377, Credential Manager credentials were restored from a backup. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 This event occurs when a user restores his Credential Manager credentials from a backup. A user (even an Administrator) cannot restore the credentials of an account other than his own. +5378, The requested credentials delegation was disallowed by policy. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Credential Delegation Information: Security Package: %5 User's UPN: %6 Target Server: %7 Credential Type: %8 +5440, The following callout was present when the Windows Filtering Platform Base Filtering Engine started. Provider Information: ID: %1 Name: %2 Callout Information: ID: %3 Name: %4 Type: %5 Run-Time ID: %6 Layer Information: ID: %7 Name: %8 Run-Time ID: %9 +5441, The following filter was present when the Windows Filtering Platform Base Filtering Engine started. Provider Information: ID: %1 Name: %2 Filter Information: ID: %3 Name: %4 Type: %5 Run-Time ID: %6 Layer Information: ID: %7 Name: %8 Run-Time ID: %9 Weight: %10 Additional Information: Conditions: %11 Filter Action: %12 Callout ID: %13 Callout Name: %14 +5442, The following provider was present when the Windows Filtering Platform Base Filtering Engine started. Provider ID: %1 Provider Name: %2 Provider Type: %3 +5443, The following provider context was present when the Windows Filtering Platform Base Filtering Engine started. Provider ID: %1 Provider Name: %2 Provider Context ID: %3 Provider Context Name: %4 Provider Context Type: %5 +5444, The following sub-layer was present when the Windows Filtering Platform Base Filtering Engine started. Provider ID: %1 Provider Name: %2 Sub-layer ID: %3 Sub-layer Name: %4 Sub-layer Type: %5 Weight: %6 +5446, A Windows Filtering Platform callout has been changed. Subject: Security ID: %2 Account Name: %3 Process Information: Process ID: %1 Provider Information: ID: %4 Name: %5 Change Information: Change Type: %6 Callout Information: ID: %7 Name: %8 Type: %9 Run-Time ID: %10 Layer Information: ID: %11 Name: %12 Run-Time ID: %13 +5447, A Windows Filtering Platform filter has been changed. Subject: Security ID: %2 Account Name: %3 Process Information: Process ID: %1 Provider Information: ID: %4 Name: %5 Change Information: Change Type: %6 Filter Information: ID: %7 Name: %8 Type: %9 Run-Time ID: %10 Layer Information: ID: %11 Name: %12 Run-Time ID: %13 Callout Information: ID: %17 Name: %18 Additional Information: Weight: %14 Conditions: %15 Filter Action: %16 +5448, A Windows Filtering Platform provider has been changed. Subject: Security ID: %2 Account Name: %3 Process Information: Process ID: %1 Change Information: Change Type: %4 Provider Information: ID: %5 Name: %6 Type: %7 +5449, A Windows Filtering Platform provider context has been changed. Subject: Security ID: %2 Account Name: %3 Process Information: Process ID: %1 Provider Information: Provider ID: %4 Provider Name: %5 Change Information: Change Type: %6 Provider Context: ID: %7 Name: %8 Type: %9 +5450, A Windows Filtering Platform sub-layer has been changed. Subject: Security ID: %2 Account Name: %3 Process Information: Process ID: %1 Provider Information: Provider ID: %4 Provider Name: %5 Change Information: Change Type: %6 Sub-layer Information: Sub-layer ID: %7 Sub-layer Name: %8 Sub-layer Type: %9 Additional Information: Weight: %10 +5451, An IPsec Quick Mode security association was established. Local Endpoint: Network Address: %1 Network Address mask: %2 Port: %3 Tunnel Endpoint: %4 Remote Endpoint: Network Address: %5 Network Address Mask: %6 Port: %7 Private Address: %8 Tunnel Endpoint: %9 Protocol: %10 Keying Module Name: %11 Cryptographic Information: Integrity Algorithm - AH: %12 Integrity Algorithm - ESP: %13 Encryption Algorithm: %14 Security Association Information: Lifetime - seconds: %15 Lifetime - data: %16 Lifetime - packets: %17 Mode: %18 Role: %19 Quick Mode Filter ID: %20 Main Mode SA ID: %21 Quick Mode SA ID: %22 Additional Information: Inbound SPI: %23 Outbound SPI: %24 +5452, An IPsec Quick Mode security association ended. Local Endpoint: Network Address: %1 Port: %2 Tunnel Endpoint: %3 Remote Endpoint: Network Address: %4 Port: %5 Tunnel Endpoint: %6 Additional Information: Protocol: %7 Quick Mode SA ID: %8 +5453, An IPsec negotiation with a remote computer failed because the IKE and AuthIP IPsec Keying Modules (IKEEXT) service is not started +5456, PAStore Engine applied Active Directory storage IPsec policy on the computer. Policy: %1 +5457, PAStore Engine failed to apply Active Directory storage IPsec policy on the computer. DN: %1 Error code: %2 +5458, PAStore Engine applied locally cached copy of Active Directory storage IPsec policy on the computer. Policy: %1 +5459, PAStore Engine failed to apply locally cached copy of Active Directory storage IPsec policy on the computer. Policy: %1 Error Code: %2 +5460, PAStore Engine applied local registry storage IPsec policy on the computer. Policy: %1 +5461, PAStore Engine failed to apply local registry storage IPsec policy on the computer. Policy: %1 Error Code: %2 +5462, PAStore Engine failed to apply some rules of the active IPsec policy on the computer. Use the IP Security Monitor snap-in to diagnose the problem. Policy: %1 Error Code: %2 +5463, PAStore Engine polled for changes to the active IPsec policy and detected no changes +5464, PAStore Engine polled for changes to the active IPsec policy, detected changes, and applied them to IPsec Services +5465, PAStore Engine received a control for forced reloading of IPsec policy and processed the control successfully +5466, PAStore Engine polled for changes to the Active Directory IPsec policy, determined that Active Directory cannot be reached, and will use the cached copy of the Active Directory IPsec policy instead. Any changes made to the Active Directory IPsec policy since the last poll could not be applied +5467, PAStore Engine polled for changes to the Active Directory IPsec policy, determined that Active Directory can be reached, and found no changes to the policy. The cached copy of the Active Directory IPsec policy is no longer being used +5468, PAStore Engine polled for changes to the Active Directory IPsec policy, determined that Active Directory can be reached, found changes to the policy, and applied those changes. The cached copy of the Active Directory IPsec policy is no longer being used +5471, PAStore Engine loaded local storage IPsec policy on the computer. Policy: %1 +5472, PAStore Engine failed to load local storage IPsec policy on the computer. Policy: %1 Error Code: %2 +5473, PAStore Engine loaded directory storage IPsec policy on the computer. Policy: %1 +5474, PAStore Engine failed to load directory storage IPsec policy on the computer. Policy: %1 Error Code: %2 +5477, PAStore Engine failed to add quick mode filter. Quick Mode Filter: %1 Error Code: %2 +5478, IPsec Services has started successfully +5479, IPsec Services has been shut down successfully. The shutdown of IPsec Services can put the computer at greater risk of network attack or expose the computer to potential security risks +5480, IPsec Services failed to get the complete list of network interfaces on the computer. This poses a potential security risk because some of the network interfaces may not get the protection provided by the applied IPsec filters. Use the IP Security Monitor snap-in to diagnose the problem +5483, IPsec Services failed to initialize RPC server. IPsec Services could not be started. Error Code: %1 +5484, IPsec Services has experienced a critical failure and has been shut down. The shutdown of IPsec Services can put the computer at greater risk of network attack or expose the computer to potential security risks. Error Code: %1 +5485, IPsec Services failed to process some IPsec filters on a plug-and-play event for network interfaces. This poses a potential security risk because some of the network interfaces may not get the protection provided by the applied IPsec filters. Use the IP Security Monitor snap-in to diagnose the problem +5632, A request was made to authenticate to a wireless network. Subject: Security ID: %2 Account Name: %3 Account Domain: %4 Logon ID: %5 Network Information: Name (SSID): %1 Interface GUID: %8 Local MAC Address: %7 Peer MAC Address: %6 Additional Information: Reason Code: %10 (%9) Error Code: %11 +5633, A request was made to authenticate to a wired network. Subject: Security ID: %2 Account Name: %3 Account Domain: %4 Logon ID: %5 Interface: Name: %1 Additional Information Reason Code: %7 (%6) Error Code: %8 +5712, A Remote Procedure Call (RPC) was attempted. Subject: SID: %1 Name: %2 Account Domain: %3 LogonId: %4 Process Information: PID: %5 Name: %6 Network Information: Remote IP Address: %7 Remote Port: %8 RPC Attributes: Interface UUID: %9 Protocol Sequence: %10 Authentication Service: %11 Authentication Level: %12 +5888, An object in the COM+ Catalog was modified. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: COM+ Catalog Collection: %5 Object Name: %6 Object Properties Modified: %7 +5889, An object was deleted from the COM+ Catalog. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: COM+ Catalog Collection: %5 Object Name: %6 Object Details: %7 This event occurs when an object is deleted from the COM+ catalog. +5890, An object was added to the COM+ Catalog. Subject: Security ID: %1 Account Name: %2 Account Domain: %3 Logon ID: %4 Object: COM+ Catalog Collection: %5 Object Name: %6 Object Details: %7 +6144, Security policy in the group policy objects has been applied successfully. Return Code: %1 GPO List: %2 +6145, One or more errors occured while processing security policy in the group policy objects. Error Code: %1 GPO List: %2 +6272, Network Policy Server granted access to a user. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Quarantine Information: Result: %25 Session Identifier: %26 +6273, Network Policy Server denied access to a user. Contact the Network Policy Server administrator for more information. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Reason Code: %25 Reason: %26 +6274, Network Policy Server discarded the request for a user. Contact the Network Policy Server administrator for more information. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Reason Code: %25 Reason: %26 +6275, Network Policy Server discarded the accounting request for a user. Contact the Network Policy Server administrator for more information. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Reason Code: %25 Reason: %26 +6276, Network Policy Server quarantined a user. Contact the Network Policy Server administrator for more information. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Quarantine Information: Result: %25 Extended-Result: %26 Session Identifier: %27 Help URL: %28 System Health Validator Result(s): %29 +6277, 0x8000000000000000 message: Network Policy Server granted access to a user but put it on probation because the host did not meet the defined health policy. Contact the Network Policy Server administrator for more information. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Quarantine Information: Result: %25 Extended-Result: %26 Session Identifier: %27 Help URL: %28 System Health Validator Result(s): %29 Quarantine Grace Time: %30 +6278, Network Policy Server granted full access to a user because the host met the defined health policy. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 Client Machine: Security ID: %5 Account Name: %6 Fully Qualified Account Name: %7 OS-Version: %8 Called Station Identifier: %9 Calling Station Identifier: %10 NAS: NAS IPv4 Address: %11 NAS IPv6 Address: %12 NAS Identifier: %13 NAS Port-Type: %14 NAS Port: %15 RADIUS Client: Client Friendly Name: %16 Client IP Address: %17 Authentication Details: Proxy Policy Name: %18 Network Policy Name: %19 Authentication Provider: %20 Authentication Server: %21 Authentication Type: %22 EAP Type: %23 Account Session Identifier: %24 Quarantine Information: Result: %25 Extended-Result: %26 Session Identifier: %27 Help URL: %28 System Health Validator Result(s): %29 +6279, Network Policy Server locked the user account due to repeated failed authentication attempts. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 +6280, Network Policy Server unlocked the user account. User: Security ID: %1 Account Name: %2 Account Domain: %3 Fully Qualified Account Name: %4 diff --git a/src/win32/win-files.txt b/src/win32/win-files.txt new file mode 100755 index 0000000..c997258 --- /dev/null +++ b/src/win32/win-files.txt @@ -0,0 +1,73 @@ +os_net os_net +os_regex os_regex +os_xml os_xml +os_crypto os_crypto +headers headers +shared shared +error_messages error_messages +addagent addagent +config config +rootcheck/db/rootkit_files.txt rootkit_files.txt +rootcheck/db/rootkit_trojans.txt rootkit_trojans.txt +os_zlib os_zlib +os_execd os_execd +external/zlib-1.2.3 zlib-1.2.3 +client-agent/config.c client-agent-config.c +client-agent/agentd.h agentd.h +client-agent/receiver.c receiver.c +client-agent/receiver-win.c receiver-win.c +client-agent/start_agent.c start_agent.c +client-agent/sendmsg.c sendmsg.c +client-agent/notify.c notify.c +client-agent/intcheck_op.c intcheck_op.c +logcollector/config.c logcollector-config.c +logcollector/logcollector.c logcollector.c +logcollector/logcollector.h logcollector.h +logcollector/read_snortfull.c read_snortfull.c +logcollector/read_syslog.c read_syslog.c +logcollector/read_win_el.c read_win_el.c +logcollector/read_nmapg.c read_nmapg.c +logcollector/read_mysql_log.c read_mysql_log.c +logcollector/read_mssql_log.c read_mssql_log.c +logcollector/read_postgresql_log.c read_postgresql_log.c +logcollector/read_djb_multilog.c read_djb_multilog.c +logcollector/read_command.c read_command.c +syscheckd/config.c syscheckd-config.c +syscheckd/create_db.c create_db.c +syscheckd/run_check.c run_check.c +syscheckd/run_realtime.c run_realtime.c +syscheckd/syscheck.c syscheck.c +syscheckd/syscheck.h syscheck.h +syscheckd/win-registry.c win-registry.c +rootcheck rootcheck +external/zlib-1.2.3/zlib.h zlib.h +external/zlib-1.2.3/zconf.h zconf.h +os_zlib/os_zlib.c os_zlib.c +os_zlib/os_zlib.h os_zlib.h +win32/os_win.h os_win.h +win32/win_agent.c win_agent.c +win32/win_service.c win_service.c +win32/make.bat make.bat +win32/setup-win.c setup/setup-win.c +win32/setup-iis.c setup/setup-iis.c +win32/setup-shared.c setup/setup-shared.c +win32/setup-shared.h setup/setup-shared.h +win32/setup-syscheck.c setup/setup-syscheck.c +win32/add-localfile.c setup/add-localfile.c +win32/ossec-win.conf default-ossec.conf +win32/vista_sec.csv vista_sec.csv +win32/internal_options-win.conf internal_options.conf +win32/doc.html doc.html +win32/help_win.txt help.txt +win32/ossec-installer.nsi ossec-installer.nsi +win32/ui.nsi ui.nsi +win32/make.sh make.sh +win32/ossec-uninstall.ico ossec-uninstall.ico +win32/service-start.c setup/service-start.c +win32/service-stop.c setup/service-stop.c +win32/LICENSE.txt LICENSE.txt +win32/route-null.cmd route-null.cmd +win32/restart-ossec.cmd restart-ossec.cmd +win32/favicon.ico favicon.ico +win32/icofile.rc icofile.rc +win32/ui ui diff --git a/src/win32/win_agent.c b/src/win32/win_agent.c new file mode 100755 index 0000000..b631a9c --- /dev/null +++ b/src/win32/win_agent.c @@ -0,0 +1,656 @@ +/* @(#) $Id: win_agent.c,v 1.56 2009/12/01 20:27:01 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifdef WIN32 + +#include "shared.h" +#include "agentd.h" +#include "logcollector.h" +#include "os_win.h" +#include "os_net/os_net.h" +#include "os_execd/execd.h" +#include "os_crypto/md5/md5_op.h" + +#ifndef ARGV0 +#define ARGV0 "ossec-agent" +#endif + +time_t __win32_curr_time = 0; +time_t __win32_shared_time = 0; +char *__win32_uname = NULL; +char *__win32_shared = NULL; +HANDLE hMutex; + + +/** Prototypes **/ +int Start_win32_Syscheck(); +void send_win32_info(time_t curr_time); + + +/* Help message */ +void agent_help() +{ + printf("\nOSSEC HIDS %s %s .\n", ARGV0, __version); + printf("Available options:\n"); + printf("\t-h This help message.\n"); + printf("\thelp This help message.\n"); + printf("\tinstall-service Installs as a service\n"); + printf("\tuninstall-service Uninstalls as a service\n"); + printf("\tstart Manually starts (not from services)\n"); + exit(1); +} + +/* syscheck main thread */ +void *skthread() +{ + verbose("%s: Starting syscheckd thread.", ARGV0); + + Start_win32_Syscheck(); + + return (NULL); +} + + +/** main(int argc, char **argv) + * .. + */ +int main(int argc, char **argv) +{ + char *tmpstr; + char mypath[OS_MAXSTR +1]; + char myfile[OS_MAXSTR +1]; + + /* Setting the name */ + OS_SetName(ARGV0); + + + /* Find where I'm */ + mypath[OS_MAXSTR] = '\0'; + myfile[OS_MAXSTR] = '\0'; + + + /* mypath is going to be the whole path of the file */ + strncpy(mypath, argv[0], OS_MAXSTR); + tmpstr = strrchr(mypath, '\\'); + if(tmpstr) + { + /* tmpstr is now the file name */ + *tmpstr = '\0'; + tmpstr++; + strncpy(myfile, tmpstr, OS_MAXSTR); + } + else + { + strncpy(myfile, argv[0], OS_MAXSTR); + mypath[0] = '.'; + mypath[1] = '\0'; + } + chdir(mypath); + getcwd(mypath, OS_MAXSTR -1); + strncat(mypath, "\\", OS_MAXSTR - (strlen(mypath) + 2)); + strncat(mypath, myfile, OS_MAXSTR - (strlen(mypath) + 2)); + + + if(argc > 1) + { + if(strcmp(argv[1], "install-service") == 0) + { + return(InstallService(mypath)); + } + else if(strcmp(argv[1], "uninstall-service") == 0) + { + return(UninstallService()); + } + else if(strcmp(argv[1], "start") == 0) + { + return(local_start()); + } + else if(strcmp(argv[1], "-h") == 0) + { + agent_help(); + } + else if(strcmp(argv[1], "help") == 0) + { + agent_help(); + } + else + { + merror("%s: Unknown option: %s", ARGV0, argv[1]); + exit(1); + } + } + + + /* Start it */ + if(!os_WinMain(argc, argv)) + { + ErrorExit("%s: Unable to start WinMain.", ARGV0); + } + + return(0); +} + + +/* Locally starts (after service/win init) */ +int local_start() +{ + int debug_level; + char *cfg = DEFAULTCPATH; + WSADATA wsaData; + DWORD threadID; + DWORD threadID2; + + + /* Starting logr */ + logr = (agent *)calloc(1, sizeof(agent)); + if(!logr) + { + ErrorExit(MEM_ERROR, ARGV0); + } + logr->port = DEFAULT_SECURE; + + + /* Getting debug level */ + debug_level = getDefine_Int("windows","debug", 0, 2); + while(debug_level != 0) + { + nowDebug(); + debug_level--; + } + + + + /* Configuration file not present */ + if(File_DateofChange(cfg) < 0) + ErrorExit("%s: Configuration file '%s' not found",ARGV0,cfg); + + + /* Starting Winsock */ + if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) + { + ErrorExit("%s: WSAStartup() failed", ARGV0); + } + + + /* Read agent config */ + debug1("%s: DEBUG: Reading agent configuration.", ARGV0); + if(ClientConf(cfg) < 0) + { + ErrorExit(CLIENT_ERROR,ARGV0); + } + + + /* Reading logcollector config file */ + debug1("%s: DEBUG: Reading logcollector configuration.", ARGV0); + if(LogCollectorConfig(cfg) < 0) + { + ErrorExit(CONFIG_ERROR, ARGV0, cfg); + } + + + /* Checking auth keys */ + if(!OS_CheckKeys()) + { + ErrorExit(AG_NOKEYS_EXIT, ARGV0); + } + + + + /* If there is not file to monitor, create a clean entry + * for the mark messages. + */ + if(logff == NULL) + { + os_calloc(2, sizeof(logreader), logff); + logff[0].file = NULL; + logff[0].ffile = NULL; + logff[0].logformat = NULL; + logff[0].fp = NULL; + logff[1].file = NULL; + logff[1].logformat = NULL; + + merror(NO_FILE, ARGV0); + } + + + /* Reading execd config. */ + if(!WinExecd_Start()) + { + logr->execdq = -1; + } + + + /* Reading keys */ + verbose(ENC_READ, ARGV0); + + OS_ReadKeys(&keys); + OS_StartCounter(&keys); + os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id); + + + /* Initial random numbers */ + srandom(time(0)); + random(); + + + /* Socket connection */ + logr->sock = -1; + StartMQ(NULL, 0); + + + /* Starting mutex */ + debug1("%s: DEBUG: Creating thread mutex.", ARGV0); + hMutex = CreateMutex(NULL, FALSE, NULL); + if(hMutex == NULL) + { + ErrorExit("%s: Error creating mutex.", ARGV0); + } + + + + /* Starting syscheck thread */ + if(CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)skthread, + NULL, + 0, + (LPDWORD)&threadID) == NULL) + { + merror(THREAD_ERROR, ARGV0); + } + + + + /* Checking if server is connected */ + os_setwait(); + + start_agent(1); + + os_delwait(); + + + /* Sending integrity message for agent configs */ + intcheck_file(cfg, ""); + intcheck_file(OSSEC_DEFINES, ""); + + + /* Starting receiver thread */ + if(CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)receiver_thread, + NULL, + 0, + (LPDWORD)&threadID2) == NULL) + { + merror(THREAD_ERROR, ARGV0); + } + + + /* Sending agent information message */ + send_win32_info(time(0)); + + + /* Startting logcollector -- main process here */ + LogCollectorStart(); + + WSACleanup(); + return(0); +} + + +/* SendMSG for windows */ +int SendMSG(int queue, char *message, char *locmsg, char loc) +{ + int _ssize; + + time_t cu_time; + + char *pl; + char tmpstr[OS_MAXSTR+2]; + char crypt_msg[OS_MAXSTR +2]; + + DWORD dwWaitResult; + + tmpstr[OS_MAXSTR +1] = '\0'; + crypt_msg[OS_MAXSTR +1] = '\0'; + + + debug2("%s: DEBUG: Attempting to send message to server.", ARGV0); + + /* Using a mutex to synchronize the writes */ + while(1) + { + dwWaitResult = WaitForSingleObject(hMutex, 1000000L); + + if(dwWaitResult != WAIT_OBJECT_0) + { + switch(dwWaitResult) + { + case WAIT_TIMEOUT: + merror("%s: Error waiting mutex (timeout).", ARGV0); + sleep(5); + continue; + case WAIT_ABANDONED: + merror("%s: Error waiting mutex (abandoned).", ARGV0); + return(0); + default: + merror("%s: Error waiting mutex.", ARGV0); + return(0); + } + } + else + { + /* Lock acquired */ + break; + } + } + + + cu_time = time(0); + + + /* Check if the server has responded */ + if((cu_time - available_server) > (NOTIFY_TIME - 180)) + { + debug1("%s: DEBUG: Sending info to server (c1)...", ARGV0); + send_win32_info(cu_time); + + + /* Attempting to send message again. */ + if((cu_time - available_server) > NOTIFY_TIME) + { + sleep(1); + send_win32_info(cu_time); + sleep(1); + + if((cu_time - available_server) > NOTIFY_TIME) + { + send_win32_info(cu_time); + } + } + + + /* If we reached here, the server is unavailable for a while. */ + if((cu_time - available_server) > ((3 * NOTIFY_TIME) - 180)) + { + int wi = 1; + + + /* Last attempt before going into reconnect mode. */ + debug1("%s: DEBUG: Sending info to server (c3)...", ARGV0); + sleep(1); + send_win32_info(cu_time); + if((cu_time - available_server) > ((3 * NOTIFY_TIME) - 180)) + { + sleep(1); + send_win32_info(cu_time); + sleep(1); + } + + + /* Checking and generating log if unavailable. */ + cu_time = time(0); + if((cu_time - available_server) > ((3 * NOTIFY_TIME) - 180)) + { + int global_sleep = 1; + int mod_sleep = 12; + + /* If response is not available, set lock and + * wait for it. + */ + verbose(SERVER_UNAV, ARGV0); + + + /* Going into reconnect mode. */ + while((cu_time - available_server) > ((3*NOTIFY_TIME) - 180)) + { + /* Sending information to see if server replies */ + if(logr->sock != -1) + { + send_win32_info(cu_time); + } + + sleep(wi); + cu_time = time(0); + + if(wi < 20) + { + wi++; + } + else + { + global_sleep++; + } + + + /* If we have more than one server, try all. */ + if(wi > 12 && logr->rip[1]) + { + int curr_rip = logr->rip_id; + merror("%s: INFO: Trying next server ip in " + "line: '%s'.", + ARGV0, + logr->rip[logr->rip_id + 1] != NULL? + logr->rip[logr->rip_id + 1]: + logr->rip[0]); + + connect_server(logr->rip_id +1); + + if(logr->rip_id != curr_rip) + { + wi = 1; + } + } + else if(global_sleep == 2 || ((global_sleep % mod_sleep) == 0) || + (logr->sock == -1)) + { + connect_server(logr->rip_id +1); + if(logr->sock == -1) + { + sleep(wi + global_sleep); + } + else + { + sleep(global_sleep); + } + + if(global_sleep > 30) + { + mod_sleep = 50; + } + } + } + + verbose(AG_CONNECTED, ARGV0, logr->rip[logr->rip_id], + logr->port); + verbose(SERVER_UP, ARGV0); + } + } + } + + + /* Send notification */ + else if((cu_time - __win32_curr_time) > (NOTIFY_TIME - 200)) + { + debug1("%s: DEBUG: Sending info to server (ctime2)...", ARGV0); + send_win32_info(cu_time); + } + + + + /* locmsg cannot have the C:, as we use it as delimiter */ + pl = strchr(locmsg, ':'); + if(pl) + { + /* Setting pl after the ":" if it exists. */ + pl++; + } + else + { + pl = locmsg; + } + + + debug2("%s: DEBUG: Sending message to server: '%s'", ARGV0, message); + + snprintf(tmpstr,OS_MAXSTR,"%c:%s:%s", loc, pl, message); + + _ssize = CreateSecMSG(&keys, tmpstr, crypt_msg, 0); + + + /* Returns NULL if can't create encrypted message */ + if(_ssize == 0) + { + merror(SEC_ERROR,ARGV0); + if(!ReleaseMutex(hMutex)) + { + merror("%s: Error releasing mutex.", ARGV0); + } + + return(-1); + } + + /* Send _ssize of crypt_msg */ + if(OS_SendUDPbySize(logr->sock, _ssize, crypt_msg) < 0) + { + merror(SEND_ERROR,ARGV0, "server"); + sleep(1); + } + + if(!ReleaseMutex(hMutex)) + { + merror("%s: Error releasing mutex.", ARGV0); + } + return(0); +} + + +/* StartMQ for windows */ +int StartMQ(char * path, short int type) +{ + /* Connecting to the server. */ + connect_server(0); + + if((path == NULL) && (type == 0)) + { + return(0); + } + + return(0); +} + + +/* Send win32 info to server */ +void send_win32_info(time_t curr_time) +{ + int msg_size; + char tmp_msg[OS_MAXSTR +2]; + char crypt_msg[OS_MAXSTR +2]; + + tmp_msg[OS_MAXSTR +1] = '\0'; + crypt_msg[OS_MAXSTR +1] = '\0'; + + + debug1("%s: DEBUG: Sending keep alive message.", ARGV0); + + + /* fixing time */ + __win32_curr_time = curr_time; + + + /* Getting uname. */ + if(!__win32_uname) + { + __win32_uname = getuname(); + if(!__win32_uname) + { + merror("%s: Error generating system information.", ARGV0); + os_strdup("Microsoft Windows - Unknown (unable to get system info)", __win32_uname); + } + } + + + /* Getting shared files list -- every 30 seconds only. */ + if((__win32_curr_time - __win32_shared_time) > 30) + { + if(__win32_shared) + { + free(__win32_shared); + __win32_shared = NULL; + } + + __win32_shared_time = __win32_curr_time; + } + + + /* get shared files */ + if(!__win32_shared) + { + __win32_shared = getsharedfiles(); + if(!__win32_shared) + { + __win32_shared = strdup("\0"); + if(!__win32_shared) + { + merror(MEM_ERROR, ARGV0); + return; + } + } + } + + + + /* creating message */ + if(File_DateofChange(AGENTCONFIGINT) > 0) + { + os_md5 md5sum; + if(OS_MD5_File(AGENTCONFIGINT, md5sum) != 0) + { + snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared); + } + else + { + snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s", __win32_uname, md5sum, __win32_shared); + } + } + else + { + snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared); + } + + + /* creating message */ + debug1("%s: DEBUG: Sending keep alive: %s", ARGV0, tmp_msg); + + msg_size = CreateSecMSG(&keys, tmp_msg, crypt_msg, 0); + + if(msg_size == 0) + { + merror(SEC_ERROR, ARGV0); + return; + } + + /* Sending UDP message */ + if(OS_SendUDPbySize(logr->sock, msg_size, crypt_msg) < 0) + { + merror(SEND_ERROR, ARGV0, "server"); + sleep(1); + } + + return; +} + +#endif +/* EOF */ diff --git a/src/win32/win_service.c b/src/win32/win_service.c new file mode 100755 index 0000000..749abad --- /dev/null +++ b/src/win32/win_service.c @@ -0,0 +1,361 @@ +/* @(#) $Id: win_service.c,v 1.13 2009/06/24 18:53:10 dcid Exp $ */ + +/* Copyright (C) 2009 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 3) as published by the FSF - Free Software + * Foundation. + * + * License details at the LICENSE file included with OSSEC or + * online at: http://www.ossec.net/en/licensing.html + */ + + +#ifdef WIN32 + +#include "shared.h" +#include "os_win.h" +#include + +#ifndef ARGV0 +#define ARGV0 "ossec-agent" +#endif + +static LPTSTR g_lpszServiceName = "OssecSvc"; +static LPTSTR g_lpszServiceDisplayName = "OSSEC Hids"; +static LPTSTR g_lpszServiceDescription = "OSSEC Hids Windows Agent"; + +static SERVICE_STATUS ossecServiceStatus; +static SERVICE_STATUS_HANDLE ossecServiceStatusHandle; + +/* ServiceStart */ +void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv); + + + +/* os_start_service: Starts ossec service */ +int os_start_service() +{ + int rc = 0; + SC_HANDLE schSCManager, schService; + + + /* Removing from the services database */ + schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (schSCManager) + { + schService = OpenService(schSCManager,g_lpszServiceName, + SC_MANAGER_ALL_ACCESS); + if(schService) + { + + if(StartService(schService, 0, NULL)) + { + rc = 1; + } + else + { + if(GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) + { + rc = -1; + } + } + + CloseServiceHandle(schService); + } + + CloseServiceHandle(schSCManager); + } + + return(rc); +} + + +/* os_start_service: Starts ossec service */ +int os_stop_service() +{ + int rc = 0; + SC_HANDLE schSCManager, schService; + + + /* Removing from the services database */ + schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (schSCManager) + { + schService = OpenService(schSCManager,g_lpszServiceName, + SC_MANAGER_ALL_ACCESS); + if(schService) + { + SERVICE_STATUS lpServiceStatus; + + if(ControlService(schService, + SERVICE_CONTROL_STOP, &lpServiceStatus)) + { + rc = 1; + } + + CloseServiceHandle(schService); + } + + CloseServiceHandle(schSCManager); + } + + return(rc); +} + + +/* int QueryService(): Checks if service is running. */ +int CheckServiceRunning() +{ + int rc = 0; + SC_HANDLE schSCManager, schService; + + + /* Removing from the services database */ + schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (schSCManager) + { + schService = OpenService(schSCManager,g_lpszServiceName, + SC_MANAGER_ALL_ACCESS); + if(schService) + { + /* Checking status */ + SERVICE_STATUS lpServiceStatus; + + if(QueryServiceStatus(schService, &lpServiceStatus)) + { + if(lpServiceStatus.dwCurrentState == SERVICE_RUNNING) + { + rc = 1; + } + } + CloseServiceHandle(schService); + } + + CloseServiceHandle(schSCManager); + } + + return(rc); +} + + +/* int InstallService() + * Install the OSSEC HIDS agent service. + */ +int InstallService(char *path) +{ + char buffer[MAX_PATH+1]; + + SC_HANDLE schSCManager, schService; + LPCTSTR lpszBinaryPathName = NULL; + SERVICE_DESCRIPTION sdBuf; + + + /* Cleaning up some variables */ + buffer[MAX_PATH] = '\0'; + + + /* Executable path -- it must be called with the + * full path + */ + lpszBinaryPathName = path; + + /* Opening the services database */ + schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); + + if (schSCManager == NULL) + { + goto install_error; + } + + /* Creating the service */ + schService = CreateService(schSCManager, + g_lpszServiceName, + g_lpszServiceDisplayName, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, + lpszBinaryPathName, + NULL, NULL, NULL, NULL, NULL); + + if (schService == NULL) + { + goto install_error; + } + + /* Setting description */ + sdBuf.lpDescription = g_lpszServiceDescription; + if(!ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdBuf)) + { + goto install_error; + } + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + + printf(" [%s] Successfully added to the Services database.\n", ARGV0); + return(1); + + + install_error: + { + char local_msg[1025]; + LPVOID lpMsgBuf; + + memset(local_msg, 0, 1025); + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL); + + merror(local_msg, 1024, "[%s] Unable to create registry " + "entry: %s", ARGV0,(LPCTSTR)lpMsgBuf); + return(0); + } +} + + +/* int UninstallService() + * Uninstall the OSSEC HIDS agent service. + */ +int UninstallService() +{ + SC_HANDLE schSCManager, schService; + + + /* Removing from the services database */ + schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (schSCManager) + { + schService = OpenService(schSCManager,g_lpszServiceName,DELETE); + if(schService) + { + if (DeleteService(schService)) + + { + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + + printf(" [%s] Successfully removed from " + "the Services database.\n", ARGV0); + return(1); + } + CloseServiceHandle(schService); + } + CloseServiceHandle(schSCManager); + } + + fprintf(stderr, " [%s] Error removing from " + "the Services database.\n", ARGV0); + + return(0); +} + + + +/** VOID WINAPI OssecServiceCtrlHandler (DWORD dwOpcode) + * "Signal" handler + */ +VOID WINAPI OssecServiceCtrlHandler(DWORD dwOpcode) +{ + switch(dwOpcode) + { + case SERVICE_CONTROL_STOP: + ossecServiceStatus.dwCurrentState = SERVICE_STOPPED; + ossecServiceStatus.dwWin32ExitCode = 0; + ossecServiceStatus.dwCheckPoint = 0; + ossecServiceStatus.dwWaitHint = 0; + + verbose("%s: Received exit signal.", ARGV0); + SetServiceStatus (ossecServiceStatusHandle, &ossecServiceStatus); + verbose("%s: Exiting...", ARGV0); + return; + default: + break; + } + return; +} + + +/** void WinSetError() + * Sets the error code in the services + */ +void WinSetError() +{ + OssecServiceCtrlHandler(SERVICE_CONTROL_STOP); +} + + +/** int os_WinMain(int argc, char **argv) + * Initializes OSSEC dispatcher + */ +int os_WinMain(int argc, char **argv) +{ + SERVICE_TABLE_ENTRY steDispatchTable[] = + { + { g_lpszServiceName, OssecServiceStart }, + { NULL, NULL } + }; + + if(!StartServiceCtrlDispatcher(steDispatchTable)) + { + merror("%s: Unable to set service information.", ARGV0); + return(1); + } + + return(1); +} + + +/** void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv) + * Starts OSSEC service + */ +void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv) +{ + ossecServiceStatus.dwServiceType = SERVICE_WIN32; + ossecServiceStatus.dwCurrentState = SERVICE_START_PENDING; + ossecServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + ossecServiceStatus.dwWin32ExitCode = 0; + ossecServiceStatus.dwServiceSpecificExitCode= 0; + ossecServiceStatus.dwCheckPoint = 0; + ossecServiceStatus.dwWaitHint = 0; + + ossecServiceStatusHandle = + RegisterServiceCtrlHandler(g_lpszServiceName, + OssecServiceCtrlHandler); + + if (ossecServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) + { + merror("%s: RegisterServiceCtrlHandler failed.", ARGV0); + return; + } + + ossecServiceStatus.dwCurrentState = SERVICE_RUNNING; + ossecServiceStatus.dwCheckPoint = 0; + ossecServiceStatus.dwWaitHint = 0; + + if (!SetServiceStatus(ossecServiceStatusHandle, &ossecServiceStatus)) + { + merror("%s: SetServiceStatus error.", ARGV0); + return; + } + + + #ifdef OSSECHIDS + /* Starting process */ + local_start(); + #endif +} + + +#endif +/* EOF */